mbase-sdk 0.0.8 → 0.0.9

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/dist/index.d.cts CHANGED
@@ -204,7 +204,7 @@ type CheckRateLimit = {
204
204
  };
205
205
  type CheckResult = {
206
206
  /** Both gates: the capacity covers the quantity **and** every rate-limit
207
- * window admits it. */
207
+ * window admits it. Under `no_cap` or a soft cap the capacity always does. */
208
208
  allowed: boolean;
209
209
  /** Unlimited for this meter. `available` is `null`. Rate limits still
210
210
  * apply — a customer who is never refused on capacity is the one a runaway
@@ -212,14 +212,19 @@ type CheckResult = {
212
212
  no_cap: boolean;
213
213
  /**
214
214
  * The whole capacity: the plan's unused entitlement for the current period,
215
- * floored at 0, plus every open grant. `null` under `no_cap`, where capacity
216
- * is not a number.
215
+ * floored at 0, plus what is left of a rollover carry, plus every open
216
+ * grant. `null` under `no_cap`, where capacity is not a number. Under a soft
217
+ * cap it is what is left of the included amount, and running out of it
218
+ * refuses nothing.
217
219
  *
218
220
  * One figure and no breakdown: `check` answers from a single cached integer,
219
221
  * and itemising where the capacity came from would cost it that. For the
220
222
  * per-grant detail, read `customers.allowances.list`.
221
223
  */
222
224
  available: number | null;
225
+ /** A soft cap: past `available`, only a rate limit refuses. `false`
226
+ * everywhere else, `no_cap` included. */
227
+ allow_overage: boolean;
223
228
  /** Which gate said no. Absent when allowed, so its presence is the denial
224
229
  * and reading it is never a branch on a truthy string. */
225
230
  reason?: CheckReason;
@@ -239,7 +244,7 @@ type CheckResult = {
239
244
  * `track` records work that already happened, so it never refuses on capacity
240
245
  * — the gate is `check`, which runs before the work. A quantity beyond the
241
246
  * customer's capacity is recorded, drives `available` to 0, and the next
242
- * `check` says no.
247
+ * `check` says no, unless the plan's cap is soft.
243
248
  */
244
249
  type TrackParams = {
245
250
  customer_id: string;
@@ -357,6 +362,12 @@ type PlanAllowance = {
357
362
  /** Units per period. `0` is legal and grants nothing. `null` under no_cap. */
358
363
  amount: number | null;
359
364
  no_cap: boolean;
365
+ /** A soft cap: once `amount` is used up, `check` and `reserve` admit rather
366
+ * than refuse, and the usage past it is overage. */
367
+ allow_overage: boolean;
368
+ /** What a period leaves unused of `amount` carries into the next, which
369
+ * spends it first. The carry lasts that one period. */
370
+ rollover: boolean;
360
371
  kind: PlanAllowanceKind;
361
372
  /** `one_time` only; `null` is a grant that never expires. */
362
373
  valid_for: Validity | null;
@@ -372,6 +383,12 @@ type PlanAllowanceSetParams = {
372
383
  meter_id: string;
373
384
  amount?: number;
374
385
  no_cap?: boolean;
386
+ /** A soft cap: past `amount`, admit rather than refuse. Defaults to `false`;
387
+ * refused beside `no_cap` and on `one_time`. */
388
+ allow_overage?: boolean;
389
+ /** Carry what a period leaves unused into the next. Defaults to `false`;
390
+ * refused beside `no_cap` and on `one_time`. */
391
+ rollover?: boolean;
375
392
  /** Defaults to `recurring`. */
376
393
  kind?: PlanAllowanceKind;
377
394
  /** `one_time` only. */
@@ -434,16 +451,30 @@ type PlanChangeNowParams = Omit<PlanChangeParams, "effective">;
434
451
  type PlanMoveParams = Pick<PlanChangeParams, "plan">;
435
452
  /** `awaiting`: the plan meters this, but its only versions land later. */
436
453
  type EntitlementState = "granted" | "awaiting";
437
- /** `used` counts toward `amount`; `total` adds what grants paid for. */
454
+ /** `used` counts toward `amount`; `total` adds what the carry and grants paid
455
+ * for. */
438
456
  type MeterEntitlement = {
439
457
  meter_id: string;
440
458
  state: EntitlementState;
441
459
  version: PlanAllowance | null;
442
460
  amount: number | null;
443
461
  no_cap: boolean;
462
+ /** The version in effect's; `false` while `awaiting`. */
463
+ allow_overage: boolean;
464
+ /** The version in effect's; `false` while `awaiting`. */
465
+ rollover: boolean;
444
466
  used: number;
445
467
  total: number;
446
468
  remaining: number | null;
469
+ /** `max(used - amount, 0)`, under a hard cap too. `null` where `remaining`
470
+ * is. */
471
+ overage_used: number | null;
472
+ /** What the period before left unused and this one took in; `0` unless
473
+ * both versions roll over. `null` where `remaining` is. */
474
+ carried_in: number | null;
475
+ /** What this period has spent of `carried_in`, counted apart from `used`.
476
+ * `null` where `remaining` is. */
477
+ carried_used: number | null;
447
478
  reserved: number;
448
479
  available: number | null;
449
480
  incoming: {
@@ -463,6 +494,33 @@ type CustomerEntitlement = {
463
494
  };
464
495
  meters: MeterEntitlement[];
465
496
  };
497
+ type ClosedPeriodParams = {
498
+ /** An RFC 3339 instant; omitted, now. To walk back, pass a period's `from`
499
+ * exactly as it came: a trip through a `Date` drops its microseconds. */
500
+ before?: string;
501
+ };
502
+ /** The entitlement meter at the period's last instant, less what describes
503
+ * now. `total - used - carried_used` is what grants absorbed. */
504
+ type ClosedPeriodMeter = Omit<MeterEntitlement, "reserved" | "available" | "incoming"> & {
505
+ /** What it passed to the next period: `max(amount - used, 0)` under a
506
+ * version that rolled over, `0` otherwise. `null` where `remaining` is. */
507
+ carried_out: number | null;
508
+ };
509
+ /** `[from, to)`, final: nothing written after it restates it. */
510
+ type ClosedPeriod = {
511
+ customer_id: string;
512
+ /** The plan in force at the period's last instant. */
513
+ plan_id: string;
514
+ cycle: PlanCycle;
515
+ /** When that plan took effect, as on the entitlement read. */
516
+ since: string;
517
+ /** Microseconds included: pass it back as `before` exactly as it came. */
518
+ from: string;
519
+ /** Its boundary, or the instant a reset closed it early. */
520
+ to: string;
521
+ /** One per meter that plan meters. */
522
+ meters: ClosedPeriodMeter[];
523
+ };
466
524
  type UsagePeriod = "current" | "last";
467
525
  /** 1–90 UTC days, ending today. */
468
526
  type UsageDaysParams = {
@@ -604,7 +662,8 @@ type ThresholdCrossing = {
604
662
  } | null;
605
663
  /** A whole percent, 1–1000; past 100 is an overage alert. */
606
664
  threshold: number;
607
- /** The plan's figures at the crossing; neither includes grants. */
665
+ /** The plan's figures at the crossing; neither includes grants or a
666
+ * carry. */
608
667
  used: number;
609
668
  entitlement: number;
610
669
  period: {
@@ -647,6 +706,20 @@ declare class CustomerAllowances$1 {
647
706
  revoke(customerId: string, allowanceId: string, options?: RequestOptions): Promise<Allowance>;
648
707
  }
649
708
 
709
+ /** A customer's ended periods, exact from the engine's counters: the figures
710
+ * to bill from. */
711
+ declare class CustomerPeriods$1 {
712
+ #private;
713
+ constructor(client: Client);
714
+ /**
715
+ * The newest period that has ended, or that ended at or before `before`;
716
+ * `null` when there is none. Walk back by passing each period's `from` as
717
+ * `before`, exactly as it came. Throws `PeriodSettlingError` for a minute
718
+ * after a period ends.
719
+ */
720
+ last(id: string, params?: ClosedPeriodParams, options?: RequestOptions): Promise<ClosedPeriod | null>;
721
+ }
722
+
650
723
  /**
651
724
  * Which plan a customer holds. The history is append-only: there is no patch
652
725
  * and no delete, and moving a customer to a different plan is the same call as
@@ -752,6 +825,8 @@ declare class Customers$1 {
752
825
  readonly plan: CustomerPlan$1;
753
826
  /** Grants, which sit on top of whatever the plan gives. */
754
827
  readonly allowances: CustomerAllowances$1;
828
+ /** Periods that have ended, with the figures to bill them from. */
829
+ readonly periods: CustomerPeriods$1;
755
830
  constructor(client: Client);
756
831
  create(params: CustomerCreateParams, options?: RequestOptions): Promise<Customer>;
757
832
  /** Lean: a listing does not embed the plan. Read one customer for that. */
@@ -892,6 +967,17 @@ declare class ReservationMismatchError extends InvalidRequestError {
892
967
  */
893
968
  declare class CycleChangeRequiresResetError extends InvalidRequestError {
894
969
  }
970
+ /**
971
+ * `409 period_settling`: the period ended under a minute ago and may still be
972
+ * taking writes. Read again after `retryAfter`; the SDK never retries it.
973
+ */
974
+ declare class PeriodSettlingError extends ConflictError {
975
+ /** Seconds until the period is final, from `Retry-After`. */
976
+ readonly retryAfter: number | undefined;
977
+ constructor(args: ConstructorParameters<typeof APIError>[0] & {
978
+ retryAfter?: number | undefined;
979
+ });
980
+ }
895
981
  declare class RateLimitError extends APIError {
896
982
  /** Seconds to wait, from `Retry-After`, when the engine sends one. */
897
983
  readonly retryAfter: number | undefined;
@@ -992,14 +1078,17 @@ declare class Meterbase {
992
1078
  * to cover the quantity, and every rate-limit window in force has to admit
993
1079
  * it. `reason` names the one that said no. `rate_limits` reports each window
994
1080
  * whether or not it refused, so a caller can ease off as its headroom closes
995
- * instead of discovering the ceiling by hitting it.
1081
+ * instead of discovering the ceiling by hitting it. Under a soft cap
1082
+ * (`allow_overage`) the capacity admits any quantity, so only a window can
1083
+ * refuse.
996
1084
  */
997
1085
  check(params: CheckParams, options?: RequestOptions): Promise<CheckResult>;
998
1086
  /**
999
1087
  * Records usage that already happened — the tokens were spent, the image
1000
1088
  * was generated — so it never refuses on capacity. A quantity beyond the
1001
1089
  * customer's capacity is recorded, drives `available` to 0, and the next
1002
- * `check` says no. The answer is a receipt, not a verdict.
1090
+ * `check` says no, unless the plan's cap is soft. The answer is a receipt,
1091
+ * not a verdict.
1003
1092
  *
1004
1093
  * `idempotency_key` is a UUIDv7, generated when omitted, so retrying this
1005
1094
  * call — the SDK's own retries included — replays the original rather than
@@ -1039,10 +1128,11 @@ declare class Meterbase {
1039
1128
  * runtime binding the bundle never has.
1040
1129
  */
1041
1130
  type CustomerAllowances = InstanceType<typeof CustomerAllowances$1>;
1131
+ type CustomerPeriods = InstanceType<typeof CustomerPeriods$1>;
1042
1132
  type CustomerPlan = InstanceType<typeof CustomerPlan$1>;
1043
1133
  type Customers = InstanceType<typeof Customers$1>;
1044
1134
  type Meters = InstanceType<typeof Meters$1>;
1045
1135
  type PlanAllowances = InstanceType<typeof PlanAllowances$1>;
1046
1136
  type Plans = InstanceType<typeof Plans$1>;
1047
1137
 
1048
- export { APIError, type Allowance, type AllowanceGrantParams, type AllowanceListParams, type AllowanceSource, type ApplyMode, type AssignPlanParams, type Assignment, AuthenticationError, type CheckParams, type CheckRateLimit, type CheckReason, type CheckResult, ConflictError, ConnectionError, type Customer, type CustomerAllowances, type CustomerCreateParams, type CustomerEntitlement, type CustomerListParams, type CustomerPlan, type CustomerUpdateParams, type CustomerUsage, type CustomerUsageParams, type CustomerWithPlan, type Customers, CycleChangeRequiresResetError, type DayUsage, type EmbeddedPlan, type EntitlementReachedEvent, type EntitlementState, type Hold, InvalidIdempotencyKeyError, InvalidRequestError, type List, type Meter, type MeterCreateParams, type MeterEntitlement, type MeterListParams, type MeterUpdateParams, type MeterUsage, type MeterUsageHistory, Meterbase, MeterbaseError, type MeterbaseOptions, type Meters, NotFoundError, PermissionDeniedError, type Plan, type PlanAllowance, type PlanAllowanceKind, type PlanAllowanceListParams, type PlanAllowanceSetParams, type PlanAllowances, type PlanChangeNowParams, type PlanChangeParams, type PlanCreateParams, type PlanCycle, type PlanListParams, type PlanMoveParams, type PlanUpdateParams, type Plans, RateLimitError, type Reconciliation, type RecordedReconciliation, type ReleaseParams, type ReleaseResult, type RequestOptions, ReservationMismatchError, type ReserveParams, type ReserveRefused, type ReserveResponse, type ReserveResult, ServerError, type ThresholdCrossedEvent, type ThresholdCrossing, TimeoutError, TooLateError, type TrackParams, type TrackResult, type UsageDaysParams, type UsageEvent, type UsagePeriod, type UsagePeriodParams, type Validity, type VerifyWebhookParams, type WebhookEvent, type WebhookHeaders, WebhookVerificationError, type WhoAmI, errorFromResponse, verifyWebhook };
1138
+ export { APIError, type Allowance, type AllowanceGrantParams, type AllowanceListParams, type AllowanceSource, type ApplyMode, type AssignPlanParams, type Assignment, AuthenticationError, type CheckParams, type CheckRateLimit, type CheckReason, type CheckResult, type ClosedPeriod, type ClosedPeriodMeter, type ClosedPeriodParams, ConflictError, ConnectionError, type Customer, type CustomerAllowances, type CustomerCreateParams, type CustomerEntitlement, type CustomerListParams, type CustomerPeriods, type CustomerPlan, type CustomerUpdateParams, type CustomerUsage, type CustomerUsageParams, type CustomerWithPlan, type Customers, CycleChangeRequiresResetError, type DayUsage, type EmbeddedPlan, type EntitlementReachedEvent, type EntitlementState, type Hold, InvalidIdempotencyKeyError, InvalidRequestError, type List, type Meter, type MeterCreateParams, type MeterEntitlement, type MeterListParams, type MeterUpdateParams, type MeterUsage, type MeterUsageHistory, Meterbase, MeterbaseError, type MeterbaseOptions, type Meters, NotFoundError, PeriodSettlingError, PermissionDeniedError, type Plan, type PlanAllowance, type PlanAllowanceKind, type PlanAllowanceListParams, type PlanAllowanceSetParams, type PlanAllowances, type PlanChangeNowParams, type PlanChangeParams, type PlanCreateParams, type PlanCycle, type PlanListParams, type PlanMoveParams, type PlanUpdateParams, type Plans, RateLimitError, type Reconciliation, type RecordedReconciliation, type ReleaseParams, type ReleaseResult, type RequestOptions, ReservationMismatchError, type ReserveParams, type ReserveRefused, type ReserveResponse, type ReserveResult, ServerError, type ThresholdCrossedEvent, type ThresholdCrossing, TimeoutError, TooLateError, type TrackParams, type TrackResult, type UsageDaysParams, type UsageEvent, type UsagePeriod, type UsagePeriodParams, type Validity, type VerifyWebhookParams, type WebhookEvent, type WebhookHeaders, WebhookVerificationError, type WhoAmI, errorFromResponse, verifyWebhook };
package/dist/index.d.ts CHANGED
@@ -204,7 +204,7 @@ type CheckRateLimit = {
204
204
  };
205
205
  type CheckResult = {
206
206
  /** Both gates: the capacity covers the quantity **and** every rate-limit
207
- * window admits it. */
207
+ * window admits it. Under `no_cap` or a soft cap the capacity always does. */
208
208
  allowed: boolean;
209
209
  /** Unlimited for this meter. `available` is `null`. Rate limits still
210
210
  * apply — a customer who is never refused on capacity is the one a runaway
@@ -212,14 +212,19 @@ type CheckResult = {
212
212
  no_cap: boolean;
213
213
  /**
214
214
  * The whole capacity: the plan's unused entitlement for the current period,
215
- * floored at 0, plus every open grant. `null` under `no_cap`, where capacity
216
- * is not a number.
215
+ * floored at 0, plus what is left of a rollover carry, plus every open
216
+ * grant. `null` under `no_cap`, where capacity is not a number. Under a soft
217
+ * cap it is what is left of the included amount, and running out of it
218
+ * refuses nothing.
217
219
  *
218
220
  * One figure and no breakdown: `check` answers from a single cached integer,
219
221
  * and itemising where the capacity came from would cost it that. For the
220
222
  * per-grant detail, read `customers.allowances.list`.
221
223
  */
222
224
  available: number | null;
225
+ /** A soft cap: past `available`, only a rate limit refuses. `false`
226
+ * everywhere else, `no_cap` included. */
227
+ allow_overage: boolean;
223
228
  /** Which gate said no. Absent when allowed, so its presence is the denial
224
229
  * and reading it is never a branch on a truthy string. */
225
230
  reason?: CheckReason;
@@ -239,7 +244,7 @@ type CheckResult = {
239
244
  * `track` records work that already happened, so it never refuses on capacity
240
245
  * — the gate is `check`, which runs before the work. A quantity beyond the
241
246
  * customer's capacity is recorded, drives `available` to 0, and the next
242
- * `check` says no.
247
+ * `check` says no, unless the plan's cap is soft.
243
248
  */
244
249
  type TrackParams = {
245
250
  customer_id: string;
@@ -357,6 +362,12 @@ type PlanAllowance = {
357
362
  /** Units per period. `0` is legal and grants nothing. `null` under no_cap. */
358
363
  amount: number | null;
359
364
  no_cap: boolean;
365
+ /** A soft cap: once `amount` is used up, `check` and `reserve` admit rather
366
+ * than refuse, and the usage past it is overage. */
367
+ allow_overage: boolean;
368
+ /** What a period leaves unused of `amount` carries into the next, which
369
+ * spends it first. The carry lasts that one period. */
370
+ rollover: boolean;
360
371
  kind: PlanAllowanceKind;
361
372
  /** `one_time` only; `null` is a grant that never expires. */
362
373
  valid_for: Validity | null;
@@ -372,6 +383,12 @@ type PlanAllowanceSetParams = {
372
383
  meter_id: string;
373
384
  amount?: number;
374
385
  no_cap?: boolean;
386
+ /** A soft cap: past `amount`, admit rather than refuse. Defaults to `false`;
387
+ * refused beside `no_cap` and on `one_time`. */
388
+ allow_overage?: boolean;
389
+ /** Carry what a period leaves unused into the next. Defaults to `false`;
390
+ * refused beside `no_cap` and on `one_time`. */
391
+ rollover?: boolean;
375
392
  /** Defaults to `recurring`. */
376
393
  kind?: PlanAllowanceKind;
377
394
  /** `one_time` only. */
@@ -434,16 +451,30 @@ type PlanChangeNowParams = Omit<PlanChangeParams, "effective">;
434
451
  type PlanMoveParams = Pick<PlanChangeParams, "plan">;
435
452
  /** `awaiting`: the plan meters this, but its only versions land later. */
436
453
  type EntitlementState = "granted" | "awaiting";
437
- /** `used` counts toward `amount`; `total` adds what grants paid for. */
454
+ /** `used` counts toward `amount`; `total` adds what the carry and grants paid
455
+ * for. */
438
456
  type MeterEntitlement = {
439
457
  meter_id: string;
440
458
  state: EntitlementState;
441
459
  version: PlanAllowance | null;
442
460
  amount: number | null;
443
461
  no_cap: boolean;
462
+ /** The version in effect's; `false` while `awaiting`. */
463
+ allow_overage: boolean;
464
+ /** The version in effect's; `false` while `awaiting`. */
465
+ rollover: boolean;
444
466
  used: number;
445
467
  total: number;
446
468
  remaining: number | null;
469
+ /** `max(used - amount, 0)`, under a hard cap too. `null` where `remaining`
470
+ * is. */
471
+ overage_used: number | null;
472
+ /** What the period before left unused and this one took in; `0` unless
473
+ * both versions roll over. `null` where `remaining` is. */
474
+ carried_in: number | null;
475
+ /** What this period has spent of `carried_in`, counted apart from `used`.
476
+ * `null` where `remaining` is. */
477
+ carried_used: number | null;
447
478
  reserved: number;
448
479
  available: number | null;
449
480
  incoming: {
@@ -463,6 +494,33 @@ type CustomerEntitlement = {
463
494
  };
464
495
  meters: MeterEntitlement[];
465
496
  };
497
+ type ClosedPeriodParams = {
498
+ /** An RFC 3339 instant; omitted, now. To walk back, pass a period's `from`
499
+ * exactly as it came: a trip through a `Date` drops its microseconds. */
500
+ before?: string;
501
+ };
502
+ /** The entitlement meter at the period's last instant, less what describes
503
+ * now. `total - used - carried_used` is what grants absorbed. */
504
+ type ClosedPeriodMeter = Omit<MeterEntitlement, "reserved" | "available" | "incoming"> & {
505
+ /** What it passed to the next period: `max(amount - used, 0)` under a
506
+ * version that rolled over, `0` otherwise. `null` where `remaining` is. */
507
+ carried_out: number | null;
508
+ };
509
+ /** `[from, to)`, final: nothing written after it restates it. */
510
+ type ClosedPeriod = {
511
+ customer_id: string;
512
+ /** The plan in force at the period's last instant. */
513
+ plan_id: string;
514
+ cycle: PlanCycle;
515
+ /** When that plan took effect, as on the entitlement read. */
516
+ since: string;
517
+ /** Microseconds included: pass it back as `before` exactly as it came. */
518
+ from: string;
519
+ /** Its boundary, or the instant a reset closed it early. */
520
+ to: string;
521
+ /** One per meter that plan meters. */
522
+ meters: ClosedPeriodMeter[];
523
+ };
466
524
  type UsagePeriod = "current" | "last";
467
525
  /** 1–90 UTC days, ending today. */
468
526
  type UsageDaysParams = {
@@ -604,7 +662,8 @@ type ThresholdCrossing = {
604
662
  } | null;
605
663
  /** A whole percent, 1–1000; past 100 is an overage alert. */
606
664
  threshold: number;
607
- /** The plan's figures at the crossing; neither includes grants. */
665
+ /** The plan's figures at the crossing; neither includes grants or a
666
+ * carry. */
608
667
  used: number;
609
668
  entitlement: number;
610
669
  period: {
@@ -647,6 +706,20 @@ declare class CustomerAllowances$1 {
647
706
  revoke(customerId: string, allowanceId: string, options?: RequestOptions): Promise<Allowance>;
648
707
  }
649
708
 
709
+ /** A customer's ended periods, exact from the engine's counters: the figures
710
+ * to bill from. */
711
+ declare class CustomerPeriods$1 {
712
+ #private;
713
+ constructor(client: Client);
714
+ /**
715
+ * The newest period that has ended, or that ended at or before `before`;
716
+ * `null` when there is none. Walk back by passing each period's `from` as
717
+ * `before`, exactly as it came. Throws `PeriodSettlingError` for a minute
718
+ * after a period ends.
719
+ */
720
+ last(id: string, params?: ClosedPeriodParams, options?: RequestOptions): Promise<ClosedPeriod | null>;
721
+ }
722
+
650
723
  /**
651
724
  * Which plan a customer holds. The history is append-only: there is no patch
652
725
  * and no delete, and moving a customer to a different plan is the same call as
@@ -752,6 +825,8 @@ declare class Customers$1 {
752
825
  readonly plan: CustomerPlan$1;
753
826
  /** Grants, which sit on top of whatever the plan gives. */
754
827
  readonly allowances: CustomerAllowances$1;
828
+ /** Periods that have ended, with the figures to bill them from. */
829
+ readonly periods: CustomerPeriods$1;
755
830
  constructor(client: Client);
756
831
  create(params: CustomerCreateParams, options?: RequestOptions): Promise<Customer>;
757
832
  /** Lean: a listing does not embed the plan. Read one customer for that. */
@@ -892,6 +967,17 @@ declare class ReservationMismatchError extends InvalidRequestError {
892
967
  */
893
968
  declare class CycleChangeRequiresResetError extends InvalidRequestError {
894
969
  }
970
+ /**
971
+ * `409 period_settling`: the period ended under a minute ago and may still be
972
+ * taking writes. Read again after `retryAfter`; the SDK never retries it.
973
+ */
974
+ declare class PeriodSettlingError extends ConflictError {
975
+ /** Seconds until the period is final, from `Retry-After`. */
976
+ readonly retryAfter: number | undefined;
977
+ constructor(args: ConstructorParameters<typeof APIError>[0] & {
978
+ retryAfter?: number | undefined;
979
+ });
980
+ }
895
981
  declare class RateLimitError extends APIError {
896
982
  /** Seconds to wait, from `Retry-After`, when the engine sends one. */
897
983
  readonly retryAfter: number | undefined;
@@ -992,14 +1078,17 @@ declare class Meterbase {
992
1078
  * to cover the quantity, and every rate-limit window in force has to admit
993
1079
  * it. `reason` names the one that said no. `rate_limits` reports each window
994
1080
  * whether or not it refused, so a caller can ease off as its headroom closes
995
- * instead of discovering the ceiling by hitting it.
1081
+ * instead of discovering the ceiling by hitting it. Under a soft cap
1082
+ * (`allow_overage`) the capacity admits any quantity, so only a window can
1083
+ * refuse.
996
1084
  */
997
1085
  check(params: CheckParams, options?: RequestOptions): Promise<CheckResult>;
998
1086
  /**
999
1087
  * Records usage that already happened — the tokens were spent, the image
1000
1088
  * was generated — so it never refuses on capacity. A quantity beyond the
1001
1089
  * customer's capacity is recorded, drives `available` to 0, and the next
1002
- * `check` says no. The answer is a receipt, not a verdict.
1090
+ * `check` says no, unless the plan's cap is soft. The answer is a receipt,
1091
+ * not a verdict.
1003
1092
  *
1004
1093
  * `idempotency_key` is a UUIDv7, generated when omitted, so retrying this
1005
1094
  * call — the SDK's own retries included — replays the original rather than
@@ -1039,10 +1128,11 @@ declare class Meterbase {
1039
1128
  * runtime binding the bundle never has.
1040
1129
  */
1041
1130
  type CustomerAllowances = InstanceType<typeof CustomerAllowances$1>;
1131
+ type CustomerPeriods = InstanceType<typeof CustomerPeriods$1>;
1042
1132
  type CustomerPlan = InstanceType<typeof CustomerPlan$1>;
1043
1133
  type Customers = InstanceType<typeof Customers$1>;
1044
1134
  type Meters = InstanceType<typeof Meters$1>;
1045
1135
  type PlanAllowances = InstanceType<typeof PlanAllowances$1>;
1046
1136
  type Plans = InstanceType<typeof Plans$1>;
1047
1137
 
1048
- export { APIError, type Allowance, type AllowanceGrantParams, type AllowanceListParams, type AllowanceSource, type ApplyMode, type AssignPlanParams, type Assignment, AuthenticationError, type CheckParams, type CheckRateLimit, type CheckReason, type CheckResult, ConflictError, ConnectionError, type Customer, type CustomerAllowances, type CustomerCreateParams, type CustomerEntitlement, type CustomerListParams, type CustomerPlan, type CustomerUpdateParams, type CustomerUsage, type CustomerUsageParams, type CustomerWithPlan, type Customers, CycleChangeRequiresResetError, type DayUsage, type EmbeddedPlan, type EntitlementReachedEvent, type EntitlementState, type Hold, InvalidIdempotencyKeyError, InvalidRequestError, type List, type Meter, type MeterCreateParams, type MeterEntitlement, type MeterListParams, type MeterUpdateParams, type MeterUsage, type MeterUsageHistory, Meterbase, MeterbaseError, type MeterbaseOptions, type Meters, NotFoundError, PermissionDeniedError, type Plan, type PlanAllowance, type PlanAllowanceKind, type PlanAllowanceListParams, type PlanAllowanceSetParams, type PlanAllowances, type PlanChangeNowParams, type PlanChangeParams, type PlanCreateParams, type PlanCycle, type PlanListParams, type PlanMoveParams, type PlanUpdateParams, type Plans, RateLimitError, type Reconciliation, type RecordedReconciliation, type ReleaseParams, type ReleaseResult, type RequestOptions, ReservationMismatchError, type ReserveParams, type ReserveRefused, type ReserveResponse, type ReserveResult, ServerError, type ThresholdCrossedEvent, type ThresholdCrossing, TimeoutError, TooLateError, type TrackParams, type TrackResult, type UsageDaysParams, type UsageEvent, type UsagePeriod, type UsagePeriodParams, type Validity, type VerifyWebhookParams, type WebhookEvent, type WebhookHeaders, WebhookVerificationError, type WhoAmI, errorFromResponse, verifyWebhook };
1138
+ export { APIError, type Allowance, type AllowanceGrantParams, type AllowanceListParams, type AllowanceSource, type ApplyMode, type AssignPlanParams, type Assignment, AuthenticationError, type CheckParams, type CheckRateLimit, type CheckReason, type CheckResult, type ClosedPeriod, type ClosedPeriodMeter, type ClosedPeriodParams, ConflictError, ConnectionError, type Customer, type CustomerAllowances, type CustomerCreateParams, type CustomerEntitlement, type CustomerListParams, type CustomerPeriods, type CustomerPlan, type CustomerUpdateParams, type CustomerUsage, type CustomerUsageParams, type CustomerWithPlan, type Customers, CycleChangeRequiresResetError, type DayUsage, type EmbeddedPlan, type EntitlementReachedEvent, type EntitlementState, type Hold, InvalidIdempotencyKeyError, InvalidRequestError, type List, type Meter, type MeterCreateParams, type MeterEntitlement, type MeterListParams, type MeterUpdateParams, type MeterUsage, type MeterUsageHistory, Meterbase, MeterbaseError, type MeterbaseOptions, type Meters, NotFoundError, PeriodSettlingError, PermissionDeniedError, type Plan, type PlanAllowance, type PlanAllowanceKind, type PlanAllowanceListParams, type PlanAllowanceSetParams, type PlanAllowances, type PlanChangeNowParams, type PlanChangeParams, type PlanCreateParams, type PlanCycle, type PlanListParams, type PlanMoveParams, type PlanUpdateParams, type Plans, RateLimitError, type Reconciliation, type RecordedReconciliation, type ReleaseParams, type ReleaseResult, type RequestOptions, ReservationMismatchError, type ReserveParams, type ReserveRefused, type ReserveResponse, type ReserveResult, ServerError, type ThresholdCrossedEvent, type ThresholdCrossing, TimeoutError, TooLateError, type TrackParams, type TrackResult, type UsageDaysParams, type UsageEvent, type UsagePeriod, type UsagePeriodParams, type Validity, type VerifyWebhookParams, type WebhookEvent, type WebhookHeaders, WebhookVerificationError, type WhoAmI, errorFromResponse, verifyWebhook };
package/dist/index.js CHANGED
@@ -43,6 +43,14 @@ var ReservationMismatchError = class extends InvalidRequestError {
43
43
  };
44
44
  var CycleChangeRequiresResetError = class extends InvalidRequestError {
45
45
  };
46
+ var PeriodSettlingError = class extends ConflictError {
47
+ /** Seconds until the period is final, from `Retry-After`. */
48
+ retryAfter;
49
+ constructor(args) {
50
+ super(args);
51
+ this.retryAfter = args.retryAfter;
52
+ }
53
+ };
46
54
  var RateLimitError = class extends APIError {
47
55
  /** Seconds to wait, from `Retry-After`, when the engine sends one. */
48
56
  retryAfter;
@@ -59,6 +67,14 @@ var TimeoutError = class extends ConnectionError {
59
67
  };
60
68
  function errorFromResponse(args) {
61
69
  switch (args.status) {
70
+ case 400:
71
+ switch (args.code) {
72
+ // A parameter that failed validation, as a 422 is a field that did.
73
+ case "invalid_query":
74
+ return new InvalidRequestError(args);
75
+ default:
76
+ return new APIError(args);
77
+ }
62
78
  case 401:
63
79
  return new AuthenticationError(args);
64
80
  case 403:
@@ -66,7 +82,12 @@ function errorFromResponse(args) {
66
82
  case 404:
67
83
  return new NotFoundError(args);
68
84
  case 409:
69
- return new ConflictError(args);
85
+ switch (args.code) {
86
+ case "period_settling":
87
+ return new PeriodSettlingError(args);
88
+ default:
89
+ return new ConflictError(args);
90
+ }
70
91
  case 422:
71
92
  switch (args.code) {
72
93
  case "cycle_change_requires_reset":
@@ -317,6 +338,35 @@ var CustomerAllowances = class {
317
338
  }
318
339
  };
319
340
 
341
+ // src/resources/customer-periods.ts
342
+ var CustomerPeriods = class {
343
+ #client;
344
+ constructor(client) {
345
+ this.#client = client;
346
+ }
347
+ /**
348
+ * The newest period that has ended, or that ended at or before `before`;
349
+ * `null` when there is none. Walk back by passing each period's `from` as
350
+ * `before`, exactly as it came. Throws `PeriodSettlingError` for a minute
351
+ * after a period ends.
352
+ */
353
+ async last(id, params = {}, options) {
354
+ try {
355
+ return await this.#client.request({
356
+ ...options,
357
+ method: "GET",
358
+ path: `/v1/customers/${encodeURIComponent(id)}/periods/last`,
359
+ query: { before: params.before }
360
+ });
361
+ } catch (error) {
362
+ if (error instanceof NotFoundError && (error.code === "no_plan_assigned" || error.code === "no_previous_period")) {
363
+ return null;
364
+ }
365
+ throw error;
366
+ }
367
+ }
368
+ };
369
+
320
370
  // src/resources/customer-plan.ts
321
371
  var CustomerPlan = class {
322
372
  #client;
@@ -475,11 +525,14 @@ var Customers = class {
475
525
  plan;
476
526
  /** Grants, which sit on top of whatever the plan gives. */
477
527
  allowances;
528
+ /** Periods that have ended, with the figures to bill them from. */
529
+ periods;
478
530
  #client;
479
531
  constructor(client) {
480
532
  this.#client = client;
481
533
  this.plan = new CustomerPlan(client);
482
534
  this.allowances = new CustomerAllowances(client);
535
+ this.periods = new CustomerPeriods(client);
483
536
  }
484
537
  create(params, options) {
485
538
  return this.#client.request({
@@ -806,7 +859,9 @@ var Meterbase = class {
806
859
  * to cover the quantity, and every rate-limit window in force has to admit
807
860
  * it. `reason` names the one that said no. `rate_limits` reports each window
808
861
  * whether or not it refused, so a caller can ease off as its headroom closes
809
- * instead of discovering the ceiling by hitting it.
862
+ * instead of discovering the ceiling by hitting it. Under a soft cap
863
+ * (`allow_overage`) the capacity admits any quantity, so only a window can
864
+ * refuse.
810
865
  */
811
866
  check(params, options) {
812
867
  return this.#client.request({
@@ -820,7 +875,8 @@ var Meterbase = class {
820
875
  * Records usage that already happened — the tokens were spent, the image
821
876
  * was generated — so it never refuses on capacity. A quantity beyond the
822
877
  * customer's capacity is recorded, drives `available` to 0, and the next
823
- * `check` says no. The answer is a receipt, not a verdict.
878
+ * `check` says no, unless the plan's cap is soft. The answer is a receipt,
879
+ * not a verdict.
824
880
  *
825
881
  * `idempotency_key` is a UUIDv7, generated when omitted, so retrying this
826
882
  * call — the SDK's own retries included — replays the original rather than
@@ -1002,6 +1058,6 @@ function idempotencyKey(atMs) {
1002
1058
  ].join("-");
1003
1059
  }
1004
1060
 
1005
- export { APIError, AuthenticationError, ConflictError, ConnectionError, CycleChangeRequiresResetError, InvalidIdempotencyKeyError, InvalidRequestError, Meterbase, MeterbaseError, NotFoundError, PermissionDeniedError, RateLimitError, ReservationMismatchError, ServerError, TimeoutError, TooLateError, WebhookVerificationError, errorFromResponse, verifyWebhook };
1061
+ export { APIError, AuthenticationError, ConflictError, ConnectionError, CycleChangeRequiresResetError, InvalidIdempotencyKeyError, InvalidRequestError, Meterbase, MeterbaseError, NotFoundError, PeriodSettlingError, PermissionDeniedError, RateLimitError, ReservationMismatchError, ServerError, TimeoutError, TooLateError, WebhookVerificationError, errorFromResponse, verifyWebhook };
1006
1062
  //# sourceMappingURL=index.js.map
1007
1063
  //# sourceMappingURL=index.js.map