meterflow 0.4.4 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -1
- package/dist/client.d.ts +3 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/index.cjs +31 -1
- package/dist/index.js +31 -1
- package/dist/index.mjs +31 -1
- package/dist/resources/entitlements.d.ts +29 -0
- package/dist/resources/entitlements.d.ts.map +1 -0
- package/dist/resources/usage.d.ts +7 -0
- package/dist/resources/usage.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,6 +23,7 @@ Track what your customers use, enforce credit balances, and manage subscriptions
|
|
|
23
23
|
- [Usage events](#usage-events)
|
|
24
24
|
- [Subscriptions](#subscriptions)
|
|
25
25
|
- [Plans](#plans)
|
|
26
|
+
- [Entitlements — ask before you act](#entitlements--ask-before-you-act)
|
|
26
27
|
- [Idempotency — safe retries for writes](#idempotency--safe-retries-for-writes)
|
|
27
28
|
- [Automatic retries](#automatic-retries)
|
|
28
29
|
- [Error handling](#error-handling)
|
|
@@ -298,6 +299,38 @@ plan.meter_limits; // included units + overage rate per meter
|
|
|
298
299
|
|
|
299
300
|
Typical use: render your pricing page or signup flow from `plans.list()` so it can never drift from what billing actually enforces.
|
|
300
301
|
|
|
302
|
+
### Entitlements — ask before you act
|
|
303
|
+
|
|
304
|
+
The one call to make **before** doing work for a customer: "may they use this feature — and how much is left?" A **hard** limit says no here; recording usage afterwards never blocks, so an app that skips this call gets an honest ledger but no enforcement.
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
const gate = await client.entitlements.check("customer_123", "images.generated");
|
|
308
|
+
|
|
309
|
+
if (!gate.allowed) {
|
|
310
|
+
// gate.reason: "hard_limit_reached" | "no_subscription" | "not_in_plan" | "insufficient_credits"
|
|
311
|
+
return showUpgradePrompt(gate); // gate.used / gate.included / gate.period_end are there for the copy
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
await generateImage();
|
|
315
|
+
await client.usage.record({ event_name: "images.generated", customer_external_id: "customer_123", value: 1, properties: {} });
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
- `feature` is a meter's `event_name` (metered — `included`, `used`, `remaining` filled in) or a plan feature key like `"sso"` (boolean).
|
|
319
|
+
- `{ quantity: 5 }` asks "may they do **5** more?" — one call instead of one per item for batch work.
|
|
320
|
+
- A **soft** limit answers `allowed: true` with `reason: "soft_limit_exceeded"` — let it through, nudge the upgrade.
|
|
321
|
+
- A **metered** limit stays allowed while the customer's credits cover the overage; otherwise `insufficient_credits`.
|
|
322
|
+
- `allowed: false` is a normal resolved answer, never an exception. A feature key the project does not know at all is a `NotFoundError` — that is a typo, not a plan.
|
|
323
|
+
- The answer carries `Cache-Control: private, max-age=15`; on hot paths cache it per customer for a few seconds rather than calling on every request.
|
|
324
|
+
|
|
325
|
+
**All of them at once** — for a settings or pricing screen:
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
const { entitlements, period_end } = await client.entitlements.get("customer_123");
|
|
329
|
+
// [{ feature: "sso", feature_type: "boolean", allowed: true }, { feature: "images.generated", feature_type: "metered", used: "120", included: 500, remaining: "380", ... }]
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Prefer to be told rather than to ask? Subscribe a webhook to `limit.reached` (see below).
|
|
333
|
+
|
|
301
334
|
## Idempotency — safe retries for writes
|
|
302
335
|
|
|
303
336
|
Connections drop. When your app can't tell whether a write arrived, the correct move is to send it again **with the same idempotency key** — MeterFlow recognises the key and acts only once:
|
|
@@ -367,7 +400,7 @@ try {
|
|
|
367
400
|
|
|
368
401
|
## Verifying webhooks
|
|
369
402
|
|
|
370
|
-
MeterFlow notifies your app of activity you'd otherwise poll for — credits granted or deducted, usage recorded, subscriptions created or updated. Every delivery is signed with **HMAC-SHA256** in the `X-MeterFlow-Signature` header, using the webhook's secret — verify before trusting:
|
|
403
|
+
MeterFlow notifies your app of activity you'd otherwise poll for — credits granted or deducted, usage recorded, subscriptions created or updated, a customer reaching a plan limit. Every delivery is signed with **HMAC-SHA256** in the `X-MeterFlow-Signature` header, using the webhook's secret — verify before trusting:
|
|
371
404
|
|
|
372
405
|
```typescript
|
|
373
406
|
import express from "express";
|
|
@@ -406,6 +439,7 @@ Every delivery is a flat JSON object (`Content-Type: application/json`) with two
|
|
|
406
439
|
| `credit.deducted` | credits are deducted | `customer_id`, `amount`, `balance_after`, `transaction_id` |
|
|
407
440
|
| `subscription.created` | a subscription is created | `customer_id`, `plan_id`, `subscription_id`, `status` |
|
|
408
441
|
| `subscription.updated` | a subscription is updated | `customer_id`, `subscription_id`, `status` |
|
|
442
|
+
| `limit.reached` | a customer first reaches a **hard** or **soft** limit's included units this billing period (once per meter per period; metered limits report through `credit.deducted` instead) | `customer_id`, `subscription_id`, `feature` (the meter's `event_name`), `meter_id`, `limit_type`, `included`, `used`, `period_start`, `period_end` |
|
|
409
443
|
|
|
410
444
|
For example, a `credit.granted` delivery:
|
|
411
445
|
|
package/dist/client.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { CreditsResource } from "./resources/credits";
|
|
|
2
2
|
import { UsageResource } from "./resources/usage";
|
|
3
3
|
import { SubscriptionsResource } from "./resources/subscriptions";
|
|
4
4
|
import { PlansResource } from "./resources/plans";
|
|
5
|
+
import { EntitlementsResource } from "./resources/entitlements";
|
|
5
6
|
export interface MeterFlowOptions {
|
|
6
7
|
apiKey: string;
|
|
7
8
|
baseUrl?: string;
|
|
@@ -21,11 +22,13 @@ export declare class MeterFlow {
|
|
|
21
22
|
private _usage?;
|
|
22
23
|
private _subscriptions?;
|
|
23
24
|
private _plans?;
|
|
25
|
+
private _entitlements?;
|
|
24
26
|
constructor(options: MeterFlowOptions);
|
|
25
27
|
get credits(): CreditsResource;
|
|
26
28
|
get usage(): UsageResource;
|
|
27
29
|
get subscriptions(): SubscriptionsResource;
|
|
28
30
|
get plans(): PlansResource;
|
|
31
|
+
get entitlements(): EntitlementsResource;
|
|
29
32
|
/** @internal — used by resource classes only; not part of the public API */
|
|
30
33
|
request<T>(method: string, path: string, opts?: RequestOptions): Promise<T>;
|
|
31
34
|
}
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +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;
|
|
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;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,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;IAC/B,OAAO,CAAC,aAAa,CAAC,CAAuB;gBAEjC,OAAO,EAAE,gBAAgB;IAerC,IAAI,OAAO,IAAI,eAAe,CAE7B;IAED,IAAI,KAAK,IAAI,aAAa,CAEzB;IAED,IAAI,aAAa,IAAI,qBAAqB,CAEzC;IAED,IAAI,KAAK,IAAI,aAAa,CAEzB;IAED,IAAI,YAAY,IAAI,oBAAoB,CAEvC;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"}
|
package/dist/index.cjs
CHANGED
|
@@ -35,7 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
37
37
|
// package.json
|
|
38
|
-
var version = "0.
|
|
38
|
+
var version = "0.5.1";
|
|
39
39
|
|
|
40
40
|
// src/errors.ts
|
|
41
41
|
var MeterFlowError = class extends Error {
|
|
@@ -276,6 +276,15 @@ var UsageResource = class {
|
|
|
276
276
|
...opts?.idempotencyKey !== void 0 && { idempotencyKey: opts.idempotencyKey }
|
|
277
277
|
});
|
|
278
278
|
}
|
|
279
|
+
/**
|
|
280
|
+
* Read one recorded event back, including `billing_outcome` — what the worker decided to bill
|
|
281
|
+
* for it, or why it billed nothing (`no_subscription`, `no_meter_limit`, `not_metered`,
|
|
282
|
+
* `within_allowance`, `not_deducted`). It is `null` while `processed` is false: the worker runs
|
|
283
|
+
* after `record` answers, so poll this when you need to know what happened to a charge.
|
|
284
|
+
*/
|
|
285
|
+
event(eventId) {
|
|
286
|
+
return this.client.request("GET", `usage/events/${encodeURIComponent(eventId)}`);
|
|
287
|
+
}
|
|
279
288
|
summary(customerId, query) {
|
|
280
289
|
return this.client.request("GET", `usage/${encodeURIComponent(customerId)}`, {
|
|
281
290
|
...query !== void 0 && { query }
|
|
@@ -330,6 +339,23 @@ var PlansResource = class {
|
|
|
330
339
|
}
|
|
331
340
|
};
|
|
332
341
|
|
|
342
|
+
// src/resources/entitlements.ts
|
|
343
|
+
var EntitlementsResource = class {
|
|
344
|
+
constructor(client) {
|
|
345
|
+
this.client = client;
|
|
346
|
+
}
|
|
347
|
+
/** Every feature on the customer's plan, with this period's usage. Empty `entitlements` without a subscription. */
|
|
348
|
+
get(customerId) {
|
|
349
|
+
return this.client.request("GET", `entitlements/${encodeURIComponent(customerId)}`);
|
|
350
|
+
}
|
|
351
|
+
/** May this customer use `feature` (`quantity` more units of it) right now? */
|
|
352
|
+
check(customerId, feature, opts) {
|
|
353
|
+
const query = { feature };
|
|
354
|
+
if (opts?.quantity !== void 0) query["quantity"] = opts.quantity;
|
|
355
|
+
return this.client.request("GET", `entitlements/${encodeURIComponent(customerId)}/check`, { query });
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
|
|
333
359
|
// src/client.ts
|
|
334
360
|
var MeterFlow = class {
|
|
335
361
|
options;
|
|
@@ -337,6 +363,7 @@ var MeterFlow = class {
|
|
|
337
363
|
_usage;
|
|
338
364
|
_subscriptions;
|
|
339
365
|
_plans;
|
|
366
|
+
_entitlements;
|
|
340
367
|
constructor(options) {
|
|
341
368
|
if (!options.apiKey.startsWith("mf_live_") && !options.apiKey.startsWith("mf_test_")) {
|
|
342
369
|
throw new Error("apiKey must start with mf_live_ or mf_test_");
|
|
@@ -363,6 +390,9 @@ var MeterFlow = class {
|
|
|
363
390
|
get plans() {
|
|
364
391
|
return this._plans ??= new PlansResource(this);
|
|
365
392
|
}
|
|
393
|
+
get entitlements() {
|
|
394
|
+
return this._entitlements ??= new EntitlementsResource(this);
|
|
395
|
+
}
|
|
366
396
|
/** @internal — used by resource classes only; not part of the public API */
|
|
367
397
|
request(method, path, opts) {
|
|
368
398
|
return httpRequest(this.options, method, path, opts);
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
37
37
|
// package.json
|
|
38
|
-
var version = "0.
|
|
38
|
+
var version = "0.5.1";
|
|
39
39
|
|
|
40
40
|
// src/errors.ts
|
|
41
41
|
var MeterFlowError = class extends Error {
|
|
@@ -276,6 +276,15 @@ var UsageResource = class {
|
|
|
276
276
|
...opts?.idempotencyKey !== void 0 && { idempotencyKey: opts.idempotencyKey }
|
|
277
277
|
});
|
|
278
278
|
}
|
|
279
|
+
/**
|
|
280
|
+
* Read one recorded event back, including `billing_outcome` — what the worker decided to bill
|
|
281
|
+
* for it, or why it billed nothing (`no_subscription`, `no_meter_limit`, `not_metered`,
|
|
282
|
+
* `within_allowance`, `not_deducted`). It is `null` while `processed` is false: the worker runs
|
|
283
|
+
* after `record` answers, so poll this when you need to know what happened to a charge.
|
|
284
|
+
*/
|
|
285
|
+
event(eventId) {
|
|
286
|
+
return this.client.request("GET", `usage/events/${encodeURIComponent(eventId)}`);
|
|
287
|
+
}
|
|
279
288
|
summary(customerId, query) {
|
|
280
289
|
return this.client.request("GET", `usage/${encodeURIComponent(customerId)}`, {
|
|
281
290
|
...query !== void 0 && { query }
|
|
@@ -330,6 +339,23 @@ var PlansResource = class {
|
|
|
330
339
|
}
|
|
331
340
|
};
|
|
332
341
|
|
|
342
|
+
// src/resources/entitlements.ts
|
|
343
|
+
var EntitlementsResource = class {
|
|
344
|
+
constructor(client) {
|
|
345
|
+
this.client = client;
|
|
346
|
+
}
|
|
347
|
+
/** Every feature on the customer's plan, with this period's usage. Empty `entitlements` without a subscription. */
|
|
348
|
+
get(customerId) {
|
|
349
|
+
return this.client.request("GET", `entitlements/${encodeURIComponent(customerId)}`);
|
|
350
|
+
}
|
|
351
|
+
/** May this customer use `feature` (`quantity` more units of it) right now? */
|
|
352
|
+
check(customerId, feature, opts) {
|
|
353
|
+
const query = { feature };
|
|
354
|
+
if (opts?.quantity !== void 0) query["quantity"] = opts.quantity;
|
|
355
|
+
return this.client.request("GET", `entitlements/${encodeURIComponent(customerId)}/check`, { query });
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
|
|
333
359
|
// src/client.ts
|
|
334
360
|
var MeterFlow = class {
|
|
335
361
|
options;
|
|
@@ -337,6 +363,7 @@ var MeterFlow = class {
|
|
|
337
363
|
_usage;
|
|
338
364
|
_subscriptions;
|
|
339
365
|
_plans;
|
|
366
|
+
_entitlements;
|
|
340
367
|
constructor(options) {
|
|
341
368
|
if (!options.apiKey.startsWith("mf_live_") && !options.apiKey.startsWith("mf_test_")) {
|
|
342
369
|
throw new Error("apiKey must start with mf_live_ or mf_test_");
|
|
@@ -363,6 +390,9 @@ var MeterFlow = class {
|
|
|
363
390
|
get plans() {
|
|
364
391
|
return this._plans ??= new PlansResource(this);
|
|
365
392
|
}
|
|
393
|
+
get entitlements() {
|
|
394
|
+
return this._entitlements ??= new EntitlementsResource(this);
|
|
395
|
+
}
|
|
366
396
|
/** @internal — used by resource classes only; not part of the public API */
|
|
367
397
|
request(method, path, opts) {
|
|
368
398
|
return httpRequest(this.options, method, path, opts);
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// package.json
|
|
2
|
-
var version = "0.
|
|
2
|
+
var version = "0.5.1";
|
|
3
3
|
|
|
4
4
|
// src/errors.ts
|
|
5
5
|
var MeterFlowError = class extends Error {
|
|
@@ -240,6 +240,15 @@ var UsageResource = class {
|
|
|
240
240
|
...opts?.idempotencyKey !== void 0 && { idempotencyKey: opts.idempotencyKey }
|
|
241
241
|
});
|
|
242
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* Read one recorded event back, including `billing_outcome` — what the worker decided to bill
|
|
245
|
+
* for it, or why it billed nothing (`no_subscription`, `no_meter_limit`, `not_metered`,
|
|
246
|
+
* `within_allowance`, `not_deducted`). It is `null` while `processed` is false: the worker runs
|
|
247
|
+
* after `record` answers, so poll this when you need to know what happened to a charge.
|
|
248
|
+
*/
|
|
249
|
+
event(eventId) {
|
|
250
|
+
return this.client.request("GET", `usage/events/${encodeURIComponent(eventId)}`);
|
|
251
|
+
}
|
|
243
252
|
summary(customerId, query) {
|
|
244
253
|
return this.client.request("GET", `usage/${encodeURIComponent(customerId)}`, {
|
|
245
254
|
...query !== void 0 && { query }
|
|
@@ -294,6 +303,23 @@ var PlansResource = class {
|
|
|
294
303
|
}
|
|
295
304
|
};
|
|
296
305
|
|
|
306
|
+
// src/resources/entitlements.ts
|
|
307
|
+
var EntitlementsResource = class {
|
|
308
|
+
constructor(client) {
|
|
309
|
+
this.client = client;
|
|
310
|
+
}
|
|
311
|
+
/** Every feature on the customer's plan, with this period's usage. Empty `entitlements` without a subscription. */
|
|
312
|
+
get(customerId) {
|
|
313
|
+
return this.client.request("GET", `entitlements/${encodeURIComponent(customerId)}`);
|
|
314
|
+
}
|
|
315
|
+
/** May this customer use `feature` (`quantity` more units of it) right now? */
|
|
316
|
+
check(customerId, feature, opts) {
|
|
317
|
+
const query = { feature };
|
|
318
|
+
if (opts?.quantity !== void 0) query["quantity"] = opts.quantity;
|
|
319
|
+
return this.client.request("GET", `entitlements/${encodeURIComponent(customerId)}/check`, { query });
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
297
323
|
// src/client.ts
|
|
298
324
|
var MeterFlow = class {
|
|
299
325
|
options;
|
|
@@ -301,6 +327,7 @@ var MeterFlow = class {
|
|
|
301
327
|
_usage;
|
|
302
328
|
_subscriptions;
|
|
303
329
|
_plans;
|
|
330
|
+
_entitlements;
|
|
304
331
|
constructor(options) {
|
|
305
332
|
if (!options.apiKey.startsWith("mf_live_") && !options.apiKey.startsWith("mf_test_")) {
|
|
306
333
|
throw new Error("apiKey must start with mf_live_ or mf_test_");
|
|
@@ -327,6 +354,9 @@ var MeterFlow = class {
|
|
|
327
354
|
get plans() {
|
|
328
355
|
return this._plans ??= new PlansResource(this);
|
|
329
356
|
}
|
|
357
|
+
get entitlements() {
|
|
358
|
+
return this._entitlements ??= new EntitlementsResource(this);
|
|
359
|
+
}
|
|
330
360
|
/** @internal — used by resource classes only; not part of the public API */
|
|
331
361
|
request(method, path, opts) {
|
|
332
362
|
return httpRequest(this.options, method, path, opts);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { MeterFlow } from "../client";
|
|
2
|
+
import type { components } from "../types/openapi";
|
|
3
|
+
type EntitlementResponse = components["schemas"]["EntitlementResponse"];
|
|
4
|
+
type EntitlementsResponse = components["schemas"]["EntitlementsResponse"];
|
|
5
|
+
export interface CheckOptions {
|
|
6
|
+
/** How many more units the app is about to use — "may they do 5 more?". Defaults to 1 on the server. */
|
|
7
|
+
quantity?: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Ask BEFORE doing the work. `check()` is where a hard limit says no; recording usage afterwards
|
|
11
|
+
* never blocks, so an app that skips this call gets no enforcement at all — only an honest ledger.
|
|
12
|
+
*
|
|
13
|
+
* `allowed: false` is a normal answer, not an error: the promise resolves and `reason` says why
|
|
14
|
+
* (`no_subscription`, `not_in_plan`, `hard_limit_reached`, `insufficient_credits`). A feature key
|
|
15
|
+
* the project does not know at all is a 404 → `NotFoundError`, because that is a typo, not a plan.
|
|
16
|
+
*
|
|
17
|
+
* Both calls return `Cache-Control: private, max-age=15` — cache per customer for a few seconds
|
|
18
|
+
* on hot paths rather than calling on every request.
|
|
19
|
+
*/
|
|
20
|
+
export declare class EntitlementsResource {
|
|
21
|
+
private readonly client;
|
|
22
|
+
constructor(client: MeterFlow);
|
|
23
|
+
/** Every feature on the customer's plan, with this period's usage. Empty `entitlements` without a subscription. */
|
|
24
|
+
get(customerId: string): Promise<EntitlementsResponse>;
|
|
25
|
+
/** May this customer use `feature` (`quantity` more units of it) right now? */
|
|
26
|
+
check(customerId: string, feature: string, opts?: CheckOptions): Promise<EntitlementResponse>;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=entitlements.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entitlements.d.ts","sourceRoot":"","sources":["../../../src/resources/entitlements.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,KAAK,mBAAmB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,qBAAqB,CAAC,CAAC;AACxE,KAAK,oBAAoB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,sBAAsB,CAAC,CAAC;AAE1E,MAAM,WAAW,YAAY;IAC3B,wGAAwG;IACxG,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,oBAAoB;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS;IAE9C,mHAAmH;IACnH,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAItD,+EAA+E;IAC/E,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAK9F"}
|
|
@@ -25,6 +25,13 @@ export declare class UsageResource {
|
|
|
25
25
|
record(body: UsageEventRequest, opts?: RecordOptions): Promise<UsageEventResponse>;
|
|
26
26
|
/** Record up to `MAX_BATCH_EVENTS` events in one request. Larger arrays are rejected locally, never sent. */
|
|
27
27
|
recordBatch(events: UsageEventRequest[], opts?: RecordOptions): Promise<UsageEventResponse[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Read one recorded event back, including `billing_outcome` — what the worker decided to bill
|
|
30
|
+
* for it, or why it billed nothing (`no_subscription`, `no_meter_limit`, `not_metered`,
|
|
31
|
+
* `within_allowance`, `not_deducted`). It is `null` while `processed` is false: the worker runs
|
|
32
|
+
* after `record` answers, so poll this when you need to know what happened to a charge.
|
|
33
|
+
*/
|
|
34
|
+
event(eventId: string): Promise<UsageEventResponse>;
|
|
28
35
|
summary(customerId: string, query?: SummaryQuery): Promise<UsageSummaryResponse>;
|
|
29
36
|
}
|
|
30
37
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../../src/resources/usage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,KAAK,iBAAiB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,CAAC;AACpE,KAAK,kBAAkB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,oBAAoB,CAAC,CAAC;AACtE,KAAK,oBAAoB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,sBAAsB,CAAC,CAAC;AAE1E,MAAM,WAAW,aAAa;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS;IAE9C,MAAM,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAOlF,6GAA6G;IAC7G,WAAW,CAAC,MAAM,EAAE,iBAAiB,EAAE,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAY7F,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAKjF"}
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../../src/resources/usage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,KAAK,iBAAiB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,CAAC;AACpE,KAAK,kBAAkB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,oBAAoB,CAAC,CAAC;AACtE,KAAK,oBAAoB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,sBAAsB,CAAC,CAAC;AAE1E,MAAM,WAAW,aAAa;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS;IAE9C,MAAM,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAOlF,6GAA6G;IAC7G,WAAW,CAAC,MAAM,EAAE,iBAAiB,EAAE,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAY7F;;;;;OAKG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAInD,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAKjF"}
|