@ophelio/sdk 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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 ?? crypto.randomUUID(),
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 ?? crypto.randomUUID(),
410
+ idempotencyKey: resolveIdempotencyKey(idempotencyKey),
402
411
  retryable: true,
403
412
  options: requestOptions
404
413
  })).usage;
@@ -525,6 +534,44 @@ var MembersResource = class extends APIResource {
525
534
  options
526
535
  })).entitlements;
527
536
  }
537
+ /**
538
+ * Updates a member's details. Accepts `name`, `date_of_birth` and `role`
539
+ * (a member-role code). To reassign the primary member use `setPrimary`;
540
+ * to rotate a card use `reissueCard`.
541
+ */
542
+ update(id, params, options) {
543
+ return this.transport.request({
544
+ method: "PATCH",
545
+ path: `/api/v1/members/${encodeURIComponent(id)}`,
546
+ body: params,
547
+ retryable: false,
548
+ options
549
+ });
550
+ }
551
+ /**
552
+ * Remove a member from its membership. Rejected if it is the last member
553
+ * or the sole primary — reassign the primary first with `setPrimary`.
554
+ */
555
+ remove(id, options) {
556
+ return this.transport.request({
557
+ method: "DELETE",
558
+ path: `/api/v1/members/${encodeURIComponent(id)}`,
559
+ retryable: false,
560
+ options
561
+ });
562
+ }
563
+ /**
564
+ * Make this member the primary of its membership, demoting the current
565
+ * primary atomically. A no-op if it is already primary.
566
+ */
567
+ setPrimary(id, options) {
568
+ return this.transport.request({
569
+ method: "POST",
570
+ path: `/api/v1/members/${encodeURIComponent(id)}/set-primary`,
571
+ retryable: false,
572
+ options
573
+ });
574
+ }
528
575
  /** Issue a fresh card id, invalidating the old card at the gate. */
529
576
  reissueCard(id, params = {}, options) {
530
577
  return this.transport.request({
@@ -561,13 +608,22 @@ var MembershipsResource = class extends APIResource {
561
608
  options
562
609
  });
563
610
  }
564
- create(params, options) {
611
+ /**
612
+ * Create a membership atomically (record, members, first term, optional
613
+ * payment). Idempotent: the Idempotency-Key is generated once per call (and
614
+ * reused across the SDK's internal retries), so a retried create returns the
615
+ * original membership instead of creating a duplicate. Supply your own key to
616
+ * dedupe application-level retries across processes.
617
+ */
618
+ create(params, options = {}) {
619
+ const { idempotencyKey, ...requestOptions } = options;
565
620
  return this.transport.request({
566
621
  method: "POST",
567
622
  path: "/api/v1/memberships",
568
623
  body: params,
569
- retryable: false,
570
- options
624
+ idempotencyKey: resolveIdempotencyKey(idempotencyKey),
625
+ retryable: true,
626
+ options: requestOptions
571
627
  });
572
628
  }
573
629
  update(id, params, options) {
@@ -614,14 +670,19 @@ var MembershipsResource = class extends APIResource {
614
670
  /**
615
671
  * Report a payment outcome. Ophel.io never processes payments — your
616
672
  * payment provider does; this records the result and drives dunning.
673
+ * Idempotent: the Idempotency-Key is generated once per call (and reused
674
+ * across the SDK's internal retries), so a retried report records the
675
+ * transaction once and does not advance dunning twice.
617
676
  */
618
- createTransaction(id, params, options) {
677
+ createTransaction(id, params, options = {}) {
678
+ const { idempotencyKey, ...requestOptions } = options;
619
679
  return this.transport.request({
620
680
  method: "POST",
621
681
  path: `/api/v1/memberships/${encodeURIComponent(id)}/transactions`,
622
682
  body: params,
623
- retryable: false,
624
- options
683
+ idempotencyKey: resolveIdempotencyKey(idempotencyKey),
684
+ retryable: true,
685
+ options: requestOptions
625
686
  });
626
687
  }
627
688
  async listMembers(id, options) {
@@ -632,17 +693,38 @@ var MembershipsResource = class extends APIResource {
632
693
  options
633
694
  })).members;
634
695
  }
635
- /** Open the next term. Rejected (409) while cancelled or cancellation-pending. */
636
- renew(id, params, options) {
696
+ /**
697
+ * Add a member to an existing membership, up to the plan's max party size.
698
+ * `role` is a member-role code; an optional `email` links the member to a
699
+ * customer record. Rejected on cancelled or expired memberships.
700
+ */
701
+ addMember(id, params, options) {
637
702
  return this.transport.request({
638
703
  method: "POST",
639
- path: `/api/v1/memberships/${encodeURIComponent(id)}/renew`,
704
+ path: `/api/v1/memberships/${encodeURIComponent(id)}/members`,
640
705
  body: params,
641
706
  retryable: false,
642
707
  options
643
708
  });
644
709
  }
645
710
  /**
711
+ * Open the next term. Rejected (409) while cancelled or cancellation-pending.
712
+ * Idempotent: the Idempotency-Key is generated once per call (and reused
713
+ * across the SDK's internal retries), so a retried renewal returns the
714
+ * original result instead of opening a second term.
715
+ */
716
+ renew(id, params, options = {}) {
717
+ const { idempotencyKey, ...requestOptions } = options;
718
+ return this.transport.request({
719
+ method: "POST",
720
+ path: `/api/v1/memberships/${encodeURIComponent(id)}/renew`,
721
+ body: params,
722
+ idempotencyKey: resolveIdempotencyKey(idempotencyKey),
723
+ retryable: true,
724
+ options: requestOptions
725
+ });
726
+ }
727
+ /**
646
728
  * Move to a linked higher plan. Applies immediately or schedules at term
647
729
  * end — `scheduled_change` is non-null in the deferred case.
648
730
  */
@@ -1187,7 +1269,9 @@ const WEBHOOK_EVENT_CODES = [
1187
1269
  "membership.downgraded",
1188
1270
  "scheduled_change.failed",
1189
1271
  "entitlement.used",
1272
+ "member.added",
1190
1273
  "member.card_issued",
1274
+ "member.updated",
1191
1275
  "member.removed",
1192
1276
  "plan.updated"
1193
1277
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ophelio/sdk",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Official JavaScript / TypeScript SDK for the Ophel.io membership & entitlement API.",
5
5
  "license": "MIT",
6
6
  "author": "Ophel.io",