@clocknext/sdk 0.14.0 → 0.15.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 +200 -140
- package/dist/index.cjs +188 -445
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +295 -818
- package/dist/index.d.ts +295 -818
- package/dist/index.js +188 -445
- package/dist/index.js.map +1 -1
- package/examples/node-basic.ts +24 -32
- package/package.json +1 -1
- package/src/client.ts +3 -27
- package/src/customer-ref.ts +14 -0
- package/src/errors.ts +8 -1
- package/src/filters.ts +1 -1
- package/src/index.ts +7 -59
- package/src/resources/customers.ts +201 -82
- package/src/resources/invoices.ts +1 -1
- package/src/resources/plans.ts +4 -56
- package/src/resources/signals.ts +5 -45
- package/src/types.ts +223 -612
- package/src/resources/composites.ts +0 -47
- package/src/resources/credits.ts +0 -76
- package/src/resources/outcomes.ts +0 -82
- package/src/resources/units.ts +0 -76
- package/src/resources/webhooks.ts +0 -37
- package/src/resources/workspace.ts +0 -33
package/dist/index.cjs
CHANGED
|
@@ -77,7 +77,8 @@ function translateFieldPaths(message) {
|
|
|
77
77
|
}
|
|
78
78
|
return out;
|
|
79
79
|
}
|
|
80
|
-
var ALLOWANCE_MESSAGE = /\binsufficient\b|\bno allowance left\b|\bno slots left\b|\boutcomes remaining\b|\btop up the (?:allowance|balance)\b/i;
|
|
80
|
+
var ALLOWANCE_MESSAGE = /\binsufficient\b|\bno allowance left\b|\bno slots left\b|\boutcomes remaining\b|\btop up the (?:allowance|balance)\b|\bbelow zero\b/i;
|
|
81
|
+
var IDEMPOTENCY_KEY_REUSED = /\bidempotency key was already used\b/i;
|
|
81
82
|
function isAllowanceFailure(message, code) {
|
|
82
83
|
if (code) return code === "ALLOWANCE_EXHAUSTED";
|
|
83
84
|
return ALLOWANCE_MESSAGE.test(message);
|
|
@@ -101,6 +102,9 @@ function errorFromResponse(status, message, retryAfterMs, meta = {}) {
|
|
|
101
102
|
});
|
|
102
103
|
}
|
|
103
104
|
if (status === 422) {
|
|
105
|
+
if (IDEMPOTENCY_KEY_REUSED.test(raw)) {
|
|
106
|
+
return new ConflictError(raw, { ...opts, retryable: false });
|
|
107
|
+
}
|
|
104
108
|
return isAllowanceFailure(raw, code) ? new AllowanceError(raw, opts) : new PlanError(raw, opts);
|
|
105
109
|
}
|
|
106
110
|
if (status === 429) return new RateLimitError(raw, { retryAfterMs, idempotencyKey });
|
|
@@ -328,7 +332,7 @@ function sleep(ms) {
|
|
|
328
332
|
}
|
|
329
333
|
|
|
330
334
|
// src/http.ts
|
|
331
|
-
var SDK_VERSION = "0.
|
|
335
|
+
var SDK_VERSION = "0.15.0" ;
|
|
332
336
|
var Transport = class {
|
|
333
337
|
constructor(cfg) {
|
|
334
338
|
this.cfg = cfg;
|
|
@@ -432,105 +436,17 @@ var Transport = class {
|
|
|
432
436
|
}
|
|
433
437
|
};
|
|
434
438
|
|
|
435
|
-
// src/
|
|
436
|
-
function
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
439
|
+
// src/idempotency.ts
|
|
440
|
+
function newKey() {
|
|
441
|
+
const c = globalThis.crypto;
|
|
442
|
+
if (typeof c?.randomUUID === "function") return c.randomUUID();
|
|
443
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (ch) => {
|
|
444
|
+
const r = Math.random() * 16 | 0;
|
|
445
|
+
const v = ch === "x" ? r : r & 3 | 8;
|
|
446
|
+
return v.toString(16);
|
|
447
|
+
});
|
|
441
448
|
}
|
|
442
449
|
|
|
443
|
-
// src/resources/composites.ts
|
|
444
|
-
var Composites = class {
|
|
445
|
-
constructor(transport) {
|
|
446
|
-
this.transport = transport;
|
|
447
|
-
}
|
|
448
|
-
transport;
|
|
449
|
-
/** List composites. Pass `{ active: true }` for only the ones a signal can
|
|
450
|
-
* still be tagged with — the default list INCLUDES archived ones, which
|
|
451
|
-
* keep every row they already own.
|
|
452
|
-
* `{ active: false }` returns only archived ones; omitting it returns
|
|
453
|
-
* both. See `activeQuery` — the API itself only supports `true`. */
|
|
454
|
-
async list(params = {}) {
|
|
455
|
-
const res = await this.transport.request({
|
|
456
|
-
method: "GET",
|
|
457
|
-
path: "/api/v1/composites",
|
|
458
|
-
query: { active: activeQuery(params.active) }
|
|
459
|
-
});
|
|
460
|
-
return filterByActive(res.composites, params.active);
|
|
461
|
-
}
|
|
462
|
-
/** Create a composite. `POST /api/v1/composites`. */
|
|
463
|
-
async create(input) {
|
|
464
|
-
const res = await this.transport.request({
|
|
465
|
-
method: "POST",
|
|
466
|
-
path: "/api/v1/composites",
|
|
467
|
-
body: input
|
|
468
|
-
});
|
|
469
|
-
return res.composite;
|
|
470
|
-
}
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
// src/resources/credits.ts
|
|
474
|
-
var Credits = class {
|
|
475
|
-
constructor(transport) {
|
|
476
|
-
this.transport = transport;
|
|
477
|
-
}
|
|
478
|
-
transport;
|
|
479
|
-
/** List credit types. Pass `{ active: true }` to only return active ones.
|
|
480
|
-
* `{ active: false }` returns only archived ones; omitting it returns
|
|
481
|
-
* both. See `activeQuery` — the API itself only supports `true`. */
|
|
482
|
-
async list(params = {}) {
|
|
483
|
-
const res = await this.transport.request({
|
|
484
|
-
method: "GET",
|
|
485
|
-
path: "/api/v1/credits",
|
|
486
|
-
query: { active: activeQuery(params.active) }
|
|
487
|
-
});
|
|
488
|
-
return filterByActive(res.credits, params.active);
|
|
489
|
-
}
|
|
490
|
-
/** Create a credit type; returns the created credit. `POST /api/v1/credits`. */
|
|
491
|
-
async create(input) {
|
|
492
|
-
const res = await this.transport.request({
|
|
493
|
-
method: "POST",
|
|
494
|
-
path: "/api/v1/credits",
|
|
495
|
-
body: input
|
|
496
|
-
});
|
|
497
|
-
return res.credit;
|
|
498
|
-
}
|
|
499
|
-
/** Fetch one credit type with usage stats. `GET /api/v1/credits/:id`. */
|
|
500
|
-
async get(id) {
|
|
501
|
-
const res = await this.transport.request({
|
|
502
|
-
method: "GET",
|
|
503
|
-
path: `/api/v1/credits/${encodeURIComponent(id)}`
|
|
504
|
-
});
|
|
505
|
-
return res.credit;
|
|
506
|
-
}
|
|
507
|
-
/** Update a credit type's definition; returns the updated credit. `PATCH /api/v1/credits/:id`. */
|
|
508
|
-
async update(id, input) {
|
|
509
|
-
const res = await this.transport.request({
|
|
510
|
-
method: "PATCH",
|
|
511
|
-
path: `/api/v1/credits/${encodeURIComponent(id)}`,
|
|
512
|
-
body: input
|
|
513
|
-
});
|
|
514
|
-
return res.credit;
|
|
515
|
-
}
|
|
516
|
-
/** Activate or deactivate a credit type. */
|
|
517
|
-
async setActive(id, isActive) {
|
|
518
|
-
const res = await this.transport.request({
|
|
519
|
-
method: "PATCH",
|
|
520
|
-
path: `/api/v1/credits/${encodeURIComponent(id)}`,
|
|
521
|
-
body: { isActive }
|
|
522
|
-
});
|
|
523
|
-
return res.credit;
|
|
524
|
-
}
|
|
525
|
-
/** Delete a credit type. Refused while a customer is linked to it. */
|
|
526
|
-
async delete(id) {
|
|
527
|
-
await this.transport.request({
|
|
528
|
-
method: "DELETE",
|
|
529
|
-
path: `/api/v1/credits/${encodeURIComponent(id)}`
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
};
|
|
533
|
-
|
|
534
450
|
// src/resources/customers.ts
|
|
535
451
|
var Customers = class {
|
|
536
452
|
constructor(transport) {
|
|
@@ -584,6 +500,36 @@ var Customers = class {
|
|
|
584
500
|
});
|
|
585
501
|
return res.customer;
|
|
586
502
|
}
|
|
503
|
+
/**
|
|
504
|
+
* Fetch one customer by YOUR id for them (its `externalId`), instead of
|
|
505
|
+
* ours. Same result as {@link get}. `GET /api/v1/customers/ext/:externalId`.
|
|
506
|
+
* An unknown external id is a `NotFoundError`; only active customers match.
|
|
507
|
+
*/
|
|
508
|
+
async getByExternalId(externalId) {
|
|
509
|
+
const res = await this.transport.request({
|
|
510
|
+
method: "GET",
|
|
511
|
+
path: `/api/v1/customers/ext/${encodeURIComponent(externalId)}`
|
|
512
|
+
});
|
|
513
|
+
return res.customer;
|
|
514
|
+
}
|
|
515
|
+
/** Update a customer (partial), addressed by its `externalId`. Same body as
|
|
516
|
+
* {@link update}. `PATCH /api/v1/customers/ext/:externalId`. */
|
|
517
|
+
async updateByExternalId(externalId, input) {
|
|
518
|
+
const res = await this.transport.request({
|
|
519
|
+
method: "PATCH",
|
|
520
|
+
path: `/api/v1/customers/ext/${encodeURIComponent(externalId)}`,
|
|
521
|
+
body: input
|
|
522
|
+
});
|
|
523
|
+
return res.customer;
|
|
524
|
+
}
|
|
525
|
+
/** {@link delete}, addressing the customer by its `externalId`.
|
|
526
|
+
* `DELETE /api/v1/customers/ext/:externalId`. */
|
|
527
|
+
async deleteByExternalId(externalId) {
|
|
528
|
+
await this.transport.request({
|
|
529
|
+
method: "DELETE",
|
|
530
|
+
path: `/api/v1/customers/ext/${encodeURIComponent(externalId)}`
|
|
531
|
+
});
|
|
532
|
+
}
|
|
587
533
|
/** Delete a customer (members, invitations, usage logs cascade). */
|
|
588
534
|
async delete(id) {
|
|
589
535
|
await this.transport.request({
|
|
@@ -591,15 +537,6 @@ var Customers = class {
|
|
|
591
537
|
path: `/api/v1/customers/${encodeURIComponent(id)}`
|
|
592
538
|
});
|
|
593
539
|
}
|
|
594
|
-
/** A customer's usage history. `GET /api/v1/usage?customerId=`. */
|
|
595
|
-
async usage(id, params = {}) {
|
|
596
|
-
const res = await this.transport.request({
|
|
597
|
-
method: "GET",
|
|
598
|
-
path: `/api/v1/usage`,
|
|
599
|
-
query: { customerId: id, limit: params.limit }
|
|
600
|
-
});
|
|
601
|
-
return { customer: res.customer, totals: res.totals, logs: res.logs };
|
|
602
|
-
}
|
|
603
540
|
/** Wallet / credit / outcome / unit balances. `GET …/:id/balances`. */
|
|
604
541
|
balances(id) {
|
|
605
542
|
return this.transport.request({
|
|
@@ -607,6 +544,14 @@ var Customers = class {
|
|
|
607
544
|
path: `/api/v1/customers/${encodeURIComponent(id)}/balances`
|
|
608
545
|
});
|
|
609
546
|
}
|
|
547
|
+
/** {@link balances}, addressing the customer by its `externalId`.
|
|
548
|
+
* `GET /api/v1/customers/ext/:externalId/balances`. */
|
|
549
|
+
balancesByExternalId(externalId) {
|
|
550
|
+
return this.transport.request({
|
|
551
|
+
method: "GET",
|
|
552
|
+
path: `/api/v1/customers/ext/${encodeURIComponent(externalId)}/balances`
|
|
553
|
+
});
|
|
554
|
+
}
|
|
610
555
|
/**
|
|
611
556
|
* One credit balance for a customer, matched by `creditId` or `creditName`;
|
|
612
557
|
* `null` when the customer has no plan or no matching credit. Convenience
|
|
@@ -645,6 +590,14 @@ var Customers = class {
|
|
|
645
590
|
path: `/api/v1/customers/${encodeURIComponent(id)}/plan`
|
|
646
591
|
});
|
|
647
592
|
}
|
|
593
|
+
/** {@link plan}, addressing the customer by its `externalId`.
|
|
594
|
+
* `GET /api/v1/customers/ext/:externalId/plan`. */
|
|
595
|
+
planByExternalId(externalId) {
|
|
596
|
+
return this.transport.request({
|
|
597
|
+
method: "GET",
|
|
598
|
+
path: `/api/v1/customers/ext/${encodeURIComponent(externalId)}/plan`
|
|
599
|
+
});
|
|
600
|
+
}
|
|
648
601
|
// --- Members -------------------------------------------------------------
|
|
649
602
|
/** List a customer's members. `GET …/:id/members`. */
|
|
650
603
|
async listMembers(id) {
|
|
@@ -680,72 +633,129 @@ var Customers = class {
|
|
|
680
633
|
});
|
|
681
634
|
return res.member;
|
|
682
635
|
}
|
|
683
|
-
// ---
|
|
684
|
-
/** The customer's wallet balance + transactions. `GET …/:id/wallet`. */
|
|
685
|
-
wallet(id, params = {}) {
|
|
686
|
-
return this.transport.request({
|
|
687
|
-
method: "GET",
|
|
688
|
-
path: `/api/v1/customers/${encodeURIComponent(id)}/wallet`,
|
|
689
|
-
query: { limit: params.limit }
|
|
690
|
-
});
|
|
691
|
-
}
|
|
692
|
-
/**
|
|
693
|
-
* Record a manual wallet entry (top-up or deduction). `amount` is always
|
|
694
|
-
* positive; the sign comes from `type`. `POST …/:id/wallet`.
|
|
695
|
-
*/
|
|
696
|
-
async addWalletEntry(id, input) {
|
|
697
|
-
return this.transport.request({
|
|
698
|
-
method: "POST",
|
|
699
|
-
path: `/api/v1/customers/${encodeURIComponent(id)}/wallet`,
|
|
700
|
-
body: input
|
|
701
|
-
});
|
|
702
|
-
}
|
|
636
|
+
// --- Billing config -----------------------------------------------------
|
|
703
637
|
// Note: a customer's currency is set through `update(id, { currencyCode })`
|
|
704
638
|
// (PATCH …/:id) — there is no separate currency endpoint. Credit-type
|
|
705
639
|
// assignment has no public API.
|
|
706
640
|
// --- Balance adjustments -------------------------------------------------
|
|
707
|
-
/** Grant or claw back a credit balance.
|
|
708
|
-
* `
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
641
|
+
/** Grant or claw back a credit balance. The credit must be a prepaid part of
|
|
642
|
+
* the customer's current plan. Pass `idempotencyKey` to make it safe to
|
|
643
|
+
* retry. `POST …/:id/credits/adjust`. */
|
|
644
|
+
adjustCredit(id, input) {
|
|
645
|
+
return this.adjust(`/api/v1/customers/${encodeURIComponent(id)}/credits/adjust`, input);
|
|
646
|
+
}
|
|
647
|
+
/** Grant or claw back an outcome balance. The outcome must be a prepaid part
|
|
648
|
+
* of the customer's current plan. `POST …/:id/outcomes/adjust`. */
|
|
649
|
+
adjustOutcome(id, input) {
|
|
650
|
+
return this.adjust(`/api/v1/customers/${encodeURIComponent(id)}/outcomes/adjust`, input);
|
|
651
|
+
}
|
|
652
|
+
/** Grant or claw back a unit balance. The unit must be a prepaid part of the
|
|
653
|
+
* customer's current plan. `POST …/:id/units/adjust`. */
|
|
654
|
+
adjustUnit(id, input) {
|
|
655
|
+
return this.adjust(`/api/v1/customers/${encodeURIComponent(id)}/units/adjust`, input);
|
|
656
|
+
}
|
|
657
|
+
/** Grant or claw back slots on a customer's ADVANCE composite pool for the
|
|
658
|
+
* current billing cycle. `remaining` is the resulting slot count.
|
|
659
|
+
* `POST …/:id/composites/adjust`. */
|
|
660
|
+
adjustComposite(id, input) {
|
|
661
|
+
return this.adjust(`/api/v1/customers/${encodeURIComponent(id)}/composites/adjust`, input);
|
|
716
662
|
}
|
|
717
|
-
/**
|
|
718
|
-
|
|
663
|
+
/**
|
|
664
|
+
* Top up (positive `delta`) or draw down (negative `delta`) a customer's
|
|
665
|
+
* wallet, in USD — allowed whatever the customer's plan. `remaining` is the
|
|
666
|
+
* resulting USD balance. No `agentKey` — a customer has exactly one wallet.
|
|
667
|
+
* Pass `pool: "RESERVED"` to move the Reserved Wallet instead (then
|
|
668
|
+
* `remaining` is its balance). `POST …/:id/wallet/adjust`.
|
|
669
|
+
*/
|
|
670
|
+
adjustWallet(id, input) {
|
|
671
|
+
return this.adjust(`/api/v1/customers/${encodeURIComponent(id)}/wallet/adjust`, input);
|
|
672
|
+
}
|
|
673
|
+
/** {@link adjustCredit}, addressing the customer by its `externalId` (`id`
|
|
674
|
+
* here). `POST /api/v1/customers/ext/:externalId/credits/adjust`. */
|
|
675
|
+
adjustCreditByExternalId(id, input) {
|
|
676
|
+
return this.adjust(`/api/v1/customers/ext/${encodeURIComponent(id)}/credits/adjust`, input);
|
|
677
|
+
}
|
|
678
|
+
/** {@link adjustOutcome}, addressing the customer by its `externalId` (`id`
|
|
679
|
+
* here). `POST /api/v1/customers/ext/:externalId/outcomes/adjust`. */
|
|
680
|
+
adjustOutcomeByExternalId(id, input) {
|
|
681
|
+
return this.adjust(`/api/v1/customers/ext/${encodeURIComponent(id)}/outcomes/adjust`, input);
|
|
682
|
+
}
|
|
683
|
+
/** {@link adjustUnit}, addressing the customer by its `externalId` (`id`
|
|
684
|
+
* here). `POST /api/v1/customers/ext/:externalId/units/adjust`. */
|
|
685
|
+
adjustUnitByExternalId(id, input) {
|
|
686
|
+
return this.adjust(`/api/v1/customers/ext/${encodeURIComponent(id)}/units/adjust`, input);
|
|
687
|
+
}
|
|
688
|
+
/** {@link adjustComposite}, addressing the customer by its `externalId`
|
|
689
|
+
* (`id` here). `POST /api/v1/customers/ext/:externalId/composites/adjust`. */
|
|
690
|
+
adjustCompositeByExternalId(id, input) {
|
|
691
|
+
return this.adjust(`/api/v1/customers/ext/${encodeURIComponent(id)}/composites/adjust`, input);
|
|
692
|
+
}
|
|
693
|
+
/** {@link adjustWallet}, addressing the customer by its `externalId` (`id`
|
|
694
|
+
* here). `POST /api/v1/customers/ext/:externalId/wallet/adjust`. */
|
|
695
|
+
adjustWalletByExternalId(id, input) {
|
|
696
|
+
return this.adjust(`/api/v1/customers/ext/${encodeURIComponent(id)}/wallet/adjust`, input);
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* The one body behind all ten adjust calls.
|
|
700
|
+
*
|
|
701
|
+
* Every adjustment carries an idempotency key — the caller's, or one
|
|
702
|
+
* generated here ONCE per call, exactly like signals. The server
|
|
703
|
+
* deduplicates on it, so a transient failure is safe to retry: the same key
|
|
704
|
+
* rides every attempt, and a retry of one that already landed comes back as
|
|
705
|
+
* `replayed: true` instead of adjusting again. The key is also copied onto
|
|
706
|
+
* any thrown error (`error.idempotencyKey`) so the caller can replay safely.
|
|
707
|
+
*/
|
|
708
|
+
async adjust(path, input) {
|
|
709
|
+
const idempotencyKey = input.idempotencyKey ?? newKey();
|
|
719
710
|
const res = await this.transport.request({
|
|
720
711
|
method: "POST",
|
|
721
|
-
path
|
|
722
|
-
|
|
712
|
+
path,
|
|
713
|
+
idempotencyKey,
|
|
714
|
+
body: { ...input, idempotencyKey },
|
|
715
|
+
retry: true
|
|
723
716
|
});
|
|
724
|
-
|
|
717
|
+
const result = {
|
|
718
|
+
remaining: res.remaining,
|
|
719
|
+
replayed: res.replayed === true,
|
|
720
|
+
customerArchived: res.customerArchived === true
|
|
721
|
+
};
|
|
722
|
+
if (result.replayed && typeof res.adjustedAt === "string") {
|
|
723
|
+
result.adjustedAt = res.adjustedAt;
|
|
724
|
+
}
|
|
725
|
+
return result;
|
|
725
726
|
}
|
|
726
|
-
|
|
727
|
-
|
|
727
|
+
// --- Recurring grants ----------------------------------------------------
|
|
728
|
+
/**
|
|
729
|
+
* Change how much a customer is granted every billing cycle (wallet top-up,
|
|
730
|
+
* credits, outcomes, units or a composite pool). Any increase or decrease
|
|
731
|
+
* applies to their current balance immediately. `PUT …/:id/recurring-grant`.
|
|
732
|
+
*/
|
|
733
|
+
async updateRecurringGrant(id, input) {
|
|
728
734
|
const res = await this.transport.request({
|
|
729
|
-
method: "
|
|
730
|
-
path: `/api/v1/customers/${encodeURIComponent(id)}/
|
|
735
|
+
method: "PUT",
|
|
736
|
+
path: `/api/v1/customers/${encodeURIComponent(id)}/recurring-grant`,
|
|
731
737
|
body: input
|
|
732
738
|
});
|
|
733
|
-
return
|
|
739
|
+
return toRecurringGrantResult(res);
|
|
734
740
|
}
|
|
735
|
-
/**
|
|
736
|
-
*
|
|
737
|
-
|
|
738
|
-
* `POST …/:id/composites/adjust`.
|
|
739
|
-
*/
|
|
740
|
-
async adjustComposite(id, input) {
|
|
741
|
+
/** {@link updateRecurringGrant}, addressing the customer by its
|
|
742
|
+
* `externalId`. `PUT /api/v1/customers/ext/:externalId/recurring-grant`. */
|
|
743
|
+
async updateRecurringGrantByExternalId(externalId, input) {
|
|
741
744
|
const res = await this.transport.request({
|
|
742
|
-
method: "
|
|
743
|
-
path: `/api/v1/customers/${encodeURIComponent(
|
|
745
|
+
method: "PUT",
|
|
746
|
+
path: `/api/v1/customers/ext/${encodeURIComponent(externalId)}/recurring-grant`,
|
|
744
747
|
body: input
|
|
745
748
|
});
|
|
746
|
-
return
|
|
749
|
+
return toRecurringGrantResult(res);
|
|
747
750
|
}
|
|
748
751
|
};
|
|
752
|
+
function toRecurringGrantResult(res) {
|
|
753
|
+
return {
|
|
754
|
+
kind: res.kind,
|
|
755
|
+
quantity: res.quantity,
|
|
756
|
+
...res.balanceUsd !== void 0 ? { balanceUsd: res.balanceUsd } : {}
|
|
757
|
+
};
|
|
758
|
+
}
|
|
749
759
|
|
|
750
760
|
// src/resources/invoices.ts
|
|
751
761
|
var Invoices = class {
|
|
@@ -774,7 +784,7 @@ var Invoices = class {
|
|
|
774
784
|
});
|
|
775
785
|
}
|
|
776
786
|
/**
|
|
777
|
-
* Mint a hosted pay link for an OPEN invoice. PAID/VOID invoices are rejected
|
|
787
|
+
* Mint a hosted pay link for an OPEN invoice. PAID/VOID/AUTO_CLOSED invoices are rejected
|
|
778
788
|
* with a `ConflictError`. `GET /api/v1/invoices/:id/pay-link`.
|
|
779
789
|
*/
|
|
780
790
|
payLink(id) {
|
|
@@ -785,67 +795,6 @@ var Invoices = class {
|
|
|
785
795
|
}
|
|
786
796
|
};
|
|
787
797
|
|
|
788
|
-
// src/resources/outcomes.ts
|
|
789
|
-
var Outcomes = class {
|
|
790
|
-
constructor(transport) {
|
|
791
|
-
this.transport = transport;
|
|
792
|
-
}
|
|
793
|
-
transport;
|
|
794
|
-
/** List outcome types. Pass `{ active: true }` to only return active ones.
|
|
795
|
-
* `{ active: false }` returns only archived ones; omitting it returns
|
|
796
|
-
* both. See `activeQuery` — the API itself only supports `true`. */
|
|
797
|
-
async list(params = {}) {
|
|
798
|
-
const res = await this.transport.request({
|
|
799
|
-
method: "GET",
|
|
800
|
-
path: "/api/v1/outcomes",
|
|
801
|
-
query: { active: activeQuery(params.active) }
|
|
802
|
-
});
|
|
803
|
-
return filterByActive(res.outcomes, params.active);
|
|
804
|
-
}
|
|
805
|
-
/** Create an outcome type with its steps. `POST /api/v1/outcomes`. */
|
|
806
|
-
async create(input) {
|
|
807
|
-
const res = await this.transport.request({
|
|
808
|
-
method: "POST",
|
|
809
|
-
path: "/api/v1/outcomes",
|
|
810
|
-
body: input
|
|
811
|
-
});
|
|
812
|
-
return res.outcome;
|
|
813
|
-
}
|
|
814
|
-
/** Fetch one outcome type with steps + stats. `GET /api/v1/outcomes/:id`. */
|
|
815
|
-
async get(id) {
|
|
816
|
-
const res = await this.transport.request({
|
|
817
|
-
method: "GET",
|
|
818
|
-
path: `/api/v1/outcomes/${encodeURIComponent(id)}`
|
|
819
|
-
});
|
|
820
|
-
return res.outcome;
|
|
821
|
-
}
|
|
822
|
-
/** Update an outcome type's definition. `PATCH /api/v1/outcomes/:id`. */
|
|
823
|
-
async update(id, input) {
|
|
824
|
-
const res = await this.transport.request({
|
|
825
|
-
method: "PATCH",
|
|
826
|
-
path: `/api/v1/outcomes/${encodeURIComponent(id)}`,
|
|
827
|
-
body: input
|
|
828
|
-
});
|
|
829
|
-
return res.outcome;
|
|
830
|
-
}
|
|
831
|
-
/** Activate or deactivate an outcome type; returns the updated outcome. */
|
|
832
|
-
async setActive(id, isActive) {
|
|
833
|
-
const res = await this.transport.request({
|
|
834
|
-
method: "PATCH",
|
|
835
|
-
path: `/api/v1/outcomes/${encodeURIComponent(id)}`,
|
|
836
|
-
body: { isActive }
|
|
837
|
-
});
|
|
838
|
-
return res.outcome;
|
|
839
|
-
}
|
|
840
|
-
/** Delete an outcome type. */
|
|
841
|
-
async delete(id) {
|
|
842
|
-
await this.transport.request({
|
|
843
|
-
method: "DELETE",
|
|
844
|
-
path: `/api/v1/outcomes/${encodeURIComponent(id)}`
|
|
845
|
-
});
|
|
846
|
-
}
|
|
847
|
-
};
|
|
848
|
-
|
|
849
798
|
// src/resources/payments.ts
|
|
850
799
|
var Payments = class {
|
|
851
800
|
constructor(transport) {
|
|
@@ -870,6 +819,14 @@ var Payments = class {
|
|
|
870
819
|
}
|
|
871
820
|
};
|
|
872
821
|
|
|
822
|
+
// src/filters.ts
|
|
823
|
+
function activeQuery(active) {
|
|
824
|
+
return active === true ? "true" : void 0;
|
|
825
|
+
}
|
|
826
|
+
function filterByActive(rows, active) {
|
|
827
|
+
return active === false ? rows.filter((row) => !row.isActive) : rows;
|
|
828
|
+
}
|
|
829
|
+
|
|
873
830
|
// src/resources/plans.ts
|
|
874
831
|
var Plans = class {
|
|
875
832
|
constructor(transport) {
|
|
@@ -887,48 +844,6 @@ var Plans = class {
|
|
|
887
844
|
});
|
|
888
845
|
return filterByActive(res.plans, params.active);
|
|
889
846
|
}
|
|
890
|
-
/** Create a plan. `POST /api/v1/plans`. */
|
|
891
|
-
async create(input) {
|
|
892
|
-
const res = await this.transport.request({
|
|
893
|
-
method: "POST",
|
|
894
|
-
path: "/api/v1/plans",
|
|
895
|
-
body: input
|
|
896
|
-
});
|
|
897
|
-
return res.plan;
|
|
898
|
-
}
|
|
899
|
-
/** Fetch one plan with aggregate subscriber/invoice stats. `GET /api/v1/plans/:id`. */
|
|
900
|
-
async get(id) {
|
|
901
|
-
const res = await this.transport.request({
|
|
902
|
-
method: "GET",
|
|
903
|
-
path: `/api/v1/plans/${encodeURIComponent(id)}`
|
|
904
|
-
});
|
|
905
|
-
return res.plan;
|
|
906
|
-
}
|
|
907
|
-
/** Replace a plan's definition (components + settings). `PATCH /api/v1/plans/:id`. */
|
|
908
|
-
async update(id, input) {
|
|
909
|
-
const res = await this.transport.request({
|
|
910
|
-
method: "PATCH",
|
|
911
|
-
path: `/api/v1/plans/${encodeURIComponent(id)}`,
|
|
912
|
-
body: input
|
|
913
|
-
});
|
|
914
|
-
return res.plan;
|
|
915
|
-
}
|
|
916
|
-
/** Activate or deactivate a plan without rewriting it. */
|
|
917
|
-
async setActive(id, isActive) {
|
|
918
|
-
const res = await this.transport.request({
|
|
919
|
-
method: "PATCH",
|
|
920
|
-
path: `/api/v1/plans/${encodeURIComponent(id)}`,
|
|
921
|
-
body: { isActive }
|
|
922
|
-
});
|
|
923
|
-
return res.plan;
|
|
924
|
-
}
|
|
925
|
-
/** Delete a plan. Refused once any customer has purchased it. */
|
|
926
|
-
async delete(id) {
|
|
927
|
-
await this.transport.request({
|
|
928
|
-
method: "DELETE",
|
|
929
|
-
path: `/api/v1/plans/${encodeURIComponent(id)}`
|
|
930
|
-
});
|
|
931
|
-
}
|
|
932
847
|
};
|
|
933
848
|
|
|
934
849
|
// src/resources/portal.ts
|
|
@@ -1011,15 +926,12 @@ var Purchases = class {
|
|
|
1011
926
|
}
|
|
1012
927
|
};
|
|
1013
928
|
|
|
1014
|
-
// src/
|
|
1015
|
-
function
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
const v = ch === "x" ? r : r & 3 | 8;
|
|
1021
|
-
return v.toString(16);
|
|
1022
|
-
});
|
|
929
|
+
// src/customer-ref.ts
|
|
930
|
+
function customerRefToWire(ref) {
|
|
931
|
+
return {
|
|
932
|
+
...ref.customerId != null ? { customerId: ref.customerId } : {},
|
|
933
|
+
...ref.externalId != null ? { externalId: ref.externalId } : {}
|
|
934
|
+
};
|
|
1023
935
|
}
|
|
1024
936
|
|
|
1025
937
|
// src/resources/signals.ts
|
|
@@ -1035,7 +947,7 @@ var USAGE_LOG_PATH = "/api/v1/signal/usage-log";
|
|
|
1035
947
|
function signalToWire(signal) {
|
|
1036
948
|
const t = signal.tokens;
|
|
1037
949
|
const body = {
|
|
1038
|
-
|
|
950
|
+
...customerRefToWire(signal),
|
|
1039
951
|
// `usage` is required on all three model-priced kinds. input/output are
|
|
1040
952
|
// always sent; `cacheTokens` only when provided (the server defaults 0).
|
|
1041
953
|
usage: {
|
|
@@ -1146,9 +1058,8 @@ var Signals = class {
|
|
|
1146
1058
|
path: OUTCOME_COMPLETE_PATH,
|
|
1147
1059
|
idempotencyKey,
|
|
1148
1060
|
body: {
|
|
1149
|
-
|
|
1061
|
+
...customerRefToWire(input),
|
|
1150
1062
|
runId: input.runId,
|
|
1151
|
-
complete: true,
|
|
1152
1063
|
...input.member ? { member: input.member } : {},
|
|
1153
1064
|
idempotencyKey
|
|
1154
1065
|
},
|
|
@@ -1163,23 +1074,6 @@ var Signals = class {
|
|
|
1163
1074
|
...handles(res)
|
|
1164
1075
|
};
|
|
1165
1076
|
}
|
|
1166
|
-
/**
|
|
1167
|
-
* Recent usage logs + totals for a customer. `GET /api/v1/usage`.
|
|
1168
|
-
*
|
|
1169
|
-
* Still the legacy path, deliberately. The `/api/v1/signal/*` family is
|
|
1170
|
-
* POST-only — it replaced how usage is INGESTED, not how it is read — so
|
|
1171
|
-
* `GET /api/v1/usage` has no successor and is not deprecated. It is also the
|
|
1172
|
-
* only way to prove a signal landed, which matters more now that ingestion
|
|
1173
|
-
* answers `202` for everything.
|
|
1174
|
-
*/
|
|
1175
|
-
async list(params) {
|
|
1176
|
-
const res = await this.transport.request({
|
|
1177
|
-
method: "GET",
|
|
1178
|
-
path: "/api/v1/usage",
|
|
1179
|
-
query: { customerId: params.customerId, limit: params.limit }
|
|
1180
|
-
});
|
|
1181
|
-
return { customer: res.customer, totals: res.totals, logs: res.logs };
|
|
1182
|
-
}
|
|
1183
1077
|
/**
|
|
1184
1078
|
* Record one unit-metered event (a fixed-price meter with no tokens),
|
|
1185
1079
|
* addressed to a catalog unit by its `agentKey`. Sent immediately — unit
|
|
@@ -1199,7 +1093,7 @@ var Signals = class {
|
|
|
1199
1093
|
path: UNIT_PATH,
|
|
1200
1094
|
idempotencyKey,
|
|
1201
1095
|
body: {
|
|
1202
|
-
|
|
1096
|
+
...customerRefToWire(input),
|
|
1203
1097
|
agentKey: input.agentKey,
|
|
1204
1098
|
...input.quantity != null ? { quantity: input.quantity } : {},
|
|
1205
1099
|
...input.member ? { member: input.member } : {},
|
|
@@ -1256,7 +1150,7 @@ var Signals = class {
|
|
|
1256
1150
|
path: COMPOSITE_COMPLETE_PATH,
|
|
1257
1151
|
idempotencyKey,
|
|
1258
1152
|
body: {
|
|
1259
|
-
|
|
1153
|
+
...customerRefToWire(input),
|
|
1260
1154
|
composite: { [input.composite.ref]: input.composite.value },
|
|
1261
1155
|
// Auto-assigned like the others. A retry here could not double-BILL
|
|
1262
1156
|
// even without it — closing a closed occurrence is a server-side
|
|
@@ -1277,19 +1171,6 @@ var Signals = class {
|
|
|
1277
1171
|
...handles(res)
|
|
1278
1172
|
};
|
|
1279
1173
|
}
|
|
1280
|
-
/**
|
|
1281
|
-
* A customer's unit balances + recent unit events. `GET /api/v1/units`.
|
|
1282
|
-
*
|
|
1283
|
-
* Legacy path for the same reason as {@link list}: the signal family is
|
|
1284
|
-
* POST-only, so the read side has no successor and is not deprecated.
|
|
1285
|
-
*/
|
|
1286
|
-
unitUsage(params) {
|
|
1287
|
-
return this.transport.request({
|
|
1288
|
-
method: "GET",
|
|
1289
|
-
path: "/api/v1/units",
|
|
1290
|
-
query: { customerId: params.customerId, limit: params.limit }
|
|
1291
|
-
});
|
|
1292
|
-
}
|
|
1293
1174
|
/**
|
|
1294
1175
|
* One customer's usage history, merged from every meter kind — credit,
|
|
1295
1176
|
* outcome, unit, wallet, and completed composite occurrences — into one
|
|
@@ -1323,133 +1204,13 @@ var Signals = class {
|
|
|
1323
1204
|
}
|
|
1324
1205
|
};
|
|
1325
1206
|
|
|
1326
|
-
// src/resources/units.ts
|
|
1327
|
-
var Units = class {
|
|
1328
|
-
constructor(transport) {
|
|
1329
|
-
this.transport = transport;
|
|
1330
|
-
}
|
|
1331
|
-
transport;
|
|
1332
|
-
/** List unit types. Pass `{ active: true }` to only return active ones.
|
|
1333
|
-
* `{ active: false }` returns only archived ones; omitting it returns
|
|
1334
|
-
* both. See `activeQuery` — the API itself only supports `true`. */
|
|
1335
|
-
async list(params = {}) {
|
|
1336
|
-
const res = await this.transport.request({
|
|
1337
|
-
method: "GET",
|
|
1338
|
-
path: "/api/v1/units-catalog",
|
|
1339
|
-
query: { active: activeQuery(params.active) }
|
|
1340
|
-
});
|
|
1341
|
-
return filterByActive(res.units, params.active);
|
|
1342
|
-
}
|
|
1343
|
-
/** Create a unit type. `POST /api/v1/units-catalog`. */
|
|
1344
|
-
async create(input) {
|
|
1345
|
-
const res = await this.transport.request({
|
|
1346
|
-
method: "POST",
|
|
1347
|
-
path: "/api/v1/units-catalog",
|
|
1348
|
-
body: input
|
|
1349
|
-
});
|
|
1350
|
-
return res.unit;
|
|
1351
|
-
}
|
|
1352
|
-
/** Fetch one unit type with stats. `GET /api/v1/units-catalog/:id`. */
|
|
1353
|
-
async get(id) {
|
|
1354
|
-
const res = await this.transport.request({
|
|
1355
|
-
method: "GET",
|
|
1356
|
-
path: `/api/v1/units-catalog/${encodeURIComponent(id)}`
|
|
1357
|
-
});
|
|
1358
|
-
return res.unit;
|
|
1359
|
-
}
|
|
1360
|
-
/** Update a unit type's definition. `PATCH /api/v1/units-catalog/:id`. */
|
|
1361
|
-
async update(id, input) {
|
|
1362
|
-
const res = await this.transport.request({
|
|
1363
|
-
method: "PATCH",
|
|
1364
|
-
path: `/api/v1/units-catalog/${encodeURIComponent(id)}`,
|
|
1365
|
-
body: input
|
|
1366
|
-
});
|
|
1367
|
-
return res.unit;
|
|
1368
|
-
}
|
|
1369
|
-
/** Activate or deactivate a unit type. */
|
|
1370
|
-
async setActive(id, isActive) {
|
|
1371
|
-
const res = await this.transport.request({
|
|
1372
|
-
method: "PATCH",
|
|
1373
|
-
path: `/api/v1/units-catalog/${encodeURIComponent(id)}`,
|
|
1374
|
-
body: { isActive }
|
|
1375
|
-
});
|
|
1376
|
-
return res.unit;
|
|
1377
|
-
}
|
|
1378
|
-
/** Delete a unit type. */
|
|
1379
|
-
async delete(id) {
|
|
1380
|
-
await this.transport.request({
|
|
1381
|
-
method: "DELETE",
|
|
1382
|
-
path: `/api/v1/units-catalog/${encodeURIComponent(id)}`
|
|
1383
|
-
});
|
|
1384
|
-
}
|
|
1385
|
-
};
|
|
1386
|
-
|
|
1387
|
-
// src/resources/webhooks.ts
|
|
1388
|
-
var Webhooks = class {
|
|
1389
|
-
constructor(transport) {
|
|
1390
|
-
this.transport = transport;
|
|
1391
|
-
}
|
|
1392
|
-
transport;
|
|
1393
|
-
/** List configured webhooks. `GET /api/v1/webhooks`. */
|
|
1394
|
-
async list() {
|
|
1395
|
-
const res = await this.transport.request({
|
|
1396
|
-
method: "GET",
|
|
1397
|
-
path: "/api/v1/webhooks"
|
|
1398
|
-
});
|
|
1399
|
-
return res.webhooks;
|
|
1400
|
-
}
|
|
1401
|
-
/** Create or replace the webhook for a kind. `POST /api/v1/webhooks`. */
|
|
1402
|
-
async upsert(input) {
|
|
1403
|
-
const res = await this.transport.request({
|
|
1404
|
-
method: "POST",
|
|
1405
|
-
path: "/api/v1/webhooks",
|
|
1406
|
-
body: input
|
|
1407
|
-
});
|
|
1408
|
-
return res.webhook;
|
|
1409
|
-
}
|
|
1410
|
-
/** Delete the webhook for a kind (idempotent). `DELETE /api/v1/webhooks/:kind`. */
|
|
1411
|
-
async delete(kind) {
|
|
1412
|
-
await this.transport.request({
|
|
1413
|
-
method: "DELETE",
|
|
1414
|
-
path: `/api/v1/webhooks/${encodeURIComponent(kind)}`
|
|
1415
|
-
});
|
|
1416
|
-
}
|
|
1417
|
-
};
|
|
1418
|
-
|
|
1419
|
-
// src/resources/workspace.ts
|
|
1420
|
-
var Workspace = class {
|
|
1421
|
-
constructor(transport) {
|
|
1422
|
-
this.transport = transport;
|
|
1423
|
-
}
|
|
1424
|
-
transport;
|
|
1425
|
-
/** Identify the org + key behind the request, incl. `sandbox` | `live`. */
|
|
1426
|
-
me() {
|
|
1427
|
-
return this.transport.request({
|
|
1428
|
-
method: "GET",
|
|
1429
|
-
path: "/api/v1/me"
|
|
1430
|
-
});
|
|
1431
|
-
}
|
|
1432
|
-
/** The org's enabled models with live prices. `{ active: true }` returns only
|
|
1433
|
-
* the models that can be metered right now.
|
|
1434
|
-
* `{ active: false }` returns only archived ones; omitting it returns
|
|
1435
|
-
* both. See `activeQuery` — the API itself only supports `true`. */
|
|
1436
|
-
async models(params = {}) {
|
|
1437
|
-
const res = await this.transport.request({
|
|
1438
|
-
method: "GET",
|
|
1439
|
-
path: "/api/v1/models",
|
|
1440
|
-
query: { active: activeQuery(params.active) }
|
|
1441
|
-
});
|
|
1442
|
-
return filterByActive(res.models, params.active);
|
|
1443
|
-
}
|
|
1444
|
-
};
|
|
1445
|
-
|
|
1446
1207
|
// src/client.ts
|
|
1447
1208
|
var ClockNext = class {
|
|
1448
|
-
/** Record
|
|
1209
|
+
/** Record usage signals (credit / wallet / outcome / unit) and read the usage log. */
|
|
1449
1210
|
signals;
|
|
1450
|
-
/** Manage customers, their members,
|
|
1211
|
+
/** Manage customers, their members, and balances. */
|
|
1451
1212
|
customers;
|
|
1452
|
-
/**
|
|
1213
|
+
/** List billing plans. */
|
|
1453
1214
|
plans;
|
|
1454
1215
|
/** Subscribe customers to plans (purchases). */
|
|
1455
1216
|
purchases;
|
|
@@ -1457,20 +1218,8 @@ var ClockNext = class {
|
|
|
1457
1218
|
invoices;
|
|
1458
1219
|
/** Read payments (paid invoices). */
|
|
1459
1220
|
payments;
|
|
1460
|
-
/** Manage the credit-type catalog. */
|
|
1461
|
-
credits;
|
|
1462
|
-
/** Manage the composite catalog — bundles billed as one thing. */
|
|
1463
|
-
composites;
|
|
1464
|
-
/** Manage the outcome-type catalog. */
|
|
1465
|
-
outcomes;
|
|
1466
|
-
/** Manage the unit-type catalog. */
|
|
1467
|
-
units;
|
|
1468
|
-
/** Configure threshold webhooks. */
|
|
1469
|
-
webhooks;
|
|
1470
1221
|
/** Mint customer-portal embed tokens. */
|
|
1471
1222
|
portal;
|
|
1472
|
-
/** Identify the workspace (sandbox/live) + list its models. `/me`, `/models`. */
|
|
1473
|
-
workspace;
|
|
1474
1223
|
cfg;
|
|
1475
1224
|
flusher;
|
|
1476
1225
|
constructor(config) {
|
|
@@ -1488,13 +1237,7 @@ var ClockNext = class {
|
|
|
1488
1237
|
this.purchases = new Purchases(transport);
|
|
1489
1238
|
this.invoices = new Invoices(transport);
|
|
1490
1239
|
this.payments = new Payments(transport);
|
|
1491
|
-
this.credits = new Credits(transport);
|
|
1492
|
-
this.composites = new Composites(transport);
|
|
1493
|
-
this.outcomes = new Outcomes(transport);
|
|
1494
|
-
this.units = new Units(transport);
|
|
1495
|
-
this.webhooks = new Webhooks(transport);
|
|
1496
1240
|
this.portal = new Portal(transport);
|
|
1497
|
-
this.workspace = new Workspace(transport);
|
|
1498
1241
|
}
|
|
1499
1242
|
/** Number of signals currently buffered (async mode). */
|
|
1500
1243
|
get pending() {
|