lago-javascript-client 1.44.0 → 1.46.0
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/esm/mod.d.ts +11 -1
- package/esm/mod.js +12 -1
- package/esm/openapi/client.d.ts +58 -16
- package/esm/openapi/client.js +1 -1
- package/esm/rate_limit_error.d.ts +10 -0
- package/esm/rate_limit_error.js +19 -0
- package/esm/rate_limit_fetch.d.ts +16 -0
- package/esm/rate_limit_fetch.js +76 -0
- package/esm/rate_limit_headers.d.ts +12 -0
- package/esm/rate_limit_headers.js +20 -0
- package/package.json +1 -1
- package/script/mod.d.ts +11 -1
- package/script/mod.js +16 -2
- package/script/openapi/client.d.ts +58 -16
- package/script/openapi/client.js +1 -1
- package/script/rate_limit_error.d.ts +10 -0
- package/script/rate_limit_error.js +23 -0
- package/script/rate_limit_fetch.d.ts +16 -0
- package/script/rate_limit_fetch.js +80 -0
- package/script/rate_limit_headers.d.ts +12 -0
- package/script/rate_limit_headers.js +24 -0
package/esm/mod.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { Api, ApiConfig, HttpResponse } from "./openapi/client.js";
|
|
2
|
-
|
|
2
|
+
import type { RateLimitFetchConfig } from "./rate_limit_fetch.js";
|
|
3
|
+
export interface LagoClientConfig extends ApiConfig {
|
|
4
|
+
/**
|
|
5
|
+
* Rate limit retry configuration
|
|
6
|
+
*/
|
|
7
|
+
rateLimitRetry?: RateLimitFetchConfig;
|
|
8
|
+
}
|
|
9
|
+
export declare const Client: (apiKey: string, apiConfig?: LagoClientConfig) => Api<unknown>;
|
|
3
10
|
type ExtractLagoError<E> = E extends (...args: any) => Promise<HttpResponse<infer T, infer P>> ? P : never;
|
|
4
11
|
export declare function getLagoError<T>(error: any): Promise<ExtractLagoError<T>>;
|
|
12
|
+
export { LagoRateLimitError } from "./rate_limit_error.js";
|
|
13
|
+
export { parseRateLimitHeaders, type RateLimitHeaders } from "./rate_limit_headers.js";
|
|
14
|
+
export { createRateLimitFetch, type RateLimitFetchConfig } from "./rate_limit_fetch.js";
|
|
5
15
|
export * from "./openapi/client.js";
|
package/esm/mod.js
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
// deno-lint-ignore-file no-explicit-any
|
|
2
2
|
import { Api } from "./openapi/client.js";
|
|
3
|
+
import { createRateLimitFetch } from "./rate_limit_fetch.js";
|
|
3
4
|
export const Client = (apiKey, apiConfig) => {
|
|
5
|
+
const { rateLimitRetry, ...restConfig } = apiConfig ?? {};
|
|
6
|
+
// Create rate-limit-aware fetch if configured
|
|
7
|
+
const customFetch = rateLimitRetry
|
|
8
|
+
? createRateLimitFetch((restConfig?.customFetch ?? globalThis.fetch), rateLimitRetry)
|
|
9
|
+
: restConfig?.customFetch;
|
|
4
10
|
const api = new Api({
|
|
5
11
|
securityWorker: (apiKey) => apiKey ? { headers: { Authorization: `Bearer ${apiKey}` } } : {},
|
|
6
12
|
// Cloudflare Workers doesn't support some options like credentials so need to override default
|
|
7
13
|
baseApiParams: {
|
|
8
14
|
redirect: "follow",
|
|
9
15
|
},
|
|
10
|
-
...
|
|
16
|
+
...restConfig,
|
|
17
|
+
...(customFetch && { customFetch }),
|
|
11
18
|
});
|
|
12
19
|
api.setSecurityData(apiKey);
|
|
13
20
|
return api;
|
|
@@ -30,4 +37,8 @@ export async function getLagoError(error) {
|
|
|
30
37
|
}
|
|
31
38
|
throw new Error(error);
|
|
32
39
|
}
|
|
40
|
+
// Rate limit exports
|
|
41
|
+
export { LagoRateLimitError } from "./rate_limit_error.js";
|
|
42
|
+
export { parseRateLimitHeaders } from "./rate_limit_headers.js";
|
|
43
|
+
export { createRateLimitFetch } from "./rate_limit_fetch.js";
|
|
33
44
|
export * from "./openapi/client.js";
|
package/esm/openapi/client.d.ts
CHANGED
|
@@ -1045,6 +1045,17 @@ export interface AppliedCouponObject {
|
|
|
1045
1045
|
* @example "Startup Deal"
|
|
1046
1046
|
*/
|
|
1047
1047
|
coupon_name: string;
|
|
1048
|
+
/**
|
|
1049
|
+
* The status of the parent coupon. Can be either `active` or `terminated`.
|
|
1050
|
+
* @example "active"
|
|
1051
|
+
*/
|
|
1052
|
+
coupon_status?: "active" | "terminated";
|
|
1053
|
+
/**
|
|
1054
|
+
* The date and time when the parent coupon was deleted. If null, the coupon still exists. It is expressed in UTC format according to the ISO 8601 datetime standard.
|
|
1055
|
+
* @format date-time
|
|
1056
|
+
* @example "2022-04-29T08:59:51Z"
|
|
1057
|
+
*/
|
|
1058
|
+
coupon_deleted_at?: string | null;
|
|
1048
1059
|
/**
|
|
1049
1060
|
* Unique identifier of the customer, created by Lago.
|
|
1050
1061
|
* @format uuid
|
|
@@ -2215,6 +2226,16 @@ export interface FeeObject {
|
|
|
2215
2226
|
* @example "0.0"
|
|
2216
2227
|
*/
|
|
2217
2228
|
precise_coupons_amount_cents?: string;
|
|
2229
|
+
/**
|
|
2230
|
+
* The sub total of the fee excluding taxes, in cents.
|
|
2231
|
+
* @example 100
|
|
2232
|
+
*/
|
|
2233
|
+
sub_total_excluding_taxes_amount_cents: number;
|
|
2234
|
+
/**
|
|
2235
|
+
* The sub total of the fee excluding taxes, with precision.
|
|
2236
|
+
* @example "100.0"
|
|
2237
|
+
*/
|
|
2238
|
+
sub_total_excluding_taxes_precise_amount_cents: string;
|
|
2218
2239
|
/** List of all unit amount details for calculating the fee. */
|
|
2219
2240
|
amount_details?: FeeAmountDetails;
|
|
2220
2241
|
/**
|
|
@@ -3826,18 +3847,20 @@ export interface AppliedInvoiceCustomSectionObject {
|
|
|
3826
3847
|
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
3827
3848
|
*/
|
|
3828
3849
|
lago_id: string;
|
|
3829
|
-
/**
|
|
3830
|
-
* Unique identifier of the invoice custom section that was applied.
|
|
3831
|
-
* @format uuid
|
|
3832
|
-
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
3833
|
-
*/
|
|
3834
|
-
invoice_custom_section_id: string;
|
|
3835
3850
|
/**
|
|
3836
3851
|
* The date of the applied invoice custom section creation, represented in ISO 8601 datetime format and expressed in Coordinated Universal Time (UTC).
|
|
3837
3852
|
* @format date-time
|
|
3838
3853
|
* @example "2023-07-06T14:35:58Z"
|
|
3839
3854
|
*/
|
|
3840
3855
|
created_at: string;
|
|
3856
|
+
/**
|
|
3857
|
+
* Unique identifier of the invoice custom section that was applied.
|
|
3858
|
+
* @deprecated
|
|
3859
|
+
* @format uuid
|
|
3860
|
+
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
3861
|
+
*/
|
|
3862
|
+
invoice_custom_section_id?: string;
|
|
3863
|
+
invoice_custom_section: InvoiceCustomSectionObject;
|
|
3841
3864
|
}
|
|
3842
3865
|
/** Reference to a specific payment method for processing the payment. */
|
|
3843
3866
|
export interface PaymentMethodReference {
|
|
@@ -7996,12 +8019,24 @@ export interface WalletTransactionObject {
|
|
|
7996
8019
|
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
7997
8020
|
*/
|
|
7998
8021
|
lago_wallet_id: string;
|
|
8022
|
+
/**
|
|
8023
|
+
* Unique identifier assigned to the invoice associated with this wallet transaction. This ID is exclusively created by Lago and serves as a unique identifier for the invoice's record within the Lago system.
|
|
8024
|
+
* @format uuid
|
|
8025
|
+
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
8026
|
+
*/
|
|
8027
|
+
lago_invoice_id: string | null;
|
|
8028
|
+
/**
|
|
8029
|
+
* Unique identifier of the credit note associated with this wallet transaction. This ID is exclusively created by Lago and serves as a unique identifier for the invoice's record within the Lago system.
|
|
8030
|
+
* @format uuid
|
|
8031
|
+
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
8032
|
+
*/
|
|
8033
|
+
lago_credit_note_id: string | null;
|
|
7999
8034
|
/**
|
|
8000
8035
|
* Unique identifier of the invoice that was voided and triggered the creation of this inbound wallet transaction. Only present for inbound transactions on traceable wallets that were created as a result of an invoice void.
|
|
8001
8036
|
* @format uuid
|
|
8002
8037
|
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
8003
8038
|
*/
|
|
8004
|
-
lago_voided_invoice_id
|
|
8039
|
+
lago_voided_invoice_id: string | null;
|
|
8005
8040
|
/**
|
|
8006
8041
|
* The status of the wallet transaction. Possible values are `pending`, `settled` or `failed`.
|
|
8007
8042
|
* @example "settled"
|
|
@@ -8038,12 +8073,12 @@ export interface WalletTransactionObject {
|
|
|
8038
8073
|
* A boolean setting that, when set to true, delays issuing an invoice for a wallet top-up until a successful payment is made; if false, the invoice is issued immediately upon wallet top-up, regardless of the payment status. Default value of false.
|
|
8039
8074
|
* @example false
|
|
8040
8075
|
*/
|
|
8041
|
-
invoice_requires_successful_payment
|
|
8076
|
+
invoice_requires_successful_payment: boolean;
|
|
8042
8077
|
/**
|
|
8043
8078
|
* This field allows you to store a list of key-value pairs that hold additional information or custom attributes related to the data.
|
|
8044
8079
|
* @example [{"key":"example key","value":"example value"},{"key":"another key","value":"another value"}]
|
|
8045
8080
|
*/
|
|
8046
|
-
metadata
|
|
8081
|
+
metadata: {
|
|
8047
8082
|
/** The unique identifier for the attribute. */
|
|
8048
8083
|
key?: string;
|
|
8049
8084
|
/** The value associated with the key. */
|
|
@@ -8053,25 +8088,30 @@ export interface WalletTransactionObject {
|
|
|
8053
8088
|
* The remaining unconsumed amount of an inbound wallet transaction, expressed in cents. Only present for inbound transactions on traceable wallets. Tracks how much of the original credited amount has not yet been consumed by outbound transactions.
|
|
8054
8089
|
* @example 5000
|
|
8055
8090
|
*/
|
|
8056
|
-
remaining_amount_cents
|
|
8091
|
+
remaining_amount_cents: number | null;
|
|
8057
8092
|
/**
|
|
8058
8093
|
* The remaining unconsumed amount of an inbound wallet transaction, expressed in credits. Only present for inbound transactions on traceable wallets.
|
|
8059
8094
|
* @pattern ^[0-9]+.?[0-9]*$
|
|
8060
8095
|
* @example "5.0"
|
|
8061
8096
|
*/
|
|
8062
|
-
remaining_credit_amount
|
|
8097
|
+
remaining_credit_amount: string | null;
|
|
8098
|
+
/**
|
|
8099
|
+
* The priority of the wallet transaction, used to determine the order in which inbound transactions are consumed. Lower values are consumed first.
|
|
8100
|
+
* @example 50
|
|
8101
|
+
*/
|
|
8102
|
+
priority: number;
|
|
8063
8103
|
/**
|
|
8064
8104
|
* The date when wallet transaction is settled, represented in ISO 8601 datetime format and expressed in Coordinated Universal Time (UTC).
|
|
8065
8105
|
* @format date-time
|
|
8066
8106
|
* @example "2022-04-29T08:59:51Z"
|
|
8067
8107
|
*/
|
|
8068
|
-
settled_at
|
|
8108
|
+
settled_at: string | null;
|
|
8069
8109
|
/**
|
|
8070
8110
|
* The date when the wallet transaction failed, represented in ISO 8601 datetime format and expressed in Coordinated Universal Time (UTC).
|
|
8071
8111
|
* @format date-time
|
|
8072
8112
|
* @example "2022-04-29T08:59:51Z"
|
|
8073
8113
|
*/
|
|
8074
|
-
failed_at
|
|
8114
|
+
failed_at: string | null;
|
|
8075
8115
|
/**
|
|
8076
8116
|
* The date of the wallet transaction creation, represented in ISO 8601 datetime format and expressed in Coordinated Universal Time (UTC).
|
|
8077
8117
|
* @format date-time
|
|
@@ -8086,7 +8126,7 @@ export interface WalletTransactionObject {
|
|
|
8086
8126
|
/** The invoice custom sections applied to invoices generated by this wallet transaction. */
|
|
8087
8127
|
applied_invoice_custom_sections?: AppliedInvoiceCustomSectionObject[];
|
|
8088
8128
|
/** The payment method assigned to this wallet transaction for processing the payment. */
|
|
8089
|
-
payment_method
|
|
8129
|
+
payment_method: PaymentMethodReference;
|
|
8090
8130
|
}
|
|
8091
8131
|
export interface WalletTransactions {
|
|
8092
8132
|
wallet_transactions: WalletTransactionObject[];
|
|
@@ -8753,7 +8793,7 @@ export declare class HttpClient<SecurityDataType = unknown> {
|
|
|
8753
8793
|
}
|
|
8754
8794
|
/**
|
|
8755
8795
|
* @title Lago API documentation
|
|
8756
|
-
* @version 1.
|
|
8796
|
+
* @version 1.45.0
|
|
8757
8797
|
* @license AGPLv3 (https://github.com/getlago/lago-openapi/blob/main/LICENSE)
|
|
8758
8798
|
* @baseUrl https://api.getlago.com/api/v1
|
|
8759
8799
|
* @externalDocs https://github.com/getlago
|
|
@@ -10288,7 +10328,9 @@ export declare class Api<SecurityDataType extends unknown> extends HttpClient<Se
|
|
|
10288
10328
|
* @request POST:/customers/{external_customer_id}/checkout_url
|
|
10289
10329
|
* @secure
|
|
10290
10330
|
*/
|
|
10291
|
-
generateCustomerCheckoutUrl: (externalCustomerId: string, params?: RequestParams) => Promise<HttpResponse<
|
|
10331
|
+
generateCustomerCheckoutUrl: (externalCustomerId: string, params?: RequestParams) => Promise<HttpResponse<{
|
|
10332
|
+
customer: CustomerCheckoutUrl;
|
|
10333
|
+
}, ApiErrorUnauthorized | ApiErrorUnprocessableEntity | ApiErrorNotFound>>;
|
|
10292
10334
|
/**
|
|
10293
10335
|
* @description This endpoint retrieves all payment methods of a Customer.
|
|
10294
10336
|
*
|
package/esm/openapi/client.js
CHANGED
|
@@ -148,7 +148,7 @@ export class HttpClient {
|
|
|
148
148
|
}
|
|
149
149
|
/**
|
|
150
150
|
* @title Lago API documentation
|
|
151
|
-
* @version 1.
|
|
151
|
+
* @version 1.45.0
|
|
152
152
|
* @license AGPLv3 (https://github.com/getlago/lago-openapi/blob/main/LICENSE)
|
|
153
153
|
* @baseUrl https://api.getlago.com/api/v1
|
|
154
154
|
* @externalDocs https://github.com/getlago
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error class for rate limit (HTTP 429) responses
|
|
3
|
+
*/
|
|
4
|
+
export declare class LagoRateLimitError extends Error {
|
|
5
|
+
readonly limit: number;
|
|
6
|
+
readonly remaining: number;
|
|
7
|
+
readonly reset: number;
|
|
8
|
+
readonly retryAfter: number;
|
|
9
|
+
constructor(limit: number, remaining: number, reset: number);
|
|
10
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error class for rate limit (HTTP 429) responses
|
|
3
|
+
*/
|
|
4
|
+
export class LagoRateLimitError extends Error {
|
|
5
|
+
limit;
|
|
6
|
+
remaining;
|
|
7
|
+
reset; // seconds until window resets
|
|
8
|
+
retryAfter; // milliseconds to wait before retrying
|
|
9
|
+
constructor(limit, remaining, reset) {
|
|
10
|
+
super(`Rate limit exceeded. Limit: ${limit}, Remaining: ${remaining}, Reset in: ${reset}s`);
|
|
11
|
+
this.name = "LagoRateLimitError";
|
|
12
|
+
this.limit = limit;
|
|
13
|
+
this.remaining = remaining;
|
|
14
|
+
this.reset = reset;
|
|
15
|
+
this.retryAfter = reset * 1000; // Convert seconds to milliseconds
|
|
16
|
+
// Maintain proper prototype chain for instanceof checks
|
|
17
|
+
Object.setPrototypeOf(this, LagoRateLimitError.prototype);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for rate limit fetch behavior
|
|
3
|
+
*/
|
|
4
|
+
export interface RateLimitFetchConfig {
|
|
5
|
+
/** Maximum number of retries on 429 (default: 3) */
|
|
6
|
+
maxRetries?: number;
|
|
7
|
+
/** Whether to automatically retry on rate limit (default: true) */
|
|
8
|
+
retryOnRateLimit?: boolean;
|
|
9
|
+
/** Maximum delay in milliseconds before a retry (default: 20000) */
|
|
10
|
+
maxRetryDelay?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates a fetch wrapper that handles rate limiting with automatic retry
|
|
14
|
+
* Compatible with both Node.js fetch and browser fetch APIs
|
|
15
|
+
*/
|
|
16
|
+
export declare function createRateLimitFetch(baseFetch: typeof fetch, config?: RateLimitFetchConfig): typeof fetch;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { LagoRateLimitError } from "./rate_limit_error.js";
|
|
2
|
+
import { parseRateLimitHeaders, } from "./rate_limit_headers.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a fetch wrapper that handles rate limiting with automatic retry
|
|
5
|
+
* Compatible with both Node.js fetch and browser fetch APIs
|
|
6
|
+
*/
|
|
7
|
+
export function createRateLimitFetch(baseFetch, config = {}) {
|
|
8
|
+
const maxRetries = config.maxRetries ?? 3;
|
|
9
|
+
const retryOnRateLimit = config.retryOnRateLimit ?? true;
|
|
10
|
+
const maxRetryDelay = config.maxRetryDelay ?? 20_000;
|
|
11
|
+
return async function rateLimitFetch(input, init) {
|
|
12
|
+
let lastError;
|
|
13
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
14
|
+
try {
|
|
15
|
+
const response = await baseFetch(input, init);
|
|
16
|
+
// Handle 429 responses
|
|
17
|
+
if (response.status === 429) {
|
|
18
|
+
const headers = parseRateLimitHeaders(response.headers);
|
|
19
|
+
const limit = headers.limit ?? -1;
|
|
20
|
+
const remaining = headers.remaining ?? 0;
|
|
21
|
+
const reset = headers.reset ?? -1;
|
|
22
|
+
const error = new LagoRateLimitError(limit, remaining, reset);
|
|
23
|
+
if (!retryOnRateLimit) {
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
if (attempt === maxRetries) {
|
|
27
|
+
throw error; // Max retries reached
|
|
28
|
+
}
|
|
29
|
+
// Wait before retry
|
|
30
|
+
const waitMs = getWaitTime(error, attempt, maxRetryDelay);
|
|
31
|
+
await sleep(waitMs);
|
|
32
|
+
continue; // Retry
|
|
33
|
+
}
|
|
34
|
+
// Success or non-rate-limit error - return the response
|
|
35
|
+
return response;
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
lastError = error;
|
|
39
|
+
if (!(error instanceof LagoRateLimitError)) {
|
|
40
|
+
throw error; // Not a rate limit error, rethrow immediately
|
|
41
|
+
}
|
|
42
|
+
if (attempt === maxRetries) {
|
|
43
|
+
throw error; // Max retries reached
|
|
44
|
+
}
|
|
45
|
+
// Will retry on next iteration
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
throw lastError;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Calculate wait time before retry
|
|
53
|
+
* Uses the exact reset time from headers if available, otherwise exponential backoff
|
|
54
|
+
*/
|
|
55
|
+
function getWaitTime(error, attempt, maxRetryDelay) {
|
|
56
|
+
let waitMs;
|
|
57
|
+
if (error.reset > 0) {
|
|
58
|
+
// Use the exact reset time from the header
|
|
59
|
+
waitMs = error.retryAfter;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Exponential backoff: 1s, 2s, 4s, 8s, etc.
|
|
63
|
+
waitMs = 1000 * Math.pow(2, attempt);
|
|
64
|
+
}
|
|
65
|
+
// Cap at maxRetryDelay
|
|
66
|
+
waitMs = Math.min(waitMs, maxRetryDelay);
|
|
67
|
+
// Add small jitter to prevent thundering herd (max 100ms)
|
|
68
|
+
const jitter = Math.random() * 100;
|
|
69
|
+
return waitMs + jitter;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Sleep for a specified number of milliseconds
|
|
73
|
+
*/
|
|
74
|
+
function sleep(ms) {
|
|
75
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
76
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses rate limit headers from HTTP responses
|
|
3
|
+
*/
|
|
4
|
+
export interface RateLimitHeaders {
|
|
5
|
+
limit: number | null;
|
|
6
|
+
remaining: number | null;
|
|
7
|
+
reset: number | null;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Extract rate limit information from response headers
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseRateLimitHeaders(headers: Headers): RateLimitHeaders;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract rate limit information from response headers
|
|
3
|
+
*/
|
|
4
|
+
export function parseRateLimitHeaders(headers) {
|
|
5
|
+
return {
|
|
6
|
+
limit: parseHeaderAsNumber(headers, "x-ratelimit-limit"),
|
|
7
|
+
remaining: parseHeaderAsNumber(headers, "x-ratelimit-remaining"),
|
|
8
|
+
reset: parseHeaderAsNumber(headers, "x-ratelimit-reset"),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Helper to parse a header value as a number
|
|
13
|
+
*/
|
|
14
|
+
function parseHeaderAsNumber(headers, headerName) {
|
|
15
|
+
const value = headers.get(headerName);
|
|
16
|
+
if (value === null)
|
|
17
|
+
return null;
|
|
18
|
+
const num = parseInt(value, 10);
|
|
19
|
+
return isNaN(num) ? null : num;
|
|
20
|
+
}
|
package/package.json
CHANGED
package/script/mod.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { Api, ApiConfig, HttpResponse } from "./openapi/client.js";
|
|
2
|
-
|
|
2
|
+
import type { RateLimitFetchConfig } from "./rate_limit_fetch.js";
|
|
3
|
+
export interface LagoClientConfig extends ApiConfig {
|
|
4
|
+
/**
|
|
5
|
+
* Rate limit retry configuration
|
|
6
|
+
*/
|
|
7
|
+
rateLimitRetry?: RateLimitFetchConfig;
|
|
8
|
+
}
|
|
9
|
+
export declare const Client: (apiKey: string, apiConfig?: LagoClientConfig) => Api<unknown>;
|
|
3
10
|
type ExtractLagoError<E> = E extends (...args: any) => Promise<HttpResponse<infer T, infer P>> ? P : never;
|
|
4
11
|
export declare function getLagoError<T>(error: any): Promise<ExtractLagoError<T>>;
|
|
12
|
+
export { LagoRateLimitError } from "./rate_limit_error.js";
|
|
13
|
+
export { parseRateLimitHeaders, type RateLimitHeaders } from "./rate_limit_headers.js";
|
|
14
|
+
export { createRateLimitFetch, type RateLimitFetchConfig } from "./rate_limit_fetch.js";
|
|
5
15
|
export * from "./openapi/client.js";
|
package/script/mod.js
CHANGED
|
@@ -14,17 +14,24 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.getLagoError = exports.Client = void 0;
|
|
17
|
+
exports.createRateLimitFetch = exports.parseRateLimitHeaders = exports.LagoRateLimitError = exports.getLagoError = exports.Client = void 0;
|
|
18
18
|
// deno-lint-ignore-file no-explicit-any
|
|
19
19
|
const client_js_1 = require("./openapi/client.js");
|
|
20
|
+
const rate_limit_fetch_js_1 = require("./rate_limit_fetch.js");
|
|
20
21
|
const Client = (apiKey, apiConfig) => {
|
|
22
|
+
const { rateLimitRetry, ...restConfig } = apiConfig ?? {};
|
|
23
|
+
// Create rate-limit-aware fetch if configured
|
|
24
|
+
const customFetch = rateLimitRetry
|
|
25
|
+
? (0, rate_limit_fetch_js_1.createRateLimitFetch)((restConfig?.customFetch ?? globalThis.fetch), rateLimitRetry)
|
|
26
|
+
: restConfig?.customFetch;
|
|
21
27
|
const api = new client_js_1.Api({
|
|
22
28
|
securityWorker: (apiKey) => apiKey ? { headers: { Authorization: `Bearer ${apiKey}` } } : {},
|
|
23
29
|
// Cloudflare Workers doesn't support some options like credentials so need to override default
|
|
24
30
|
baseApiParams: {
|
|
25
31
|
redirect: "follow",
|
|
26
32
|
},
|
|
27
|
-
...
|
|
33
|
+
...restConfig,
|
|
34
|
+
...(customFetch && { customFetch }),
|
|
28
35
|
});
|
|
29
36
|
api.setSecurityData(apiKey);
|
|
30
37
|
return api;
|
|
@@ -49,4 +56,11 @@ async function getLagoError(error) {
|
|
|
49
56
|
throw new Error(error);
|
|
50
57
|
}
|
|
51
58
|
exports.getLagoError = getLagoError;
|
|
59
|
+
// Rate limit exports
|
|
60
|
+
var rate_limit_error_js_1 = require("./rate_limit_error.js");
|
|
61
|
+
Object.defineProperty(exports, "LagoRateLimitError", { enumerable: true, get: function () { return rate_limit_error_js_1.LagoRateLimitError; } });
|
|
62
|
+
var rate_limit_headers_js_1 = require("./rate_limit_headers.js");
|
|
63
|
+
Object.defineProperty(exports, "parseRateLimitHeaders", { enumerable: true, get: function () { return rate_limit_headers_js_1.parseRateLimitHeaders; } });
|
|
64
|
+
var rate_limit_fetch_js_2 = require("./rate_limit_fetch.js");
|
|
65
|
+
Object.defineProperty(exports, "createRateLimitFetch", { enumerable: true, get: function () { return rate_limit_fetch_js_2.createRateLimitFetch; } });
|
|
52
66
|
__exportStar(require("./openapi/client.js"), exports);
|
|
@@ -1045,6 +1045,17 @@ export interface AppliedCouponObject {
|
|
|
1045
1045
|
* @example "Startup Deal"
|
|
1046
1046
|
*/
|
|
1047
1047
|
coupon_name: string;
|
|
1048
|
+
/**
|
|
1049
|
+
* The status of the parent coupon. Can be either `active` or `terminated`.
|
|
1050
|
+
* @example "active"
|
|
1051
|
+
*/
|
|
1052
|
+
coupon_status?: "active" | "terminated";
|
|
1053
|
+
/**
|
|
1054
|
+
* The date and time when the parent coupon was deleted. If null, the coupon still exists. It is expressed in UTC format according to the ISO 8601 datetime standard.
|
|
1055
|
+
* @format date-time
|
|
1056
|
+
* @example "2022-04-29T08:59:51Z"
|
|
1057
|
+
*/
|
|
1058
|
+
coupon_deleted_at?: string | null;
|
|
1048
1059
|
/**
|
|
1049
1060
|
* Unique identifier of the customer, created by Lago.
|
|
1050
1061
|
* @format uuid
|
|
@@ -2215,6 +2226,16 @@ export interface FeeObject {
|
|
|
2215
2226
|
* @example "0.0"
|
|
2216
2227
|
*/
|
|
2217
2228
|
precise_coupons_amount_cents?: string;
|
|
2229
|
+
/**
|
|
2230
|
+
* The sub total of the fee excluding taxes, in cents.
|
|
2231
|
+
* @example 100
|
|
2232
|
+
*/
|
|
2233
|
+
sub_total_excluding_taxes_amount_cents: number;
|
|
2234
|
+
/**
|
|
2235
|
+
* The sub total of the fee excluding taxes, with precision.
|
|
2236
|
+
* @example "100.0"
|
|
2237
|
+
*/
|
|
2238
|
+
sub_total_excluding_taxes_precise_amount_cents: string;
|
|
2218
2239
|
/** List of all unit amount details for calculating the fee. */
|
|
2219
2240
|
amount_details?: FeeAmountDetails;
|
|
2220
2241
|
/**
|
|
@@ -3826,18 +3847,20 @@ export interface AppliedInvoiceCustomSectionObject {
|
|
|
3826
3847
|
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
3827
3848
|
*/
|
|
3828
3849
|
lago_id: string;
|
|
3829
|
-
/**
|
|
3830
|
-
* Unique identifier of the invoice custom section that was applied.
|
|
3831
|
-
* @format uuid
|
|
3832
|
-
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
3833
|
-
*/
|
|
3834
|
-
invoice_custom_section_id: string;
|
|
3835
3850
|
/**
|
|
3836
3851
|
* The date of the applied invoice custom section creation, represented in ISO 8601 datetime format and expressed in Coordinated Universal Time (UTC).
|
|
3837
3852
|
* @format date-time
|
|
3838
3853
|
* @example "2023-07-06T14:35:58Z"
|
|
3839
3854
|
*/
|
|
3840
3855
|
created_at: string;
|
|
3856
|
+
/**
|
|
3857
|
+
* Unique identifier of the invoice custom section that was applied.
|
|
3858
|
+
* @deprecated
|
|
3859
|
+
* @format uuid
|
|
3860
|
+
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
3861
|
+
*/
|
|
3862
|
+
invoice_custom_section_id?: string;
|
|
3863
|
+
invoice_custom_section: InvoiceCustomSectionObject;
|
|
3841
3864
|
}
|
|
3842
3865
|
/** Reference to a specific payment method for processing the payment. */
|
|
3843
3866
|
export interface PaymentMethodReference {
|
|
@@ -7996,12 +8019,24 @@ export interface WalletTransactionObject {
|
|
|
7996
8019
|
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
7997
8020
|
*/
|
|
7998
8021
|
lago_wallet_id: string;
|
|
8022
|
+
/**
|
|
8023
|
+
* Unique identifier assigned to the invoice associated with this wallet transaction. This ID is exclusively created by Lago and serves as a unique identifier for the invoice's record within the Lago system.
|
|
8024
|
+
* @format uuid
|
|
8025
|
+
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
8026
|
+
*/
|
|
8027
|
+
lago_invoice_id: string | null;
|
|
8028
|
+
/**
|
|
8029
|
+
* Unique identifier of the credit note associated with this wallet transaction. This ID is exclusively created by Lago and serves as a unique identifier for the invoice's record within the Lago system.
|
|
8030
|
+
* @format uuid
|
|
8031
|
+
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
8032
|
+
*/
|
|
8033
|
+
lago_credit_note_id: string | null;
|
|
7999
8034
|
/**
|
|
8000
8035
|
* Unique identifier of the invoice that was voided and triggered the creation of this inbound wallet transaction. Only present for inbound transactions on traceable wallets that were created as a result of an invoice void.
|
|
8001
8036
|
* @format uuid
|
|
8002
8037
|
* @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
|
|
8003
8038
|
*/
|
|
8004
|
-
lago_voided_invoice_id
|
|
8039
|
+
lago_voided_invoice_id: string | null;
|
|
8005
8040
|
/**
|
|
8006
8041
|
* The status of the wallet transaction. Possible values are `pending`, `settled` or `failed`.
|
|
8007
8042
|
* @example "settled"
|
|
@@ -8038,12 +8073,12 @@ export interface WalletTransactionObject {
|
|
|
8038
8073
|
* A boolean setting that, when set to true, delays issuing an invoice for a wallet top-up until a successful payment is made; if false, the invoice is issued immediately upon wallet top-up, regardless of the payment status. Default value of false.
|
|
8039
8074
|
* @example false
|
|
8040
8075
|
*/
|
|
8041
|
-
invoice_requires_successful_payment
|
|
8076
|
+
invoice_requires_successful_payment: boolean;
|
|
8042
8077
|
/**
|
|
8043
8078
|
* This field allows you to store a list of key-value pairs that hold additional information or custom attributes related to the data.
|
|
8044
8079
|
* @example [{"key":"example key","value":"example value"},{"key":"another key","value":"another value"}]
|
|
8045
8080
|
*/
|
|
8046
|
-
metadata
|
|
8081
|
+
metadata: {
|
|
8047
8082
|
/** The unique identifier for the attribute. */
|
|
8048
8083
|
key?: string;
|
|
8049
8084
|
/** The value associated with the key. */
|
|
@@ -8053,25 +8088,30 @@ export interface WalletTransactionObject {
|
|
|
8053
8088
|
* The remaining unconsumed amount of an inbound wallet transaction, expressed in cents. Only present for inbound transactions on traceable wallets. Tracks how much of the original credited amount has not yet been consumed by outbound transactions.
|
|
8054
8089
|
* @example 5000
|
|
8055
8090
|
*/
|
|
8056
|
-
remaining_amount_cents
|
|
8091
|
+
remaining_amount_cents: number | null;
|
|
8057
8092
|
/**
|
|
8058
8093
|
* The remaining unconsumed amount of an inbound wallet transaction, expressed in credits. Only present for inbound transactions on traceable wallets.
|
|
8059
8094
|
* @pattern ^[0-9]+.?[0-9]*$
|
|
8060
8095
|
* @example "5.0"
|
|
8061
8096
|
*/
|
|
8062
|
-
remaining_credit_amount
|
|
8097
|
+
remaining_credit_amount: string | null;
|
|
8098
|
+
/**
|
|
8099
|
+
* The priority of the wallet transaction, used to determine the order in which inbound transactions are consumed. Lower values are consumed first.
|
|
8100
|
+
* @example 50
|
|
8101
|
+
*/
|
|
8102
|
+
priority: number;
|
|
8063
8103
|
/**
|
|
8064
8104
|
* The date when wallet transaction is settled, represented in ISO 8601 datetime format and expressed in Coordinated Universal Time (UTC).
|
|
8065
8105
|
* @format date-time
|
|
8066
8106
|
* @example "2022-04-29T08:59:51Z"
|
|
8067
8107
|
*/
|
|
8068
|
-
settled_at
|
|
8108
|
+
settled_at: string | null;
|
|
8069
8109
|
/**
|
|
8070
8110
|
* The date when the wallet transaction failed, represented in ISO 8601 datetime format and expressed in Coordinated Universal Time (UTC).
|
|
8071
8111
|
* @format date-time
|
|
8072
8112
|
* @example "2022-04-29T08:59:51Z"
|
|
8073
8113
|
*/
|
|
8074
|
-
failed_at
|
|
8114
|
+
failed_at: string | null;
|
|
8075
8115
|
/**
|
|
8076
8116
|
* The date of the wallet transaction creation, represented in ISO 8601 datetime format and expressed in Coordinated Universal Time (UTC).
|
|
8077
8117
|
* @format date-time
|
|
@@ -8086,7 +8126,7 @@ export interface WalletTransactionObject {
|
|
|
8086
8126
|
/** The invoice custom sections applied to invoices generated by this wallet transaction. */
|
|
8087
8127
|
applied_invoice_custom_sections?: AppliedInvoiceCustomSectionObject[];
|
|
8088
8128
|
/** The payment method assigned to this wallet transaction for processing the payment. */
|
|
8089
|
-
payment_method
|
|
8129
|
+
payment_method: PaymentMethodReference;
|
|
8090
8130
|
}
|
|
8091
8131
|
export interface WalletTransactions {
|
|
8092
8132
|
wallet_transactions: WalletTransactionObject[];
|
|
@@ -8753,7 +8793,7 @@ export declare class HttpClient<SecurityDataType = unknown> {
|
|
|
8753
8793
|
}
|
|
8754
8794
|
/**
|
|
8755
8795
|
* @title Lago API documentation
|
|
8756
|
-
* @version 1.
|
|
8796
|
+
* @version 1.45.0
|
|
8757
8797
|
* @license AGPLv3 (https://github.com/getlago/lago-openapi/blob/main/LICENSE)
|
|
8758
8798
|
* @baseUrl https://api.getlago.com/api/v1
|
|
8759
8799
|
* @externalDocs https://github.com/getlago
|
|
@@ -10288,7 +10328,9 @@ export declare class Api<SecurityDataType extends unknown> extends HttpClient<Se
|
|
|
10288
10328
|
* @request POST:/customers/{external_customer_id}/checkout_url
|
|
10289
10329
|
* @secure
|
|
10290
10330
|
*/
|
|
10291
|
-
generateCustomerCheckoutUrl: (externalCustomerId: string, params?: RequestParams) => Promise<HttpResponse<
|
|
10331
|
+
generateCustomerCheckoutUrl: (externalCustomerId: string, params?: RequestParams) => Promise<HttpResponse<{
|
|
10332
|
+
customer: CustomerCheckoutUrl;
|
|
10333
|
+
}, ApiErrorUnauthorized | ApiErrorUnprocessableEntity | ApiErrorNotFound>>;
|
|
10292
10334
|
/**
|
|
10293
10335
|
* @description This endpoint retrieves all payment methods of a Customer.
|
|
10294
10336
|
*
|
package/script/openapi/client.js
CHANGED
|
@@ -152,7 +152,7 @@ class HttpClient {
|
|
|
152
152
|
exports.HttpClient = HttpClient;
|
|
153
153
|
/**
|
|
154
154
|
* @title Lago API documentation
|
|
155
|
-
* @version 1.
|
|
155
|
+
* @version 1.45.0
|
|
156
156
|
* @license AGPLv3 (https://github.com/getlago/lago-openapi/blob/main/LICENSE)
|
|
157
157
|
* @baseUrl https://api.getlago.com/api/v1
|
|
158
158
|
* @externalDocs https://github.com/getlago
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error class for rate limit (HTTP 429) responses
|
|
3
|
+
*/
|
|
4
|
+
export declare class LagoRateLimitError extends Error {
|
|
5
|
+
readonly limit: number;
|
|
6
|
+
readonly remaining: number;
|
|
7
|
+
readonly reset: number;
|
|
8
|
+
readonly retryAfter: number;
|
|
9
|
+
constructor(limit: number, remaining: number, reset: number);
|
|
10
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LagoRateLimitError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Error class for rate limit (HTTP 429) responses
|
|
6
|
+
*/
|
|
7
|
+
class LagoRateLimitError extends Error {
|
|
8
|
+
limit;
|
|
9
|
+
remaining;
|
|
10
|
+
reset; // seconds until window resets
|
|
11
|
+
retryAfter; // milliseconds to wait before retrying
|
|
12
|
+
constructor(limit, remaining, reset) {
|
|
13
|
+
super(`Rate limit exceeded. Limit: ${limit}, Remaining: ${remaining}, Reset in: ${reset}s`);
|
|
14
|
+
this.name = "LagoRateLimitError";
|
|
15
|
+
this.limit = limit;
|
|
16
|
+
this.remaining = remaining;
|
|
17
|
+
this.reset = reset;
|
|
18
|
+
this.retryAfter = reset * 1000; // Convert seconds to milliseconds
|
|
19
|
+
// Maintain proper prototype chain for instanceof checks
|
|
20
|
+
Object.setPrototypeOf(this, LagoRateLimitError.prototype);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.LagoRateLimitError = LagoRateLimitError;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for rate limit fetch behavior
|
|
3
|
+
*/
|
|
4
|
+
export interface RateLimitFetchConfig {
|
|
5
|
+
/** Maximum number of retries on 429 (default: 3) */
|
|
6
|
+
maxRetries?: number;
|
|
7
|
+
/** Whether to automatically retry on rate limit (default: true) */
|
|
8
|
+
retryOnRateLimit?: boolean;
|
|
9
|
+
/** Maximum delay in milliseconds before a retry (default: 20000) */
|
|
10
|
+
maxRetryDelay?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates a fetch wrapper that handles rate limiting with automatic retry
|
|
14
|
+
* Compatible with both Node.js fetch and browser fetch APIs
|
|
15
|
+
*/
|
|
16
|
+
export declare function createRateLimitFetch(baseFetch: typeof fetch, config?: RateLimitFetchConfig): typeof fetch;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRateLimitFetch = void 0;
|
|
4
|
+
const rate_limit_error_js_1 = require("./rate_limit_error.js");
|
|
5
|
+
const rate_limit_headers_js_1 = require("./rate_limit_headers.js");
|
|
6
|
+
/**
|
|
7
|
+
* Creates a fetch wrapper that handles rate limiting with automatic retry
|
|
8
|
+
* Compatible with both Node.js fetch and browser fetch APIs
|
|
9
|
+
*/
|
|
10
|
+
function createRateLimitFetch(baseFetch, config = {}) {
|
|
11
|
+
const maxRetries = config.maxRetries ?? 3;
|
|
12
|
+
const retryOnRateLimit = config.retryOnRateLimit ?? true;
|
|
13
|
+
const maxRetryDelay = config.maxRetryDelay ?? 20_000;
|
|
14
|
+
return async function rateLimitFetch(input, init) {
|
|
15
|
+
let lastError;
|
|
16
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
17
|
+
try {
|
|
18
|
+
const response = await baseFetch(input, init);
|
|
19
|
+
// Handle 429 responses
|
|
20
|
+
if (response.status === 429) {
|
|
21
|
+
const headers = (0, rate_limit_headers_js_1.parseRateLimitHeaders)(response.headers);
|
|
22
|
+
const limit = headers.limit ?? -1;
|
|
23
|
+
const remaining = headers.remaining ?? 0;
|
|
24
|
+
const reset = headers.reset ?? -1;
|
|
25
|
+
const error = new rate_limit_error_js_1.LagoRateLimitError(limit, remaining, reset);
|
|
26
|
+
if (!retryOnRateLimit) {
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
if (attempt === maxRetries) {
|
|
30
|
+
throw error; // Max retries reached
|
|
31
|
+
}
|
|
32
|
+
// Wait before retry
|
|
33
|
+
const waitMs = getWaitTime(error, attempt, maxRetryDelay);
|
|
34
|
+
await sleep(waitMs);
|
|
35
|
+
continue; // Retry
|
|
36
|
+
}
|
|
37
|
+
// Success or non-rate-limit error - return the response
|
|
38
|
+
return response;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
lastError = error;
|
|
42
|
+
if (!(error instanceof rate_limit_error_js_1.LagoRateLimitError)) {
|
|
43
|
+
throw error; // Not a rate limit error, rethrow immediately
|
|
44
|
+
}
|
|
45
|
+
if (attempt === maxRetries) {
|
|
46
|
+
throw error; // Max retries reached
|
|
47
|
+
}
|
|
48
|
+
// Will retry on next iteration
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
throw lastError;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
exports.createRateLimitFetch = createRateLimitFetch;
|
|
55
|
+
/**
|
|
56
|
+
* Calculate wait time before retry
|
|
57
|
+
* Uses the exact reset time from headers if available, otherwise exponential backoff
|
|
58
|
+
*/
|
|
59
|
+
function getWaitTime(error, attempt, maxRetryDelay) {
|
|
60
|
+
let waitMs;
|
|
61
|
+
if (error.reset > 0) {
|
|
62
|
+
// Use the exact reset time from the header
|
|
63
|
+
waitMs = error.retryAfter;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// Exponential backoff: 1s, 2s, 4s, 8s, etc.
|
|
67
|
+
waitMs = 1000 * Math.pow(2, attempt);
|
|
68
|
+
}
|
|
69
|
+
// Cap at maxRetryDelay
|
|
70
|
+
waitMs = Math.min(waitMs, maxRetryDelay);
|
|
71
|
+
// Add small jitter to prevent thundering herd (max 100ms)
|
|
72
|
+
const jitter = Math.random() * 100;
|
|
73
|
+
return waitMs + jitter;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Sleep for a specified number of milliseconds
|
|
77
|
+
*/
|
|
78
|
+
function sleep(ms) {
|
|
79
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
80
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses rate limit headers from HTTP responses
|
|
3
|
+
*/
|
|
4
|
+
export interface RateLimitHeaders {
|
|
5
|
+
limit: number | null;
|
|
6
|
+
remaining: number | null;
|
|
7
|
+
reset: number | null;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Extract rate limit information from response headers
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseRateLimitHeaders(headers: Headers): RateLimitHeaders;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseRateLimitHeaders = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Extract rate limit information from response headers
|
|
6
|
+
*/
|
|
7
|
+
function parseRateLimitHeaders(headers) {
|
|
8
|
+
return {
|
|
9
|
+
limit: parseHeaderAsNumber(headers, "x-ratelimit-limit"),
|
|
10
|
+
remaining: parseHeaderAsNumber(headers, "x-ratelimit-remaining"),
|
|
11
|
+
reset: parseHeaderAsNumber(headers, "x-ratelimit-reset"),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
exports.parseRateLimitHeaders = parseRateLimitHeaders;
|
|
15
|
+
/**
|
|
16
|
+
* Helper to parse a header value as a number
|
|
17
|
+
*/
|
|
18
|
+
function parseHeaderAsNumber(headers, headerName) {
|
|
19
|
+
const value = headers.get(headerName);
|
|
20
|
+
if (value === null)
|
|
21
|
+
return null;
|
|
22
|
+
const num = parseInt(value, 10);
|
|
23
|
+
return isNaN(num) ? null : num;
|
|
24
|
+
}
|