lago-javascript-client 1.46.1 → 1.47.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.
@@ -0,0 +1,33 @@
1
+ import type { RateLimitInfoCallback } from "./rate_limit_fetch.js";
2
+ /**
3
+ * Default usage thresholds (80%, 90%, 95%) at which the observer emits a log.
4
+ */
5
+ export declare const DEFAULT_RATE_LIMIT_THRESHOLDS: readonly number[];
6
+ /**
7
+ * Configuration for the LoggingRateLimitObserver.
8
+ */
9
+ export interface LoggingRateLimitObserverOptions {
10
+ /** Usage fractions (0.0 - 1.0) that should produce a log line. */
11
+ thresholds?: readonly number[];
12
+ /**
13
+ * Function used to emit the log line. Defaults to `console.warn`.
14
+ * Useful when injecting a structured logger.
15
+ */
16
+ log?: (message: string) => void;
17
+ }
18
+ /**
19
+ * Returns a ready-to-use `onRateLimitInfo` callback that logs a warning each
20
+ * time rate limit usage crosses one of the configured thresholds.
21
+ *
22
+ * Example:
23
+ *
24
+ * ```ts
25
+ * import { Client } from "@getlago/lago-javascript-client";
26
+ * import { loggingRateLimitObserver } from "@getlago/lago-javascript-client";
27
+ *
28
+ * const client = Client(apiKey, {
29
+ * rateLimitRetry: { onRateLimitInfo: loggingRateLimitObserver() },
30
+ * });
31
+ * ```
32
+ */
33
+ export declare function loggingRateLimitObserver(options?: LoggingRateLimitObserverOptions): RateLimitInfoCallback;
@@ -0,0 +1,43 @@
1
+ import { rateLimitUsagePct } from "./rate_limit_headers.js";
2
+ /**
3
+ * Default usage thresholds (80%, 90%, 95%) at which the observer emits a log.
4
+ */
5
+ export const DEFAULT_RATE_LIMIT_THRESHOLDS = [
6
+ 0.8,
7
+ 0.9,
8
+ 0.95,
9
+ ];
10
+ /**
11
+ * Returns a ready-to-use `onRateLimitInfo` callback that logs a warning each
12
+ * time rate limit usage crosses one of the configured thresholds.
13
+ *
14
+ * Example:
15
+ *
16
+ * ```ts
17
+ * import { Client } from "@getlago/lago-javascript-client";
18
+ * import { loggingRateLimitObserver } from "@getlago/lago-javascript-client";
19
+ *
20
+ * const client = Client(apiKey, {
21
+ * rateLimitRetry: { onRateLimitInfo: loggingRateLimitObserver() },
22
+ * });
23
+ * ```
24
+ */
25
+ export function loggingRateLimitObserver(options = {}) {
26
+ const thresholds = [...(options.thresholds ?? DEFAULT_RATE_LIMIT_THRESHOLDS)]
27
+ .sort((a, b) => b - a); // descending
28
+ // deno-lint-ignore no-console
29
+ const log = options.log ?? ((m) => console.warn(m));
30
+ return function observe(info) {
31
+ const pct = rateLimitUsagePct(info);
32
+ if (pct === null)
33
+ return;
34
+ for (const threshold of thresholds) {
35
+ if (pct >= threshold) {
36
+ log(`Lago rate limit at ${(pct * 100).toFixed(0)}% (limit=${info.limit}, ` +
37
+ `remaining=${info.remaining}, reset=${info.reset}s, ` +
38
+ `${info.method} ${info.url})`);
39
+ return;
40
+ }
41
+ }
42
+ };
43
+ }
package/esm/mod.d.ts CHANGED
@@ -10,6 +10,7 @@ export declare const Client: (apiKey: string, apiConfig?: LagoClientConfig) => A
10
10
  type ExtractLagoError<E> = E extends (...args: any) => Promise<HttpResponse<infer T, infer P>> ? P : never;
11
11
  export declare function getLagoError<T>(error: any): Promise<ExtractLagoError<T>>;
