@moonbase.sh/storefront-api 3.2.0 → 3.3.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 CHANGED
@@ -76,6 +76,40 @@ const redeemed = await client.vouchers.redeem('MY-CODE')
76
76
  console.log(redeemed)
77
77
  ```
78
78
 
79
+ ### Enroll a customer in a group
80
+
81
+ Merchant-owned customer lists that have been opened to public sign-ups can be
82
+ named by ID on sign-up, on a newsletter subscription, and on an order:
83
+
84
+ ```ts
85
+ await client.identity.signUp('Jane', 'jane@example.com', 'password', null, true, true, true, {
86
+ groupIds: ['newsletter-2026'],
87
+ })
88
+
89
+ await client.communications.subscribe({ email: 'jane@example.com', groupIds: ['newsletter-2026'] })
90
+
91
+ // On an order, after it has been pushed and before it is paid. Additive: each
92
+ // call adds to what the order already carries.
93
+ await client.orders.joinGroups(order.id, ['buyers-2026'])
94
+ ```
95
+
96
+ None of those three report which groups were applied. An ID naming a list that
97
+ is closed, deleted, rule-driven or another tenant's is skipped in silence, so a
98
+ stale ID can never fail a registration or a sale. IDs are matched lowercase and
99
+ at most five per request are applied.
100
+
101
+ For a customer who is already signed in, joining is a request of its own, and it
102
+ is the one that does report failure:
103
+
104
+ ```ts
105
+ await client.groups.join('beta') // throws NotFoundError if it isn't joinable
106
+ ```
107
+
108
+ Every reason it can be refused (no such group, deleted, closed, a segment,
109
+ another tenant's) arrives as the same `NotFoundError`, so that a signed-in
110
+ customer cannot use it to enumerate a merchant's group IDs. Joining twice
111
+ succeeds and changes nothing.
112
+
79
113
  ## Inventory flow
80
114
 
81
115
  Most inventory endpoints require an authenticated user:
@@ -97,7 +131,7 @@ while (page.hasMore && page.next) {
97
131
 
98
132
  ## Endpoint groups
99
133
 
100
- `client.storefront`, `client.identity`, `client.orders`, `client.vouchers`, `client.inventory`, `client.activationRequests`, `client.vendor`.
134
+ `client.storefront`, `client.identity`, `client.orders`, `client.vouchers`, `client.inventory`, `client.activationRequests`, `client.vendor`, `client.communications`, `client.groups`.
101
135
 
102
136
  ## Image renditions
103
137
 
package/dist/index.cjs CHANGED
@@ -53,6 +53,7 @@ __export(index_exports, {
53
53
  isPromotionDisplay: () => isPromotionDisplay,
54
54
  isTransformableImageUrl: () => isTransformableImageUrl,
55
55
  maxImageDimension: () => maxImageDimension,
56
+ normalizeGroupIds: () => normalizeGroupIds,
56
57
  objectToQuery: () => objectToQuery,
57
58
  parseOffSiteReferrer: () => parseOffSiteReferrer,
58
59
  problemDetailsSchema: () => problemDetailsSchema,
@@ -490,6 +491,19 @@ var ActivationRequestEndpoints = class {
490
491
  }
491
492
  };
492
493
 
494
+ // src/utils/groups.ts
495
+ function normalizeGroupIds(groupIds) {
496
+ if (!groupIds)
497
+ return void 0;
498
+ const normalized = [];
499
+ for (const groupId of groupIds) {
500
+ const trimmed = groupId == null ? void 0 : groupId.trim().toLowerCase();
501
+ if (trimmed && !normalized.includes(trimmed))
502
+ normalized.push(trimmed);
503
+ }
504
+ return normalized.length > 0 ? normalized : void 0;
505
+ }
506
+
493
507
  // src/communications/schemas.ts
494
508
  var schemas_exports4 = {};
495
509
  __export(schemas_exports4, {
@@ -523,7 +537,8 @@ var CommunicationsEndpoints = class {
523
537
  email: input.email,
524
538
  name: ((_a = input.name) == null ? void 0 : _a.trim()) || null,
525
539
  newsletter: (_b = input.newsletter) != null ? _b : true,
526
- productUpdates: (_c = input.productUpdates) != null ? _c : true
540
+ productUpdates: (_c = input.productUpdates) != null ? _c : true,
541
+ groupIds: normalizeGroupIds(input.groupIds)
527
542
  }
528
543
  });
529
544
  return response.data;
@@ -565,6 +580,37 @@ var CommunicationsEndpoints = class {
565
580
  }
566
581
  };
567
582
 
583
+ // src/groups/endpoints.ts
584
+ var GroupEndpoints = class {
585
+ constructor(api) {
586
+ this.api = api;
587
+ }
588
+ /**
589
+ * Joins the signed-in customer to a merchant-owned group that has been opened
590
+ * to public sign-ups.
591
+ *
592
+ * The one group call that reports failure. Group IDs sent along with sign-up,
593
+ * a newsletter subscription or a checkout are passengers on a request that
594
+ * wanted something else, so an unusable one is skipped rather than allowed to
595
+ * fail the account, the subscription or the sale. Here joining *is* the
596
+ * request, so it throws.
597
+ *
598
+ * Every reason it can fail (no such group, deleted, closed, a segment, a
599
+ * system group, another tenant's) arrives as the same `NotFoundError`, so
600
+ * that a customer of one tenant can't enumerate that merchant's group IDs.
601
+ *
602
+ * Idempotent: joining a group the customer is already in succeeds and changes
603
+ * nothing.
604
+ */
605
+ async join(groupId) {
606
+ await this.api.authenticatedFetch(
607
+ `/api/customer/groups/${encodeURIComponent(groupId)}/join`,
608
+ null,
609
+ { method: "POST" }
610
+ );
611
+ }
612
+ };
613
+
568
614
  // src/utils/errors.ts
569
615
  var NotAuthorizedError = class extends Error {
570
616
  constructor() {
@@ -768,7 +814,7 @@ var IdentityEndpoints = class {
768
814
  this.tokenStore.setUser(identity);
769
815
  return userSchema.parse(identity);
770
816
  }
771
- async signUp(name, email, password, address, acceptedPrivacyPolicy, acceptedTermsAndConditions, communicationOptIn) {
817
+ async signUp(name, email, password, address, acceptedPrivacyPolicy, acceptedTermsAndConditions, communicationOptIn, options) {
772
818
  const path = `/api/customer/identity/sign-up?scheme=JWT&communicationOptIn=${communicationOptIn ? "true" : "false"}`;
773
819
  const response = await fetch(`${this.api.baseUrl}${path}`, {
774
820
  method: "POST",
@@ -783,7 +829,8 @@ var IdentityEndpoints = class {
783
829
  password,
784
830
  address,
785
831
  acceptedPrivacyPolicy,
786
- acceptedTermsAndConditions
832
+ acceptedTermsAndConditions,
833
+ groupIds: normalizeGroupIds(options == null ? void 0 : options.groupIds)
787
834
  })
788
835
  });
789
836
  if (response.status >= 400)
@@ -1505,6 +1552,28 @@ var OrderEndpoints = class {
1505
1552
  const response = await this.api.fetch(`/api/customer/orders/${orderId}/coupons`, openOrderSchema, { method: "DELETE" });
1506
1553
  return response.data;
1507
1554
  }
1555
+ /**
1556
+ * Records merchant-owned customer groups the buyer should join once this order
1557
+ * completes. The order has to exist server-side first, so call it after a
1558
+ * `pushContent`, and before the payment rather than after: the enrollment
1559
+ * rides on the order until the payment webhook settles it.
1560
+ *
1561
+ * Additive rather than a replacement: each call adds to what the order already
1562
+ * carries, and the accumulated set is capped server-side. Groups the merchant
1563
+ * has not opened to public sign-ups are skipped in silence, so a stale ID in a
1564
+ * checkout form can never fail a sale.
1565
+ *
1566
+ * Kept apart from the marketing opt-in on purpose: a checkout can offer both
1567
+ * independently, and merging them would opt a buyer who only asked to join a
1568
+ * list into email they never asked for.
1569
+ */
1570
+ async joinGroups(orderId, groupIds) {
1571
+ const response = await this.api.fetch(`/api/customer/orders/${orderId}/groups`, openOrderSchema, {
1572
+ method: "POST",
1573
+ body: { groupIds: normalizeGroupIds(groupIds) }
1574
+ });
1575
+ return response.data;
1576
+ }
1508
1577
  };
1509
1578
 
1510
1579
  // src/storefront/endpoints.ts
@@ -2481,6 +2550,7 @@ var MoonbaseClient = class {
2481
2550
  this.storefront = new StorefrontEndpoints(this.api, this.configuration);
2482
2551
  this.identity = new IdentityEndpoints(this.api, this.tokenStore, this.logger);
2483
2552
  this.communications = new CommunicationsEndpoints(this.api);
2553
+ this.groups = new GroupEndpoints(this.api);
2484
2554
  this.vouchers = new VoucherEndpoints(this.api);
2485
2555
  this.orders = new OrderEndpoints(this.api);
2486
2556
  this.inventory = new InventoryEndpoints(this.api, this.configuration);
@@ -2523,6 +2593,7 @@ var MoonbaseClient = class {
2523
2593
  isPromotionDisplay,
2524
2594
  isTransformableImageUrl,
2525
2595
  maxImageDimension,
2596
+ normalizeGroupIds,
2526
2597
  objectToQuery,
2527
2598
  parseOffSiteReferrer,
2528
2599
  problemDetailsSchema,
package/dist/index.d.cts CHANGED
@@ -1123,6 +1123,13 @@ interface SubscribeInput {
1123
1123
  name?: string | null;
1124
1124
  newsletter?: boolean;
1125
1125
  productUpdates?: boolean;
1126
+ /**
1127
+ * Merchant-owned customer groups to enroll the subscriber into. Applied on
1128
+ * the same terms as the opt-in beside them: on a tenant that requires double
1129
+ * opt-in they land when the confirmation link is clicked, not here. Groups the
1130
+ * merchant has not opened to public sign-ups are skipped in silence.
1131
+ */
1132
+ groupIds?: string[];
1126
1133
  }
1127
1134
  interface CommunicationPreferencesInput {
1128
1135
  newsletter: boolean;
@@ -1139,6 +1146,29 @@ declare class CommunicationsEndpoints {
1139
1146
  unsubscribe(email: string, token: string): Promise<void>;
1140
1147
  }
1141
1148
 
1149
+ declare class GroupEndpoints {
1150
+ private api;
1151
+ constructor(api: MoonbaseApi);
1152
+ /**
1153
+ * Joins the signed-in customer to a merchant-owned group that has been opened
1154
+ * to public sign-ups.
1155
+ *
1156
+ * The one group call that reports failure. Group IDs sent along with sign-up,
1157
+ * a newsletter subscription or a checkout are passengers on a request that
1158
+ * wanted something else, so an unusable one is skipped rather than allowed to
1159
+ * fail the account, the subscription or the sale. Here joining *is* the
1160
+ * request, so it throws.
1161
+ *
1162
+ * Every reason it can fail (no such group, deleted, closed, a segment, a
1163
+ * system group, another tenant's) arrives as the same `NotFoundError`, so
1164
+ * that a customer of one tenant can't enumerate that merchant's group IDs.
1165
+ *
1166
+ * Idempotent: joining a group the customer is already in succeeds and changes
1167
+ * nothing.
1168
+ */
1169
+ join(groupId: string): Promise<void>;
1170
+ }
1171
+
1142
1172
  declare const addressSchema: z.ZodObject<{
1143
1173
  countryCode: z.ZodString;
1144
1174
  streetAddress1: z.ZodString;
@@ -1631,6 +1661,17 @@ type SignUpResult = {
1631
1661
  status: 'activation-pending';
1632
1662
  email: string;
1633
1663
  };
1664
+ interface SignUpOptions {
1665
+ /**
1666
+ * Merchant-owned customer groups to enroll the new account into.
1667
+ *
1668
+ * Only groups the merchant has opened to public sign-ups are applied, and the
1669
+ * response does not say which ones were: an ID naming a group that is closed,
1670
+ * deleted, rule-driven or another tenant's is skipped in silence, so a stale
1671
+ * ID left in a form can never fail a registration.
1672
+ */
1673
+ groupIds?: string[];
1674
+ }
1634
1675
 
1635
1676
  declare class IdentityEndpoints {
1636
1677
  private api;
@@ -1639,7 +1680,7 @@ declare class IdentityEndpoints {
1639
1680
  constructor(api: MoonbaseApi, tokenStore: ITokenStore, logger: ILogger);
1640
1681
  get(): Promise<User>;
1641
1682
  signIn(email: string, password: string): Promise<User>;
1642
- signUp(name: string, email: string, password: string, address: Address | null | undefined, acceptedPrivacyPolicy: boolean, acceptedTermsAndConditions: boolean, communicationOptIn?: boolean): Promise<SignUpResult>;
1683
+ signUp(name: string, email: string, password: string, address: Address | null | undefined, acceptedPrivacyPolicy: boolean, acceptedTermsAndConditions: boolean, communicationOptIn?: boolean, options?: SignUpOptions): Promise<SignUpResult>;
1643
1684
  signOut(): Promise<void>;
1644
1685
  update(name: string | null, email: string, emailConfirmationToken?: string, communicationPreferences?: CommunicationPreferences): Promise<{
1645
1686
  needsEmailConfirmationToken: boolean;
@@ -2692,17 +2733,17 @@ declare const milestoneProgressSchema: z.ZodObject<{
2692
2733
  fromNormalizedCycleNumber: z.ZodNumber;
2693
2734
  toCycleNumber: z.ZodNumber;
2694
2735
  toNormalizedCycleNumber: z.ZodNumber;
2695
- events: z.ZodRecord<z.ZodNumber, z.ZodArray<z.ZodDiscriminatedUnion<"type", [z.ZodObject<z.objectUtil.extendShape<{
2736
+ events: z.ZodRecord<z.ZodNumber, z.ZodArray<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2696
2737
  milestoneId: z.ZodString;
2697
2738
  fulfilled: z.ZodBoolean;
2698
2739
  afterCycleNumber: z.ZodNumber;
2699
2740
  afterNormalizedCycleNumber: z.ZodNumber;
2700
2741
  message: z.ZodOptional<z.ZodString>;
2701
- }, {
2742
+ } & {
2702
2743
  type: z.ZodLiteral<"CouponCodeMilestone">;
2703
2744
  code: z.ZodOptional<z.ZodString>;
2704
2745
  redeemed: z.ZodOptional<z.ZodBoolean>;
2705
- }>, "strip", z.ZodTypeAny, {
2746
+ }, "strip", z.ZodTypeAny, {
2706
2747
  type: "CouponCodeMilestone";
2707
2748
  milestoneId: string;
2708
2749
  fulfilled: boolean;
@@ -2720,15 +2761,15 @@ declare const milestoneProgressSchema: z.ZodObject<{
2720
2761
  code?: string | undefined;
2721
2762
  message?: string | undefined;
2722
2763
  redeemed?: boolean | undefined;
2723
- }>, z.ZodObject<z.objectUtil.extendShape<{
2764
+ }>, z.ZodObject<{
2724
2765
  milestoneId: z.ZodString;
2725
2766
  fulfilled: z.ZodBoolean;
2726
2767
  afterCycleNumber: z.ZodNumber;
2727
2768
  afterNormalizedCycleNumber: z.ZodNumber;
2728
2769
  message: z.ZodOptional<z.ZodString>;
2729
- }, {
2770
+ } & {
2730
2771
  type: z.ZodLiteral<"PerpetualLicenseConversionMilestone">;
2731
- }>, "strip", z.ZodTypeAny, {
2772
+ }, "strip", z.ZodTypeAny, {
2732
2773
  type: "PerpetualLicenseConversionMilestone";
2733
2774
  milestoneId: string;
2734
2775
  fulfilled: boolean;
@@ -2931,17 +2972,17 @@ declare const subscriptionSchema: z.ZodObject<{
2931
2972
  fromNormalizedCycleNumber: z.ZodNumber;
2932
2973
  toCycleNumber: z.ZodNumber;
2933
2974
  toNormalizedCycleNumber: z.ZodNumber;
2934
- events: z.ZodRecord<z.ZodNumber, z.ZodArray<z.ZodDiscriminatedUnion<"type", [z.ZodObject<z.objectUtil.extendShape<{
2975
+ events: z.ZodRecord<z.ZodNumber, z.ZodArray<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2935
2976
  milestoneId: z.ZodString;
2936
2977
  fulfilled: z.ZodBoolean;
2937
2978
  afterCycleNumber: z.ZodNumber;
2938
2979
  afterNormalizedCycleNumber: z.ZodNumber;
2939
2980
  message: z.ZodOptional<z.ZodString>;
2940
- }, {
2981
+ } & {
2941
2982
  type: z.ZodLiteral<"CouponCodeMilestone">;
2942
2983
  code: z.ZodOptional<z.ZodString>;
2943
2984
  redeemed: z.ZodOptional<z.ZodBoolean>;
2944
- }>, "strip", z.ZodTypeAny, {
2985
+ }, "strip", z.ZodTypeAny, {
2945
2986
  type: "CouponCodeMilestone";
2946
2987
  milestoneId: string;
2947
2988
  fulfilled: boolean;
@@ -2959,15 +3000,15 @@ declare const subscriptionSchema: z.ZodObject<{
2959
3000
  code?: string | undefined;
2960
3001
  message?: string | undefined;
2961
3002
  redeemed?: boolean | undefined;
2962
- }>, z.ZodObject<z.objectUtil.extendShape<{
3003
+ }>, z.ZodObject<{
2963
3004
  milestoneId: z.ZodString;
2964
3005
  fulfilled: z.ZodBoolean;
2965
3006
  afterCycleNumber: z.ZodNumber;
2966
3007
  afterNormalizedCycleNumber: z.ZodNumber;
2967
3008
  message: z.ZodOptional<z.ZodString>;
2968
- }, {
3009
+ } & {
2969
3010
  type: z.ZodLiteral<"PerpetualLicenseConversionMilestone">;
2970
- }>, "strip", z.ZodTypeAny, {
3011
+ }, "strip", z.ZodTypeAny, {
2971
3012
  type: "PerpetualLicenseConversionMilestone";
2972
3013
  milestoneId: string;
2973
3014
  fulfilled: boolean;
@@ -13027,7 +13068,7 @@ declare const completedOrderSchema: z.ZodObject<{
13027
13068
  validUntil?: string | undefined;
13028
13069
  } | undefined;
13029
13070
  }>;
13030
- declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.objectUtil.extendShape<{
13071
+ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<{
13031
13072
  id: z.ZodString;
13032
13073
  currency: z.ZodString;
13033
13074
  total: z.ZodOptional<z.ZodNullable<z.ZodObject<{
@@ -14408,9 +14449,9 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
14408
14449
  checkoutUrl: z.ZodOptional<z.ZodString>;
14409
14450
  hostedCheckoutUrl: z.ZodOptional<z.ZodString>;
14410
14451
  embeddedCheckoutUrl: z.ZodOptional<z.ZodString>;
14411
- }, {
14452
+ } & {
14412
14453
  status: z.ZodLiteral<OrderStatus.Open>;
14413
- }>, "strip", z.ZodTypeAny, {
14454
+ }, "strip", z.ZodTypeAny, {
14414
14455
  id: string;
14415
14456
  status: OrderStatus.Open;
14416
14457
  currency: string;
@@ -14954,7 +14995,7 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
14954
14995
  checkoutUrl?: string | undefined;
14955
14996
  hostedCheckoutUrl?: string | undefined;
14956
14997
  embeddedCheckoutUrl?: string | undefined;
14957
- }>, z.ZodObject<z.objectUtil.extendShape<{
14998
+ }>, z.ZodObject<{
14958
14999
  id: z.ZodString;
14959
15000
  currency: z.ZodString;
14960
15001
  total: z.ZodOptional<z.ZodNullable<z.ZodObject<{
@@ -16335,9 +16376,9 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
16335
16376
  checkoutUrl: z.ZodOptional<z.ZodString>;
16336
16377
  hostedCheckoutUrl: z.ZodOptional<z.ZodString>;
16337
16378
  embeddedCheckoutUrl: z.ZodOptional<z.ZodString>;
16338
- }, {
16379
+ } & {
16339
16380
  status: z.ZodLiteral<OrderStatus.PaymentProcessing>;
16340
- }>, "strip", z.ZodTypeAny, {
16381
+ }, "strip", z.ZodTypeAny, {
16341
16382
  id: string;
16342
16383
  status: OrderStatus.PaymentProcessing;
16343
16384
  currency: string;
@@ -16881,7 +16922,7 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
16881
16922
  checkoutUrl?: string | undefined;
16882
16923
  hostedCheckoutUrl?: string | undefined;
16883
16924
  embeddedCheckoutUrl?: string | undefined;
16884
- }>, z.ZodObject<z.objectUtil.extendShape<{
16925
+ }>, z.ZodObject<{
16885
16926
  id: z.ZodString;
16886
16927
  currency: z.ZodString;
16887
16928
  total: z.ZodOptional<z.ZodNullable<z.ZodObject<{
@@ -18262,9 +18303,9 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
18262
18303
  checkoutUrl: z.ZodOptional<z.ZodString>;
18263
18304
  hostedCheckoutUrl: z.ZodOptional<z.ZodString>;
18264
18305
  embeddedCheckoutUrl: z.ZodOptional<z.ZodString>;
18265
- }, {
18306
+ } & {
18266
18307
  status: z.ZodLiteral<OrderStatus.Paid>;
18267
- }>, "strip", z.ZodTypeAny, {
18308
+ }, "strip", z.ZodTypeAny, {
18268
18309
  id: string;
18269
18310
  status: OrderStatus.Paid;
18270
18311
  currency: string;
@@ -18808,7 +18849,7 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
18808
18849
  checkoutUrl?: string | undefined;
18809
18850
  hostedCheckoutUrl?: string | undefined;
18810
18851
  embeddedCheckoutUrl?: string | undefined;
18811
- }>, z.ZodObject<z.objectUtil.extendShape<{
18852
+ }>, z.ZodObject<{
18812
18853
  id: z.ZodString;
18813
18854
  currency: z.ZodString;
18814
18855
  total: z.ZodOptional<z.ZodNullable<z.ZodObject<{
@@ -20189,9 +20230,9 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
20189
20230
  checkoutUrl: z.ZodOptional<z.ZodString>;
20190
20231
  hostedCheckoutUrl: z.ZodOptional<z.ZodString>;
20191
20232
  embeddedCheckoutUrl: z.ZodOptional<z.ZodString>;
20192
- }, {
20233
+ } & {
20193
20234
  status: z.ZodLiteral<OrderStatus.Failed>;
20194
- }>, "strip", z.ZodTypeAny, {
20235
+ }, "strip", z.ZodTypeAny, {
20195
20236
  id: string;
20196
20237
  status: OrderStatus.Failed;
20197
20238
  currency: string;
@@ -24189,6 +24230,22 @@ declare class OrderEndpoints {
24189
24230
  addCouponCode(orderId: string, code: string): Promise<OpenOrder>;
24190
24231
  removeCouponCode(orderId: string, code: string): Promise<OpenOrder>;
24191
24232
  clearCouponCodes(orderId: string): Promise<OpenOrder>;
24233
+ /**
24234
+ * Records merchant-owned customer groups the buyer should join once this order
24235
+ * completes. The order has to exist server-side first, so call it after a
24236
+ * `pushContent`, and before the payment rather than after: the enrollment
24237
+ * rides on the order until the payment webhook settles it.
24238
+ *
24239
+ * Additive rather than a replacement: each call adds to what the order already
24240
+ * carries, and the accumulated set is capped server-side. Groups the merchant
24241
+ * has not opened to public sign-ups are skipped in silence, so a stale ID in a
24242
+ * checkout form can never fail a sale.
24243
+ *
24244
+ * Kept apart from the marketing opt-in on purpose: a checkout can offer both
24245
+ * independently, and merging them would opt a buyer who only asked to join a
24246
+ * list into email they never asked for.
24247
+ */
24248
+ joinGroups(orderId: string, groupIds: string[]): Promise<OpenOrder>;
24192
24249
  }
24193
24250
 
24194
24251
  declare class StorefrontEndpoints {
@@ -46932,6 +46989,26 @@ declare class MoonbaseError extends Error {
46932
46989
  constructor(title: string, detail: string | undefined, status?: number | undefined, errors?: Record<string, string> | undefined);
46933
46990
  }
46934
46991
 
46992
+ /**
46993
+ * Cleans up merchant-authored group IDs before they go on the wire.
46994
+ *
46995
+ * Deliberately normalizes without validating. The server sanitizes these itself,
46996
+ * dropping IDs that are too long, malformed, closed, or belonging to another
46997
+ * tenant, and capping the request at five. It does so in silence, so the
46998
+ * endpoints can't be used to enumerate a tenant's groups. Re-implementing those
46999
+ * rules here would only mean a merchant's typo disappears in the one place they
47000
+ * can't see it, so anything that survives trimming is sent and the server has
47001
+ * the last word.
47002
+ *
47003
+ * Lowercasing is the exception, and it earns its place by making the de-dupe
47004
+ * correct: group IDs are lowercase server-side, so `VIP` and `vip` are one
47005
+ * group and should only cost one of the five slots.
47006
+ *
47007
+ * Returns `undefined` rather than `[]` when nothing survives, so the field is
47008
+ * omitted from the request body entirely for every caller not using this.
47009
+ */
47010
+ declare function normalizeGroupIds(groupIds?: readonly string[] | null): string[] | undefined;
47011
+
46935
47012
  /**
46936
47013
  * Builds URLs for on-the-fly renditions of images stored in Moonbase's asset CDN.
46937
47014
  *
@@ -47072,6 +47149,7 @@ declare class MoonbaseClient {
47072
47149
  storefront: StorefrontEndpoints;
47073
47150
  identity: IdentityEndpoints;
47074
47151
  communications: CommunicationsEndpoints;
47152
+ groups: GroupEndpoints;
47075
47153
  vouchers: VoucherEndpoints;
47076
47154
  activationRequests: ActivationRequestEndpoints;
47077
47155
  inventory: InventoryEndpoints;
@@ -47079,4 +47157,4 @@ declare class MoonbaseClient {
47079
47157
  orders: OrderEndpoints;
47080
47158
  }
47081
47159
 
47082
- export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, Architecture, type BundleLineItem, type CartCatalog, type CartOrder, type CartTotal, type CartTotalCondition, CartUtils, type CommunicationPreferences, type CommunicationPreferencesInput, type CommunicationPreferencesView, type CompletedOrder, ConnectableAccountProvider, type ConnectedAccount, ConsoleLogger, CycleLength, type Discount, DiscountUtils, type Download, type DownloadManifest, type ILogger, type IRecurrence, type IStore, type ITokenStore, type Identity, type ImageFit, type ImageFormat, type ImageTransform, ImageUtils, InMemoryStore, type License, LicenseStatus, type LineItem, type LineItemTotal, LocalStorageStore, LogLevel, MarketingConsentType, type MilestoneProgress, type Money, type MoneyCollection, MoneyCollectionUtils, MoonbaseApi, MoonbaseClient, type MoonbaseConfiguration, MoonbaseError, NotAuthenticatedError, NotAuthorizedError, NotFoundError, type OfferCondition, type OfferConditionContext, type OfferProgress, type OfferScope, OfferUtils, type OpenOrder, type Order, OrderStatus, type OrderTotal, type OwnedProduct, type Page, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type PromotionDisplay, type Quantifiable, type RawPropertyArray, type RawPropertyObject, type RawPropertyValue, type SignUpResult, type SingleOrMultiple, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontOfferTarget, type StorefrontProduct, type StorefrontPromotion, type StorefrontPromotionCta, type StorefrontPromotionTarget, type SubscribeInput, type SubscribeResponse, type Subscription, SubscriptionStatus, type TaxEstimate, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type UserAccountConfirmedStatus, type Vendor, type Voucher, imageWidths, isLocalStorageAvailable, isPromotionDisplay, isTransformableImageUrl, maxImageDimension, objectToQuery, parseOffSiteReferrer, problemDetailsSchema, promotionDisplays, resolveUtm, schemas, utmToObject };
47160
+ export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, Architecture, type BundleLineItem, type CartCatalog, type CartOrder, type CartTotal, type CartTotalCondition, CartUtils, type CommunicationPreferences, type CommunicationPreferencesInput, type CommunicationPreferencesView, type CompletedOrder, ConnectableAccountProvider, type ConnectedAccount, ConsoleLogger, CycleLength, type Discount, DiscountUtils, type Download, type DownloadManifest, type ILogger, type IRecurrence, type IStore, type ITokenStore, type Identity, type ImageFit, type ImageFormat, type ImageTransform, ImageUtils, InMemoryStore, type License, LicenseStatus, type LineItem, type LineItemTotal, LocalStorageStore, LogLevel, MarketingConsentType, type MilestoneProgress, type Money, type MoneyCollection, MoneyCollectionUtils, MoonbaseApi, MoonbaseClient, type MoonbaseConfiguration, MoonbaseError, NotAuthenticatedError, NotAuthorizedError, NotFoundError, type OfferCondition, type OfferConditionContext, type OfferProgress, type OfferScope, OfferUtils, type OpenOrder, type Order, OrderStatus, type OrderTotal, type OwnedProduct, type Page, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type PromotionDisplay, type Quantifiable, type RawPropertyArray, type RawPropertyObject, type RawPropertyValue, type SignUpOptions, type SignUpResult, type SingleOrMultiple, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontOfferTarget, type StorefrontProduct, type StorefrontPromotion, type StorefrontPromotionCta, type StorefrontPromotionTarget, type SubscribeInput, type SubscribeResponse, type Subscription, SubscriptionStatus, type TaxEstimate, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type UserAccountConfirmedStatus, type Vendor, type Voucher, imageWidths, isLocalStorageAvailable, isPromotionDisplay, isTransformableImageUrl, maxImageDimension, normalizeGroupIds, objectToQuery, parseOffSiteReferrer, problemDetailsSchema, promotionDisplays, resolveUtm, schemas, utmToObject };
package/dist/index.d.ts CHANGED
@@ -1123,6 +1123,13 @@ interface SubscribeInput {
1123
1123
  name?: string | null;
1124
1124
  newsletter?: boolean;
1125
1125
  productUpdates?: boolean;
1126
+ /**
1127
+ * Merchant-owned customer groups to enroll the subscriber into. Applied on
1128
+ * the same terms as the opt-in beside them: on a tenant that requires double
1129
+ * opt-in they land when the confirmation link is clicked, not here. Groups the
1130
+ * merchant has not opened to public sign-ups are skipped in silence.
1131
+ */
1132
+ groupIds?: string[];
1126
1133
  }
1127
1134
  interface CommunicationPreferencesInput {
1128
1135
  newsletter: boolean;
@@ -1139,6 +1146,29 @@ declare class CommunicationsEndpoints {
1139
1146
  unsubscribe(email: string, token: string): Promise<void>;
1140
1147
  }
1141
1148
 
1149
+ declare class GroupEndpoints {
1150
+ private api;
1151
+ constructor(api: MoonbaseApi);
1152
+ /**
1153
+ * Joins the signed-in customer to a merchant-owned group that has been opened
1154
+ * to public sign-ups.
1155
+ *
1156
+ * The one group call that reports failure. Group IDs sent along with sign-up,
1157
+ * a newsletter subscription or a checkout are passengers on a request that
1158
+ * wanted something else, so an unusable one is skipped rather than allowed to
1159
+ * fail the account, the subscription or the sale. Here joining *is* the
1160
+ * request, so it throws.
1161
+ *
1162
+ * Every reason it can fail (no such group, deleted, closed, a segment, a
1163
+ * system group, another tenant's) arrives as the same `NotFoundError`, so
1164
+ * that a customer of one tenant can't enumerate that merchant's group IDs.
1165
+ *
1166
+ * Idempotent: joining a group the customer is already in succeeds and changes
1167
+ * nothing.
1168
+ */
1169
+ join(groupId: string): Promise<void>;
1170
+ }
1171
+
1142
1172
  declare const addressSchema: z.ZodObject<{
1143
1173
  countryCode: z.ZodString;
1144
1174
  streetAddress1: z.ZodString;
@@ -1631,6 +1661,17 @@ type SignUpResult = {
1631
1661
  status: 'activation-pending';
1632
1662
  email: string;
1633
1663
  };
1664
+ interface SignUpOptions {
1665
+ /**
1666
+ * Merchant-owned customer groups to enroll the new account into.
1667
+ *
1668
+ * Only groups the merchant has opened to public sign-ups are applied, and the
1669
+ * response does not say which ones were: an ID naming a group that is closed,
1670
+ * deleted, rule-driven or another tenant's is skipped in silence, so a stale
1671
+ * ID left in a form can never fail a registration.
1672
+ */
1673
+ groupIds?: string[];
1674
+ }
1634
1675
 
1635
1676
  declare class IdentityEndpoints {
1636
1677
  private api;
@@ -1639,7 +1680,7 @@ declare class IdentityEndpoints {
1639
1680
  constructor(api: MoonbaseApi, tokenStore: ITokenStore, logger: ILogger);
1640
1681
  get(): Promise<User>;
1641
1682
  signIn(email: string, password: string): Promise<User>;
1642
- signUp(name: string, email: string, password: string, address: Address | null | undefined, acceptedPrivacyPolicy: boolean, acceptedTermsAndConditions: boolean, communicationOptIn?: boolean): Promise<SignUpResult>;
1683
+ signUp(name: string, email: string, password: string, address: Address | null | undefined, acceptedPrivacyPolicy: boolean, acceptedTermsAndConditions: boolean, communicationOptIn?: boolean, options?: SignUpOptions): Promise<SignUpResult>;
1643
1684
  signOut(): Promise<void>;
1644
1685
  update(name: string | null, email: string, emailConfirmationToken?: string, communicationPreferences?: CommunicationPreferences): Promise<{
1645
1686
  needsEmailConfirmationToken: boolean;
@@ -2692,17 +2733,17 @@ declare const milestoneProgressSchema: z.ZodObject<{
2692
2733
  fromNormalizedCycleNumber: z.ZodNumber;
2693
2734
  toCycleNumber: z.ZodNumber;
2694
2735
  toNormalizedCycleNumber: z.ZodNumber;
2695
- events: z.ZodRecord<z.ZodNumber, z.ZodArray<z.ZodDiscriminatedUnion<"type", [z.ZodObject<z.objectUtil.extendShape<{
2736
+ events: z.ZodRecord<z.ZodNumber, z.ZodArray<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2696
2737
  milestoneId: z.ZodString;
2697
2738
  fulfilled: z.ZodBoolean;
2698
2739
  afterCycleNumber: z.ZodNumber;
2699
2740
  afterNormalizedCycleNumber: z.ZodNumber;
2700
2741
  message: z.ZodOptional<z.ZodString>;
2701
- }, {
2742
+ } & {
2702
2743
  type: z.ZodLiteral<"CouponCodeMilestone">;
2703
2744
  code: z.ZodOptional<z.ZodString>;
2704
2745
  redeemed: z.ZodOptional<z.ZodBoolean>;
2705
- }>, "strip", z.ZodTypeAny, {
2746
+ }, "strip", z.ZodTypeAny, {
2706
2747
  type: "CouponCodeMilestone";
2707
2748
  milestoneId: string;
2708
2749
  fulfilled: boolean;
@@ -2720,15 +2761,15 @@ declare const milestoneProgressSchema: z.ZodObject<{
2720
2761
  code?: string | undefined;
2721
2762
  message?: string | undefined;
2722
2763
  redeemed?: boolean | undefined;
2723
- }>, z.ZodObject<z.objectUtil.extendShape<{
2764
+ }>, z.ZodObject<{
2724
2765
  milestoneId: z.ZodString;
2725
2766
  fulfilled: z.ZodBoolean;
2726
2767
  afterCycleNumber: z.ZodNumber;
2727
2768
  afterNormalizedCycleNumber: z.ZodNumber;
2728
2769
  message: z.ZodOptional<z.ZodString>;
2729
- }, {
2770
+ } & {
2730
2771
  type: z.ZodLiteral<"PerpetualLicenseConversionMilestone">;
2731
- }>, "strip", z.ZodTypeAny, {
2772
+ }, "strip", z.ZodTypeAny, {
2732
2773
  type: "PerpetualLicenseConversionMilestone";
2733
2774
  milestoneId: string;
2734
2775
  fulfilled: boolean;
@@ -2931,17 +2972,17 @@ declare const subscriptionSchema: z.ZodObject<{
2931
2972
  fromNormalizedCycleNumber: z.ZodNumber;
2932
2973
  toCycleNumber: z.ZodNumber;
2933
2974
  toNormalizedCycleNumber: z.ZodNumber;
2934
- events: z.ZodRecord<z.ZodNumber, z.ZodArray<z.ZodDiscriminatedUnion<"type", [z.ZodObject<z.objectUtil.extendShape<{
2975
+ events: z.ZodRecord<z.ZodNumber, z.ZodArray<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2935
2976
  milestoneId: z.ZodString;
2936
2977
  fulfilled: z.ZodBoolean;
2937
2978
  afterCycleNumber: z.ZodNumber;
2938
2979
  afterNormalizedCycleNumber: z.ZodNumber;
2939
2980
  message: z.ZodOptional<z.ZodString>;
2940
- }, {
2981
+ } & {
2941
2982
  type: z.ZodLiteral<"CouponCodeMilestone">;
2942
2983
  code: z.ZodOptional<z.ZodString>;
2943
2984
  redeemed: z.ZodOptional<z.ZodBoolean>;
2944
- }>, "strip", z.ZodTypeAny, {
2985
+ }, "strip", z.ZodTypeAny, {
2945
2986
  type: "CouponCodeMilestone";
2946
2987
  milestoneId: string;
2947
2988
  fulfilled: boolean;
@@ -2959,15 +3000,15 @@ declare const subscriptionSchema: z.ZodObject<{
2959
3000
  code?: string | undefined;
2960
3001
  message?: string | undefined;
2961
3002
  redeemed?: boolean | undefined;
2962
- }>, z.ZodObject<z.objectUtil.extendShape<{
3003
+ }>, z.ZodObject<{
2963
3004
  milestoneId: z.ZodString;
2964
3005
  fulfilled: z.ZodBoolean;
2965
3006
  afterCycleNumber: z.ZodNumber;
2966
3007
  afterNormalizedCycleNumber: z.ZodNumber;
2967
3008
  message: z.ZodOptional<z.ZodString>;
2968
- }, {
3009
+ } & {
2969
3010
  type: z.ZodLiteral<"PerpetualLicenseConversionMilestone">;
2970
- }>, "strip", z.ZodTypeAny, {
3011
+ }, "strip", z.ZodTypeAny, {
2971
3012
  type: "PerpetualLicenseConversionMilestone";
2972
3013
  milestoneId: string;
2973
3014
  fulfilled: boolean;
@@ -13027,7 +13068,7 @@ declare const completedOrderSchema: z.ZodObject<{
13027
13068
  validUntil?: string | undefined;
13028
13069
  } | undefined;
13029
13070
  }>;
13030
- declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.objectUtil.extendShape<{
13071
+ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<{
13031
13072
  id: z.ZodString;
13032
13073
  currency: z.ZodString;
13033
13074
  total: z.ZodOptional<z.ZodNullable<z.ZodObject<{
@@ -14408,9 +14449,9 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
14408
14449
  checkoutUrl: z.ZodOptional<z.ZodString>;
14409
14450
  hostedCheckoutUrl: z.ZodOptional<z.ZodString>;
14410
14451
  embeddedCheckoutUrl: z.ZodOptional<z.ZodString>;
14411
- }, {
14452
+ } & {
14412
14453
  status: z.ZodLiteral<OrderStatus.Open>;
14413
- }>, "strip", z.ZodTypeAny, {
14454
+ }, "strip", z.ZodTypeAny, {
14414
14455
  id: string;
14415
14456
  status: OrderStatus.Open;
14416
14457
  currency: string;
@@ -14954,7 +14995,7 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
14954
14995
  checkoutUrl?: string | undefined;
14955
14996
  hostedCheckoutUrl?: string | undefined;
14956
14997
  embeddedCheckoutUrl?: string | undefined;
14957
- }>, z.ZodObject<z.objectUtil.extendShape<{
14998
+ }>, z.ZodObject<{
14958
14999
  id: z.ZodString;
14959
15000
  currency: z.ZodString;
14960
15001
  total: z.ZodOptional<z.ZodNullable<z.ZodObject<{
@@ -16335,9 +16376,9 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
16335
16376
  checkoutUrl: z.ZodOptional<z.ZodString>;
16336
16377
  hostedCheckoutUrl: z.ZodOptional<z.ZodString>;
16337
16378
  embeddedCheckoutUrl: z.ZodOptional<z.ZodString>;
16338
- }, {
16379
+ } & {
16339
16380
  status: z.ZodLiteral<OrderStatus.PaymentProcessing>;
16340
- }>, "strip", z.ZodTypeAny, {
16381
+ }, "strip", z.ZodTypeAny, {
16341
16382
  id: string;
16342
16383
  status: OrderStatus.PaymentProcessing;
16343
16384
  currency: string;
@@ -16881,7 +16922,7 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
16881
16922
  checkoutUrl?: string | undefined;
16882
16923
  hostedCheckoutUrl?: string | undefined;
16883
16924
  embeddedCheckoutUrl?: string | undefined;
16884
- }>, z.ZodObject<z.objectUtil.extendShape<{
16925
+ }>, z.ZodObject<{
16885
16926
  id: z.ZodString;
16886
16927
  currency: z.ZodString;
16887
16928
  total: z.ZodOptional<z.ZodNullable<z.ZodObject<{
@@ -18262,9 +18303,9 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
18262
18303
  checkoutUrl: z.ZodOptional<z.ZodString>;
18263
18304
  hostedCheckoutUrl: z.ZodOptional<z.ZodString>;
18264
18305
  embeddedCheckoutUrl: z.ZodOptional<z.ZodString>;
18265
- }, {
18306
+ } & {
18266
18307
  status: z.ZodLiteral<OrderStatus.Paid>;
18267
- }>, "strip", z.ZodTypeAny, {
18308
+ }, "strip", z.ZodTypeAny, {
18268
18309
  id: string;
18269
18310
  status: OrderStatus.Paid;
18270
18311
  currency: string;
@@ -18808,7 +18849,7 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
18808
18849
  checkoutUrl?: string | undefined;
18809
18850
  hostedCheckoutUrl?: string | undefined;
18810
18851
  embeddedCheckoutUrl?: string | undefined;
18811
- }>, z.ZodObject<z.objectUtil.extendShape<{
18852
+ }>, z.ZodObject<{
18812
18853
  id: z.ZodString;
18813
18854
  currency: z.ZodString;
18814
18855
  total: z.ZodOptional<z.ZodNullable<z.ZodObject<{
@@ -20189,9 +20230,9 @@ declare const orderSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<z.obje
20189
20230
  checkoutUrl: z.ZodOptional<z.ZodString>;
20190
20231
  hostedCheckoutUrl: z.ZodOptional<z.ZodString>;
20191
20232
  embeddedCheckoutUrl: z.ZodOptional<z.ZodString>;
20192
- }, {
20233
+ } & {
20193
20234
  status: z.ZodLiteral<OrderStatus.Failed>;
20194
- }>, "strip", z.ZodTypeAny, {
20235
+ }, "strip", z.ZodTypeAny, {
20195
20236
  id: string;
20196
20237
  status: OrderStatus.Failed;
20197
20238
  currency: string;
@@ -24189,6 +24230,22 @@ declare class OrderEndpoints {
24189
24230
  addCouponCode(orderId: string, code: string): Promise<OpenOrder>;
24190
24231
  removeCouponCode(orderId: string, code: string): Promise<OpenOrder>;
24191
24232
  clearCouponCodes(orderId: string): Promise<OpenOrder>;
24233
+ /**
24234
+ * Records merchant-owned customer groups the buyer should join once this order
24235
+ * completes. The order has to exist server-side first, so call it after a
24236
+ * `pushContent`, and before the payment rather than after: the enrollment
24237
+ * rides on the order until the payment webhook settles it.
24238
+ *
24239
+ * Additive rather than a replacement: each call adds to what the order already
24240
+ * carries, and the accumulated set is capped server-side. Groups the merchant
24241
+ * has not opened to public sign-ups are skipped in silence, so a stale ID in a
24242
+ * checkout form can never fail a sale.
24243
+ *
24244
+ * Kept apart from the marketing opt-in on purpose: a checkout can offer both
24245
+ * independently, and merging them would opt a buyer who only asked to join a
24246
+ * list into email they never asked for.
24247
+ */
24248
+ joinGroups(orderId: string, groupIds: string[]): Promise<OpenOrder>;
24192
24249
  }
24193
24250
 
24194
24251
  declare class StorefrontEndpoints {
@@ -46932,6 +46989,26 @@ declare class MoonbaseError extends Error {
46932
46989
  constructor(title: string, detail: string | undefined, status?: number | undefined, errors?: Record<string, string> | undefined);
46933
46990
  }
46934
46991
 
46992
+ /**
46993
+ * Cleans up merchant-authored group IDs before they go on the wire.
46994
+ *
46995
+ * Deliberately normalizes without validating. The server sanitizes these itself,
46996
+ * dropping IDs that are too long, malformed, closed, or belonging to another
46997
+ * tenant, and capping the request at five. It does so in silence, so the
46998
+ * endpoints can't be used to enumerate a tenant's groups. Re-implementing those
46999
+ * rules here would only mean a merchant's typo disappears in the one place they
47000
+ * can't see it, so anything that survives trimming is sent and the server has
47001
+ * the last word.
47002
+ *
47003
+ * Lowercasing is the exception, and it earns its place by making the de-dupe
47004
+ * correct: group IDs are lowercase server-side, so `VIP` and `vip` are one
47005
+ * group and should only cost one of the five slots.
47006
+ *
47007
+ * Returns `undefined` rather than `[]` when nothing survives, so the field is
47008
+ * omitted from the request body entirely for every caller not using this.
47009
+ */
47010
+ declare function normalizeGroupIds(groupIds?: readonly string[] | null): string[] | undefined;
47011
+
46935
47012
  /**
46936
47013
  * Builds URLs for on-the-fly renditions of images stored in Moonbase's asset CDN.
46937
47014
  *
@@ -47072,6 +47149,7 @@ declare class MoonbaseClient {
47072
47149
  storefront: StorefrontEndpoints;
47073
47150
  identity: IdentityEndpoints;
47074
47151
  communications: CommunicationsEndpoints;
47152
+ groups: GroupEndpoints;
47075
47153
  vouchers: VoucherEndpoints;
47076
47154
  activationRequests: ActivationRequestEndpoints;
47077
47155
  inventory: InventoryEndpoints;
@@ -47079,4 +47157,4 @@ declare class MoonbaseClient {
47079
47157
  orders: OrderEndpoints;
47080
47158
  }
47081
47159
 
47082
- export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, Architecture, type BundleLineItem, type CartCatalog, type CartOrder, type CartTotal, type CartTotalCondition, CartUtils, type CommunicationPreferences, type CommunicationPreferencesInput, type CommunicationPreferencesView, type CompletedOrder, ConnectableAccountProvider, type ConnectedAccount, ConsoleLogger, CycleLength, type Discount, DiscountUtils, type Download, type DownloadManifest, type ILogger, type IRecurrence, type IStore, type ITokenStore, type Identity, type ImageFit, type ImageFormat, type ImageTransform, ImageUtils, InMemoryStore, type License, LicenseStatus, type LineItem, type LineItemTotal, LocalStorageStore, LogLevel, MarketingConsentType, type MilestoneProgress, type Money, type MoneyCollection, MoneyCollectionUtils, MoonbaseApi, MoonbaseClient, type MoonbaseConfiguration, MoonbaseError, NotAuthenticatedError, NotAuthorizedError, NotFoundError, type OfferCondition, type OfferConditionContext, type OfferProgress, type OfferScope, OfferUtils, type OpenOrder, type Order, OrderStatus, type OrderTotal, type OwnedProduct, type Page, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type PromotionDisplay, type Quantifiable, type RawPropertyArray, type RawPropertyObject, type RawPropertyValue, type SignUpResult, type SingleOrMultiple, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontOfferTarget, type StorefrontProduct, type StorefrontPromotion, type StorefrontPromotionCta, type StorefrontPromotionTarget, type SubscribeInput, type SubscribeResponse, type Subscription, SubscriptionStatus, type TaxEstimate, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type UserAccountConfirmedStatus, type Vendor, type Voucher, imageWidths, isLocalStorageAvailable, isPromotionDisplay, isTransformableImageUrl, maxImageDimension, objectToQuery, parseOffSiteReferrer, problemDetailsSchema, promotionDisplays, resolveUtm, schemas, utmToObject };
47160
+ export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, Architecture, type BundleLineItem, type CartCatalog, type CartOrder, type CartTotal, type CartTotalCondition, CartUtils, type CommunicationPreferences, type CommunicationPreferencesInput, type CommunicationPreferencesView, type CompletedOrder, ConnectableAccountProvider, type ConnectedAccount, ConsoleLogger, CycleLength, type Discount, DiscountUtils, type Download, type DownloadManifest, type ILogger, type IRecurrence, type IStore, type ITokenStore, type Identity, type ImageFit, type ImageFormat, type ImageTransform, ImageUtils, InMemoryStore, type License, LicenseStatus, type LineItem, type LineItemTotal, LocalStorageStore, LogLevel, MarketingConsentType, type MilestoneProgress, type Money, type MoneyCollection, MoneyCollectionUtils, MoonbaseApi, MoonbaseClient, type MoonbaseConfiguration, MoonbaseError, NotAuthenticatedError, NotAuthorizedError, NotFoundError, type OfferCondition, type OfferConditionContext, type OfferProgress, type OfferScope, OfferUtils, type OpenOrder, type Order, OrderStatus, type OrderTotal, type OwnedProduct, type Page, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type PromotionDisplay, type Quantifiable, type RawPropertyArray, type RawPropertyObject, type RawPropertyValue, type SignUpOptions, type SignUpResult, type SingleOrMultiple, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontOfferTarget, type StorefrontProduct, type StorefrontPromotion, type StorefrontPromotionCta, type StorefrontPromotionTarget, type SubscribeInput, type SubscribeResponse, type Subscription, SubscriptionStatus, type TaxEstimate, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type UserAccountConfirmedStatus, type Vendor, type Voucher, imageWidths, isLocalStorageAvailable, isPromotionDisplay, isTransformableImageUrl, maxImageDimension, normalizeGroupIds, objectToQuery, parseOffSiteReferrer, problemDetailsSchema, promotionDisplays, resolveUtm, schemas, utmToObject };
package/dist/index.js CHANGED
@@ -431,6 +431,19 @@ var ActivationRequestEndpoints = class {
431
431
  }
432
432
  };
433
433
 
434
+ // src/utils/groups.ts
435
+ function normalizeGroupIds(groupIds) {
436
+ if (!groupIds)
437
+ return void 0;
438
+ const normalized = [];
439
+ for (const groupId of groupIds) {
440
+ const trimmed = groupId == null ? void 0 : groupId.trim().toLowerCase();
441
+ if (trimmed && !normalized.includes(trimmed))
442
+ normalized.push(trimmed);
443
+ }
444
+ return normalized.length > 0 ? normalized : void 0;
445
+ }
446
+
434
447
  // src/communications/schemas.ts
435
448
  var schemas_exports4 = {};
436
449
  __export(schemas_exports4, {
@@ -464,7 +477,8 @@ var CommunicationsEndpoints = class {
464
477
  email: input.email,
465
478
  name: ((_a = input.name) == null ? void 0 : _a.trim()) || null,
466
479
  newsletter: (_b = input.newsletter) != null ? _b : true,
467
- productUpdates: (_c = input.productUpdates) != null ? _c : true
480
+ productUpdates: (_c = input.productUpdates) != null ? _c : true,
481
+ groupIds: normalizeGroupIds(input.groupIds)
468
482
  }
469
483
  });
470
484
  return response.data;
@@ -506,6 +520,37 @@ var CommunicationsEndpoints = class {
506
520
  }
507
521
  };
508
522
 
523
+ // src/groups/endpoints.ts
524
+ var GroupEndpoints = class {
525
+ constructor(api) {
526
+ this.api = api;
527
+ }
528
+ /**
529
+ * Joins the signed-in customer to a merchant-owned group that has been opened
530
+ * to public sign-ups.
531
+ *
532
+ * The one group call that reports failure. Group IDs sent along with sign-up,
533
+ * a newsletter subscription or a checkout are passengers on a request that
534
+ * wanted something else, so an unusable one is skipped rather than allowed to
535
+ * fail the account, the subscription or the sale. Here joining *is* the
536
+ * request, so it throws.
537
+ *
538
+ * Every reason it can fail (no such group, deleted, closed, a segment, a
539
+ * system group, another tenant's) arrives as the same `NotFoundError`, so
540
+ * that a customer of one tenant can't enumerate that merchant's group IDs.
541
+ *
542
+ * Idempotent: joining a group the customer is already in succeeds and changes
543
+ * nothing.
544
+ */
545
+ async join(groupId) {
546
+ await this.api.authenticatedFetch(
547
+ `/api/customer/groups/${encodeURIComponent(groupId)}/join`,
548
+ null,
549
+ { method: "POST" }
550
+ );
551
+ }
552
+ };
553
+
509
554
  // src/utils/errors.ts
510
555
  var NotAuthorizedError = class extends Error {
511
556
  constructor() {
@@ -709,7 +754,7 @@ var IdentityEndpoints = class {
709
754
  this.tokenStore.setUser(identity);
710
755
  return userSchema.parse(identity);
711
756
  }
712
- async signUp(name, email, password, address, acceptedPrivacyPolicy, acceptedTermsAndConditions, communicationOptIn) {
757
+ async signUp(name, email, password, address, acceptedPrivacyPolicy, acceptedTermsAndConditions, communicationOptIn, options) {
713
758
  const path = `/api/customer/identity/sign-up?scheme=JWT&communicationOptIn=${communicationOptIn ? "true" : "false"}`;
714
759
  const response = await fetch(`${this.api.baseUrl}${path}`, {
715
760
  method: "POST",
@@ -724,7 +769,8 @@ var IdentityEndpoints = class {
724
769
  password,
725
770
  address,
726
771
  acceptedPrivacyPolicy,
727
- acceptedTermsAndConditions
772
+ acceptedTermsAndConditions,
773
+ groupIds: normalizeGroupIds(options == null ? void 0 : options.groupIds)
728
774
  })
729
775
  });
730
776
  if (response.status >= 400)
@@ -1446,6 +1492,28 @@ var OrderEndpoints = class {
1446
1492
  const response = await this.api.fetch(`/api/customer/orders/${orderId}/coupons`, openOrderSchema, { method: "DELETE" });
1447
1493
  return response.data;
1448
1494
  }
1495
+ /**
1496
+ * Records merchant-owned customer groups the buyer should join once this order
1497
+ * completes. The order has to exist server-side first, so call it after a
1498
+ * `pushContent`, and before the payment rather than after: the enrollment
1499
+ * rides on the order until the payment webhook settles it.
1500
+ *
1501
+ * Additive rather than a replacement: each call adds to what the order already
1502
+ * carries, and the accumulated set is capped server-side. Groups the merchant
1503
+ * has not opened to public sign-ups are skipped in silence, so a stale ID in a
1504
+ * checkout form can never fail a sale.
1505
+ *
1506
+ * Kept apart from the marketing opt-in on purpose: a checkout can offer both
1507
+ * independently, and merging them would opt a buyer who only asked to join a
1508
+ * list into email they never asked for.
1509
+ */
1510
+ async joinGroups(orderId, groupIds) {
1511
+ const response = await this.api.fetch(`/api/customer/orders/${orderId}/groups`, openOrderSchema, {
1512
+ method: "POST",
1513
+ body: { groupIds: normalizeGroupIds(groupIds) }
1514
+ });
1515
+ return response.data;
1516
+ }
1449
1517
  };
1450
1518
 
1451
1519
  // src/storefront/endpoints.ts
@@ -2422,6 +2490,7 @@ var MoonbaseClient = class {
2422
2490
  this.storefront = new StorefrontEndpoints(this.api, this.configuration);
2423
2491
  this.identity = new IdentityEndpoints(this.api, this.tokenStore, this.logger);
2424
2492
  this.communications = new CommunicationsEndpoints(this.api);
2493
+ this.groups = new GroupEndpoints(this.api);
2425
2494
  this.vouchers = new VoucherEndpoints(this.api);
2426
2495
  this.orders = new OrderEndpoints(this.api);
2427
2496
  this.inventory = new InventoryEndpoints(this.api, this.configuration);
@@ -2463,6 +2532,7 @@ export {
2463
2532
  isPromotionDisplay,
2464
2533
  isTransformableImageUrl,
2465
2534
  maxImageDimension,
2535
+ normalizeGroupIds,
2466
2536
  objectToQuery,
2467
2537
  parseOffSiteReferrer,
2468
2538
  problemDetailsSchema,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@moonbase.sh/storefront-api",
3
3
  "type": "module",
4
- "version": "3.2.0",
4
+ "version": "3.3.1",
5
5
  "description": "Package to let you build storefronts with Moonbase.sh as payment and delivery provider",
6
6
  "author": "Tobias Lønnerød Madsen <m@dsen.tv>",
7
7
  "license": "MIT",