@ophelio/sdk 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/dist/index.cjs +42 -12
- package/dist/index.d.cts +62 -11
- package/dist/index.d.mts +62 -11
- package/dist/index.mjs +42 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,10 +66,12 @@ GETs are retried automatically on network errors / 429 / 502 / 503 / 504
|
|
|
66
66
|
(exponential backoff with jitter, `Retry-After` honoured; configure with
|
|
67
67
|
`maxRetries`, default 2). Plain mutations are **never** retried.
|
|
68
68
|
|
|
69
|
-
`
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
The idempotency-keyed mutations — `memberships.create`, `memberships.renew`,
|
|
70
|
+
`memberships.createTransaction`, `entitlements.redeem`, and
|
|
71
|
+
`entitlements.recordUsage` — each generate a key per call and reuse it across
|
|
72
|
+
the SDK's own retries, so they're safely retried on transient failures. If you
|
|
73
|
+
retry at the application level (offline gate queues, at-least-once job runners),
|
|
74
|
+
pass your own key so replays are recognised across processes:
|
|
73
75
|
|
|
74
76
|
```ts
|
|
75
77
|
await ophelio.entitlements.redeem(
|
|
@@ -170,7 +172,8 @@ Everything reachable with an API key is covered:
|
|
|
170
172
|
| `webhookSubscriptions` | `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)`, `listDeliveries(id, params?)` |
|
|
171
173
|
|
|
172
174
|
Every method accepts a trailing `options` argument: `{ signal?, headers? }`
|
|
173
|
-
(plus `idempotencyKey?` on
|
|
175
|
+
(plus `idempotencyKey?` on the idempotency-keyed mutations: `memberships.create`
|
|
176
|
+
/ `renew` / `createTransaction` and `entitlements.redeem` / `recordUsage`).
|
|
174
177
|
|
|
175
178
|
Endpoints requiring a user session (API key management, organisation and
|
|
176
179
|
project admin) are intentionally not in the SDK — API keys cannot call them.
|
package/dist/index.cjs
CHANGED
|
@@ -117,6 +117,15 @@ function sleep(ms) {
|
|
|
117
117
|
const DEFAULT_BASE_URL = "https://api.ophel.io";
|
|
118
118
|
const DEFAULT_TIMEOUT_MS = 3e4;
|
|
119
119
|
const DEFAULT_MAX_RETRIES = 2;
|
|
120
|
+
/**
|
|
121
|
+
* Resolves the caller-supplied idempotency key to the value sent on the wire.
|
|
122
|
+
* Trims it and falls back to a generated key when it is absent, empty, or
|
|
123
|
+
* whitespace-only — a blank key must never leave an idempotency-keyed mutation
|
|
124
|
+
* retryable but unkeyed, or a retried write could duplicate.
|
|
125
|
+
*/
|
|
126
|
+
function resolveIdempotencyKey(idempotencyKey) {
|
|
127
|
+
return idempotencyKey?.trim() || crypto.randomUUID();
|
|
128
|
+
}
|
|
120
129
|
var Transport = class {
|
|
121
130
|
apiKey;
|
|
122
131
|
baseUrl;
|
|
@@ -384,7 +393,7 @@ var EntitlementsResource = class extends APIResource {
|
|
|
384
393
|
method: "POST",
|
|
385
394
|
path: "/api/v1/entitlements/redeem",
|
|
386
395
|
body: params,
|
|
387
|
-
idempotencyKey: idempotencyKey
|
|
396
|
+
idempotencyKey: resolveIdempotencyKey(idempotencyKey),
|
|
388
397
|
retryable: true,
|
|
389
398
|
options: requestOptions
|
|
390
399
|
});
|
|
@@ -399,7 +408,7 @@ var EntitlementsResource = class extends APIResource {
|
|
|
399
408
|
method: "POST",
|
|
400
409
|
path: "/api/v1/entitlements/usage",
|
|
401
410
|
body: params,
|
|
402
|
-
idempotencyKey: idempotencyKey
|
|
411
|
+
idempotencyKey: resolveIdempotencyKey(idempotencyKey),
|
|
403
412
|
retryable: true,
|
|
404
413
|
options: requestOptions
|
|
405
414
|
})).usage;
|
|
@@ -562,13 +571,22 @@ var MembershipsResource = class extends APIResource {
|
|
|
562
571
|
options
|
|
563
572
|
});
|
|
564
573
|
}
|
|
565
|
-
|
|
574
|
+
/**
|
|
575
|
+
* Create a membership atomically (record, members, first term, optional
|
|
576
|
+
* payment). Idempotent: the Idempotency-Key is generated once per call (and
|
|
577
|
+
* reused across the SDK's internal retries), so a retried create returns the
|
|
578
|
+
* original membership instead of creating a duplicate. Supply your own key to
|
|
579
|
+
* dedupe application-level retries across processes.
|
|
580
|
+
*/
|
|
581
|
+
create(params, options = {}) {
|
|
582
|
+
const { idempotencyKey, ...requestOptions } = options;
|
|
566
583
|
return this.transport.request({
|
|
567
584
|
method: "POST",
|
|
568
585
|
path: "/api/v1/memberships",
|
|
569
586
|
body: params,
|
|
570
|
-
|
|
571
|
-
|
|
587
|
+
idempotencyKey: resolveIdempotencyKey(idempotencyKey),
|
|
588
|
+
retryable: true,
|
|
589
|
+
options: requestOptions
|
|
572
590
|
});
|
|
573
591
|
}
|
|
574
592
|
update(id, params, options) {
|
|
@@ -615,14 +633,19 @@ var MembershipsResource = class extends APIResource {
|
|
|
615
633
|
/**
|
|
616
634
|
* Report a payment outcome. Ophel.io never processes payments — your
|
|
617
635
|
* payment provider does; this records the result and drives dunning.
|
|
636
|
+
* Idempotent: the Idempotency-Key is generated once per call (and reused
|
|
637
|
+
* across the SDK's internal retries), so a retried report records the
|
|
638
|
+
* transaction once and does not advance dunning twice.
|
|
618
639
|
*/
|
|
619
|
-
createTransaction(id, params, options) {
|
|
640
|
+
createTransaction(id, params, options = {}) {
|
|
641
|
+
const { idempotencyKey, ...requestOptions } = options;
|
|
620
642
|
return this.transport.request({
|
|
621
643
|
method: "POST",
|
|
622
644
|
path: `/api/v1/memberships/${encodeURIComponent(id)}/transactions`,
|
|
623
645
|
body: params,
|
|
624
|
-
|
|
625
|
-
|
|
646
|
+
idempotencyKey: resolveIdempotencyKey(idempotencyKey),
|
|
647
|
+
retryable: true,
|
|
648
|
+
options: requestOptions
|
|
626
649
|
});
|
|
627
650
|
}
|
|
628
651
|
async listMembers(id, options) {
|
|
@@ -633,14 +656,21 @@ var MembershipsResource = class extends APIResource {
|
|
|
633
656
|
options
|
|
634
657
|
})).members;
|
|
635
658
|
}
|
|
636
|
-
/**
|
|
637
|
-
|
|
659
|
+
/**
|
|
660
|
+
* Open the next term. Rejected (409) while cancelled or cancellation-pending.
|
|
661
|
+
* Idempotent: the Idempotency-Key is generated once per call (and reused
|
|
662
|
+
* across the SDK's internal retries), so a retried renewal returns the
|
|
663
|
+
* original result instead of opening a second term.
|
|
664
|
+
*/
|
|
665
|
+
renew(id, params, options = {}) {
|
|
666
|
+
const { idempotencyKey, ...requestOptions } = options;
|
|
638
667
|
return this.transport.request({
|
|
639
668
|
method: "POST",
|
|
640
669
|
path: `/api/v1/memberships/${encodeURIComponent(id)}/renew`,
|
|
641
670
|
body: params,
|
|
642
|
-
|
|
643
|
-
|
|
671
|
+
idempotencyKey: resolveIdempotencyKey(idempotencyKey),
|
|
672
|
+
retryable: true,
|
|
673
|
+
options: requestOptions
|
|
644
674
|
});
|
|
645
675
|
}
|
|
646
676
|
/**
|
package/dist/index.d.cts
CHANGED
|
@@ -2916,8 +2916,7 @@ interface operations {
|
|
|
2916
2916
|
parameters: {
|
|
2917
2917
|
query?: never;
|
|
2918
2918
|
header: {
|
|
2919
|
-
|
|
2920
|
-
"Idempotency-Key": string;
|
|
2919
|
+
/** @description Required idempotency key, up to 255 characters. Deduplicated per member: repeating a request with the same key and member returns the original redemption, and reusing that key for the same member with a different entitlement returns 409. A longer key is rejected with 400. */"Idempotency-Key": string;
|
|
2921
2920
|
};
|
|
2922
2921
|
path?: never;
|
|
2923
2922
|
cookie?: never;
|
|
@@ -2952,14 +2951,21 @@ interface operations {
|
|
|
2952
2951
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
2953
2952
|
};
|
|
2954
2953
|
};
|
|
2954
|
+
409: {
|
|
2955
|
+
headers: {
|
|
2956
|
+
[name: string]: unknown;
|
|
2957
|
+
};
|
|
2958
|
+
content: {
|
|
2959
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
2960
|
+
};
|
|
2961
|
+
};
|
|
2955
2962
|
};
|
|
2956
2963
|
};
|
|
2957
2964
|
EntitlementsController_usage: {
|
|
2958
2965
|
parameters: {
|
|
2959
2966
|
query?: never;
|
|
2960
2967
|
header: {
|
|
2961
|
-
|
|
2962
|
-
"Idempotency-Key": string;
|
|
2968
|
+
/** @description Required idempotency key, up to 255 characters. One usage row is recorded per member, so the same key may carry different members across calls. A longer key is rejected with 400. */"Idempotency-Key": string;
|
|
2963
2969
|
};
|
|
2964
2970
|
path?: never;
|
|
2965
2971
|
cookie?: never;
|
|
@@ -3654,7 +3660,9 @@ interface operations {
|
|
|
3654
3660
|
MembershipsController_create: {
|
|
3655
3661
|
parameters: {
|
|
3656
3662
|
query?: never;
|
|
3657
|
-
header?:
|
|
3663
|
+
header?: {
|
|
3664
|
+
/** @description Optional idempotency key, up to 255 characters. Repeating a request with the same key returns the original result; reusing a key with a different request body returns 409. A longer key is rejected with 400, and an empty or whitespace-only value is treated as no key. */"Idempotency-Key"?: string;
|
|
3665
|
+
};
|
|
3658
3666
|
path?: never;
|
|
3659
3667
|
cookie?: never;
|
|
3660
3668
|
};
|
|
@@ -3680,6 +3688,14 @@ interface operations {
|
|
|
3680
3688
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
3681
3689
|
};
|
|
3682
3690
|
};
|
|
3691
|
+
409: {
|
|
3692
|
+
headers: {
|
|
3693
|
+
[name: string]: unknown;
|
|
3694
|
+
};
|
|
3695
|
+
content: {
|
|
3696
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
3697
|
+
};
|
|
3698
|
+
};
|
|
3683
3699
|
};
|
|
3684
3700
|
};
|
|
3685
3701
|
MembershipsController_get: {
|
|
@@ -3828,7 +3844,9 @@ interface operations {
|
|
|
3828
3844
|
MembershipsController_renew: {
|
|
3829
3845
|
parameters: {
|
|
3830
3846
|
query?: never;
|
|
3831
|
-
header?:
|
|
3847
|
+
header?: {
|
|
3848
|
+
/** @description Optional idempotency key, up to 255 characters. Repeating a request with the same key returns the original result; reusing a key with a different request body returns 409. A longer key is rejected with 400, and an empty or whitespace-only value is treated as no key. */"Idempotency-Key"?: string;
|
|
3849
|
+
};
|
|
3832
3850
|
path?: never;
|
|
3833
3851
|
cookie?: never;
|
|
3834
3852
|
};
|
|
@@ -3854,6 +3872,14 @@ interface operations {
|
|
|
3854
3872
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
3855
3873
|
};
|
|
3856
3874
|
};
|
|
3875
|
+
409: {
|
|
3876
|
+
headers: {
|
|
3877
|
+
[name: string]: unknown;
|
|
3878
|
+
};
|
|
3879
|
+
content: {
|
|
3880
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
3881
|
+
};
|
|
3882
|
+
};
|
|
3857
3883
|
};
|
|
3858
3884
|
};
|
|
3859
3885
|
MembershipsController_upgrade: {
|
|
@@ -3999,7 +4025,9 @@ interface operations {
|
|
|
3999
4025
|
MembershipsController_recordTransaction: {
|
|
4000
4026
|
parameters: {
|
|
4001
4027
|
query?: never;
|
|
4002
|
-
header?:
|
|
4028
|
+
header?: {
|
|
4029
|
+
/** @description Optional idempotency key, up to 255 characters. Repeating a request with the same key returns the original result; reusing a key with a different request body returns 409. A longer key is rejected with 400, and an empty or whitespace-only value is treated as no key. */"Idempotency-Key"?: string;
|
|
4030
|
+
};
|
|
4003
4031
|
path?: never;
|
|
4004
4032
|
cookie?: never;
|
|
4005
4033
|
};
|
|
@@ -4025,6 +4053,14 @@ interface operations {
|
|
|
4025
4053
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
4026
4054
|
};
|
|
4027
4055
|
};
|
|
4056
|
+
409: {
|
|
4057
|
+
headers: {
|
|
4058
|
+
[name: string]: unknown;
|
|
4059
|
+
};
|
|
4060
|
+
content: {
|
|
4061
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
4062
|
+
};
|
|
4063
|
+
};
|
|
4028
4064
|
};
|
|
4029
4065
|
};
|
|
4030
4066
|
MembershipsController_listTermTransactions: {
|
|
@@ -4523,7 +4559,14 @@ declare class MembersResource extends APIResource {
|
|
|
4523
4559
|
declare class MembershipsResource extends APIResource {
|
|
4524
4560
|
list(params?: PageParams, options?: RequestOptions): Promise<Page<Membership>>;
|
|
4525
4561
|
get(id: string, options?: RequestOptions): Promise<Membership>;
|
|
4526
|
-
|
|
4562
|
+
/**
|
|
4563
|
+
* Create a membership atomically (record, members, first term, optional
|
|
4564
|
+
* payment). Idempotent: the Idempotency-Key is generated once per call (and
|
|
4565
|
+
* reused across the SDK's internal retries), so a retried create returns the
|
|
4566
|
+
* original membership instead of creating a duplicate. Supply your own key to
|
|
4567
|
+
* dedupe application-level retries across processes.
|
|
4568
|
+
*/
|
|
4569
|
+
create(params: CreateMembershipParams, options?: IdempotentRequestOptions): Promise<Membership>;
|
|
4527
4570
|
update(id: string, params: UpdateMembershipParams, options?: RequestOptions): Promise<Membership>;
|
|
4528
4571
|
/** Cancellation is a state change, not a delete — see also `uncancel`. */
|
|
4529
4572
|
cancel(id: string, params: CancelMembershipParams, options?: RequestOptions): Promise<Membership>;
|
|
@@ -4532,11 +4575,19 @@ declare class MembershipsResource extends APIResource {
|
|
|
4532
4575
|
/**
|
|
4533
4576
|
* Report a payment outcome. Ophel.io never processes payments — your
|
|
4534
4577
|
* payment provider does; this records the result and drives dunning.
|
|
4578
|
+
* Idempotent: the Idempotency-Key is generated once per call (and reused
|
|
4579
|
+
* across the SDK's internal retries), so a retried report records the
|
|
4580
|
+
* transaction once and does not advance dunning twice.
|
|
4535
4581
|
*/
|
|
4536
|
-
createTransaction(id: string, params: CreateTransactionParams, options?:
|
|
4582
|
+
createTransaction(id: string, params: CreateTransactionParams, options?: IdempotentRequestOptions): Promise<Transaction>;
|
|
4537
4583
|
listMembers(id: string, options?: RequestOptions): Promise<Member[]>;
|
|
4538
|
-
/**
|
|
4539
|
-
|
|
4584
|
+
/**
|
|
4585
|
+
* Open the next term. Rejected (409) while cancelled or cancellation-pending.
|
|
4586
|
+
* Idempotent: the Idempotency-Key is generated once per call (and reused
|
|
4587
|
+
* across the SDK's internal retries), so a retried renewal returns the
|
|
4588
|
+
* original result instead of opening a second term.
|
|
4589
|
+
*/
|
|
4590
|
+
renew(id: string, params: RenewMembershipParams, options?: IdempotentRequestOptions): Promise<Membership>;
|
|
4540
4591
|
/**
|
|
4541
4592
|
* Move to a linked higher plan. Applies immediately or schedules at term
|
|
4542
4593
|
* end — `scheduled_change` is non-null in the deferred case.
|
package/dist/index.d.mts
CHANGED
|
@@ -2916,8 +2916,7 @@ interface operations {
|
|
|
2916
2916
|
parameters: {
|
|
2917
2917
|
query?: never;
|
|
2918
2918
|
header: {
|
|
2919
|
-
|
|
2920
|
-
"Idempotency-Key": string;
|
|
2919
|
+
/** @description Required idempotency key, up to 255 characters. Deduplicated per member: repeating a request with the same key and member returns the original redemption, and reusing that key for the same member with a different entitlement returns 409. A longer key is rejected with 400. */"Idempotency-Key": string;
|
|
2921
2920
|
};
|
|
2922
2921
|
path?: never;
|
|
2923
2922
|
cookie?: never;
|
|
@@ -2952,14 +2951,21 @@ interface operations {
|
|
|
2952
2951
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
2953
2952
|
};
|
|
2954
2953
|
};
|
|
2954
|
+
409: {
|
|
2955
|
+
headers: {
|
|
2956
|
+
[name: string]: unknown;
|
|
2957
|
+
};
|
|
2958
|
+
content: {
|
|
2959
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
2960
|
+
};
|
|
2961
|
+
};
|
|
2955
2962
|
};
|
|
2956
2963
|
};
|
|
2957
2964
|
EntitlementsController_usage: {
|
|
2958
2965
|
parameters: {
|
|
2959
2966
|
query?: never;
|
|
2960
2967
|
header: {
|
|
2961
|
-
|
|
2962
|
-
"Idempotency-Key": string;
|
|
2968
|
+
/** @description Required idempotency key, up to 255 characters. One usage row is recorded per member, so the same key may carry different members across calls. A longer key is rejected with 400. */"Idempotency-Key": string;
|
|
2963
2969
|
};
|
|
2964
2970
|
path?: never;
|
|
2965
2971
|
cookie?: never;
|
|
@@ -3654,7 +3660,9 @@ interface operations {
|
|
|
3654
3660
|
MembershipsController_create: {
|
|
3655
3661
|
parameters: {
|
|
3656
3662
|
query?: never;
|
|
3657
|
-
header?:
|
|
3663
|
+
header?: {
|
|
3664
|
+
/** @description Optional idempotency key, up to 255 characters. Repeating a request with the same key returns the original result; reusing a key with a different request body returns 409. A longer key is rejected with 400, and an empty or whitespace-only value is treated as no key. */"Idempotency-Key"?: string;
|
|
3665
|
+
};
|
|
3658
3666
|
path?: never;
|
|
3659
3667
|
cookie?: never;
|
|
3660
3668
|
};
|
|
@@ -3680,6 +3688,14 @@ interface operations {
|
|
|
3680
3688
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
3681
3689
|
};
|
|
3682
3690
|
};
|
|
3691
|
+
409: {
|
|
3692
|
+
headers: {
|
|
3693
|
+
[name: string]: unknown;
|
|
3694
|
+
};
|
|
3695
|
+
content: {
|
|
3696
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
3697
|
+
};
|
|
3698
|
+
};
|
|
3683
3699
|
};
|
|
3684
3700
|
};
|
|
3685
3701
|
MembershipsController_get: {
|
|
@@ -3828,7 +3844,9 @@ interface operations {
|
|
|
3828
3844
|
MembershipsController_renew: {
|
|
3829
3845
|
parameters: {
|
|
3830
3846
|
query?: never;
|
|
3831
|
-
header?:
|
|
3847
|
+
header?: {
|
|
3848
|
+
/** @description Optional idempotency key, up to 255 characters. Repeating a request with the same key returns the original result; reusing a key with a different request body returns 409. A longer key is rejected with 400, and an empty or whitespace-only value is treated as no key. */"Idempotency-Key"?: string;
|
|
3849
|
+
};
|
|
3832
3850
|
path?: never;
|
|
3833
3851
|
cookie?: never;
|
|
3834
3852
|
};
|
|
@@ -3854,6 +3872,14 @@ interface operations {
|
|
|
3854
3872
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
3855
3873
|
};
|
|
3856
3874
|
};
|
|
3875
|
+
409: {
|
|
3876
|
+
headers: {
|
|
3877
|
+
[name: string]: unknown;
|
|
3878
|
+
};
|
|
3879
|
+
content: {
|
|
3880
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
3881
|
+
};
|
|
3882
|
+
};
|
|
3857
3883
|
};
|
|
3858
3884
|
};
|
|
3859
3885
|
MembershipsController_upgrade: {
|
|
@@ -3999,7 +4025,9 @@ interface operations {
|
|
|
3999
4025
|
MembershipsController_recordTransaction: {
|
|
4000
4026
|
parameters: {
|
|
4001
4027
|
query?: never;
|
|
4002
|
-
header?:
|
|
4028
|
+
header?: {
|
|
4029
|
+
/** @description Optional idempotency key, up to 255 characters. Repeating a request with the same key returns the original result; reusing a key with a different request body returns 409. A longer key is rejected with 400, and an empty or whitespace-only value is treated as no key. */"Idempotency-Key"?: string;
|
|
4030
|
+
};
|
|
4003
4031
|
path?: never;
|
|
4004
4032
|
cookie?: never;
|
|
4005
4033
|
};
|
|
@@ -4025,6 +4053,14 @@ interface operations {
|
|
|
4025
4053
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
4026
4054
|
};
|
|
4027
4055
|
};
|
|
4056
|
+
409: {
|
|
4057
|
+
headers: {
|
|
4058
|
+
[name: string]: unknown;
|
|
4059
|
+
};
|
|
4060
|
+
content: {
|
|
4061
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
4062
|
+
};
|
|
4063
|
+
};
|
|
4028
4064
|
};
|
|
4029
4065
|
};
|
|
4030
4066
|
MembershipsController_listTermTransactions: {
|
|
@@ -4523,7 +4559,14 @@ declare class MembersResource extends APIResource {
|
|
|
4523
4559
|
declare class MembershipsResource extends APIResource {
|
|
4524
4560
|
list(params?: PageParams, options?: RequestOptions): Promise<Page<Membership>>;
|
|
4525
4561
|
get(id: string, options?: RequestOptions): Promise<Membership>;
|
|
4526
|
-
|
|
4562
|
+
/**
|
|
4563
|
+
* Create a membership atomically (record, members, first term, optional
|
|
4564
|
+
* payment). Idempotent: the Idempotency-Key is generated once per call (and
|
|
4565
|
+
* reused across the SDK's internal retries), so a retried create returns the
|
|
4566
|
+
* original membership instead of creating a duplicate. Supply your own key to
|
|
4567
|
+
* dedupe application-level retries across processes.
|
|
4568
|
+
*/
|
|
4569
|
+
create(params: CreateMembershipParams, options?: IdempotentRequestOptions): Promise<Membership>;
|
|
4527
4570
|
update(id: string, params: UpdateMembershipParams, options?: RequestOptions): Promise<Membership>;
|
|
4528
4571
|
/** Cancellation is a state change, not a delete — see also `uncancel`. */
|
|
4529
4572
|
cancel(id: string, params: CancelMembershipParams, options?: RequestOptions): Promise<Membership>;
|
|
@@ -4532,11 +4575,19 @@ declare class MembershipsResource extends APIResource {
|
|
|
4532
4575
|
/**
|
|
4533
4576
|
* Report a payment outcome. Ophel.io never processes payments — your
|
|
4534
4577
|
* payment provider does; this records the result and drives dunning.
|
|
4578
|
+
* Idempotent: the Idempotency-Key is generated once per call (and reused
|
|
4579
|
+
* across the SDK's internal retries), so a retried report records the
|
|
4580
|
+
* transaction once and does not advance dunning twice.
|
|
4535
4581
|
*/
|
|
4536
|
-
createTransaction(id: string, params: CreateTransactionParams, options?:
|
|
4582
|
+
createTransaction(id: string, params: CreateTransactionParams, options?: IdempotentRequestOptions): Promise<Transaction>;
|
|
4537
4583
|
listMembers(id: string, options?: RequestOptions): Promise<Member[]>;
|
|
4538
|
-
/**
|
|
4539
|
-
|
|
4584
|
+
/**
|
|
4585
|
+
* Open the next term. Rejected (409) while cancelled or cancellation-pending.
|
|
4586
|
+
* Idempotent: the Idempotency-Key is generated once per call (and reused
|
|
4587
|
+
* across the SDK's internal retries), so a retried renewal returns the
|
|
4588
|
+
* original result instead of opening a second term.
|
|
4589
|
+
*/
|
|
4590
|
+
renew(id: string, params: RenewMembershipParams, options?: IdempotentRequestOptions): Promise<Membership>;
|
|
4540
4591
|
/**
|
|
4541
4592
|
* Move to a linked higher plan. Applies immediately or schedules at term
|
|
4542
4593
|
* end — `scheduled_change` is non-null in the deferred case.
|
package/dist/index.mjs
CHANGED
|
@@ -116,6 +116,15 @@ function sleep(ms) {
|
|
|
116
116
|
const DEFAULT_BASE_URL = "https://api.ophel.io";
|
|
117
117
|
const DEFAULT_TIMEOUT_MS = 3e4;
|
|
118
118
|
const DEFAULT_MAX_RETRIES = 2;
|
|
119
|
+
/**
|
|
120
|
+
* Resolves the caller-supplied idempotency key to the value sent on the wire.
|
|
121
|
+
* Trims it and falls back to a generated key when it is absent, empty, or
|
|
122
|
+
* whitespace-only — a blank key must never leave an idempotency-keyed mutation
|
|
123
|
+
* retryable but unkeyed, or a retried write could duplicate.
|
|
124
|
+
*/
|
|
125
|
+
function resolveIdempotencyKey(idempotencyKey) {
|
|
126
|
+
return idempotencyKey?.trim() || crypto.randomUUID();
|
|
127
|
+
}
|
|
119
128
|
var Transport = class {
|
|
120
129
|
apiKey;
|
|
121
130
|
baseUrl;
|
|
@@ -383,7 +392,7 @@ var EntitlementsResource = class extends APIResource {
|
|
|
383
392
|
method: "POST",
|
|
384
393
|
path: "/api/v1/entitlements/redeem",
|
|
385
394
|
body: params,
|
|
386
|
-
idempotencyKey: idempotencyKey
|
|
395
|
+
idempotencyKey: resolveIdempotencyKey(idempotencyKey),
|
|
387
396
|
retryable: true,
|
|
388
397
|
options: requestOptions
|
|
389
398
|
});
|
|
@@ -398,7 +407,7 @@ var EntitlementsResource = class extends APIResource {
|
|
|
398
407
|
method: "POST",
|
|
399
408
|
path: "/api/v1/entitlements/usage",
|
|
400
409
|
body: params,
|
|
401
|
-
idempotencyKey: idempotencyKey
|
|
410
|
+
idempotencyKey: resolveIdempotencyKey(idempotencyKey),
|
|
402
411
|
retryable: true,
|
|
403
412
|
options: requestOptions
|
|
404
413
|
})).usage;
|
|
@@ -561,13 +570,22 @@ var MembershipsResource = class extends APIResource {
|
|
|
561
570
|
options
|
|
562
571
|
});
|
|
563
572
|
}
|
|
564
|
-
|
|
573
|
+
/**
|
|
574
|
+
* Create a membership atomically (record, members, first term, optional
|
|
575
|
+
* payment). Idempotent: the Idempotency-Key is generated once per call (and
|
|
576
|
+
* reused across the SDK's internal retries), so a retried create returns the
|
|
577
|
+
* original membership instead of creating a duplicate. Supply your own key to
|
|
578
|
+
* dedupe application-level retries across processes.
|
|
579
|
+
*/
|
|
580
|
+
create(params, options = {}) {
|
|
581
|
+
const { idempotencyKey, ...requestOptions } = options;
|
|
565
582
|
return this.transport.request({
|
|
566
583
|
method: "POST",
|
|
567
584
|
path: "/api/v1/memberships",
|
|
568
585
|
body: params,
|
|
569
|
-
|
|
570
|
-
|
|
586
|
+
idempotencyKey: resolveIdempotencyKey(idempotencyKey),
|
|
587
|
+
retryable: true,
|
|
588
|
+
options: requestOptions
|
|
571
589
|
});
|
|
572
590
|
}
|
|
573
591
|
update(id, params, options) {
|
|
@@ -614,14 +632,19 @@ var MembershipsResource = class extends APIResource {
|
|
|
614
632
|
/**
|
|
615
633
|
* Report a payment outcome. Ophel.io never processes payments — your
|
|
616
634
|
* payment provider does; this records the result and drives dunning.
|
|
635
|
+
* Idempotent: the Idempotency-Key is generated once per call (and reused
|
|
636
|
+
* across the SDK's internal retries), so a retried report records the
|
|
637
|
+
* transaction once and does not advance dunning twice.
|
|
617
638
|
*/
|
|
618
|
-
createTransaction(id, params, options) {
|
|
639
|
+
createTransaction(id, params, options = {}) {
|
|
640
|
+
const { idempotencyKey, ...requestOptions } = options;
|
|
619
641
|
return this.transport.request({
|
|
620
642
|
method: "POST",
|
|
621
643
|
path: `/api/v1/memberships/${encodeURIComponent(id)}/transactions`,
|
|
622
644
|
body: params,
|
|
623
|
-
|
|
624
|
-
|
|
645
|
+
idempotencyKey: resolveIdempotencyKey(idempotencyKey),
|
|
646
|
+
retryable: true,
|
|
647
|
+
options: requestOptions
|
|
625
648
|
});
|
|
626
649
|
}
|
|
627
650
|
async listMembers(id, options) {
|
|
@@ -632,14 +655,21 @@ var MembershipsResource = class extends APIResource {
|
|
|
632
655
|
options
|
|
633
656
|
})).members;
|
|
634
657
|
}
|
|
635
|
-
/**
|
|
636
|
-
|
|
658
|
+
/**
|
|
659
|
+
* Open the next term. Rejected (409) while cancelled or cancellation-pending.
|
|
660
|
+
* Idempotent: the Idempotency-Key is generated once per call (and reused
|
|
661
|
+
* across the SDK's internal retries), so a retried renewal returns the
|
|
662
|
+
* original result instead of opening a second term.
|
|
663
|
+
*/
|
|
664
|
+
renew(id, params, options = {}) {
|
|
665
|
+
const { idempotencyKey, ...requestOptions } = options;
|
|
637
666
|
return this.transport.request({
|
|
638
667
|
method: "POST",
|
|
639
668
|
path: `/api/v1/memberships/${encodeURIComponent(id)}/renew`,
|
|
640
669
|
body: params,
|
|
641
|
-
|
|
642
|
-
|
|
670
|
+
idempotencyKey: resolveIdempotencyKey(idempotencyKey),
|
|
671
|
+
retryable: true,
|
|
672
|
+
options: requestOptions
|
|
643
673
|
});
|
|
644
674
|
}
|
|
645
675
|
/**
|