12
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";
13
+ export { parseRateLimitHeaders, parseRateLimitInfo, type RateLimitHeaders, type RateLimitInfo, rateLimitUsagePct, } from "./rate_limit_headers.js";
14
+ export { createRateLimitFetch, type RateLimitFetchConfig, type RateLimitInfoCallback, } from "./rate_limit_fetch.js";
15
+ export { DEFAULT_RATE_LIMIT_THRESHOLDS, loggingRateLimitObserver, type LoggingRateLimitObserverOptions, } from "./logging_rate_limit_observer.js";
15
16
  export * from "./openapi/client.js";
package/esm/mod.js CHANGED
@@ -39,6 +39,7 @@ export async function getLagoError(error) {
39
39
  }
40
40
  // Rate limit exports
41
41
  export { LagoRateLimitError } from "./rate_limit_error.js";
42
- export { parseRateLimitHeaders } from "./rate_limit_headers.js";
43
- export { createRateLimitFetch } from "./rate_limit_fetch.js";
42
+ export { parseRateLimitHeaders, parseRateLimitInfo, rateLimitUsagePct, } from "./rate_limit_headers.js";
43
+ export { createRateLimitFetch, } from "./rate_limit_fetch.js";
44
+ export { DEFAULT_RATE_LIMIT_THRESHOLDS, loggingRateLimitObserver, } from "./logging_rate_limit_observer.js";
44
45
  export * from "./openapi/client.js";
@@ -8857,7 +8857,7 @@ export declare class HttpClient<SecurityDataType = unknown> {
8857
8857
  }
8858
8858
  /**
8859
8859
  * @title Lago API documentation
8860
- * @version 1.45.0
8860
+ * @version 1.45.2
8861
8861
  * @license AGPLv3 (https://github.com/getlago/lago-openapi/blob/main/LICENSE)
8862
8862
  * @baseUrl https://api.getlago.com/api/v1
8863
8863
  * @externalDocs https://github.com/getlago
@@ -10302,24 +10302,48 @@ export declare class Api<SecurityDataType extends unknown> extends HttpClient<Se
10302
10302
  * @example true
10303
10303
  */
10304
10304
  apply_taxes?: boolean;
10305
+ /**
10306
+ * Filter usage to a specific charge by its Lago ID (UUID). Replaces deprecated `filter_by_charge_id`.
10307
+ * @format uuid
10308
+ * @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
10309
+ */
10310
+ charge_id?: string;
10311
+ /**
10312
+ * Filter usage to a specific charge by its code. Replaces deprecated `filter_by_charge_code`.
10313
+ * @example "storage"
10314
+ */
10315
+ charge_code?: string;
10316
+ /**
10317
+ * Filter usage to a specific billable metric by its code.
10318
+ * @example "storage"
10319
+ */
10320
+ billable_metric_code?: string;
10321
+ /**
10322
+ * Filter usage by pricing group. Pass key/value pairs as query parameters, e.g. `group[cloud]=aws`. Replaces deprecated `filter_by_group`.
10323
+ * @example {"cloud":"aws"}
10324
+ */
10325
+ group?: Record<string, string>;
10305
10326
  /**
10306
10327
  * Filter usage to a specific charge by its Lago ID (UUID).
10328
+ * @deprecated
10307
10329
  * @format uuid
10308
10330
  * @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
10309
10331
  */
10310
10332
  filter_by_charge_id?: string;
10311
10333
  /**
10312
10334
  * Filter usage to a specific charge by its code.
10335
+ * @deprecated
10313
10336
  * @example "storage"
10314
10337
  */
10315
10338
  filter_by_charge_code?: string;
10316
10339
  /**
10317
10340
  * Filter usage by pricing group. Pass key/value pairs as query parameters, e.g. `filter_by_group[cloud]=aws`.
10341
+ * @deprecated
10318
10342
  * @example {"cloud":"aws"}
10319
10343
  */
10320
10344
  filter_by_group?: Record<string, string>;
10321
10345
  /**
10322
- * When `true`, returns usage since subscription start instead of the current billing period. Requires either `filter_by_charge_id`, `filter_by_charge_code`, or `filter_by_group` to be set.
10346
+ * When `true`, returns usage since subscription start instead of the current billing period. Requires one of `charge_id`, `charge_code`, `group` (or their deprecated `filter_by_*` equivalents) to be set.
10323
10347
  * @default false
10324
10348
  * @example true
10325
10349
  */
@@ -148,7 +148,7 @@ export class HttpClient {
148
148
  }
