Skip to content

Commit f1c8e1a

Browse files
committed
doc: Improve doc splitting
1 parent a8829ca commit f1c8e1a

7 files changed

Lines changed: 283 additions & 310 deletions

File tree

README.md

Lines changed: 46 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Strongly typed, full-featured, light, versatile yet powerful Twitter API v1.1 an
1010

1111
**Ready for v2 and good ol' v1.1 Twitter API**
1212

13-
**Light: No dependencies, 15.2kb minified+gzipped**
13+
**Light: No dependencies, 16kb minified+gzipped**
1414

1515
**Bundled types for request parameters and responses**
1616

@@ -33,47 +33,14 @@ A small feature comparaison with other libs:
3333

3434
| Package | API version(s) | Response typings | Media helpers | Pagination | Subdeps | Size (gzip) | Install size |
3535
| -------------- | -------------- | ---------------- | ------------- | ---------- | --------------- | -------------:| -------------:|
36-
| twitter-api-v2 | v1.1, v2, labs |||| 0 | ~15.2 kB | [![twitter-api-v2 install size badge](https://badgen.net/packagephobia/install/twitter-api-v2)](https://packagephobia.com/result?p=twitter-api-v2) |
36+
| twitter-api-v2 | v1.1, v2, labs |||| 0 | ~16 kB | [![twitter-api-v2 install size badge](https://badgen.net/packagephobia/install/twitter-api-v2)](https://packagephobia.com/result?p=twitter-api-v2) |
3737
| twit | v1.1 |||| 51 | ~214.5 kB | [![twit install size badge](https://badgen.net/packagephobia/install/twit)](https://packagephobia.com/result?p=twit) |
3838
| twitter | v1.1 |||| 50 | ~182.1 kB | [![twitter install size badge](https://badgen.net/packagephobia/install/twitter)](https://packagephobia.com/result?p=twitter) |
3939
| twitter-lite | v1.1, v2 ||* || 4 | ~5.3 kB | [![twitter-lite install size badge](https://badgen.net/packagephobia/install/twitter-lite)](https://packagephobia.com/result?p=twitter-lite) |
4040
| twitter-v2 | v2 |||| 7 | ~4.5 kB | [![twitter-v2 install size badge](https://badgen.net/packagephobia/install/twitter-v2)](https://packagephobia.com/result?p=twitter-v2) |
4141

4242
\**No support for `media/upload`, cannot send a `multipart/form-data` encoded-body without tricks*
4343

44-
## Features
45-
46-
Here's the detailed feature list of `twitter-api-v2`:
47-
48-
### Basics:
49-
- Support for v1.1 and **v2 of Twitter API**
50-
- Make signed HTTP requests to Twitter with every Twitter required auth type:
51-
- classic **OAuth 1.0a** authentification for user-context endpoints
52-
- **OAuth2 Bearer token** for app-only endpoints
53-
- **Basic** HTTP Authorization, required for some auth endpoints or Entreprise API
54-
- Helpers for numerous HTTP request methods (`GET`, `POST`, `PUT`, `DELETE` and `PATCH`),
55-
that handle query string parse & format, automatic body formatting and more
56-
- High-class support for stream endpoints, with easy data consumption and auto-reconnect on stream errors
57-
58-
### Request helpers:
59-
- Automatic paginator for endpoints like user and tweet timelines,
60-
allowing payload consumption with modern asynchronous iterators until your rate-limit is hit
61-
- Convenient methods for authentication - generate auth links and ask for tokens to your users will be a breeze
62-
- Media upload with API v1.1, including **long video & subtitles support**, automatic media type detection,
63-
**chunked upload** and support for **concurrent uploads**
64-
- Dedicated methods that wraps API v1.1 & v2 endpoints, with **typed arguments** and fully **typed responses**
65-
*(WIP - not all public endpoints are available)*
66-
- Bundled parsing of rate limit headers
67-
- Typed errors, meaningful error messages, error enumerations for both v1.1 and v2
68-
69-
### Type-safe first:
70-
- **Typings for tweet, user, media entities (and more) are bundled in this package!**
71-
- Type-safe wrapping of dedicated methods in 3 right level: *DM*/*Read-write*/*Read-only* (just like Twitter API do!) -
72-
you can declare a read-only client - you will only see the methods associated with read-only endpoints
73-
74-
75-
And last but not least, fully powered by native `Promise`s.
76-
7744
## How to use
7845

7946
Install it through your favorite package manager:
@@ -99,36 +66,56 @@ const user = await roClient.v2.userByUsername('plhery');
9966
await twitterClient.v1.tweet('Hello, this is a test.');
10067
// You can upload media easily!
10168
await twitterClient.v1.uploadMedia('./big-buck-bunny.mp4');
102-
103-
// Or manually call the API
104-
await twitterClient.v2.get('tweets/search/recent', { query: 'nodeJS', max_results: 100 });
105-
const tweets = await twitterClient.get('https://api.twitter.com/2/tweets/search/recent?query=nodeJS&max_results=100');
10669
```
10770

108-
**Note:** Top-level use of `await` is not available in most of Node.js usage. You might need to wrap `await`s into async functions. See [MDN related documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function).
109-
110-
### Basics
111-
112-
You want **to know more about client usage? See [the Basics](./doc/basics.md)**!
113-
114-
This lib also provide a bunch of helpers to work around Twitter API responses. See [the helpers part here](./doc/helpers.md).
71+
## Documentation
72+
73+
Learn how to use the full potential of `twitter-api-v2`.
74+
75+
- Get started
76+
- [Create a client and make your first request](./doc/basics.md)
77+
- [Handle Twitter authentification flows](./doc/auth.md)
78+
- [Explore some examples](./doc/examples.md)
79+
- Use endpoints wrappers — ensure typings of request & response
80+
- [Available endpoint wrappers for v1.1 API](./doc/v1.md)
81+
- [Available endpoint wrappers for v2 API](./doc/v2.md)
82+
- [Use Twitter streaming endpoints (v1.1 & v2)](./doc/streaming.md)
83+
- Deep diving into requests
84+
- [Use direct HTTP-method wrappers](./doc/http-wrappers.md)
85+
- [Use rate limit helpers](./doc/rate-limiting.md)
86+
- [Handle errors](./doc/errors.md)
87+
- [Master `twitter-api-v2` paginators](./doc/paginators.md)
88+
- [Discover available helpers](./doc/helpers.md)
11589

116-
### Examples
117-
118-
Wanna see that in action? Jump to [Examples part](./doc/examples.md).
119-
120-
## Authentification
90+
## Features
12191

122-
Lost between the different ways to auth inside Twitter API?
123-
Don't know how to implement 3-legged OAuth flow?
92+
Here's the detailed feature list of `twitter-api-v2`:
12493

125-
See [Authentification part](./doc/auth.md) to know more and have a comprehensive guide a every Twitter authentification process.
94+
### Basics:
95+
- Support for v1.1 and **v2 of Twitter API**
96+
- Make signed HTTP requests to Twitter with every Twitter required auth type:
97+
- classic **OAuth 1.0a** authentification for user-context endpoints
98+
- **OAuth2 Bearer token** for app-only endpoints
99+
- **Basic** HTTP Authorization, required for some auth endpoints or Entreprise API
100+
- Helpers for numerous HTTP request methods (`GET`, `POST`, `PUT`, `DELETE` and `PATCH`),
101+
that handle query string parse & format, automatic body formatting and more
102+
- High-class support for stream endpoints, with easy data consumption and auto-reconnect on stream errors
126103

127-
## Streaming
104+
### Request helpers:
105+
- Automatic paginator for endpoints like user and tweet timelines,
106+
allowing payload consumption with modern asynchronous iterators until your rate-limit is hit
107+
- Convenient methods for authentication - generate auth links and ask for tokens to your users will be a breeze
108+
- Media upload with API v1.1, including **long video & subtitles support**, automatic media type detection,
109+
**chunked upload** and support for **concurrent uploads**
110+
- Dedicated methods that wraps API v1.1 & v2 endpoints, with **typed arguments** and fully **typed responses**
111+
*(WIP - not all public endpoints are available)*
112+
- Bundled parsing of rate limit headers
113+
- Typed errors, meaningful error messages, error enumerations for both v1.1 and v2
128114

129-
APIs dedicated to streaming are available in [Streaming part](./doc/streaming.md).
115+
### Type-safe first:
116+
- **Typings for tweet, user, media entities (and more) are bundled in this package!**
117+
- Type-safe wrapping of dedicated methods in 3 right level: *DM*/*Read-write*/*Read-only* (just like Twitter API do!) -
118+
you can declare a read-only client - you will only see the methods associated with read-only endpoints
130119

131-
## Full package API
132120

133-
Each Twitter endpoint > method association is described in details inside [the v1.1 comprehensive documentation](./doc/v1.md)
134-
and [the v2 comprehensive documentation](./doc/v2.md).
121+
And last but not least, fully powered by native `Promise`s.

doc/basics.md

Lines changed: 4 additions & 230 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ const userClient = new TwitterApi({
4040
});
4141

4242
// OAuth2 (App-only context)
43+
// Create a client with an already known bearer token
4344
const appOnlyClient = new TwitterApi('bearerToken');
44-
// - you can also create a app-only client from your consumer keys -
45+
// OR - you can also create a app-only client from your consumer keys -
4546
const appOnlyClientFromConsumer = await userClient.appLogin();
4647
```
4748

@@ -68,11 +69,7 @@ you can use the method `.currentUser()`.
6869
This a shortcut to `.v1.verifyCredentials()` with a **cache that store user to avoid multiple API calls**.
6970
Its returns a `UserV1` object.
7071

71-
## Request basics
72-
73-
The main goal of those clients is to make requests (right?). Let's see how we do it!
74-
75-
### Use the versionned API clients
72+
## Use the versionned API clients - URL prefixes
7673

7774
By default, `twitter-api-v2` don't know which version of API you want to use (because it supports both!).
7875

@@ -90,229 +87,6 @@ Using the versionned client **auto-prefix requests** with default prefixes
9087
for labs v2: `https://api.twitter.com/labs/2/`)
9188
and gives you access to endpoint-wrapper methods!
9289

93-
### Use the endpoint-wrapper methods
90+
## Use the endpoint-wrapper methods
9491

9592
See the [documentation for v1 client API](./v1.md) or [documentation for v2 client API](./v2.md).
96-
97-
### Use the direct HTTP methods wrappers
98-
99-
If the endpoint-wrapper for your request has not been made yet, don't leave!
100-
You can make requests on your own!
101-
102-
- `.get` and `.delete`, that takes `(partialUrl: string, query?: TRequestQuery, requestSettings?: TGetClientRequestArgs)` in parameters
103-
- `.post`, `.put` and `.patch` that takes `(partialUrl: string, body?: TRequestBody, requestSettings?: TGetClientRequestArgs)` in parameters
104-
105-
```ts
106-
// Don't forget the .json in most of the v1 endpoints!
107-
client.v1.get('statuses/user_timeline.json', { user_id: 14 });
108-
109-
// or, for v2
110-
client.v2.get('users/14/tweets');
111-
```
112-
113-
#### Specify request args
114-
115-
Sometimes, you need to customize request settings (API prefix, body mode, response mode). You can pass request options through the **third parameter** of HTTP methods wrappers.
116-
```ts
117-
// [prefix]
118-
// Customize API prefix (prefix that will be prepended to URL in first argument)
119-
client.v1.post('media/upload.json', { media: Buffer.alloc(1024) }, { prefix: 'https://upload.twitter.com/1.1/' })
120-
121-
// [forceBodyMode]
122-
// Customize body mode (if automatic body detection don't work)
123-
// Body mode can be 'url', 'form-data', 'json' or 'raw' [only with buffers]
124-
client.v1.post('statuses/update.json', { status: 'Hello' }, { forceBodyMode: 'url' })
125-
126-
// [fullResponse]
127-
// Obtain the full response object with rate limits
128-
const res = await client.v1.get('statuses/home_timeline.json', undefined, { fullResponse: true })
129-
console.log(res.rateLimit, res.data)
130-
131-
// [headers]
132-
// Customize sent HTTP headers
133-
client.v1.post('statuses/update.json', { status: 'Hello' }, { headers: { 'X-Custom-Header': 'My Header Value' } })
134-
```
135-
136-
### Advanced: make a custom signed request
137-
138-
`twitter-api-v2` gives you a client that handles all the request signin boilerplate for you.
139-
140-
Sometimes, you need to dive deep and make the request on your own.
141-
2 raw helpers allow you to make the request you want:
142-
- `.send`: Make a request, awaits its complete response, parse it and returns it
143-
- `.sendStream`: Make a requests, returns a stream when server responds OK
144-
145-
**Warning**: When you use those methods, you need to prefix your requests (no auto-prefixing)!
146-
Make sure you use a URL that begins with `https://...` with raw request managers.
147-
148-
#### .send
149-
150-
**Template types**: `T = any`
151-
152-
**Args**: `IGetHttpRequestArgs`
153-
154-
**Returns**: (async) `TwitterResponse<T>`
155-
156-
```ts
157-
const response = await client.send({
158-
method: 'GET',
159-
url: 'https://api.twitter.com/2/tweets/search/all',
160-
query: { max_results: 200 },
161-
headers: { 'X-Custom-Header': 'True' },
162-
});
163-
164-
response.data; // Twitter response body: { data: Tweet[], meta: {...} }
165-
response.rateLimit.limit; // Ex: 900
166-
```
167-
168-
#### .sendStream
169-
170-
**Args**: `IGetHttpRequestArgs`
171-
172-
**Returns**: (async) `TweetStream`
173-
174-
```ts
175-
const stream = await client.sendStream({
176-
method: 'GET',
177-
url: 'https://api.twitter.com/2/tweets/sample/stream',
178-
});
179-
// For response handling, see streaming documentation
180-
```
181-
182-
## Rate limiting
183-
184-
### Get last rate limit info
185-
186-
#### Using endpoint wrappers
187-
188-
You can obtain lastly collected information of rate limit for each already used endpoint.
189-
190-
First, you need to know **which endpoint URL is concerned by the used endpoint wrapper**, for example,
191-
for `.v1.tweets`, it is `statuses/lookup.json`. The endpoint is always specified in the lib documentation.
192-
193-
Use the endpoint URL to know:
194-
- The last received status of rate limiting with `.getLastRateLimitStatus`
195-
- If the stored rate limit information has expired with `.isRateLimitStatusObsolete`
196-
- If you hit the rate limit the last time you called this endpoint, with `.hasHitRateLimit`
197-
198-
```ts
199-
// Usage of statuses/lookup.json
200-
const tweets = await client.v1.tweets(['20', '30']);
201-
202-
// Don't forget to add .v1, otherwise you need to prefix
203-
// your endpoint URL with https://api.twitter.com/... :)
204-
console.log(client.v1.getLastRateLimitStatus('statuses/lookup.json'));
205-
// => { limit: 900, remaining: 899, reset: 1631015719 }
206-
207-
console.log(client.v1.isRateLimitStatusObsolete('statuses/lookup.json'));
208-
// => false if 'reset' property mentions a timestamp in the future
209-
210-
console.log(client.v1.hasHitRateLimit('statuses/lookup.json'));
211-
// => false if 'remaining' property is > 0
212-
```
213-
214-
#### Special case of HTTP methods helpers
215-
216-
If you use a HTTP method helper (`.get`, `.post`, ...), you can get a **full response** object that directly contains the rate limit information,
217-
even if the request didn't fail!
218-
```ts
219-
const manualFullResponse = await client.v1.get<TweetV1TimelineResult>('statuses/home_timeline.json', { since_id: '20' }, { fullResponse: true });
220-
221-
// Response data
222-
manualFullResponse.data; // TweetV1TimelineResult
223-
// Rate limit information
224-
manualFullResponse.rateLimit; // { limit: number, remaining: number, reset: number }
225-
```
226-
227-
### Handle errors - Everywhere in this library
228-
229-
This library helps you to handle rate limiting.
230-
When a request fails (with a Twitter response), it create a `ApiResponseError` instance and throw it.
231-
232-
If `ApiResponseErrorInstance.rateLimitError` is `true`, then you just hit the rate limit.
233-
You have access to rate limit limits with `ApiResponseErrorInstance.rateLimit`:
234-
235-
```ts
236-
import { ApiResponseError } from 'twitter-api-v2';
237-
238-
try {
239-
// Get a single tweet
240-
await client.v1.tweet('20');
241-
} catch (error) {
242-
if (error instanceof ApiResponseError && error.rateLimitError && error.rateLimit) {
243-
console.log(`You just hit the rate limit! Limit for this endpoint is ${error.rateLimit.limit} requests!`);
244-
console.log(`Request counter will reset at timestamp ${error.rateLimit.reset}.`);
245-
}
246-
}
247-
```
248-
249-
---
250-
251-
**Example**: You can automate this process with a waiter that will retry a failed request after the reset timer is over:
252-
253-
*Warning*: This method can be VERY ineffective, as it can wait up to 15 minutes (Twitter's usual rate limit reset time).
254-
```ts
255-
function sleep(ms: number) {
256-
return new Promise(resolve => setTimeout(ms, resolve));
257-
}
258-
259-
async function autoRetryOnRateLimitError<T>(callback: () => T | Promise<T>) {
260-
while (true) {
261-
try {
262-
return await callback();
263-
} catch (error) {
264-
if (error instanceof ApiResponseError && error.rateLimitError && error.rateLimit) {
265-
const resetTimeout = error.rateLimit.reset * 1000; // convert to ms time instead of seconds time
266-
const timeToWait = resetTimeout - Date.now();
267-
268-
await sleep(timeToWait);
269-
continue;
270-
}
271-
272-
throw error;
273-
}
274-
}
275-
}
276-
277-
// Then use it...
278-
await autoRetryOnRateLimitError(() => client.v1.tweet('20'));
279-
```
280-
281-
### Special case of paginators
282-
283-
Paginators will automatically handle the rate limit when using `.fetchLast` or async iteration.
284-
The `.fetchLast` or iteration will automatically ends when rate limit is hit.
285-
286-
Moreover, you can access current rate limit status for paginator's endpoint with the `.rateLimit` getter.
287-
```ts
288-
const paginator = await client.v1.homeTimeline();
289-
console.log(paginator.rateLimit); // { limit: number, remaining: number, reset: number }
290-
```
291-
292-
## Error handling
293-
294-
When a request fails, you get a `ApiRequestError` or a `ApiResponseError` object (both instances of `Error`), that contain useful information about whats happening.
295-
296-
- An `ApiRequestError` happens when the request **failed to sent** (network error, bad URL...).
297-
- An `ApiResponseError` happens when **Twitter replies with an error**.
298-
299-
Some properties are common for both objects:
300-
- `error` is `true`
301-
- `type` contains either `ETwitterApiError.Request` or `ETwitterApiError.Response` (depending of error)
302-
- `request` containing node's raw `ClientRequest` instance
303-
304-
### Specific properties of `ApiRequestError`
305-
- `requestError`, an instance of `Error` that has been thrown through `request.on('error')` handler
306-
307-
### Specific properties of `ApiResponseError`
308-
- `data`, containing parsed Twitter response data (type of `TwitterApiErrorData`)
309-
- `code` is a `number` containing the HTTP error code (`401`, `404`, ...)
310-
- `response`, containing raw node's `IncomingMessage` instance
311-
- `headers`, containing `IncomingHttpHeaders`
312-
- `rateLimit` (can be undefined or `TwitterRateLimit`), containing parsed rate limit headers (if any)
313-
- (getter) `errors`, direct access of parsed Twitter errors (`(ErrorV1 | ErrorV2)[]` or `undefined`)
314-
- (getter) `rateLimitError`, `true` if this error is fired because a rate limit has been hit
315-
- (getter) `isAuthError`, `true` if this error is fired because logged user cannot do this action (invalid token, invalid app rights...)
316-
317-
### Specific methods of `ApiResponseError`
318-
- `hasErrorCode(code: number | EApiV1ErrorCode | EApiV2ErrorCode)`: Tells if given Twitter error code is present in error response

0 commit comments

Comments
 (0)