@clocknext/sdk 0.10.0 → 0.12.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/README.md +518 -264
- package/dist/index.cjs +257 -138
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +221 -56
- package/dist/index.d.ts +221 -56
- package/dist/index.js +257 -139
- package/dist/index.js.map +1 -1
- package/examples/node-basic.ts +93 -0
- package/examples/serverless-flush.ts +47 -0
- package/package.json +3 -1
- package/src/client.ts +107 -0
- package/src/config.ts +112 -0
- package/src/errors.ts +215 -0
- package/src/filters.ts +33 -0
- package/src/flusher.ts +144 -0
- package/src/http.ts +178 -0
- package/src/idempotency.ts +33 -0
- package/src/index.ts +165 -0
- package/src/queue.ts +48 -0
- package/src/resources/composites.ts +47 -0
- package/src/resources/credits.ts +76 -0
- package/src/resources/customers.ts +298 -0
- package/src/resources/invoices.ts +51 -0
- package/src/resources/outcomes.ts +82 -0
- package/src/resources/payments.ts +30 -0
- package/src/resources/plans.ts +76 -0
- package/src/resources/portal.ts +31 -0
- package/src/resources/purchases.ts +75 -0
- package/src/resources/signals.ts +386 -0
- package/src/resources/units.ts +76 -0
- package/src/resources/webhooks.ts +37 -0
- package/src/resources/workspace.ts +33 -0
- package/src/retry.ts +56 -0
- package/src/types.ts +1599 -0
package/dist/index.d.ts
CHANGED
|
@@ -139,6 +139,11 @@ interface OutcomeSignal extends SignalBase {
|
|
|
139
139
|
* Set `true` on the LAST step signal to declare the run finished — completion
|
|
140
140
|
* is never inferred from step coverage. Sending it twice is a safe no-op and
|
|
141
141
|
* can't bill again.
|
|
142
|
+
*
|
|
143
|
+
* This closes the RUN only. If the signal also carries a `composite`, that
|
|
144
|
+
* occurrence stays open and unbilled until you call
|
|
145
|
+
* `signals.completeComposite()` — the two completions are separate, and
|
|
146
|
+
* neither implies the other.
|
|
142
147
|
*/
|
|
143
148
|
complete?: boolean;
|
|
144
149
|
/** Optional composite this signal belongs to. See {@link CompositeTag}. */
|
|
@@ -176,7 +181,7 @@ interface SerializedOutcomeAttribution {
|
|
|
176
181
|
/** The customer's remaining balance for the dimension a signal metered, AFTER
|
|
177
182
|
* the signal was applied — update an on-screen meter straight from the record
|
|
178
183
|
* response. Populated on recorded (inline / `{ wait: true }`) signals; `null`
|
|
179
|
-
* on
|
|
184
|
+
* on read-back. */
|
|
180
185
|
interface UsageBalance {
|
|
181
186
|
dimension: "credit" | "outcome" | "wallet";
|
|
182
187
|
/** Post-signal remaining. `null` when the meter is uncapped — an ARREAR
|
|
@@ -203,7 +208,7 @@ interface SerializedUsageLog {
|
|
|
203
208
|
status: SignalStatus;
|
|
204
209
|
appliedRules: SerializedRuleApplication[];
|
|
205
210
|
outcome: SerializedOutcomeAttribution | null;
|
|
206
|
-
/** Post-signal balance for the metered dimension. Null on
|
|
211
|
+
/** Post-signal balance for the metered dimension. Null on
|
|
207
212
|
* read-back. */
|
|
208
213
|
balance: UsageBalance | null;
|
|
209
214
|
createdAt: string;
|
|
@@ -228,9 +233,44 @@ interface SerializedUsageLog {
|
|
|
228
233
|
* When the server has no queue configured it prices inline instead and returns
|
|
229
234
|
* `queued: false` with a populated `usageLog`, validating synchronously.
|
|
230
235
|
*/
|
|
236
|
+
/**
|
|
237
|
+
* How far a metering call actually got. See {@link TrackResult.status} — the
|
|
238
|
+
* three states differ in whether the signal can still be lost, and in whether
|
|
239
|
+
* it has been billed.
|
|
240
|
+
*/
|
|
241
|
+
type SignalDelivery = "buffered" | "accepted" | "recorded" | "dropped";
|
|
231
242
|
interface TrackResult {
|
|
232
|
-
/**
|
|
233
|
-
*
|
|
243
|
+
/**
|
|
244
|
+
* How far this signal has actually got. Branch on this, not on `queued`.
|
|
245
|
+
*
|
|
246
|
+
* `"buffered"` — held in THIS process's memory and not yet sent. Lost if
|
|
247
|
+
* the process exits first, so `flush()`/`close()` before it
|
|
248
|
+
* can. No `rawId` exists yet.
|
|
249
|
+
* `"accepted"` — the server has written it to its durable inbox (`202`)
|
|
250
|
+
* and will price it shortly. It can no longer be lost, but
|
|
251
|
+
* it is not billed yet and `usageLog` is null. A rejection
|
|
252
|
+
* discovered during pricing will NOT come back to you here —
|
|
253
|
+
* read it back with `signals.list()`.
|
|
254
|
+
* `"recorded"` — the server priced it inline and `usageLog` is populated.
|
|
255
|
+
* `"dropped"` — the SDK threw it away without sending: the client is
|
|
256
|
+
* closed, or the local queue is full. `onDrop` fired with
|
|
257
|
+
* the reason. This state exists because the alternative was
|
|
258
|
+
* reporting `"buffered"` for a signal that was discarded —
|
|
259
|
+
* a success-shaped answer to a lost billable event.
|
|
260
|
+
*
|
|
261
|
+
* Note what none of these mean: "waited for a price". Even `{ wait: true }`
|
|
262
|
+
* waits only for the server to ACCEPT the signal, never for it to finish
|
|
263
|
+
* pricing — holding a request thread open for a billing round-trip is
|
|
264
|
+
* exactly the cost this design exists to avoid.
|
|
265
|
+
*/
|
|
266
|
+
status: SignalDelivery;
|
|
267
|
+
/**
|
|
268
|
+
* True for both `"buffered"` and `"accepted"` — i.e. "not priced yet".
|
|
269
|
+
*
|
|
270
|
+
* Kept for compatibility, but it collapses two states with opposite failure
|
|
271
|
+
* behaviour (one is lost when the process dies, the other cannot be) into
|
|
272
|
+
* one boolean, which is why {@link TrackResult.status} exists. Prefer that.
|
|
273
|
+
*/
|
|
234
274
|
queued: boolean;
|
|
235
275
|
/** The computed usage log. Non-null ONLY when the server priced the signal
|
|
236
276
|
* inline (`queued: false`); null on a `202` hand-off and absent while the
|
|
@@ -416,7 +456,15 @@ type BillingCycle = "MONTHLY" | "QUARTERLY" | "SEMI_ANNUAL" | "YEARLY" | "EVERY_
|
|
|
416
456
|
type PlanType = "WALLET" | "BUNDLE";
|
|
417
457
|
type PlanKind = "FLAT_PRICE" | "PAY_AS_YOU_GO" | "PAY_PER_SEAT";
|
|
418
458
|
/** A plan component's meter type. */
|
|
419
|
-
|
|
459
|
+
/**
|
|
460
|
+
* A plan component's kind.
|
|
461
|
+
*
|
|
462
|
+
* `PRICING_METRIC` is a COMPOSITE component — the server's wire name for it,
|
|
463
|
+
* kept verbatim because that is the string you will actually receive and must
|
|
464
|
+
* send back. It was missing here, which made a `switch` over `PlanComponent.type`
|
|
465
|
+
* look exhaustive to TypeScript while silently skipping every composite.
|
|
466
|
+
*/
|
|
467
|
+
type ComponentType = "WALLET" | "CREDIT" | "OUTCOME" | "UNIT" | "FLAT" | "PRICING_METRIC";
|
|
420
468
|
/** ADVANCE bills up-front for the cycle; ARREAR bills for what was consumed. */
|
|
421
469
|
type BillingMode = "ADVANCE" | "ARREAR";
|
|
422
470
|
/** Prepaid USD wallet. `amount` is the funded balance (required). Max one
|
|
@@ -536,6 +584,11 @@ interface PlanComponent {
|
|
|
536
584
|
creditId: string | null;
|
|
537
585
|
outcomeId: string | null;
|
|
538
586
|
unitId: string | null;
|
|
587
|
+
/** The composite this component sells, on a `PRICING_METRIC` component.
|
|
588
|
+
* Without it a plan read back could not be written back: the write shape
|
|
589
|
+
* ({@link CompositeComponentInput}) requires this id, so a read-modify-write
|
|
590
|
+
* silently dropped every composite component. */
|
|
591
|
+
pricingMetricId: string | null;
|
|
539
592
|
targetName: string | null;
|
|
540
593
|
quantity: number | null;
|
|
541
594
|
amount: number | null;
|
|
@@ -550,6 +603,9 @@ interface Plan {
|
|
|
550
603
|
cost: number;
|
|
551
604
|
/** Signed adjustment applied to the plan's headline price (default 0). */
|
|
552
605
|
priceAdjustment: number;
|
|
606
|
+
/** When true, ARREAR consumption is funded from the customer's wallet as it
|
|
607
|
+
* happens instead of being invoiced at cycle end. All-or-nothing per plan. */
|
|
608
|
+
walletFundedArrear: boolean;
|
|
553
609
|
currencyCode: string;
|
|
554
610
|
isActive: boolean;
|
|
555
611
|
components: PlanComponent[];
|
|
@@ -591,6 +647,8 @@ interface Purchase {
|
|
|
591
647
|
hasCredit: boolean;
|
|
592
648
|
hasOutcome: boolean;
|
|
593
649
|
hasUnit: boolean;
|
|
650
|
+
/** True when the purchased plan sells at least one composite. */
|
|
651
|
+
hasComposite: boolean;
|
|
594
652
|
billingCycle: BillingCycle;
|
|
595
653
|
cost: number;
|
|
596
654
|
currencyCode: string;
|
|
@@ -798,9 +856,16 @@ interface UpdateMemberInput {
|
|
|
798
856
|
email?: string;
|
|
799
857
|
}
|
|
800
858
|
type WalletTransactionType = "CREDIT" | "DEBIT";
|
|
859
|
+
/** What produced a wallet entry. `null` on rows written before the column
|
|
860
|
+
* existed. */
|
|
861
|
+
type WalletTransactionSource = "TOPUP" | "USAGE" | "SETTLE" | "ADJUSTMENT";
|
|
862
|
+
/** The entitlement kinds a wallet-funded metering debit can name. */
|
|
863
|
+
type WalletEntitlementKind = "CREDIT" | "OUTCOME" | "UNIT";
|
|
801
864
|
interface WalletTransaction {
|
|
802
865
|
id: string;
|
|
803
866
|
type: WalletTransactionType;
|
|
867
|
+
/** What produced the entry. Null on rows older than the column. */
|
|
868
|
+
source: WalletTransactionSource | null;
|
|
804
869
|
amount: number;
|
|
805
870
|
amountUsd: number;
|
|
806
871
|
currencyCode: string;
|
|
@@ -809,6 +874,19 @@ interface WalletTransaction {
|
|
|
809
874
|
batchId: string | null;
|
|
810
875
|
createdAt: string;
|
|
811
876
|
createdByName: string | null;
|
|
877
|
+
/** Set only on a wallet-funded metering debit: which kind of entitlement was
|
|
878
|
+
* consumed. Null on top-ups and manual adjustments. */
|
|
879
|
+
entitlementType: WalletEntitlementKind | null;
|
|
880
|
+
/** Id of the credit / outcome / unit consumed. Null unless
|
|
881
|
+
* `entitlementType` is set. */
|
|
882
|
+
targetId: string | null;
|
|
883
|
+
/** Its name at the time of the debit. */
|
|
884
|
+
targetName: string | null;
|
|
885
|
+
/** The signal this debit paid for (credit / outcome). In wallet-funded mode
|
|
886
|
+
* no invoice exists, so this is the only trail from a charge to its cause. */
|
|
887
|
+
usageLogId: string | null;
|
|
888
|
+
/** The unit event this debit paid for. */
|
|
889
|
+
unitUsageLogId: string | null;
|
|
812
890
|
}
|
|
813
891
|
interface WalletList {
|
|
814
892
|
balanceUsd: number;
|
|
@@ -959,14 +1037,14 @@ interface Outcome {
|
|
|
959
1037
|
isActive: boolean;
|
|
960
1038
|
marginPercent: number;
|
|
961
1039
|
pricePerOutcome: number;
|
|
962
|
-
createdAt: string;
|
|
963
|
-
steps?: {
|
|
964
|
-
name: string;
|
|
965
|
-
agentKey: string;
|
|
966
|
-
}[];
|
|
967
1040
|
}
|
|
968
1041
|
/** `outcomes.get()` — adds steps plus in-flight/completed stats. */
|
|
969
1042
|
interface OutcomeDetail extends Outcome {
|
|
1043
|
+
/** Only the DETAIL row carries these — `outcomes.list()` returns neither.
|
|
1044
|
+
* They were previously declared on {@link Outcome} itself, where
|
|
1045
|
+
* `createdAt` was typed as a required `string` that is always `undefined`
|
|
1046
|
+
* in practice. */
|
|
1047
|
+
createdAt: string;
|
|
970
1048
|
createdByName: string | null;
|
|
971
1049
|
steps: {
|
|
972
1050
|
name: string;
|
|
@@ -1130,7 +1208,11 @@ interface UnitInput {
|
|
|
1130
1208
|
* a bare `{ unitUsage }`. Branch on `queued`; never assume `unitUsage`.
|
|
1131
1209
|
*/
|
|
1132
1210
|
interface UnitTrackResult {
|
|
1133
|
-
/**
|
|
1211
|
+
/** How far the report got. Never `"buffered"` — unit reports are always sent
|
|
1212
|
+
* immediately, not queued client-side. See {@link TrackResult.status}. */
|
|
1213
|
+
status: Extract<SignalDelivery, "accepted" | "recorded">;
|
|
1214
|
+
/** True when the report was accepted but not yet priced (`202`). Prefer
|
|
1215
|
+
* {@link UnitTrackResult.status}. */
|
|
1134
1216
|
queued: boolean;
|
|
1135
1217
|
/** The priced unit event. Non-null ONLY when the server priced inline. */
|
|
1136
1218
|
unitUsage?: SerializedUnitUsage | null;
|
|
@@ -1227,10 +1309,16 @@ interface CreateCompositeInput {
|
|
|
1227
1309
|
* lands. That case answers with no `status`, only a `rawId` to follow.
|
|
1228
1310
|
*/
|
|
1229
1311
|
interface CompositeCompletionResult {
|
|
1230
|
-
/**
|
|
1312
|
+
/** How far the ping got. Never `"buffered"` — completions are always sent
|
|
1313
|
+
* immediately. `"recorded"` means the occurrence was closed inline. See
|
|
1314
|
+
* {@link TrackResult.status}. */
|
|
1315
|
+
delivery: Extract<SignalDelivery, "accepted" | "recorded">;
|
|
1316
|
+
/** True when the ping was accepted but not yet applied (`202`). Prefer
|
|
1317
|
+
* {@link CompositeCompletionResult.delivery}. */
|
|
1231
1318
|
queued: boolean;
|
|
1232
1319
|
/** `COMPLETED` on the first close, `ALREADY_COMPLETED` on a replay. Absent
|
|
1233
|
-
* when the ping was queued or parked.
|
|
1320
|
+
* when the ping was queued or parked. Distinct from `delivery`: this is the
|
|
1321
|
+
* server's verdict on the OCCURRENCE, that is how far the REQUEST got. */
|
|
1234
1322
|
status?: "COMPLETED" | "ALREADY_COMPLETED";
|
|
1235
1323
|
/** The composite that was closed. Null on the replay of a historical row
|
|
1236
1324
|
* whose occurrence can no longer be read back. */
|
|
@@ -1281,10 +1369,14 @@ interface UnitUsageList {
|
|
|
1281
1369
|
}
|
|
1282
1370
|
type ThresholdKind = "CREDIT" | "OUTCOME" | "WALLET";
|
|
1283
1371
|
interface Webhook {
|
|
1372
|
+
id: string;
|
|
1284
1373
|
kind: ThresholdKind;
|
|
1285
1374
|
threshold: number;
|
|
1286
1375
|
url: string;
|
|
1287
1376
|
isActive: boolean;
|
|
1377
|
+
createdAt: string;
|
|
1378
|
+
updatedAt: string;
|
|
1379
|
+
createdByName: string | null;
|
|
1288
1380
|
}
|
|
1289
1381
|
interface UpsertWebhookInput {
|
|
1290
1382
|
kind: ThresholdKind;
|
|
@@ -1300,7 +1392,16 @@ interface Logger {
|
|
|
1300
1392
|
warn?: (...args: unknown[]) => void;
|
|
1301
1393
|
error?: (...args: unknown[]) => void;
|
|
1302
1394
|
}
|
|
1303
|
-
|
|
1395
|
+
/**
|
|
1396
|
+
* Why a signal was dropped without being billed.
|
|
1397
|
+
*
|
|
1398
|
+
* `queue_full` — the local buffer hit `batch.maxQueueSize`; never sent.
|
|
1399
|
+
* `closed` — tracked after `close()`; never sent.
|
|
1400
|
+
* `send_failed` — sent, and permanently rejected or unreachable. This is the
|
|
1401
|
+
* only reason that also fires `onError`, which carries the
|
|
1402
|
+
* error (and its `idempotencyKey`, for a safe replay).
|
|
1403
|
+
*/
|
|
1404
|
+
type DropReason = "queue_full" | "closed" | "send_failed";
|
|
1304
1405
|
interface ClockNextConfig {
|
|
1305
1406
|
/** The org API key (`cnk_…`). Required. */
|
|
1306
1407
|
apiKey: string;
|
|
@@ -1391,6 +1492,15 @@ interface RequestOptions {
|
|
|
1391
1492
|
* opt in explicitly.
|
|
1392
1493
|
*/
|
|
1393
1494
|
retry?: boolean;
|
|
1495
|
+
/**
|
|
1496
|
+
* The idempotency key carried in this request's body, for metering calls.
|
|
1497
|
+
*
|
|
1498
|
+
* Copied onto any error thrown, so a caller handling a permanent failure can
|
|
1499
|
+
* replay the signal with the SAME key instead of minting a fresh one — which
|
|
1500
|
+
* would defeat server-side dedup and bill twice. See
|
|
1501
|
+
* `ClockNextError.idempotencyKey`.
|
|
1502
|
+
*/
|
|
1503
|
+
idempotencyKey?: string;
|
|
1394
1504
|
}
|
|
1395
1505
|
/**
|
|
1396
1506
|
* The single HTTP seam. Builds the authenticated request, enforces a timeout,
|
|
@@ -1428,7 +1538,9 @@ declare class Composites {
|
|
|
1428
1538
|
constructor(transport: Transport);
|
|
1429
1539
|
/** List composites. Pass `{ active: true }` for only the ones a signal can
|
|
1430
1540
|
* still be tagged with — the default list INCLUDES archived ones, which
|
|
1431
|
-
* keep every row they already own.
|
|
1541
|
+
* keep every row they already own.
|
|
1542
|
+
* `{ active: false }` returns only archived ones; omitting it returns
|
|
1543
|
+
* both. See `activeQuery` — the API itself only supports `true`. */
|
|
1432
1544
|
list(params?: {
|
|
1433
1545
|
active?: boolean;
|
|
1434
1546
|
}): Promise<Composite[]>;
|
|
@@ -1444,7 +1556,9 @@ declare class Composites {
|
|
|
1444
1556
|
declare class Credits {
|
|
1445
1557
|
private readonly transport;
|
|
1446
1558
|
constructor(transport: Transport);
|
|
1447
|
-
/** List credit types. Pass `{ active: true }` to only return active ones.
|
|
1559
|
+
/** List credit types. Pass `{ active: true }` to only return active ones.
|
|
1560
|
+
* `{ active: false }` returns only archived ones; omitting it returns
|
|
1561
|
+
* both. See `activeQuery` — the API itself only supports `true`. */
|
|
1448
1562
|
list(params?: {
|
|
1449
1563
|
active?: boolean;
|
|
1450
1564
|
}): Promise<Credit[]>;
|
|
@@ -1593,7 +1707,9 @@ declare class Invoices {
|
|
|
1593
1707
|
declare class Outcomes {
|
|
1594
1708
|
private readonly transport;
|
|
1595
1709
|
constructor(transport: Transport);
|
|
1596
|
-
/** List outcome types. Pass `{ active: true }` to only return active ones.
|
|
1710
|
+
/** List outcome types. Pass `{ active: true }` to only return active ones.
|
|
1711
|
+
* `{ active: false }` returns only archived ones; omitting it returns
|
|
1712
|
+
* both. See `activeQuery` — the API itself only supports `true`. */
|
|
1597
1713
|
list(params?: {
|
|
1598
1714
|
active?: boolean;
|
|
1599
1715
|
}): Promise<Outcome[]>;
|
|
@@ -1633,7 +1749,9 @@ declare class Payments {
|
|
|
1633
1749
|
declare class Plans {
|
|
1634
1750
|
private readonly transport;
|
|
1635
1751
|
constructor(transport: Transport);
|
|
1636
|
-
/** List plans, oldest-first. Pass `{ active: true }` to only return active plans.
|
|
1752
|
+
/** List plans, oldest-first. Pass `{ active: true }` to only return active plans.
|
|
1753
|
+
* `{ active: false }` returns only archived ones; omitting it returns
|
|
1754
|
+
* both. See `activeQuery` — the API itself only supports `true`. */
|
|
1637
1755
|
list(params?: {
|
|
1638
1756
|
active?: boolean;
|
|
1639
1757
|
}): Promise<Plan[]>;
|
|
@@ -1725,13 +1843,30 @@ declare class Flusher {
|
|
|
1725
1843
|
private draining;
|
|
1726
1844
|
private closed;
|
|
1727
1845
|
constructor(transport: Transport, cfg: ResolvedConfig);
|
|
1728
|
-
/**
|
|
1729
|
-
|
|
1846
|
+
/**
|
|
1847
|
+
* Buffer one signal. Drops (with onDrop) when closed or the queue is full.
|
|
1848
|
+
* Returns whether it was actually buffered, so `track()` can report a drop
|
|
1849
|
+
* honestly instead of answering "buffered" for a signal it threw away.
|
|
1850
|
+
*/
|
|
1851
|
+
enqueue(item: QueuedSignal): boolean;
|
|
1730
1852
|
/** Arm the interval timer if it isn't already running. */
|
|
1731
1853
|
private arm;
|
|
1854
|
+
/** Cancel the interval timer if one is armed. */
|
|
1855
|
+
private clearTimer;
|
|
1732
1856
|
/**
|
|
1733
|
-
* Send everything
|
|
1734
|
-
*
|
|
1857
|
+
* Send everything buffered at the moment this resolves.
|
|
1858
|
+
*
|
|
1859
|
+
* Overlapping calls CHAIN onto the in-flight drain rather than sharing it.
|
|
1860
|
+
* Sharing looks equivalent and is not: a drain that has already passed its
|
|
1861
|
+
* final `size() > 0` check cannot see a signal enqueued a moment later, so
|
|
1862
|
+
* handing that same promise back would resolve `flush()` — and therefore
|
|
1863
|
+
* `close()` — with the buffer non-empty. Since `close()` has already set
|
|
1864
|
+
* `closed`, `arm()` will not re-arm, and the timer it did arm is `unref`'d,
|
|
1865
|
+
* so the process is free to exit and that signal is simply lost. Chaining
|
|
1866
|
+
* guarantees at least one full drain begins after this call.
|
|
1867
|
+
*
|
|
1868
|
+
* Concurrency is unaffected: drains run one after another, and each one
|
|
1869
|
+
* sends at most `maxConcurrency` signals at a time.
|
|
1735
1870
|
*/
|
|
1736
1871
|
flush(): Promise<void>;
|
|
1737
1872
|
/** Drain the buffer in concurrency-bounded waves until it's empty. */
|
|
@@ -1765,18 +1900,24 @@ declare function signalToWire(signal: Signal): Record<string, unknown>;
|
|
|
1765
1900
|
* The `signals` resource: record usage signals and read them back.
|
|
1766
1901
|
*
|
|
1767
1902
|
* In async mode (default), `track()` buffers the signal locally and returns
|
|
1768
|
-
* immediately with `{
|
|
1769
|
-
* client in `sync` mode) to await the request.
|
|
1903
|
+
* immediately with `{ status: "buffered" }`. Pass `{ wait: true }` (or
|
|
1904
|
+
* construct the client in `sync` mode) to await the request instead.
|
|
1905
|
+
*
|
|
1906
|
+
* Awaiting the request does NOT mean waiting for a price, and deliberately so.
|
|
1907
|
+
* The server writes every signal to a durable inbox and hands it to a worker,
|
|
1908
|
+
* answering `202` — so `track()` resolves `{ status: "accepted", messageId,
|
|
1909
|
+
* rawId, usageLog: null }`: impossible to lose, not yet billed. Only when the
|
|
1910
|
+
* server prices inline do you get `{ status: "recorded", usageLog }`. Branch on
|
|
1911
|
+
* `status`; never assume `usageLog`.
|
|
1770
1912
|
*
|
|
1771
|
-
*
|
|
1772
|
-
*
|
|
1773
|
-
*
|
|
1774
|
-
* null }` — accepted and impossible to lose, but not yet billed. Only when the
|
|
1775
|
-
* server prices inline do you get `{ queued: false, usageLog }`. Branch on
|
|
1776
|
-
* `queued`; never assume `usageLog`.
|
|
1913
|
+
* Nothing here ever blocks a request thread on billing. That is the point: a
|
|
1914
|
+
* meter that makes the caller wait for pricing has moved your billing system
|
|
1915
|
+
* onto your product's critical path.
|
|
1777
1916
|
*
|
|
1778
|
-
*
|
|
1779
|
-
*
|
|
1917
|
+
* Because of that, a signal the server later REJECTS (unknown `agentKey`, a
|
|
1918
|
+
* model the org has not enabled, no active plan) cannot come back through this
|
|
1919
|
+
* promise. It surfaces on the `onError` hook, and `list()` is how you confirm
|
|
1920
|
+
* one actually landed — ingestion being asynchronous, the only way to.
|
|
1780
1921
|
*/
|
|
1781
1922
|
declare class Signals {
|
|
1782
1923
|
private readonly transport;
|
|
@@ -1794,17 +1935,6 @@ declare class Signals {
|
|
|
1794
1935
|
track(signal: Signal, opts?: {
|
|
1795
1936
|
wait?: boolean;
|
|
1796
1937
|
}): Promise<TrackResult>;
|
|
1797
|
-
/**
|
|
1798
|
-
* Validate + price a signal WITHOUT recording it (server `dryRun`). Returns
|
|
1799
|
-
* the projected usage log so an integration can preflight before sending real
|
|
1800
|
-
* traffic — no inbox row, wallet / outcome writes, or webhooks fire.
|
|
1801
|
-
*
|
|
1802
|
-
* Only the model-priced kinds support this. A dry run is not offered for unit
|
|
1803
|
-
* reports or composite completions, and the server REJECTS the flag on those
|
|
1804
|
-
* routes rather than accepting and ignoring it — which is why there is no
|
|
1805
|
-
* dry-run path through `unit()` or `completeComposite()`.
|
|
1806
|
-
*/
|
|
1807
|
-
verify(signal: Signal): Promise<SerializedUsageLog | null>;
|
|
1808
1938
|
/** Meter a named credit. `POST /api/v1/signal/credit`. */
|
|
1809
1939
|
credit(input: CreditInput, opts?: {
|
|
1810
1940
|
wait?: boolean;
|
|
@@ -1854,9 +1984,13 @@ declare class Signals {
|
|
|
1854
1984
|
* arrive in any order and the occurrence stays open and unbilled until you
|
|
1855
1985
|
* say otherwise. Put it on the line before your own `return`.
|
|
1856
1986
|
*
|
|
1857
|
-
*
|
|
1858
|
-
*
|
|
1859
|
-
*
|
|
1987
|
+
* EVERY composite needs this, outcome-backed ones included. An outcome's own
|
|
1988
|
+
* `complete: true` closes its RUN and nothing else — it does not close the
|
|
1989
|
+
* composite occurrence the run was tagged into, whatever mix of credits,
|
|
1990
|
+
* outcomes and units that composite wraps. (Earlier versions of this SDK
|
|
1991
|
+
* documented the opposite. Believing it means the occurrence stays ONGOING
|
|
1992
|
+
* forever and is never billed, so if you tag outcome signals with a
|
|
1993
|
+
* `composite`, you must still call this.)
|
|
1860
1994
|
*
|
|
1861
1995
|
* Closing twice is safe: the second call answers `ALREADY_COMPLETED` and
|
|
1862
1996
|
* cannot bill again. Calling it EARLY is also safe — before every entitlement
|
|
@@ -1885,7 +2019,9 @@ declare class Signals {
|
|
|
1885
2019
|
declare class Units {
|
|
1886
2020
|
private readonly transport;
|
|
1887
2021
|
constructor(transport: Transport);
|
|
1888
|
-
/** List unit types. Pass `{ active: true }` to only return active ones.
|
|
2022
|
+
/** List unit types. Pass `{ active: true }` to only return active ones.
|
|
2023
|
+
* `{ active: false }` returns only archived ones; omitting it returns
|
|
2024
|
+
* both. See `activeQuery` — the API itself only supports `true`. */
|
|
1889
2025
|
list(params?: {
|
|
1890
2026
|
active?: boolean;
|
|
1891
2027
|
}): Promise<Unit[]>;
|
|
@@ -1927,7 +2063,9 @@ declare class Workspace {
|
|
|
1927
2063
|
/** Identify the org + key behind the request, incl. `sandbox` | `live`. */
|
|
1928
2064
|
me(): Promise<WorkspaceIdentity>;
|
|
1929
2065
|
/** The org's enabled models with live prices. `{ active: true }` returns only
|
|
1930
|
-
* the models that can be metered right now.
|
|
2066
|
+
* the models that can be metered right now.
|
|
2067
|
+
* `{ active: false }` returns only archived ones; omitting it returns
|
|
2068
|
+
* both. See `activeQuery` — the API itself only supports `true`. */
|
|
1931
2069
|
models(params?: {
|
|
1932
2070
|
active?: boolean;
|
|
1933
2071
|
}): Promise<Model[]>;
|
|
@@ -1989,24 +2127,45 @@ declare class ClockNext {
|
|
|
1989
2127
|
}
|
|
1990
2128
|
|
|
1991
2129
|
/**
|
|
1992
|
-
* Typed error hierarchy. The server returns `{
|
|
1993
|
-
* meaningful HTTP status; we map that status to a class so callers can
|
|
1994
|
-
* on the *kind* of failure (e.g. allowance exhausted ⇒ upsell; network ⇒
|
|
1995
|
-
* it's queued) rather than string-matching messages.
|
|
2130
|
+
* Typed error hierarchy. The server returns `{ statusCode, statusDetail, result }`
|
|
2131
|
+
* with a meaningful HTTP status; we map that status to a class so callers can
|
|
2132
|
+
* branch on the *kind* of failure (e.g. allowance exhausted ⇒ upsell; network ⇒
|
|
2133
|
+
* ignore, it's queued) rather than string-matching messages.
|
|
1996
2134
|
*/
|
|
2135
|
+
/** Machine-readable failure code, when the server sends one
|
|
2136
|
+
* (`statusDetail.code`). Preferred over any message heuristic. */
|
|
2137
|
+
type ClockNextErrorCode = "ALLOWANCE_EXHAUSTED" | "PLAN_REJECTED" | "IDEMPOTENCY_UNRESOLVED" | (string & {});
|
|
1997
2138
|
declare class ClockNextError extends Error {
|
|
1998
2139
|
/** HTTP status, when the failure came from a server response. */
|
|
1999
2140
|
readonly status?: number;
|
|
2000
2141
|
/** Whether the SDK considers this failure worth retrying. */
|
|
2001
2142
|
readonly retryable: boolean;
|
|
2143
|
+
/**
|
|
2144
|
+
* The server's machine-readable code, when it sent one. Branch on this in
|
|
2145
|
+
* preference to `.message`, which is human copy and may be reworded.
|
|
2146
|
+
*/
|
|
2147
|
+
readonly code?: ClockNextErrorCode;
|
|
2148
|
+
/**
|
|
2149
|
+
* The idempotency key of the request that failed, for metering calls.
|
|
2150
|
+
*
|
|
2151
|
+
* This is what makes a dead-letter retry safe: re-send the failed signal with
|
|
2152
|
+
* this SAME key and the server deduplicates it instead of billing twice. A
|
|
2153
|
+
* fresh key would double-bill, so never generate one when replaying.
|
|
2154
|
+
*/
|
|
2155
|
+
readonly idempotencyKey?: string;
|
|
2002
2156
|
constructor(message: string, opts?: {
|
|
2003
2157
|
status?: number;
|
|
2004
2158
|
retryable?: boolean;
|
|
2159
|
+
code?: ClockNextErrorCode;
|
|
2160
|
+
idempotencyKey?: string;
|
|
2005
2161
|
});
|
|
2006
2162
|
}
|
|
2007
2163
|
/** 401 — missing / invalid / expired API key. */
|
|
2008
2164
|
declare class AuthError extends ClockNextError {
|
|
2009
2165
|
}
|
|
2166
|
+
/** 403 — the key is valid but cannot perform this operation. */
|
|
2167
|
+
declare class ForbiddenError extends ClockNextError {
|
|
2168
|
+
}
|
|
2010
2169
|
/** 400 — malformed request / schema validation failure. */
|
|
2011
2170
|
declare class ValidationError extends ClockNextError {
|
|
2012
2171
|
}
|
|
@@ -2016,10 +2175,13 @@ declare class NotFoundError extends ClockNextError {
|
|
|
2016
2175
|
/** 422 — no active plan, meter not in plan, model not enabled, member missing. */
|
|
2017
2176
|
declare class PlanError extends ClockNextError {
|
|
2018
2177
|
}
|
|
2019
|
-
/** 422 —
|
|
2178
|
+
/** 422 — the entitlement ran out: no credits / units / outcomes / composite
|
|
2179
|
+
* slots left. Distinct from {@link PlanError} because the fix is different —
|
|
2180
|
+
* this one is a top-up or an upsell, not a configuration change. */
|
|
2020
2181
|
declare class AllowanceError extends ClockNextError {
|
|
2021
2182
|
}
|
|
2022
|
-
/** 409 — conflict.
|
|
2183
|
+
/** 409 — conflict. Almost always permanent (an archived customer); only the
|
|
2184
|
+
* idempotency-resolution conflict is transient, and only that one retries. */
|
|
2023
2185
|
declare class ConflictError extends ClockNextError {
|
|
2024
2186
|
}
|
|
2025
2187
|
/** 429 — rate limited. */
|
|
@@ -2027,6 +2189,7 @@ declare class RateLimitError extends ClockNextError {
|
|
|
2027
2189
|
readonly retryAfterMs?: number;
|
|
2028
2190
|
constructor(message: string, opts?: {
|
|
2029
2191
|
retryAfterMs?: number;
|
|
2192
|
+
idempotencyKey?: string;
|
|
2030
2193
|
});
|
|
2031
2194
|
}
|
|
2032
2195
|
/** 5xx — server-side error. */
|
|
@@ -2034,7 +2197,9 @@ declare class ServerError extends ClockNextError {
|
|
|
2034
2197
|
}
|
|
2035
2198
|
/** fetch threw / request timed out — request never completed. */
|
|
2036
2199
|
declare class NetworkError extends ClockNextError {
|
|
2037
|
-
constructor(message: string
|
|
2200
|
+
constructor(message: string, opts?: {
|
|
2201
|
+
idempotencyKey?: string;
|
|
2202
|
+
});
|
|
2038
2203
|
}
|
|
2039
2204
|
|
|
2040
|
-
export { type AddMemberInput, AllowanceError, type ApiCustomer, AuthError, type BillingCycle, type BillingMode, ClockNext, type ClockNextConfig, ClockNextError, type ComponentType, type Composite, type CompositeCatalogueRef, type CompositeCompletionInput, type CompositeCompletionResult, type CompositeComponentInput, type CompositeTag, ConflictError, type CostPoint, type CostStats, type CreateCompositeInput, type CreateCreditInput, type CreateCustomerInput, type CreateOutcomeInput, type CreatePlanInput, type CreatePurchaseInput, type CreateUnitInput, type Credit, type CreditAdjustInput, type CreditAnalytics, type CreditBalance, type CreditComponentInput, type CreditDetail, type CreditInput, type CreditSignal, type CustomerBalances, type CustomerList, type CustomerPlan, type CustomerPlanDetails, type CustomerProfileInput, type DropReason, type FetchLike, type FlatComponentInput, type FlatUnitInput, type Invoice, type InvoiceDetail, type InvoiceLineItem, type InvoiceListRow, type InvoiceParty, type InvoicePlanSnapshot, type InvoiceStatus, type Logger, type Member, type MemberProfile, type Model, type ModelBundleEntry, NetworkError, NotFoundError, type Outcome, type OutcomeAdjustInput, type OutcomeAnalytics, type OutcomeBalance, type OutcomeComponentInput, type OutcomeDetail, type OutcomeInput, type OutcomeSignal, type OutcomeStepInput, type PayLink, type PaymentDetail, type PaymentRow, type Plan, type PlanComponent, type PlanComponentInput, type PlanDetail, PlanError, type PlanKind, type PlanRef, type PlanType, type PortalToken, type PortalTokenInput, type Purchase, type PurchaseDetail, type PurchaseStatus, RateLimitError, type RemovedMember, type SerializedOutcomeAttribution, type SerializedRuleApplication, type SerializedUnitUsage, type SerializedUsageLog, ServerError, type Signal, type SignalStatus, type SignalType, type ThresholdKind, type TieredUnitInput, type Tokens, type TrackResult, type Unit, type UnitAdjustInput, type UnitBalance, type UnitComponentInput, type UnitCustomerRow, type UnitDetail, type UnitInput, type UnitPricingType, type UnitTier, type UnitTierInput, type UnitTrackResult, type UnitUsageList, type UnitUsageRow, type UpdateCreditInput, type UpdateMemberInput, type UpdateOutcomeInput, type UpdatePlanInput, type UpdateUnitInput, type UpsertWebhookInput, type UsageBalance, type UsageList, ValidationError, type WalletComponentInput, type WalletEntryInput, type WalletInput, type WalletList, type WalletSignal, type WalletTransaction, type WalletTransactionType, type Webhook, type WorkspaceIdentity, signalToWire };
|
|
2205
|
+
export { type AddMemberInput, AllowanceError, type ApiCustomer, AuthError, type BillingCycle, type BillingMode, ClockNext, type ClockNextConfig, ClockNextError, type ClockNextErrorCode, type ComponentType, type Composite, type CompositeCatalogueRef, type CompositeCompletionInput, type CompositeCompletionResult, type CompositeComponentInput, type CompositeTag, ConflictError, type CostPoint, type CostStats, type CreateCompositeInput, type CreateCreditInput, type CreateCustomerInput, type CreateOutcomeInput, type CreatePlanInput, type CreatePurchaseInput, type CreateUnitInput, type Credit, type CreditAdjustInput, type CreditAnalytics, type CreditBalance, type CreditComponentInput, type CreditDetail, type CreditInput, type CreditSignal, type CustomerBalances, type CustomerList, type CustomerPlan, type CustomerPlanDetails, type CustomerProfileInput, type DropReason, type FetchLike, type FlatComponentInput, type FlatUnitInput, ForbiddenError, type Invoice, type InvoiceDetail, type InvoiceLineItem, type InvoiceListRow, type InvoiceParty, type InvoicePlanSnapshot, type InvoiceStatus, type Logger, type Member, type MemberProfile, type Model, type ModelBundleEntry, NetworkError, NotFoundError, type Outcome, type OutcomeAdjustInput, type OutcomeAnalytics, type OutcomeBalance, type OutcomeComponentInput, type OutcomeDetail, type OutcomeInput, type OutcomeSignal, type OutcomeStepInput, type PayLink, type PaymentDetail, type PaymentRow, type Plan, type PlanComponent, type PlanComponentInput, type PlanDetail, PlanError, type PlanKind, type PlanRef, type PlanType, type PortalToken, type PortalTokenInput, type Purchase, type PurchaseDetail, type PurchaseStatus, RateLimitError, type RemovedMember, type SerializedOutcomeAttribution, type SerializedRuleApplication, type SerializedUnitUsage, type SerializedUsageLog, ServerError, type Signal, type SignalDelivery, type SignalStatus, type SignalType, type ThresholdKind, type TieredUnitInput, type Tokens, type TrackResult, type Unit, type UnitAdjustInput, type UnitBalance, type UnitComponentInput, type UnitCustomerRow, type UnitDetail, type UnitInput, type UnitPricingType, type UnitTier, type UnitTierInput, type UnitTrackResult, type UnitUsageList, type UnitUsageRow, type UpdateCreditInput, type UpdateMemberInput, type UpdateOutcomeInput, type UpdatePlanInput, type UpdateUnitInput, type UpsertWebhookInput, type UsageBalance, type UsageList, ValidationError, type WalletComponentInput, type WalletEntitlementKind, type WalletEntryInput, type WalletInput, type WalletList, type WalletSignal, type WalletTransaction, type WalletTransactionSource, type WalletTransactionType, type Webhook, type WorkspaceIdentity, signalToWire };
|