149
149
  /**
150
150
  * @title Lago API documentation
151
- * @version 1.45.0
151
+ * @version 1.45.2
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
@@ -1,3 +1,13 @@
1
+ import { type RateLimitInfo } from "./rate_limit_headers.js";
2
+ /**
3
+ * Callback invoked after every successful response with parsed rate limit
4
+ * headers. Use this to build observability around the rate limit (warn at
5
+ * thresholds, emit metrics, etc.).
6
+ *
7
+ * Errors thrown by the callback are caught and logged so they cannot break
8
+ * the underlying request flow.
9
+ */
10
+ export type RateLimitInfoCallback = (info: RateLimitInfo) => void;
1
11
  /**
2
12
  * Configuration for rate limit fetch behavior
3
13
  */
@@ -8,6 +18,11 @@ export interface RateLimitFetchConfig {
8
18
  retryOnRateLimit?: boolean;
9
19
  /** Maximum delay in milliseconds before a retry (default: 20000) */
10
20
  maxRetryDelay?: number;
21
+ /**
22
+ * Optional callback invoked after every successful (non-429) response
23
+ * with parsed rate limit headers. See `RateLimitInfoCallback`.
24
+ */
25
+ onRateLimitInfo?: RateLimitInfoCallback;
11
26
  }
12
27
  /**
13
28
  * Creates a fetch wrapper that handles rate limiting with automatic retry
@@ -1,5 +1,5 @@
1
1
  import { LagoRateLimitError } from "./rate_limit_error.js";
2
- import { parseRateLimitHeaders, } from "./rate_limit_headers.js";
2
+ import { parseRateLimitHeaders, parseRateLimitInfo, } from "./rate_limit_headers.js";
3
3
  /**
4
4
  * Creates a fetch wrapper that handles rate limiting with automatic retry
5
5
  * Compatible with both Node.js fetch and browser fetch APIs
@@ -8,6 +8,7 @@ export function createRateLimitFetch(baseFetch, config = {}) {
8
8
  const maxRetries = config.maxRetries ?? 3;
9
9
  const retryOnRateLimit = config.retryOnRateLimit ?? true;
10
10
  const maxRetryDelay = config.maxRetryDelay ?? 20_000;
11
+ const onRateLimitInfo = config.onRateLimitInfo;
11
12
  return async function rateLimitFetch(input, init) {
12
13
  let lastError;
13
14
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
@@ -31,7 +32,12 @@ export function createRateLimitFetch(baseFetch, config = {}) {
31
32
  await sleep(waitMs);
32
33
  continue; // Retry
33
34
  }
34
- // Success or non-rate-limit error - return the response
35
+ // Success: emit observability info. Non-2xx, non-429 responses are
36
+ // returned as-is without invoking the callback because their headers
37
+ // do not carry useful rate limit context.
38
+ if (onRateLimitInfo && response.ok) {
39
+ emitRateLimitInfo(onRateLimitInfo, response, input, init);
40
+ }
35
41
  return response;
36
42
  }
37
43
  catch (error) {
@@ -48,6 +54,35 @@ export function createRateLimitFetch(baseFetch, config = {}) {
48
54
  throw lastError;
49
55
  };
50
56
  }
57
+ /**
58
+ * Invoke the configured callback with parsed rate limit info, swallowing any
59
+ * exception so a buggy observer cannot break the request.
60
+ */
61
+ function emitRateLimitInfo(callback, response, input, init) {
62
+ try {
63
+ // Honor the method on a Request input when init.method is undefined
64
+ // (a valid fetch signature: fetch(new Request(url, { method: 'POST' }))).
65
+ const method = (init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase();
66
+ const url = requestUrl(input);
67
+ const info = parseRateLimitInfo(response.headers, method, url);
68
+ if (info === null)
69
+ return;
70
+ callback(info);
71
+ }
72
+ catch (err) {
73
+ // Never let observability break the request flow.
74
+ // deno-lint-ignore no-console
75
+ console.warn("Lago: onRateLimitInfo callback raised:", err);
76
+ }
77
+ }
78
+ function requestUrl(input) {
79
+ if (typeof input === "string")
80
+ return input;
81
+ if (input instanceof URL)
82
+ return input.toString();
83
+ // Request
84
+ return input.url;
85
+ }
51
86
  /**
52
87
  * Calculate wait time before retry
53
88
  * Uses the exact reset time from headers if available, otherwise exponential backoff
@@ -6,7 +6,33 @@ export interface RateLimitHeaders {
6
6
  remaining: number | null;
7
7
  reset: number | null;
8
8
  }
9
+ /**
10
+ * Parsed rate limit headers plus the request context they came from.
11
+ *
12
+ * Delivered to the `onRateLimitInfo` callback after every successful request
13
+ * so callers can build observability around the rate limit (warn at thresholds,
14
+ * emit metrics, etc.).
15
+ */
16
+ export interface RateLimitInfo extends RateLimitHeaders {
17
+ /** HTTP method of the call (GET, POST, ...). */
18
+ method: string;
19
+ /** Request URL. */
20
+ url: string;
21
+ }
22
+ /**
23
+ * Returns the fraction of the rate limit currently used in [0.0, 1.0],
24
+ * or `null` when the headers aren't usable (missing limit, zero limit,
25
+ * missing remaining).
26
+ */
27
+ export declare function rateLimitUsagePct(info: RateLimitHeaders): number | null;
9
28
  /**
10
29
  * Extract rate limit information from response headers
11
30
  */
12
31
  export declare function parseRateLimitHeaders(headers: Headers): RateLimitHeaders;
32
+ /**
33
+ * Returns a `RateLimitInfo` (headers + request context), or `null` when no
34
+ * `x-ratelimit-*` headers are present (e.g. self-hosted Lago instance with
35
+ * limits disabled). Useful for skipping observability emission entirely when
36
+ * there's nothing to report.
37
+ */
38
+ export declare function parseRateLimitInfo(headers: Headers, method: string, url: string): RateLimitInfo | null;
@@ -1,3 +1,14 @@
1
+ /**
2
+ * Returns the fraction of the rate limit currently used in [0.0, 1.0],
3
+ * or `null` when the headers aren't usable (missing limit, zero limit,
4
+ * missing remaining).
5
+ */
6
+ export function rateLimitUsagePct(info) {
7
+ if (info.limit == null || info.remaining == null || info.limit <= 0) {
8
+ return null;
9
+ }
10
+ return 1 - info.remaining / info.limit;
11
+ }
1
12
  /**
2
13
  * Extract rate limit information from response headers
3
14
  */
@@ -8,6 +19,19 @@ export function parseRateLimitHeaders(headers) {
8
19
  reset: parseHeaderAsNumber(headers, "x-ratelimit-reset"),
9
20
  };
10
21
  }
