scrapebadger 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,7 +19,8 @@ The official Node.js/TypeScript client library for the [ScrapeBadger](https://sc
19
19
  - **Full TypeScript Support** - Complete type definitions for all API endpoints
20
20
  - **Modern ESM & CommonJS** - Works with both module systems
21
21
  - **Async Iterators** - Automatic pagination with `for await...of` syntax
22
- - **Retry Logic** - Built-in exponential backoff for reliability
22
+ - **Smart Rate Limit Handling** - Reads API rate limit headers and automatically throttles pagination to avoid hitting limits
23
+ - **Resilient Retries** - 10 automatic retries with exponential backoff on server errors, with colored console warnings on each retry
23
24
  - **Error Handling** - Typed exceptions for different error scenarios
24
25
  - **Tree Shakeable** - Import only what you need
25
26
 
@@ -345,20 +346,45 @@ const client = new ScrapeBadger({
345
346
  // Required: Your API key (or use SCRAPEBADGER_API_KEY env var)
346
347
  apiKey: "your-api-key",
347
348
 
348
- // Optional: Custom base URL (default: https://api.scrapebadger.com)
349
- baseUrl: "https://api.scrapebadger.com",
349
+ // Optional: Custom base URL (default: https://scrapebadger.com)
350
+ baseUrl: "https://scrapebadger.com",
350
351
 
351
352
  // Optional: Request timeout in milliseconds (default: 30000)
352
353
  timeout: 30000,
353
354
 
354
- // Optional: Maximum retry attempts (default: 3)
355
- maxRetries: 3,
355
+ // Optional: Maximum retry attempts (default: 10)
356
+ maxRetries: 10,
356
357
 
357
358
  // Optional: Initial retry delay in milliseconds (default: 1000)
358
359
  retryDelay: 1000,
359
360
  });
360
361
  ```
361
362
 
363
+ ### Retry Behavior
364
+
365
+ The SDK automatically retries requests that fail with server errors (5xx) or rate
366
+ limits (429) using exponential backoff (1s, 2s, 4s, 8s, ...). Each retry prints a
367
+ colored warning:
368
+
369
+ ```
370
+ ⚠ ScrapeBadger: 503 Service Unavailable — retrying in 4s (attempt 3/10)
371
+ ```
372
+
373
+ ### Rate Limit Aware Pagination
374
+
375
+ When using `*All` pagination methods (e.g. `searchAll`, `getFollowersAll`), the SDK
376
+ reads `X-RateLimit-Remaining` and `X-RateLimit-Reset` headers from each response.
377
+ When remaining requests drop below 20% of your tier's limit, pagination automatically
378
+ slows down to spread requests across the remaining window — preventing 429 errors:
379
+
380
+ ```
381
+ ⚠ ScrapeBadger: Rate limit: 25/300 remaining (resets in 42s), throttling pagination
382
+ ```
383
+
384
+ This works transparently with all tier levels (Free: 60/min, Basic: 300/min,
385
+ Pro: 1000/min, Enterprise: 5000/min).
386
+ ```
387
+
362
388
  ## API Reference
363
389
 
364
390
  ### Client
@@ -27,6 +27,15 @@ interface ResolvedConfig {
27
27
  * Base HTTP client with retry logic and error handling.
28
28
  */
29
29
 
30
+ interface RateLimit {
31
+ limit: number;
32
+ remaining: number;
33
+ reset: number;
34
+ }
35
+ interface ResponseWithHeaders<T> {
36
+ data: T;
37
+ rateLimit?: RateLimit;
38
+ }
30
39
  interface RequestOptions {
31
40
  method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
32
41
  params?: Record<string, string | number | boolean | undefined>;
@@ -43,10 +52,22 @@ declare class BaseClient {
43
52
  * Make an HTTP request to the API.
44
53
  */
45
54
  request<T>(path: string, options?: RequestOptions): Promise<T>;
55
+ /**
56
+ * Make an HTTP request and return both data and rate limit headers.
57
+ */
58
+ requestWithHeaders<T>(path: string, options?: RequestOptions): Promise<ResponseWithHeaders<T>>;
59
+ /**
60
+ * Internal method that builds the request and executes it, returning data and rate limit info.
61
+ */
62
+ private requestRaw;
46
63
  /**
47
64
  * Execute request with exponential backoff retry logic.
48
65
  */
49
66
  private executeWithRetry;
67
+ /**
68
+ * Parse rate limit headers from an HTTP response.
69
+ */
70
+ private parseRateLimitHeaders;
50
71
  /**
51
72
  * Fetch with timeout support.
52
73
  */
@@ -64,6 +85,7 @@ declare class BaseClient {
64
85
  /**
65
86
  * Pagination utilities for the ScrapeBadger SDK.
66
87
  */
88
+
67
89
  /**
68
90
  * Response wrapper for paginated API responses.
69
91
  */
@@ -256,6 +278,26 @@ interface Tweet {
256
278
  username?: string;
257
279
  /** Author's display name */
258
280
  user_name?: string;
281
+ /** Author's profile image URL */
282
+ user_profile_image_url?: string;
283
+ /** Author's bio */
284
+ user_description?: string;
285
+ /** Author's location */
286
+ user_location?: string;
287
+ /** Author's website URL */
288
+ user_url?: string;
289
+ /** Author's follower count */
290
+ user_followers_count?: number;
291
+ /** Author's following count */
292
+ user_following_count?: number;
293
+ /** Author's tweet count */
294
+ user_tweet_count?: number;
295
+ /** Author's legacy verification status */
296
+ user_verified?: boolean;
297
+ /** Author's Twitter Blue verification status */
298
+ user_is_blue_verified?: boolean;
299
+ /** Author's account creation date */
300
+ user_created_at?: string;
259
301
  /** Number of likes */
260
302
  favorite_count: number;
261
303
  /** Number of retweets */
@@ -27,6 +27,15 @@ interface ResolvedConfig {
27
27
  * Base HTTP client with retry logic and error handling.
28
28
  */
29
29
 
30
+ interface RateLimit {
31
+ limit: number;
32
+ remaining: number;
33
+ reset: number;
34
+ }
35
+ interface ResponseWithHeaders<T> {
36
+ data: T;
37
+ rateLimit?: RateLimit;
38
+ }
30
39
  interface RequestOptions {
31
40
  method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
32
41
  params?: Record<string, string | number | boolean | undefined>;
@@ -43,10 +52,22 @@ declare class BaseClient {
43
52
  * Make an HTTP request to the API.
44
53
  */
45
54
  request<T>(path: string, options?: RequestOptions): Promise<T>;
55
+ /**
56
+ * Make an HTTP request and return both data and rate limit headers.
57
+ */
58
+ requestWithHeaders<T>(path: string, options?: RequestOptions): Promise<ResponseWithHeaders<T>>;
59
+ /**
60
+ * Internal method that builds the request and executes it, returning data and rate limit info.
61
+ */
62
+ private requestRaw;
46
63
  /**
47
64
  * Execute request with exponential backoff retry logic.
48
65
  */
49
66
  private executeWithRetry;
67
+ /**
68
+ * Parse rate limit headers from an HTTP response.
69
+ */
70
+ private parseRateLimitHeaders;
50
71
  /**
51
72
  * Fetch with timeout support.
52
73
  */
@@ -64,6 +85,7 @@ declare class BaseClient {
64
85
  /**
65
86
  * Pagination utilities for the ScrapeBadger SDK.
66
87
  */
88
+
67
89
  /**
68
90
  * Response wrapper for paginated API responses.
69
91
  */
@@ -256,6 +278,26 @@ interface Tweet {
256
278
  username?: string;
257
279
  /** Author's display name */
258
280
  user_name?: string;
281
+ /** Author's profile image URL */
282
+ user_profile_image_url?: string;
283
+ /** Author's bio */
284
+ user_description?: string;
285
+ /** Author's location */
286
+ user_location?: string;
287
+ /** Author's website URL */
288
+ user_url?: string;
289
+ /** Author's follower count */
290
+ user_followers_count?: number;
291
+ /** Author's following count */
292
+ user_following_count?: number;
293
+ /** Author's tweet count */
294
+ user_tweet_count?: number;
295
+ /** Author's legacy verification status */
296
+ user_verified?: boolean;
297
+ /** Author's Twitter Blue verification status */
298
+ user_is_blue_verified?: boolean;
299
+ /** Author's account creation date */
300
+ user_created_at?: string;
259
301
  /** Number of likes */
260
302
  favorite_count: number;
261
303
  /** Number of retweets */
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as BaseClient, T as TwitterClient, S as ScrapeBadgerConfig } from './index-BbCkdZXy.cjs';
2
- export { e as AccountRestrictedError, _ as ApiResponse, A as AuthenticationError, ae as BillingLog, af as BillingLogList, j as CommunitiesClient, J as Community, E as CommunityBanner, K as CommunityMember, F as CommunityRule, p as CommunityTweetType, C as ConflictError, ag as ConnectOptions, a6 as ConnectedEvent, a3 as CreateMonitorParams, ac as DeliveryLog, ad as DeliveryLogList, a9 as ErrorEvent, aj as FilterRuleCreate, ao as FilterRuleDeliveryLog, ap as FilterRuleDeliveryLogListResponse, am as FilterRuleListResponse, al as FilterRulePricingTier, aq as FilterRulePricingTiersResponse, ai as FilterRuleResponse, ah as FilterRuleStatus, ak as FilterRuleUpdate, an as FilterRuleValidateResponse, G as GeoClient, l as GeoSearchOptions, H as Hashtag, I as InsufficientCreditsError, g as IteratorOptions, D as List, $ as ListResponse, L as ListsClient, X as Location, M as Media, a0 as MonitorStatus, N as NotFoundError, P as PaginatedResponse, f as PaginationOptions, a7 as PingEvent, Z as Place, Y as PlaceTrends, r as Poll, q as PollOption, Q as QueryType, b as RateLimitError, R as ResolvedConfig, a as ScrapeBadgerError, c as ServerError, m as StreamClient, n as StreamEmitter, aa as StreamEvent, ab as StreamEventType, a1 as StreamMonitor, a2 as StreamMonitorList, a5 as StreamTweet, d as TimeoutError, O as Trend, o as TrendCategory, k as TrendsClient, w as Tweet, a8 as TweetEvent, u as TweetPlace, i as TweetsClient, a4 as UpdateMonitorParams, s as Url, x as User, y as UserAbout, z as UserIds, t as UserMention, U as UsersClient, V as ValidationError, W as WebSocketStreamError, h as collectAll, v as verifyWebhookSignature } from './index-BbCkdZXy.cjs';
1
+ import { B as BaseClient, T as TwitterClient, S as ScrapeBadgerConfig } from './index-Cg0sNluO.cjs';
2
+ export { e as AccountRestrictedError, _ as ApiResponse, A as AuthenticationError, ae as BillingLog, af as BillingLogList, j as CommunitiesClient, J as Community, E as CommunityBanner, K as CommunityMember, F as CommunityRule, p as CommunityTweetType, C as ConflictError, ag as ConnectOptions, a6 as ConnectedEvent, a3 as CreateMonitorParams, ac as DeliveryLog, ad as DeliveryLogList, a9 as ErrorEvent, aj as FilterRuleCreate, ao as FilterRuleDeliveryLog, ap as FilterRuleDeliveryLogListResponse, am as FilterRuleListResponse, al as FilterRulePricingTier, aq as FilterRulePricingTiersResponse, ai as FilterRuleResponse, ah as FilterRuleStatus, ak as FilterRuleUpdate, an as FilterRuleValidateResponse, G as GeoClient, l as GeoSearchOptions, H as Hashtag, I as InsufficientCreditsError, g as IteratorOptions, D as List, $ as ListResponse, L as ListsClient, X as Location, M as Media, a0 as MonitorStatus, N as NotFoundError, P as PaginatedResponse, f as PaginationOptions, a7 as PingEvent, Z as Place, Y as PlaceTrends, r as Poll, q as PollOption, Q as QueryType, b as RateLimitError, R as ResolvedConfig, a as ScrapeBadgerError, c as ServerError, m as StreamClient, n as StreamEmitter, aa as StreamEvent, ab as StreamEventType, a1 as StreamMonitor, a2 as StreamMonitorList, a5 as StreamTweet, d as TimeoutError, O as Trend, o as TrendCategory, k as TrendsClient, w as Tweet, a8 as TweetEvent, u as TweetPlace, i as TweetsClient, a4 as UpdateMonitorParams, s as Url, x as User, y as UserAbout, z as UserIds, t as UserMention, U as UsersClient, V as ValidationError, W as WebSocketStreamError, h as collectAll, v as verifyWebhookSignature } from './index-Cg0sNluO.cjs';
3
3
  import 'node:events';
4
4
 
5
5
  /**
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as BaseClient, T as TwitterClient, S as ScrapeBadgerConfig } from './index-BbCkdZXy.js';
2
- export { e as AccountRestrictedError, _ as ApiResponse, A as AuthenticationError, ae as BillingLog, af as BillingLogList, j as CommunitiesClient, J as Community, E as CommunityBanner, K as CommunityMember, F as CommunityRule, p as CommunityTweetType, C as ConflictError, ag as ConnectOptions, a6 as ConnectedEvent, a3 as CreateMonitorParams, ac as DeliveryLog, ad as DeliveryLogList, a9 as ErrorEvent, aj as FilterRuleCreate, ao as FilterRuleDeliveryLog, ap as FilterRuleDeliveryLogListResponse, am as FilterRuleListResponse, al as FilterRulePricingTier, aq as FilterRulePricingTiersResponse, ai as FilterRuleResponse, ah as FilterRuleStatus, ak as FilterRuleUpdate, an as FilterRuleValidateResponse, G as GeoClient, l as GeoSearchOptions, H as Hashtag, I as InsufficientCreditsError, g as IteratorOptions, D as List, $ as ListResponse, L as ListsClient, X as Location, M as Media, a0 as MonitorStatus, N as NotFoundError, P as PaginatedResponse, f as PaginationOptions, a7 as PingEvent, Z as Place, Y as PlaceTrends, r as Poll, q as PollOption, Q as QueryType, b as RateLimitError, R as ResolvedConfig, a as ScrapeBadgerError, c as ServerError, m as StreamClient, n as StreamEmitter, aa as StreamEvent, ab as StreamEventType, a1 as StreamMonitor, a2 as StreamMonitorList, a5 as StreamTweet, d as TimeoutError, O as Trend, o as TrendCategory, k as TrendsClient, w as Tweet, a8 as TweetEvent, u as TweetPlace, i as TweetsClient, a4 as UpdateMonitorParams, s as Url, x as User, y as UserAbout, z as UserIds, t as UserMention, U as UsersClient, V as ValidationError, W as WebSocketStreamError, h as collectAll, v as verifyWebhookSignature } from './index-BbCkdZXy.js';
1
+ import { B as BaseClient, T as TwitterClient, S as ScrapeBadgerConfig } from './index-Cg0sNluO.js';
2
+ export { e as AccountRestrictedError, _ as ApiResponse, A as AuthenticationError, ae as BillingLog, af as BillingLogList, j as CommunitiesClient, J as Community, E as CommunityBanner, K as CommunityMember, F as CommunityRule, p as CommunityTweetType, C as ConflictError, ag as ConnectOptions, a6 as ConnectedEvent, a3 as CreateMonitorParams, ac as DeliveryLog, ad as DeliveryLogList, a9 as ErrorEvent, aj as FilterRuleCreate, ao as FilterRuleDeliveryLog, ap as FilterRuleDeliveryLogListResponse, am as FilterRuleListResponse, al as FilterRulePricingTier, aq as FilterRulePricingTiersResponse, ai as FilterRuleResponse, ah as FilterRuleStatus, ak as FilterRuleUpdate, an as FilterRuleValidateResponse, G as GeoClient, l as GeoSearchOptions, H as Hashtag, I as InsufficientCreditsError, g as IteratorOptions, D as List, $ as ListResponse, L as ListsClient, X as Location, M as Media, a0 as MonitorStatus, N as NotFoundError, P as PaginatedResponse, f as PaginationOptions, a7 as PingEvent, Z as Place, Y as PlaceTrends, r as Poll, q as PollOption, Q as QueryType, b as RateLimitError, R as ResolvedConfig, a as ScrapeBadgerError, c as ServerError, m as StreamClient, n as StreamEmitter, aa as StreamEvent, ab as StreamEventType, a1 as StreamMonitor, a2 as StreamMonitorList, a5 as StreamTweet, d as TimeoutError, O as Trend, o as TrendCategory, k as TrendsClient, w as Tweet, a8 as TweetEvent, u as TweetPlace, i as TweetsClient, a4 as UpdateMonitorParams, s as Url, x as User, y as UserAbout, z as UserIds, t as UserMention, U as UsersClient, V as ValidationError, W as WebSocketStreamError, h as collectAll, v as verifyWebhookSignature } from './index-Cg0sNluO.js';
3
3
  import 'node:events';
4
4
 
5
5
  /**
package/dist/index.js CHANGED
@@ -130,6 +130,19 @@ var BaseClient = class {
130
130
  * Make an HTTP request to the API.
131
131
  */
132
132
  async request(path, options = {}) {
133
+ const { data } = await this.requestRaw(path, options);
134
+ return data;
135
+ }
136
+ /**
137
+ * Make an HTTP request and return both data and rate limit headers.
138
+ */
139
+ async requestWithHeaders(path, options = {}) {
140
+ return this.requestRaw(path, options);
141
+ }
142
+ /**
143
+ * Internal method that builds the request and executes it, returning data and rate limit info.
144
+ */
145
+ async requestRaw(path, options = {}) {
133
146
  const { method = "GET", params, body, headers = {} } = options;
134
147
  const url = new URL(path, this.config.baseUrl);
135
148
  if (params) {
@@ -143,7 +156,7 @@ var BaseClient = class {
143
156
  "Content-Type": "application/json",
144
157
  Accept: "application/json",
145
158
  "X-API-Key": this.config.apiKey,
146
- "User-Agent": "scrapebadger-node/0.1.0",
159
+ "User-Agent": "scrapebadger-node/0.3.1",
147
160
  ...headers
148
161
  };
149
162
  const fetchOptions = {
@@ -162,8 +175,10 @@ var BaseClient = class {
162
175
  let lastError;
163
176
  for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
164
177
  try {
165
- const response = await this.fetchWithTimeout(url, options);
166
- return await this.handleResponse(response);
178
+ const httpResponse = await this.fetchWithTimeout(url, options);
179
+ const data = await this.handleResponse(httpResponse);
180
+ const rateLimit = this.parseRateLimitHeaders(httpResponse.headers);
181
+ return { data, rateLimit };
167
182
  } catch (error) {
168
183
  lastError = error;
169
184
  if (error instanceof ScrapeBadgerError && !(error instanceof RateLimitError)) {
@@ -173,18 +188,56 @@ var BaseClient = class {
173
188
  break;
174
189
  }
175
190
  const delay = this.config.retryDelay * Math.pow(2, attempt);
176
- if (error instanceof RateLimitError && error.retryAfter) {
177
- const retryDelay = (error.retryAfter - Date.now() / 1e3) * 1e3;
178
- if (retryDelay > 0 && retryDelay < 6e4) {
179
- await this.sleep(retryDelay);
180
- continue;
191
+ const delaySec = Math.round(delay / 1e3);
192
+ const attemptNum = attempt + 1;
193
+ const maxRetries = this.config.maxRetries;
194
+ if (error instanceof RateLimitError) {
195
+ console.warn(
196
+ `\x1B[33m\u26A0 ScrapeBadger: 429 Rate Limited \u2014 retrying in ${delaySec}s (attempt ${attemptNum}/${maxRetries})\x1B[0m`
197
+ );
198
+ if (error.retryAfter) {
199
+ const retryDelay = (error.retryAfter - Date.now() / 1e3) * 1e3;
200
+ if (retryDelay > 0 && retryDelay < 6e4) {
201
+ await this.sleep(retryDelay);
202
+ continue;
203
+ }
181
204
  }
205
+ } else if (error instanceof TimeoutError) {
206
+ console.warn(
207
+ `\x1B[33m\u26A0 ScrapeBadger: TimeoutError \u2014 retrying in ${delaySec}s (attempt ${attemptNum}/${maxRetries})\x1B[0m`
208
+ );
209
+ } else if (error instanceof ServerError) {
210
+ console.warn(
211
+ `\x1B[33m\u26A0 ScrapeBadger: ${error.statusCode} ${error.message} \u2014 retrying in ${delaySec}s (attempt ${attemptNum}/${maxRetries})\x1B[0m`
212
+ );
213
+ } else {
214
+ console.warn(
215
+ `\x1B[33m\u26A0 ScrapeBadger: ${error.name} \u2014 retrying in ${delaySec}s (attempt ${attemptNum}/${maxRetries})\x1B[0m`
216
+ );
182
217
  }
183
218
  await this.sleep(delay);
184
219
  }
185
220
  }
186
221
  throw lastError ?? new ScrapeBadgerError("Request failed after retries");
187
222
  }
223
+ /**
224
+ * Parse rate limit headers from an HTTP response.
225
+ */
226
+ parseRateLimitHeaders(headers) {
227
+ const limit = headers.get("X-RateLimit-Limit");
228
+ const remaining = headers.get("X-RateLimit-Remaining");
229
+ const reset = headers.get("X-RateLimit-Reset");
230
+ if (limit === null || remaining === null || reset === null) {
231
+ return void 0;
232
+ }
233
+ const parsedLimit = parseInt(limit, 10);
234
+ const parsedRemaining = parseInt(remaining, 10);
235
+ const parsedReset = parseInt(reset, 10);
236
+ if (isNaN(parsedLimit) || isNaN(parsedRemaining) || isNaN(parsedReset)) {
237
+ return void 0;
238
+ }
239
+ return { limit: parsedLimit, remaining: parsedRemaining, reset: parsedReset };
240
+ }
188
241
  /**
189
242
  * Fetch with timeout support.
190
243
  */
@@ -266,7 +319,7 @@ var BaseClient = class {
266
319
  // src/internal/config.ts
267
320
  var DEFAULT_BASE_URL = "https://scrapebadger.com";
268
321
  var DEFAULT_TIMEOUT = 3e4;
269
- var DEFAULT_MAX_RETRIES = 3;
322
+ var DEFAULT_MAX_RETRIES = 10;
270
323
  var DEFAULT_RETRY_DELAY = 1e3;
271
324
  function resolveConfig(config) {
272
325
  if (!config.apiKey) {
@@ -295,12 +348,26 @@ function createPaginatedResponse(data, cursor) {
295
348
  hasMore: !!cursor
296
349
  };
297
350
  }
351
+ var RATE_LIMIT_WARN_THRESHOLD = 0.2;
298
352
  async function* paginate(fetchPage, options = {}) {
299
353
  const { maxItems } = options;
300
354
  let cursor;
301
355
  let totalYielded = 0;
302
356
  do {
303
- const response = await fetchPage(cursor);
357
+ const { response, rateLimit } = await fetchPage(cursor);
358
+ if (rateLimit) {
359
+ const { limit, remaining, reset } = rateLimit;
360
+ if (limit > 0 && remaining / limit < RATE_LIMIT_WARN_THRESHOLD) {
361
+ const nowSec = Date.now() / 1e3;
362
+ const windowRemainingSec = Math.max(reset - nowSec, 1);
363
+ const delayMs = remaining > 0 ? windowRemainingSec / remaining * 1e3 : windowRemainingSec * 1e3;
364
+ const resetInSec = Math.round(windowRemainingSec);
365
+ console.warn(
366
+ `\x1B[33m\u26A0 ScrapeBadger: Rate limit: ${remaining}/${limit} remaining (resets in ${resetInSec}s), throttling pagination\x1B[0m`
367
+ );
368
+ await sleep(delayMs);
369
+ }
370
+ }
304
371
  for (const item of response.data) {
305
372
  yield item;
306
373
  totalYielded++;
@@ -318,6 +385,9 @@ async function collectAll(generator) {
318
385
  }
319
386
  return items;
320
387
  }
388
+ function sleep(ms) {
389
+ return new Promise((resolve) => setTimeout(resolve, ms));
390
+ }
321
391
 
322
392
  // src/twitter/tweets.ts
323
393
  var TweetsClient = class {
@@ -515,7 +585,8 @@ var TweetsClient = class {
515
585
  */
516
586
  async *getQuotesAll(tweetId, options = {}) {
517
587
  const fetchPage = async (cursor) => {
518
- return this.getQuotes(tweetId, { ...options, cursor });
588
+ const { data, rateLimit } = await this.client.requestWithHeaders(`/v1/twitter/tweets/tweet/${tweetId}/quotes`, { params: { cursor } });
589
+ return { response: createPaginatedResponse(data.data ?? [], data.next_cursor), rateLimit };
519
590
  };
520
591
  yield* paginate(fetchPage, options);
521
592
  }
@@ -582,7 +653,15 @@ var TweetsClient = class {
582
653
  */
583
654
  async *searchAll(query, options = {}) {
584
655
  const fetchPage = async (cursor) => {
585
- return this.search(query, { ...options, cursor });
656
+ const { data, rateLimit } = await this.client.requestWithHeaders("/v1/twitter/tweets/advanced_search", {
657
+ params: {
658
+ query,
659
+ query_type: options.queryType ?? "Top",
660
+ count: options.count,
661
+ cursor
662
+ }
663
+ });
664
+ return { response: createPaginatedResponse(data.data ?? [], data.next_cursor), rateLimit };
586
665
  };
587
666
  yield* paginate(fetchPage, options);
588
667
  }
@@ -626,7 +705,8 @@ var TweetsClient = class {
626
705
  */
627
706
  async *getUserTweetsAll(username, options = {}) {
628
707
  const fetchPage = async (cursor) => {
629
- return this.getUserTweets(username, { ...options, cursor });
708
+ const { data, rateLimit } = await this.client.requestWithHeaders(`/v1/twitter/users/${username}/latest_tweets`, { params: { cursor } });
709
+ return { response: createPaginatedResponse(data.data ?? [], data.next_cursor), rateLimit };
630
710
  };
631
711
  yield* paginate(fetchPage, options);
632
712
  }
@@ -736,7 +816,8 @@ var UsersClient = class {
736
816
  */
737
817
  async *getFollowersAll(username, options = {}) {
738
818
  const fetchPage = async (cursor) => {
739
- return this.getFollowers(username, { ...options, cursor });
819
+ const { data, rateLimit } = await this.client.requestWithHeaders(`/v1/twitter/users/${username}/followers`, { params: { cursor } });
820
+ return { response: createPaginatedResponse(data.data ?? [], data.next_cursor), rateLimit };
740
821
  };
741
822
  yield* paginate(fetchPage, options);
742
823
  }
@@ -771,7 +852,8 @@ var UsersClient = class {
771
852
  */
772
853
  async *getFollowingAll(username, options = {}) {
773
854
  const fetchPage = async (cursor) => {
774
- return this.getFollowing(username, { ...options, cursor });
855
+ const { data, rateLimit } = await this.client.requestWithHeaders(`/v1/twitter/users/${username}/followings`, { params: { cursor } });
856
+ return { response: createPaginatedResponse(data.data ?? [], data.next_cursor), rateLimit };
775
857
  };
776
858
  yield* paginate(fetchPage, options);
777
859
  }
@@ -934,7 +1016,8 @@ var UsersClient = class {
934
1016
  */
935
1017
  async *searchAll(query, options = {}) {
936
1018
  const fetchPage = async (cursor) => {
937
- return this.search(query, { ...options, cursor });
1019
+ const { data, rateLimit } = await this.client.requestWithHeaders("/v1/twitter/users/search_users", { params: { query, cursor } });
1020
+ return { response: createPaginatedResponse(data.data ?? [], data.next_cursor), rateLimit };
938
1021
  };
939
1022
  yield* paginate(fetchPage, options);
940
1023
  }
@@ -994,7 +1077,8 @@ var ListsClient = class {
994
1077
  */
995
1078
  async *getTweetsAll(listId, options = {}) {
996
1079
  const fetchPage = async (cursor) => {
997
- return this.getTweets(listId, { ...options, cursor });
1080
+ const { data, rateLimit } = await this.client.requestWithHeaders(`/v1/twitter/lists/${listId}/tweets`, { params: { cursor } });
1081
+ return { response: createPaginatedResponse(data.data ?? [], data.next_cursor), rateLimit };
998
1082
  };
999
1083
  yield* paginate(fetchPage, options);
1000
1084
  }
@@ -1029,7 +1113,8 @@ var ListsClient = class {
1029
1113
  */
1030
1114
  async *getMembersAll(listId, options = {}) {
1031
1115
  const fetchPage = async (cursor) => {
1032
- return this.getMembers(listId, { ...options, cursor });
1116
+ const { data, rateLimit } = await this.client.requestWithHeaders(`/v1/twitter/lists/${listId}/members`, { params: { cursor } });
1117
+ return { response: createPaginatedResponse(data.data ?? [], data.next_cursor), rateLimit };
1033
1118
  };
1034
1119
  yield* paginate(fetchPage, options);
1035
1120
  }
@@ -1177,7 +1262,14 @@ var CommunitiesClient = class {
1177
1262
  */
1178
1263
  async *getTweetsAll(communityId, options = {}) {
1179
1264
  const fetchPage = async (cursor) => {
1180
- return this.getTweets(communityId, { ...options, cursor });
1265
+ const { data, rateLimit } = await this.client.requestWithHeaders(`/v1/twitter/communities/${communityId}/tweets`, {
1266
+ params: {
1267
+ tweet_type: options.tweetType ?? "Top",
1268
+ count: options.count ?? 40,
1269
+ cursor
1270
+ }
1271
+ });
1272
+ return { response: createPaginatedResponse(data.data ?? [], data.next_cursor), rateLimit };
1181
1273
  };
1182
1274
  yield* paginate(fetchPage, options);
1183
1275
  }