meterflow 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MeterFlow
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # meterflow
2
+
3
+ Official Node.js SDK for [MeterFlow](https://meterflow.com) — usage-based billing, credit management, and metering.
4
+
5
+ ## Requirements
6
+
7
+ - Node.js ≥ 18
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install meterflow
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```typescript
18
+ import { MeterFlow } from "meterflow";
19
+
20
+ const client = new MeterFlow({ apiKey: "mf_live_your_api_key" });
21
+
22
+ // Grant credits to a customer
23
+ await client.credits.grant({
24
+ customer_external_id: "customer_123",
25
+ amount: 100,
26
+ description: "Welcome credits",
27
+ });
28
+
29
+ // Record a usage event
30
+ await client.usage.record({
31
+ customer_external_id: "customer_123",
32
+ meter_name: "api_calls",
33
+ quantity: 1,
34
+ });
35
+
36
+ // Check credit balance
37
+ const balance = await client.credits.balance("customer_123");
38
+ console.log(balance.balance);
39
+ ```
40
+
41
+ ## Configuration
42
+
43
+ ```typescript
44
+ const client = new MeterFlow({
45
+ apiKey: "mf_live_your_api_key", // required; mf_live_* or mf_test_*
46
+ baseUrl: "https://api.meterflow.com/api/v1", // optional override
47
+ timeout: 30_000, // ms; default 30 s
48
+ retries: 3, // default 3; 0 to disable
49
+ });
50
+ ```
51
+
52
+ ## Resources
53
+
54
+ | Resource | Methods |
55
+ |---|---|
56
+ | `client.credits` | `grant`, `deduct`, `balance`, `transactions` |
57
+ | `client.usage` | `record`, `recordBatch`, `summary` |
58
+ | `client.subscriptions` | `create`, `list`, `get`, `update`, `delete` |
59
+ | `client.plans` | `list`, `get` |
60
+
61
+ ## Webhook verification
62
+
63
+ ```typescript
64
+ import { verifyWebhook } from "meterflow";
65
+
66
+ const isValid = verifyWebhook(rawBody, req.headers["x-meterflow-signature"], webhookSecret);
67
+ ```
68
+
69
+ ## Error handling
70
+
71
+ ```typescript
72
+ import { MeterFlowError, InsufficientCreditsError, RateLimitError } from "meterflow";
73
+
74
+ try {
75
+ await client.credits.deduct({ customer_external_id: "cust_1", amount: 999 });
76
+ } catch (err) {
77
+ if (err instanceof InsufficientCreditsError) {
78
+ console.log("Not enough credits");
79
+ } else if (err instanceof RateLimitError) {
80
+ console.log(`Rate limited, retry after ${err.retryAfter}s`);
81
+ } else if (err instanceof MeterFlowError) {
82
+ console.log(`Request ID for support: ${err.requestId}`);
83
+ }
84
+ }
85
+ ```
86
+
87
+ ## License
88
+
89
+ MIT
@@ -0,0 +1,32 @@
1
+ import { CreditsResource } from "./resources/credits";
2
+ import { UsageResource } from "./resources/usage";
3
+ import { SubscriptionsResource } from "./resources/subscriptions";
4
+ import { PlansResource } from "./resources/plans";
5
+ export interface MeterFlowOptions {
6
+ apiKey: string;
7
+ baseUrl?: string;
8
+ timeout?: number;
9
+ retries?: number;
10
+ fetch?: typeof globalThis.fetch;
11
+ }
12
+ export interface RequestOptions {
13
+ body?: unknown;
14
+ query?: Record<string, string | number | boolean>;
15
+ idempotencyKey?: string;
16
+ timeout?: number;
17
+ }
18
+ export declare class MeterFlow {
19
+ readonly options: Required<MeterFlowOptions>;
20
+ private _credits?;
21
+ private _usage?;
22
+ private _subscriptions?;
23
+ private _plans?;
24
+ constructor(options: MeterFlowOptions);
25
+ get credits(): CreditsResource;
26
+ get usage(): UsageResource;
27
+ get subscriptions(): SubscriptionsResource;
28
+ get plans(): PlansResource;
29
+ /** @internal — used by resource classes only; not part of the public API */
30
+ request<T>(method: string, path: string, opts?: RequestOptions): Promise<T>;
31
+ }
32
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,SAAS;IACpB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAE7C,OAAO,CAAC,QAAQ,CAAC,CAAkB;IACnC,OAAO,CAAC,MAAM,CAAC,CAAgB;IAC/B,OAAO,CAAC,cAAc,CAAC,CAAwB;IAC/C,OAAO,CAAC,MAAM,CAAC,CAAgB;gBAEnB,OAAO,EAAE,gBAAgB;IAarC,IAAI,OAAO,IAAI,eAAe,CAE7B;IAED,IAAI,KAAK,IAAI,aAAa,CAEzB;IAED,IAAI,aAAa,IAAI,qBAAqB,CAEzC;IAED,IAAI,KAAK,IAAI,aAAa,CAEzB;IAED,4EAA4E;IAC5E,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;CAG5E"}
@@ -0,0 +1,30 @@
1
+ export declare class MeterFlowError extends Error {
2
+ readonly errorType: string;
3
+ readonly requestId: string | undefined;
4
+ readonly statusCode: number | undefined;
5
+ readonly retryable: boolean;
6
+ constructor(message: string, errorType: string, retryable: boolean, requestId?: string, statusCode?: number);
7
+ }
8
+ export declare class AuthError extends MeterFlowError {
9
+ constructor(message: string, requestId?: string, statusCode?: number);
10
+ }
11
+ export declare class NotFoundError extends MeterFlowError {
12
+ constructor(message: string, requestId?: string);
13
+ }
14
+ export declare class InsufficientCreditsError extends MeterFlowError {
15
+ constructor(message: string, requestId?: string);
16
+ }
17
+ export declare class ConflictError extends MeterFlowError {
18
+ constructor(message: string, requestId?: string);
19
+ }
20
+ export declare class ValidationError extends MeterFlowError {
21
+ constructor(message: string, requestId?: string);
22
+ }
23
+ export declare class RateLimitError extends MeterFlowError {
24
+ readonly retryAfter: number | undefined;
25
+ constructor(message: string, retryAfter?: number, requestId?: string);
26
+ }
27
+ export declare class ServerError extends MeterFlowError {
28
+ constructor(message: string, requestId?: string, statusCode?: number);
29
+ }
30
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;gBAEhB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAQ5G;AAED,qBAAa,SAAU,SAAQ,cAAc;gBAC/B,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,SAAM;CAIlE;AAED,qBAAa,aAAc,SAAQ,cAAc;gBACnC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAIhD;AAED,qBAAa,wBAAyB,SAAQ,cAAc;gBAC9C,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAIhD;AAED,qBAAa,aAAc,SAAQ,cAAc;gBACnC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAIhD;AAED,qBAAa,eAAgB,SAAQ,cAAc;gBACrC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAIhD;AAED,qBAAa,cAAe,SAAQ,cAAc;IAChD,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE5B,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAKrE;AAED,qBAAa,WAAY,SAAQ,cAAc;gBACjC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,SAAM;CAIlE"}
package/dist/index.cjs ADDED
@@ -0,0 +1,358 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AuthError: () => AuthError,
24
+ ConflictError: () => ConflictError,
25
+ InsufficientCreditsError: () => InsufficientCreditsError,
26
+ MeterFlow: () => MeterFlow,
27
+ MeterFlowError: () => MeterFlowError,
28
+ NotFoundError: () => NotFoundError,
29
+ RateLimitError: () => RateLimitError,
30
+ ServerError: () => ServerError,
31
+ ValidationError: () => ValidationError,
32
+ verifyWebhook: () => verifyWebhook
33
+ });
34
+ module.exports = __toCommonJS(index_exports);
35
+
36
+ // src/errors.ts
37
+ var MeterFlowError = class extends Error {
38
+ errorType;
39
+ requestId;
40
+ statusCode;
41
+ retryable;
42
+ constructor(message, errorType, retryable2, requestId, statusCode) {
43
+ super(message);
44
+ this.name = "MeterFlowError";
45
+ this.errorType = errorType;
46
+ this.retryable = retryable2;
47
+ this.requestId = requestId;
48
+ this.statusCode = statusCode;
49
+ }
50
+ };
51
+ var AuthError = class extends MeterFlowError {
52
+ constructor(message, requestId, statusCode = 401) {
53
+ super(message, "auth_error", false, requestId, statusCode);
54
+ this.name = "AuthError";
55
+ }
56
+ };
57
+ var NotFoundError = class extends MeterFlowError {
58
+ constructor(message, requestId) {
59
+ super(message, "not_found", false, requestId, 404);
60
+ this.name = "NotFoundError";
61
+ }
62
+ };
63
+ var InsufficientCreditsError = class extends MeterFlowError {
64
+ constructor(message, requestId) {
65
+ super(message, "insufficient_credits", false, requestId, 402);
66
+ this.name = "InsufficientCreditsError";
67
+ }
68
+ };
69
+ var ConflictError = class extends MeterFlowError {
70
+ constructor(message, requestId) {
71
+ super(message, "conflict", false, requestId, 409);
72
+ this.name = "ConflictError";
73
+ }
74
+ };
75
+ var ValidationError = class extends MeterFlowError {
76
+ constructor(message, requestId) {
77
+ super(message, "validation_error", false, requestId, 422);
78
+ this.name = "ValidationError";
79
+ }
80
+ };
81
+ var RateLimitError = class extends MeterFlowError {
82
+ retryAfter;
83
+ constructor(message, retryAfter, requestId) {
84
+ super(message, "rate_limit", true, requestId, 429);
85
+ this.name = "RateLimitError";
86
+ this.retryAfter = retryAfter;
87
+ }
88
+ };
89
+ var ServerError = class extends MeterFlowError {
90
+ constructor(message, requestId, statusCode = 500) {
91
+ super(message, "server_error", true, requestId, statusCode);
92
+ this.name = "ServerError";
93
+ }
94
+ };
95
+
96
+ // src/utils/retry.ts
97
+ function sleep(ms) {
98
+ return new Promise((resolve) => setTimeout(resolve, ms));
99
+ }
100
+ async function retryable(fn, opts, shouldRetry = () => true) {
101
+ let lastError;
102
+ for (let attempt = 0; attempt <= opts.retries; attempt++) {
103
+ try {
104
+ return await fn();
105
+ } catch (err) {
106
+ lastError = err;
107
+ const isLast = attempt === opts.retries;
108
+ if (isLast || !shouldRetry(err)) {
109
+ throw err;
110
+ }
111
+ let delayMs;
112
+ if (err instanceof RateLimitError && err.retryAfter != null) {
113
+ delayMs = err.retryAfter * 1e3;
114
+ } else {
115
+ const baseMs = Math.min(1e3 * Math.pow(opts.factor, attempt), opts.maxDelayMs);
116
+ delayMs = opts.jitter ? baseMs * (0.75 + Math.random() * 0.5) : baseMs;
117
+ }
118
+ await sleep(delayMs);
119
+ }
120
+ }
121
+ throw lastError;
122
+ }
123
+
124
+ // src/utils/http.ts
125
+ var SDK_VERSION = "0.1.0";
126
+ function buildUrl(baseUrl, path, query) {
127
+ const url = new URL(path, baseUrl.endsWith("/") ? baseUrl : baseUrl + "/");
128
+ if (query) {
129
+ for (const [key, value] of Object.entries(query)) {
130
+ url.searchParams.set(key, String(value));
131
+ }
132
+ }
133
+ return url.toString();
134
+ }
135
+ function buildHeaders(options, opts) {
136
+ const headers = {
137
+ Authorization: `Bearer ${options.apiKey}`,
138
+ "User-Agent": `meterflow-node/${SDK_VERSION}`,
139
+ Accept: "application/json"
140
+ };
141
+ if (opts?.body !== void 0) {
142
+ headers["Content-Type"] = "application/json";
143
+ }
144
+ if (opts?.idempotencyKey) {
145
+ headers["Idempotency-Key"] = opts.idempotencyKey;
146
+ }
147
+ return headers;
148
+ }
149
+ async function parseErrorBody(response) {
150
+ try {
151
+ const json = await response.json();
152
+ if (typeof json["detail"] === "string") return json["detail"];
153
+ return JSON.stringify(json);
154
+ } catch {
155
+ return response.statusText || `HTTP ${response.status}`;
156
+ }
157
+ }
158
+ function mapResponseError(status, message, requestId, response) {
159
+ if (status === 401 || status === 403) return new AuthError(message, requestId, status);
160
+ if (status === 402) return new InsufficientCreditsError(message, requestId);
161
+ if (status === 404) return new NotFoundError(message, requestId);
162
+ if (status === 409) return new ConflictError(message, requestId);
163
+ if (status === 422) return new ValidationError(message, requestId);
164
+ if (status === 429) {
165
+ const retryAfterRaw = response.headers.get("Retry-After");
166
+ const retryAfter = retryAfterRaw != null ? parseInt(retryAfterRaw, 10) : void 0;
167
+ return new RateLimitError(message, Number.isFinite(retryAfter) ? retryAfter : void 0, requestId);
168
+ }
169
+ if (status >= 500) return new ServerError(message, requestId, status);
170
+ return new MeterFlowError(message, "request_error", false, requestId, status);
171
+ }
172
+ async function httpRequest(options, method, path, opts) {
173
+ const url = buildUrl(options.baseUrl, path, opts?.query);
174
+ const headers = buildHeaders(options, opts);
175
+ const body = opts?.body !== void 0 ? JSON.stringify(opts.body) : void 0;
176
+ const timeoutMs = opts?.timeout ?? options.timeout;
177
+ return retryable(
178
+ async () => {
179
+ const signal = AbortSignal.timeout(timeoutMs);
180
+ const fetchInit = { method, headers, signal };
181
+ if (body !== void 0) fetchInit.body = body;
182
+ const response = await options.fetch(url, fetchInit);
183
+ const requestId = response.headers.get("x-request-id") ?? void 0;
184
+ if (!response.ok) {
185
+ const message = await parseErrorBody(response);
186
+ throw mapResponseError(response.status, message, requestId, response);
187
+ }
188
+ if (response.status === 204 || response.headers.get("content-length") === "0") {
189
+ return void 0;
190
+ }
191
+ return await response.json();
192
+ },
193
+ { retries: options.retries, factor: 2, jitter: true, maxDelayMs: 1e4 },
194
+ (err) => {
195
+ if (err instanceof MeterFlowError) return err.retryable;
196
+ return true;
197
+ }
198
+ );
199
+ }
200
+
201
+ // src/resources/credits.ts
202
+ var CreditsResource = class {
203
+ constructor(client) {
204
+ this.client = client;
205
+ }
206
+ grant(body, opts) {
207
+ return this.client.request("POST", "credits/grant", {
208
+ body,
209
+ ...opts?.idempotencyKey !== void 0 && { idempotencyKey: opts.idempotencyKey }
210
+ });
211
+ }
212
+ deduct(body, opts) {
213
+ return this.client.request("POST", "credits/deduct", {
214
+ body,
215
+ ...opts?.idempotencyKey !== void 0 && { idempotencyKey: opts.idempotencyKey }
216
+ });
217
+ }
218
+ balance(customerId) {
219
+ return this.client.request("GET", `credits/${encodeURIComponent(customerId)}/balance`);
220
+ }
221
+ transactions(customerId, query) {
222
+ return this.client.request("GET", `credits/${encodeURIComponent(customerId)}/transactions`, {
223
+ ...query !== void 0 && { query }
224
+ });
225
+ }
226
+ };
227
+
228
+ // src/resources/usage.ts
229
+ var UsageResource = class {
230
+ constructor(client) {
231
+ this.client = client;
232
+ }
233
+ record(body, opts) {
234
+ return this.client.request("POST", "usage/events", {
235
+ body,
236
+ ...opts?.idempotencyKey !== void 0 && { idempotencyKey: opts.idempotencyKey }
237
+ });
238
+ }
239
+ recordBatch(events, opts) {
240
+ return this.client.request("POST", "usage/events/batch", {
241
+ body: { events },
242
+ ...opts?.idempotencyKey !== void 0 && { idempotencyKey: opts.idempotencyKey }
243
+ });
244
+ }
245
+ summary(customerId, query) {
246
+ return this.client.request("GET", `usage/${encodeURIComponent(customerId)}`, {
247
+ ...query !== void 0 && { query }
248
+ });
249
+ }
250
+ };
251
+
252
+ // src/resources/subscriptions.ts
253
+ var SubscriptionsResource = class {
254
+ constructor(client) {
255
+ this.client = client;
256
+ }
257
+ create(body, opts) {
258
+ return this.client.request("POST", "subscriptions", {
259
+ body,
260
+ ...opts?.idempotencyKey !== void 0 && { idempotencyKey: opts.idempotencyKey }
261
+ });
262
+ }
263
+ list(query) {
264
+ return this.client.request("GET", "subscriptions", {
265
+ ...query !== void 0 && { query }
266
+ });
267
+ }
268
+ get(subscriptionId) {
269
+ return this.client.request("GET", `subscriptions/${encodeURIComponent(subscriptionId)}`);
270
+ }
271
+ update(subscriptionId, body, opts) {
272
+ return this.client.request("PATCH", `subscriptions/${encodeURIComponent(subscriptionId)}`, {
273
+ body,
274
+ ...opts?.idempotencyKey !== void 0 && { idempotencyKey: opts.idempotencyKey }
275
+ });
276
+ }
277
+ delete(subscriptionId) {
278
+ return this.client.request("DELETE", `subscriptions/${encodeURIComponent(subscriptionId)}`);
279
+ }
280
+ };
281
+
282
+ // src/resources/plans.ts
283
+ var PlansResource = class {
284
+ constructor(client) {
285
+ this.client = client;
286
+ }
287
+ list(query) {
288
+ return this.client.request("GET", "plans", {
289
+ ...query !== void 0 && { query }
290
+ });
291
+ }
292
+ get(planId, query) {
293
+ return this.client.request("GET", `plans/${encodeURIComponent(planId)}`, {
294
+ ...query !== void 0 && { query }
295
+ });
296
+ }
297
+ };
298
+
299
+ // src/client.ts
300
+ var MeterFlow = class {
301
+ options;
302
+ _credits;
303
+ _usage;
304
+ _subscriptions;
305
+ _plans;
306
+ constructor(options) {
307
+ if (!options.apiKey.startsWith("mf_live_") && !options.apiKey.startsWith("mf_test_")) {
308
+ throw new Error("apiKey must start with mf_live_ or mf_test_");
309
+ }
310
+ this.options = {
311
+ apiKey: options.apiKey,
312
+ baseUrl: options.baseUrl ?? "https://api.meterflow.com/api/v1",
313
+ timeout: options.timeout ?? 3e4,
314
+ retries: options.retries ?? 3,
315
+ fetch: options.fetch ?? globalThis.fetch
316
+ };
317
+ }
318
+ get credits() {
319
+ return this._credits ??= new CreditsResource(this);
320
+ }
321
+ get usage() {
322
+ return this._usage ??= new UsageResource(this);
323
+ }
324
+ get subscriptions() {
325
+ return this._subscriptions ??= new SubscriptionsResource(this);
326
+ }
327
+ get plans() {
328
+ return this._plans ??= new PlansResource(this);
329
+ }
330
+ /** @internal — used by resource classes only; not part of the public API */
331
+ request(method, path, opts) {
332
+ return httpRequest(this.options, method, path, opts);
333
+ }
334
+ };
335
+
336
+ // src/utils/webhook-verify.ts
337
+ var import_crypto = require("crypto");
338
+ function verifyWebhook(rawBody, signature, secret) {
339
+ const body = typeof rawBody === "string" ? Buffer.from(rawBody, "utf8") : rawBody;
340
+ const expected = (0, import_crypto.createHmac)("sha256", secret).update(body).digest("hex");
341
+ const expectedBuf = Buffer.from(expected, "utf8");
342
+ const actualBuf = Buffer.from(signature, "utf8");
343
+ if (expectedBuf.length !== actualBuf.length) return false;
344
+ return (0, import_crypto.timingSafeEqual)(expectedBuf, actualBuf);
345
+ }
346
+ // Annotate the CommonJS export names for ESM import in node:
347
+ 0 && (module.exports = {
348
+ AuthError,
349
+ ConflictError,
350
+ InsufficientCreditsError,
351
+ MeterFlow,
352
+ MeterFlowError,
353
+ NotFoundError,
354
+ RateLimitError,
355
+ ServerError,
356
+ ValidationError,
357
+ verifyWebhook
358
+ });
@@ -0,0 +1,4 @@
1
+ export { MeterFlow } from "./client";
2
+ export { verifyWebhook } from "./utils/webhook-verify";
3
+ export { MeterFlowError, AuthError, NotFoundError, InsufficientCreditsError, ConflictError, ValidationError, RateLimitError, ServerError, } from "./errors";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EACL,cAAc,EACd,SAAS,EACT,aAAa,EACb,wBAAwB,EACxB,aAAa,EACb,eAAe,EACf,cAAc,EACd,WAAW,GACZ,MAAM,UAAU,CAAC"}