22
+ /**
23
+ * Returns a `RateLimitInfo` (headers + request context), or `null` when no
24
+ * `x-ratelimit-*` headers are present (e.g. self-hosted Lago instance with
25
+ * limits disabled). Useful for skipping observability emission entirely when
26
+ * there's nothing to report.
27
+ */
28
+ export function parseRateLimitInfo(headers, method, url) {
29
+ const parsed = parseRateLimitHeaders(headers);
30
+ if (parsed.limit == null && parsed.remaining == null && parsed.reset == null) {
31
+ return null;
32
+ }
33
+ return { ...parsed, method, url };
34
+ }
11
35
  /**
12
36
  * Helper to parse a header value as a number
13
37
  */
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "main": "./script/mod.js",
4
4
  "name": "lago-javascript-client",
5
5
  "sideEffects": false,
6
- "version": "v1.46.1",
6
+ "version": "v1.47.0",
7
7
  "description": "Lago JavaScript API Client",
8
8
  "repository": {
9
9
  "type": "git",
@@ -0,0 +1,33 @@
1
+ import type { RateLimitInfoCallback } from "./rate_limit_fetch.js";
2
+ /**
3
+ * Default usage thresholds (80%, 90%, 95%) at which the observer emits a log.
4
+ */
5
+ export declare const DEFAULT_RATE_LIMIT_THRESHOLDS: readonly number[];
6
+ /**
7
+ * Configuration for the LoggingRateLimitObserver.
8
+ */
9
+ export interface LoggingRateLimitObserverOptions {
10
+ /** Usage fractions (0.0 - 1.0) that should produce a log line. */
11
+ thresholds?: readonly number[];
12
+ /**
13
+ * Function used to emit the log line. Defaults to `console.warn`.
14
+ * Useful when injecting a structured logger.
15
+ */
16
+ log?: (message: string) => void;
17
+ }
18
+ /**
19
+ * Returns a ready-to-use `onRateLimitInfo` callback that logs a warning each
20
+ * time rate limit usage crosses one of the configured thresholds.
21
+ *
22
+ * Example:
23
+ *
24
+ * ```ts
25
+ * import { Client } from "@getlago/lago-javascript-client";
26
+ * import { loggingRateLimitObserver } from "@getlago/lago-javascript-client";
27
+ *
28
+ * const client = Client(apiKey, {
29
+ * rateLimitRetry: { onRateLimitInfo: loggingRateLimitObserver() },
30
+ * });
31
+ * ```
32
+ */
33
+ export declare function loggingRateLimitObserver(options?: LoggingRateLimitObserverOptions): RateLimitInfoCallback;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loggingRateLimitObserver = exports.DEFAULT_RATE_LIMIT_THRESHOLDS = void 0;
4
+ const rate_limit_headers_js_1 = require("./rate_limit_headers.js");
5
+ /**
6
+ * Default usage thresholds (80%, 90%, 95%) at which the observer emits a log.
7
+ */
8
+ exports.DEFAULT_RATE_LIMIT_THRESHOLDS = [
9
+ 0.8,
10
+ 0.9,
11
+ 0.95,
12
+ ];
13
+ /**
14
+ * Returns a ready-to-use `onRateLimitInfo` callback that logs a warning each
15
+ * time rate limit usage crosses one of the configured thresholds.
16
+ *
17
+ * Example:
18
+ *
19
+ * ```ts
20
+ * import { Client } from "@getlago/lago-javascript-client";
21
+ * import { loggingRateLimitObserver } from "@getlago/lago-javascript-client";
22
+ *
23
+ * const client = Client(apiKey, {
24
+ * rateLimitRetry: { onRateLimitInfo: loggingRateLimitObserver() },
25
+ * });
26
+ * ```
27
+ */
28
+ function loggingRateLimitObserver(options = {}) {
29
+ const thresholds = [...(options.thresholds ?? exports.DEFAULT_RATE_LIMIT_THRESHOLDS)]
30
+ .sort((a, b) => b - a); // descending
31
+ // deno-lint-ignore no-console
32
+ const log = options.log ?? ((m) => console.warn(m));
33
+ return function observe(info) {
34
+ const pct = (0, rate_limit_headers_js_1.rateLimitUsagePct)(info);
35
+ if (pct === null)
36
+ return;
37
+ for (const threshold of thresholds) {
38
+ if (pct >= threshold) {
39
+ log(`Lago rate limit at ${(pct * 100).toFixed(0)}% (limit=${info.limit}, ` +
40
+ `remaining=${info.remaining}, reset=${info.reset}s, ` +
41
+ `${info.method} ${info.url})`);
42
+ return;
43
+ }
44
+ }
45
+ };
46
+ }
47
+ exports.loggingRateLimitObserver = loggingRateLimitObserver;
package/script/mod.d.ts CHANGED
@@ -10,6 +10,7 @@ export declare const Client: (apiKey: string, apiConfig?: LagoClientConfig) => A
10
10
  type ExtractLagoError<E> = E extends (...args: any) => Promise<HttpResponse<infer T, infer P>> ? P : never;
11
11
  export declare function getLagoError<T>(error: any): Promise<ExtractLagoError<T>>;
12
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";
13
+ export { parseRateLimitHeaders, parseRateLimitInfo, type RateLimitHeaders, type RateLimitInfo, rateLimitUsagePct, } from "./rate_limit_headers.js";
14
+ export { createRateLimitFetch, type RateLimitFetchConfig, type RateLimitInfoCallback, } from "./rate_limit_fetch.js";
15
+ export { DEFAULT_RATE_LIMIT_THRESHOLDS, loggingRateLimitObserver, type LoggingRateLimitObserverOptions, } from "./logging_rate_limit_observer.js";
15
16
  export * from "./openapi/client.js";
package/script/mod.js CHANGED
@@ -14,7 +14,7 @@ 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.createRateLimitFetch = exports.parseRateLimitHeaders = exports.LagoRateLimitError = exports.getLagoError = exports.Client = void 0;
17
+ exports.loggingRateLimitObserver = exports.DEFAULT_RATE_LIMIT_THRESHOLDS = exports.createRateLimitFetch = exports.rateLimitUsagePct = exports.parseRateLimitInfo = 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
20
  const rate_limit_fetch_js_1 = require("./rate_limit_fetch.js");
@@ -61,6 +61,11 @@ var rate_limit_error_js_1 = require("./rate_limit_error.js");
61
61
  Object.defineProperty(exports, "LagoRateLimitError", { enumerable: true, get: function () { return rate_limit_error_js_1.LagoRateLimitError; } });
62
62
  var rate_limit_headers_js_1 = require("./rate_limit_headers.js");
63
63
  Object.defineProperty(exports, "parseRateLimitHeaders", { enumerable: true, get: function () { return rate_limit_headers_js_1.parseRateLimitHeaders; } });
64
+ Object.defineProperty(exports, "parseRateLimitInfo", { enumerable: true, get: function () { return rate_limit_headers_js_1.parseRateLimitInfo; } });
65
+ Object.defineProperty(exports, "rateLimitUsagePct", { enumerable: true, get: function () { return rate_limit_headers_js_1.rateLimitUsagePct; } });
64
66
  var rate_limit_fetch_js_2 = require("./rate_limit_fetch.js");
65
67
  Object.defineProperty(exports, "createRateLimitFetch", { enumerable: true, get: function () { return rate_limit_fetch_js_2.createRateLimitFetch; } });
68
+ var logging_rate_limit_observer_js_1 = require("./logging_rate_limit_observer.js");
69
+ Object.defineProperty(exports, "DEFAULT_RATE_LIMIT_THRESHOLDS", { enumerable: true, get: function () { return logging_rate_limit_observer_js_1.DEFAULT_RATE_LIMIT_THRESHOLDS; } });
70
+ Object.defineProperty(exports, "loggingRateLimitObserver", { enumerable: true, get: function () { return logging_rate_limit_observer_js_1.loggingRateLimitObserver; } });
66
71
  __exportStar(require("./openapi/client.js"), exports);
@@ -8857,7 +8857,7 @@ export declare class HttpClient<SecurityDataType = unknown> {
8857
8857
  }
8858
8858
  /**
8859
8859
  * @title Lago API documentation
8860
- * @version 1.45.0
8860
+ * @version 1.45.2
8861
8861
  * @license AGPLv3 (https://github.com/getlago/lago-openapi/blob/main/LICENSE)
8862
8862
  * @baseUrl https://api.getlago.com/api/v1
8863
8863
  * @externalDocs https://github.com/getlago
@@ -10302,24 +10302,48 @@ export declare class Api<SecurityDataType extends unknown> extends HttpClient<Se
10302
10302
  * @example true
10303
10303
  */
10304
10304
  apply_taxes?: boolean;
10305
+ /**
10306
+ * Filter usage to a specific charge by its Lago ID (UUID). Replaces deprecated `filter_by_charge_id`.
10307
+ * @format uuid
10308
+ * @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
10309
+ */
10310
+ charge_id?: string;
10311
+ /**
10312
+ * Filter usage to a specific charge by its code. Replaces deprecated `filter_by_charge_code`.
10313
+ * @example "storage"
10314
+ */
10315
+ charge_code?: string;
10316
+ /**
10317
+ * Filter usage to a specific billable metric by its code.
10318
+ * @example "storage"
10319
+ */
10320
+ billable_metric_code?: string;
10321
+ /**
10322
+ * Filter usage by pricing group. Pass key/value pairs as query parameters, e.g. `group[cloud]=aws`. Replaces deprecated `filter_by_group`.
10323
+ * @example {"cloud":"aws"}
10324
+ */
10325
+ group?: Record<string, string>;
10305
10326
  /**
10306
10327
  * Filter usage to a specific charge by its Lago ID (UUID).
10328
+ * @deprecated
10307
10329
  * @format uuid
10308
10330
  * @example "1a901a90-1a90-1a90-1a90-1a901a901a90"
10309
10331
  */
10310
10332
  filter_by_charge_id?: string;
10311
10333
  /**
10312
10334
  * Filter usage to a specific charge by its code.
10335
+ * @deprecated
10313
10336
  * @example "storage"
10314
10337
  */
10315
10338
  filter_by_charge_code?: string;
10316
10339
  /**
10317
10340
  * Filter usage by pricing group. Pass key/value pairs as query parameters, e.g. `filter_by_group[cloud]=aws`.
10341
+ * @deprecated
10318
10342
  * @example {"cloud":"aws"}
10319
10343
  */
10320
10344
  filter_by_group?: Record<string, string>;
10321
10345
  /**
10322
- * When `true`, returns usage since subscription start instead of the current billing period. Requires either `filter_by_charge_id`, `filter_by_charge_code`, or `filter_by_group` to be set.
10346
+ * When `true`, returns usage since subscription start instead of the current billing period. Requires one of `charge_id`, `charge_code`, `group` (or their deprecated `filter_by_*` equivalents) to be set.
10323
10347
  * @default false
10324
10348
  * @example true
10325
10349
  */
@@ -152,7 +152,7 @@ class HttpClient {
152
152
  exports.HttpClient = HttpClient;
153
153
  /**
154
154
  * @title Lago API documentation
155
- * @version 1.45.0
155
+ * @version 1.45.2
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
@@ -1,3 +1,13 @@
1
+ import { type RateLimitInfo } from "./rate_limit_headers.js";
2
+ /**
3
+ * Callback invoked after every successful response with parsed rate limit
4
+ * headers. Use this to build observability around the rate limit (warn at
5
+ * thresholds, emit metrics, etc.).
6
+ *
7
+ * Errors thrown by the callback are caught and logged so they cannot break
8
+ * the underlying request flow.
9
+ */
10
+ export type RateLimitInfoCallback = (info: RateLimitInfo) => void;
1
11
  /**
2
12
  * Configuration for rate limit fetch behavior
3
13
  */
@@ -8,6 +18,11 @@ export interface RateLimitFetchConfig {
8
18
  retryOnRateLimit?: boolean;
9
19
  /** Maximum delay in milliseconds before a retry (default: 20000) */
10
20
  maxRetryDelay?: number;
21
+ /**
22
+ * Optional callback invoked after every successful (non-429) response
23
+ * with parsed rate limit headers. See `RateLimitInfoCallback`.
24
+ */
25
+ onRateLimitInfo?: RateLimitInfoCallback;
11
26
  }
12
27
  /**
13
28
  * Creates a fetch wrapper that handles rate limiting with automatic retry
@@ -11,6 +11,7 @@ function createRateLimitFetch(baseFetch, config = {}) {
11
11
  const maxRetries = config.maxRetries ?? 3;
12
12
  const retryOnRateLimit = config.retryOnRateLimit ?? true;
13
13
  const maxRetryDelay = config.maxRetryDelay ?? 20_000;
14
+ const onRateLimitInfo = config.onRateLimitInfo;
14
15
  return async function rateLimitFetch(input, init) {
15
16
  let lastError;
16
17
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
@@ -34,7 +35,12 @@ function createRateLimitFetch(baseFetch, config = {}) {
34
35
  await sleep(waitMs);
35
36
  continue; // Retry
36
37
  }
37
- // Success or non-rate-limit error - return the response
38
+ // Success: emit observability info. Non-2xx, non-429 responses are
39
+ // returned as-is without invoking the callback because their headers
40
+ // do not carry useful rate limit context.
41
+ if (onRateLimitInfo && response.ok) {
42
+ emitRateLimitInfo(onRateLimitInfo, response, input, init);
43
+ }
38
44
  return response;
39
45
  }
40
46
  catch (error) {
@@ -52,6 +58,35 @@ function createRateLimitFetch(baseFetch, config = {}) {
52
58
  };
53
59
  }
54
60
  exports.createRateLimitFetch = createRateLimitFetch;
61
+ /**
62
+ * Invoke the configured callback with parsed rate limit info, swallowing any
63
+ * exception so a buggy observer cannot break the request.
64
+ */
65
+ function emitRateLimitInfo(callback, response, input, init) {
66
+ try {
67
+ // Honor the method on a Request input when init.method is undefined
68
+ // (a valid fetch signature: fetch(new Request(url, { method: 'POST' }))).
69
+ const method = (init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase();
70
+ const url = requestUrl(input);
71
+ const info = (0, rate_limit_headers_js_1.parseRateLimitInfo)(response.headers, method, url);
72
+ if (info === null)
73
+ return;
74
+ callback(info);
75
+ }
76
+ catch (err) {
77
+ // Never let observability break the request flow.
78
+ // deno-lint-ignore no-console
79
+ console.warn("Lago: onRateLimitInfo callback raised:", err);
80
+ }
81
+ }
82
+ function requestUrl(input) {
83
+ if (typeof input === "string")
84
+ return input;
85
+ if (input instanceof URL)
86
+ return input.toString();
87
+ // Request
88
+ return input.url;
89
+ }
55
90
  /**
56
91
  * Calculate wait time before retry
57
92
  * Uses the exact reset time from headers if available, otherwise exponential backoff
@@ -6,7 +6,33 @@ export interface RateLimitHeaders {
6
6
  remaining: number | null;
7
7
  reset: number | null;
8
8
  }
9
+ /**
10
+ * Parsed rate limit headers plus the request context they came from.
11
+ *
12
+ * Delivered to the `onRateLimitInfo` callback after every successful request
13
+ * so callers can build observability around the rate limit (warn at thresholds,
14
+ * emit metrics, etc.).
15
+ */
16
+ export interface RateLimitInfo extends RateLimitHeaders {
17
+ /** HTTP method of the call (GET, POST, ...). */
18
+ method: string;
19
+ /** Request URL. */
20
+ url: string;
21
+ }
22
+ /**
23
+ * Returns the fraction of the rate limit currently used in [0.0, 1.0],
24
+ * or `null` when the headers aren't usable (missing limit, zero limit,
25
+ * missing remaining).
26
+ */
27
+ export declare function rateLimitUsagePct(info: RateLimitHeaders): number | null;
9
28
  /**
10
29
  * Extract rate limit information from response headers
11
30
  */
12
31
  export declare function parseRateLimitHeaders(headers: Headers): RateLimitHeaders;
32
+ /**
33
+ * Returns a `RateLimitInfo` (headers + request context), or `null` when no
34
+ * `x-ratelimit-*` headers are present (e.g. self-hosted Lago instance with
35
+ * limits disabled). Useful for skipping observability emission entirely when
36
+ * there's nothing to report.
37
+ */
38
+ export declare function parseRateLimitInfo(headers: Headers, method: string, url: string): RateLimitInfo | null;
@@ -1,6 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseRateLimitHeaders = void 0;
3
+ exports.parseRateLimitInfo = exports.parseRateLimitHeaders = exports.rateLimitUsagePct = void 0;
4
+ /**
5
+ * Returns the fraction of the rate limit currently used in [0.0, 1.0],
6
+ * or `null` when the headers aren't usable (missing limit, zero limit,
7
+ * missing remaining).
8
+ */
9
+ function rateLimitUsagePct(info) {
10
+ if (info.limit == null || info.remaining == null || info.limit <= 0) {
11
+ return null;
12
+ }
13
+ return 1 - info.remaining / info.limit;
14
+ }
15
+ exports.rateLimitUsagePct = rateLimitUsagePct;
4
16
  /**
5
17
  * Extract rate limit information from response headers
6
18
  */
@@ -12,6 +24,20 @@ function parseRateLimitHeaders(headers) {
12
24
  };
13
25
  }
14
26
  exports.parseRateLimitHeaders = parseRateLimitHeaders;
27
+ /**
28
+ * Returns a `RateLimitInfo` (headers + request context), or `null` when no
29
+ * `x-ratelimit-*` headers are present (e.g. self-hosted Lago instance with
30
+ * limits disabled). Useful for skipping observability emission entirely when
31
+ * there's nothing to report.
32
+ */
33
+ function parseRateLimitInfo(headers, method, url) {
34
+ const parsed = parseRateLimitHeaders(headers);
35
+ if (parsed.limit == null && parsed.remaining == null && parsed.reset == null) {
36
+ return null;
37
+ }
38
+ return { ...parsed, method, url };
39
+ }
40
+ exports.parseRateLimitInfo = parseRateLimitInfo;
15
41
  /**
16
42
  * Helper to parse a header value as a number
17
43
  */