@moonbase.sh/storefront-api 3.8.0 → 3.9.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/dist/index.cjs CHANGED
@@ -46,6 +46,7 @@ __export(index_exports, {
46
46
  NotFoundError: () => NotFoundError,
47
47
  OfferUtils: () => OfferUtils,
48
48
  OrderStatus: () => OrderStatus,
49
+ PasswordSetupRequiredError: () => PasswordSetupRequiredError,
49
50
  Platform: () => Platform,
50
51
  StoreClosedError: () => StoreClosedError,
51
52
  SubscriptionCancellationReason: () => SubscriptionCancellationReason,
@@ -685,6 +686,12 @@ var CaptchaRequiredError = class extends MoonbaseError {
685
686
  this.name = "CaptchaRequiredError";
686
687
  }
687
688
  };
689
+ var PasswordSetupRequiredError = class extends MoonbaseError {
690
+ constructor(detail, title, status) {
691
+ super(title != null ? title : "Password setup required", detail, status);
692
+ this.name = "PasswordSetupRequiredError";
693
+ }
694
+ };
688
695
 
689
696
  // src/utils/problemDetails.ts
690
697
  var import_zod7 = require("zod");
@@ -708,6 +715,7 @@ function camelCase(str) {
708
715
  }).join("");
709
716
  }
710
717
  async function handleResponseProblem(response, logger) {
718
+ var _a;
711
719
  if (response.status === 404)
712
720
  throw new NotFoundError();
713
721
  if (response.status === 401) {
@@ -729,6 +737,8 @@ async function handleResponseProblem(response, logger) {
729
737
  throw new StoreClosedError(problemDetails.detail);
730
738
  if (problemDetails.errorType === "CaptchaRequired")
731
739
  throw new CaptchaRequiredError(problemDetails.detail, problemDetails.title);
740
+ if (problemDetails.errorType === "PasswordSetupRequired")
741
+ throw new PasswordSetupRequiredError(problemDetails.detail, problemDetails.title, (_a = problemDetails.status) != null ? _a : response.status);
732
742
  throw new MoonbaseError(
733
743
  problemDetails.title,
734
744
  problemDetails.detail,
@@ -747,6 +757,7 @@ __export(schemas_exports5, {
747
757
  identitySchema: () => identitySchema,
748
758
  ilokConnectedAccountSchema: () => ilokConnectedAccountSchema,
749
759
  pendingActivationSchema: () => pendingActivationSchema,
760
+ pendingPasswordProblemSchema: () => pendingPasswordProblemSchema,
750
761
  userAccountConfirmedSchema: () => userAccountConfirmedSchema,
751
762
  userAccountConfirmedStatusSchema: () => userAccountConfirmedStatusSchema,
752
763
  userSchema: () => userSchema
@@ -820,13 +831,18 @@ var pendingActivationSchema = import_zod8.z.object({
820
831
  status: import_zod8.z.literal("activation_pending"),
821
832
  email: import_zod8.z.string()
822
833
  });
834
+ var pendingPasswordProblemSchema = import_zod8.z.object({
835
+ errorType: import_zod8.z.literal("PasswordSetupRequired"),
836
+ pendingPasswordToken: import_zod8.z.string()
837
+ });
823
838
 
824
839
  // src/identity/endpoints.ts
825
840
  var IdentityEndpoints = class {
826
- constructor(api, tokenStore, logger) {
841
+ constructor(api, tokenStore, logger, pendingPasswords) {
827
842
  this.api = api;
828
843
  this.tokenStore = tokenStore;
829
844
  this.logger = logger;
845
+ this.pendingPasswords = pendingPasswords;
830
846
  }
831
847
  async get() {
832
848
  const response = await this.api.authenticatedFetch("/api/customer/meta/user", userSchema);
@@ -882,8 +898,11 @@ var IdentityEndpoints = class {
882
898
  groupIds: normalizeGroupIds(options == null ? void 0 : options.groupIds)
883
899
  })
884
900
  });
885
- if (response.status >= 400)
901
+ if (response.status >= 400) {
902
+ if (response.status === 409)
903
+ await this.keepPendingPassword(email, response.clone());
886
904
  await handleResponseProblem(response, this.logger);
905
+ }
887
906
  const data = await response.json();
888
907
  if (response.status === 202) {
889
908
  const parsed = pendingActivationSchema.parse(data);
@@ -899,6 +918,19 @@ var IdentityEndpoints = class {
899
918
  this.tokenStore.setUser(identity);
900
919
  return { status: "signed-in", user: userSchema.parse(identity) };
901
920
  }
921
+ /**
922
+ * The address already has an account with no password, so the server emailed it a link and
923
+ * handed back the password just typed, sealed, for that link to set once it is opened here.
924
+ * Never thrown: the caller still gets the `PasswordSetupRequiredError` from the response.
925
+ */
926
+ async keepPendingPassword(email, response) {
927
+ try {
928
+ const problem = pendingPasswordProblemSchema.safeParse(await response.json());
929
+ if (problem.success)
930
+ this.pendingPasswords.set(email, problem.data.pendingPasswordToken);
931
+ } catch (e) {
932
+ }
933
+ }
902
934
  /**
903
935
  * Signs the buyer out here at once, and ends the session on the server so its refresh
904
936
  * token stops working too. Resolves once the server has answered, and never rejects:
@@ -950,7 +982,13 @@ var IdentityEndpoints = class {
950
982
  await handleResponseProblem(response, this.logger);
951
983
  }
952
984
  async confirmAccount(email, code) {
953
- const response = await this.api.fetch(`/api/customer/identity/confirm-account?email=${encodeURIComponent(email)}&code=${encodeURIComponent(code.replaceAll(" ", "+"))}&scheme=JWT`, userAccountConfirmedSchema, { method: "POST" });
985
+ const pendingPasswordToken = this.pendingPasswords.get(email);
986
+ const response = await this.api.fetch(`/api/customer/identity/confirm-account?email=${encodeURIComponent(email)}&code=${encodeURIComponent(code.replaceAll(" ", "+"))}&scheme=JWT`, userAccountConfirmedSchema, {
987
+ method: "POST",
988
+ body: pendingPasswordToken ? { pendingPasswordToken } : void 0
989
+ });
990
+ if (pendingPasswordToken)
991
+ this.pendingPasswords.remove(email);
954
992
  const result = response.data;
955
993
  if (result.status === "SignedIn") {
956
994
  if (!result.accessToken || !result.refreshToken) {
@@ -1147,7 +1185,7 @@ var ProductEndpoints = class {
1147
1185
  var import_zod14 = require("zod");
1148
1186
 
1149
1187
  // package.json
1150
- var version = "3.8.0";
1188
+ var version = "3.9.0";
1151
1189
 
1152
1190
  // src/utils/client.ts
1153
1191
  function buildClientHeader(sdk) {
@@ -1155,6 +1193,11 @@ function buildClientHeader(sdk) {
1155
1193
  }
1156
1194
 
1157
1195
  // src/utils/api.ts
1196
+ function loggableBody(body) {
1197
+ if (!body || typeof body !== "object" || Array.isArray(body))
1198
+ return body;
1199
+ return Object.fromEntries(Object.entries(body).map(([key, value]) => [key, /password|token/i.test(key) && value != null ? "[redacted]" : value]));
1200
+ }
1158
1201
  function objectToQuery(obj) {
1159
1202
  return Object.entries(obj != null ? obj : {}).filter(([_, value]) => value !== void 0).map(([key, value]) => `${key}=${encodeURIComponent(value instanceof Date ? value.toISOString() : value)}`).join("&");
1160
1203
  }
@@ -1176,7 +1219,7 @@ var MoonbaseApi = class {
1176
1219
  const contentType = (_a = options == null ? void 0 : options.contentType) != null ? _a : "application/json";
1177
1220
  this.logger.debug("Making request to Moonbase API...", {
1178
1221
  path,
1179
- body: options == null ? void 0 : options.body
1222
+ body: loggableBody(options == null ? void 0 : options.body)
1180
1223
  });
1181
1224
  const startedAt = /* @__PURE__ */ new Date();
1182
1225
  const request = {
@@ -1825,6 +1868,50 @@ var InMemoryStore = class {
1825
1868
  }
1826
1869
  };
1827
1870
 
1871
+ // src/utils/pendingPasswords.ts
1872
+ var lifetime = 24 * 60 * 60 * 1e3;
1873
+ function normalizeEmail(email) {
1874
+ return email.trim().toLowerCase();
1875
+ }
1876
+ var _PendingPasswordStore = class _PendingPasswordStore {
1877
+ constructor(store) {
1878
+ this.store = store != null ? store : isLocalStorageAvailable() ? new LocalStorageStore() : new InMemoryStore();
1879
+ }
1880
+ get(email) {
1881
+ var _a, _b;
1882
+ return (_b = (_a = this.read()[normalizeEmail(email)]) == null ? void 0 : _a.token) != null ? _b : null;
1883
+ }
1884
+ set(email, token) {
1885
+ this.write({ ...this.read(), [normalizeEmail(email)]: { token, storedAt: Date.now() } });
1886
+ }
1887
+ remove(email) {
1888
+ const entries = this.read();
1889
+ delete entries[normalizeEmail(email)];
1890
+ this.write(entries);
1891
+ }
1892
+ /** The entries still worth keeping. Drops the rest from storage as it goes. */
1893
+ read() {
1894
+ const stored = this.store.get(_PendingPasswordStore.storageKey);
1895
+ if (!stored || typeof stored !== "object")
1896
+ return {};
1897
+ const now = Date.now();
1898
+ const fresh = Object.fromEntries(Object.entries(stored).filter(
1899
+ ([, entry]) => typeof (entry == null ? void 0 : entry.token) === "string" && typeof entry.storedAt === "number" && now - entry.storedAt < lifetime
1900
+ ));
1901
+ if (Object.keys(fresh).length !== Object.keys(stored).length)
1902
+ this.write(fresh);
1903
+ return fresh;
1904
+ }
1905
+ write(entries) {
1906
+ if (Object.keys(entries).length > 0)
1907
+ this.store.set(_PendingPasswordStore.storageKey, entries);
1908
+ else
1909
+ this.store.remove(_PendingPasswordStore.storageKey);
1910
+ }
1911
+ };
1912
+ _PendingPasswordStore.storageKey = "moonbase_pending_passwords";
1913
+ var PendingPasswordStore = _PendingPasswordStore;
1914
+
1828
1915
  // src/utils/tokenStore.ts
1829
1916
  var defaultAccessTokenLifetime = 15 * 60 * 1e3;
1830
1917
  var renewBeforeExpiry = 5 * 60 * 1e3;
@@ -1834,9 +1921,9 @@ function accessTokenLifetime(accessToken) {
1834
1921
  try {
1835
1922
  const payload = accessToken.split(".")[1].replaceAll("-", "+").replaceAll("_", "/");
1836
1923
  const claims = JSON.parse(atob(payload.padEnd(Math.ceil(payload.length / 4) * 4, "=")));
1837
- const lifetime = (Number(claims.exp) - Number(claims.iat)) * 1e3;
1838
- if (Number.isFinite(lifetime) && lifetime > 0 && lifetime <= 24 * 60 * 60 * 1e3)
1839
- return lifetime;
1924
+ const lifetime2 = (Number(claims.exp) - Number(claims.iat)) * 1e3;
1925
+ if (Number.isFinite(lifetime2) && lifetime2 > 0 && lifetime2 <= 24 * 60 * 60 * 1e3)
1926
+ return lifetime2;
1840
1927
  } catch (e) {
1841
1928
  }
1842
1929
  return defaultAccessTokenLifetime;
@@ -2778,7 +2865,7 @@ var MoonbaseClient = class {
2778
2865
  this.tokenStore = new TokenStore(configuration);
2779
2866
  this.api = new MoonbaseApi(this.configuration.endpoint, this.tokenStore, this.logger, this.configuration.sdk);
2780
2867
  this.storefront = new StorefrontEndpoints(this.api, this.configuration);
2781
- this.identity = new IdentityEndpoints(this.api, this.tokenStore, this.logger);
2868
+ this.identity = new IdentityEndpoints(this.api, this.tokenStore, this.logger, new PendingPasswordStore(configuration.store));
2782
2869
  this.communications = new CommunicationsEndpoints(this.api);
2783
2870
  this.groups = new GroupEndpoints(this.api);
2784
2871
  this.vouchers = new VoucherEndpoints(this.api);
@@ -2816,6 +2903,7 @@ var MoonbaseClient = class {
2816
2903
  NotFoundError,
2817
2904
  OfferUtils,
2818
2905
  OrderStatus,
2906
+ PasswordSetupRequiredError,
2819
2907
  Platform,
2820
2908
  StoreClosedError,
2821
2909
  SubscriptionCancellationReason,
package/dist/index.d.cts CHANGED
@@ -1214,6 +1214,33 @@ declare class GroupEndpoints {
1214
1214
  join(groupId: string): Promise<void>;
1215
1215
  }
1216
1216
 
1217
+ /**
1218
+ * The password a customer chose at sign-up for an address that already had an account without
1219
+ * one, kept until the link Moonbase emails comes back. The server hands it back sealed, as
1220
+ * `pendingPasswordToken`, and confirming the account with it sets that password rather than
1221
+ * asking for another.
1222
+ *
1223
+ * Kept in `localStorage`, so the link finds it in whichever tab of this site it opens in, and
1224
+ * only in the browser that typed the password: whoever signs up with somebody else's address
1225
+ * gets the token, but never the emailed code it needs. Like the token store, every operation
1226
+ * degrades to memory when storage fails, in which case the link asks for the password again.
1227
+ *
1228
+ * Only ever filled from a sign-up response, never from a URL parameter or anything else a link
1229
+ * can carry: a token planted from a link would let an attacker's password ride on the victim's
1230
+ * own click.
1231
+ */
1232
+ declare class PendingPasswordStore {
1233
+ private readonly store;
1234
+ static readonly storageKey = "moonbase_pending_passwords";
1235
+ constructor(store?: IStore);
1236
+ get(email: string): string | null;
1237
+ set(email: string, token: string): void;
1238
+ remove(email: string): void;
1239
+ /** The entries still worth keeping. Drops the rest from storage as it goes. */
1240
+ private read;
1241
+ private write;
1242
+ }
1243
+
1217
1244
  declare const moneySchema: z.ZodObject<{
1218
1245
  currency: z.ZodString;
1219
1246
  amount: z.ZodNumber;
@@ -2020,6 +2047,17 @@ declare const pendingActivationSchema: z.ZodObject<{
2020
2047
  email: string;
2021
2048
  status: "activation_pending";
2022
2049
  }>;
2050
+ /** Sign-up's 409 for an address whose account has no password yet. See `PendingPasswordStore`. */
2051
+ declare const pendingPasswordProblemSchema: z.ZodObject<{
2052
+ errorType: z.ZodLiteral<"PasswordSetupRequired">;
2053
+ pendingPasswordToken: z.ZodString;
2054
+ }, "strip", z.ZodTypeAny, {
2055
+ errorType: "PasswordSetupRequired";
2056
+ pendingPasswordToken: string;
2057
+ }, {
2058
+ errorType: "PasswordSetupRequired";
2059
+ pendingPasswordToken: string;
2060
+ }>;
2023
2061
 
2024
2062
  declare const schemas$9_addressSchema: typeof addressSchema;
2025
2063
  declare const schemas$9_communicationPreferencesSchema: typeof communicationPreferencesSchema;
@@ -2028,11 +2066,12 @@ declare const schemas$9_connectionUrlSchema: typeof connectionUrlSchema;
2028
2066
  declare const schemas$9_identitySchema: typeof identitySchema;
2029
2067
  declare const schemas$9_ilokConnectedAccountSchema: typeof ilokConnectedAccountSchema;
2030
2068
  declare const schemas$9_pendingActivationSchema: typeof pendingActivationSchema;
2069
+ declare const schemas$9_pendingPasswordProblemSchema: typeof pendingPasswordProblemSchema;
2031
2070
  declare const schemas$9_userAccountConfirmedSchema: typeof userAccountConfirmedSchema;
2032
2071
  declare const schemas$9_userAccountConfirmedStatusSchema: typeof userAccountConfirmedStatusSchema;
2033
2072
  declare const schemas$9_userSchema: typeof userSchema;
2034
2073
  declare namespace schemas$9 {
2035
- export { schemas$9_addressSchema as addressSchema, schemas$9_communicationPreferencesSchema as communicationPreferencesSchema, schemas$9_connectedAccountSchema as connectedAccountSchema, schemas$9_connectionUrlSchema as connectionUrlSchema, schemas$9_identitySchema as identitySchema, schemas$9_ilokConnectedAccountSchema as ilokConnectedAccountSchema, schemas$9_pendingActivationSchema as pendingActivationSchema, schemas$9_userAccountConfirmedSchema as userAccountConfirmedSchema, schemas$9_userAccountConfirmedStatusSchema as userAccountConfirmedStatusSchema, schemas$9_userSchema as userSchema };
2074
+ export { schemas$9_addressSchema as addressSchema, schemas$9_communicationPreferencesSchema as communicationPreferencesSchema, schemas$9_connectedAccountSchema as connectedAccountSchema, schemas$9_connectionUrlSchema as connectionUrlSchema, schemas$9_identitySchema as identitySchema, schemas$9_ilokConnectedAccountSchema as ilokConnectedAccountSchema, schemas$9_pendingActivationSchema as pendingActivationSchema, schemas$9_pendingPasswordProblemSchema as pendingPasswordProblemSchema, schemas$9_userAccountConfirmedSchema as userAccountConfirmedSchema, schemas$9_userAccountConfirmedStatusSchema as userAccountConfirmedStatusSchema, schemas$9_userSchema as userSchema };
2036
2075
  }
2037
2076
 
2038
2077
  type CommunicationPreferences = z.infer<typeof communicationPreferencesSchema>;
@@ -2084,10 +2123,17 @@ declare class IdentityEndpoints {
2084
2123
  private api;
2085
2124
  private tokenStore;
2086
2125
  private logger;
2087
- constructor(api: MoonbaseApi, tokenStore: ITokenStore, logger: ILogger);
2126
+ private pendingPasswords;
2127
+ constructor(api: MoonbaseApi, tokenStore: ITokenStore, logger: ILogger, pendingPasswords: PendingPasswordStore);
2088
2128
  get(): Promise<User>;
2089
2129
  signIn(email: string, password: string): Promise<User>;
2090
2130
  signUp(name: string, email: string, password: string, address: Address | null | undefined, acceptedPrivacyPolicy: boolean, acceptedTermsAndConditions: boolean, communicationOptIn?: boolean, options?: SignUpOptions): Promise<SignUpResult>;
2131
+ /**
2132
+ * The address already has an account with no password, so the server emailed it a link and
2133
+ * handed back the password just typed, sealed, for that link to set once it is opened here.
2134
+ * Never thrown: the caller still gets the `PasswordSetupRequiredError` from the response.
2135
+ */
2136
+ private keepPendingPassword;
2091
2137
  /**
2092
2138
  * Signs the buyer out here at once, and ends the session on the server so its refresh
2093
2139
  * token stops working too. Resolves once the server has answered, and never rejects:
@@ -47317,6 +47363,20 @@ declare class MoonbaseError extends Error {
47317
47363
  declare class CaptchaRequiredError extends MoonbaseError {
47318
47364
  constructor(detail?: string, title?: string);
47319
47365
  }
47366
+ /**
47367
+ * The address already has an account, but one without a password: the store gave the customer a
47368
+ * license, or they bought something without one. Anyone can type any address into a form, so the
47369
+ * password they typed is not set from here. Moonbase emails the address a link to finish instead.
47370
+ * `message` is the API's own copy for the customer, safe to show as is.
47371
+ *
47372
+ * From `identity.signUp`, that link sets the password the customer just chose and signs them in,
47373
+ * provided they open it in this same browser. Anywhere else, it asks them for a password again.
47374
+ *
47375
+ * A `MoonbaseError` like any other refusal, so code that already handles those keeps working.
47376
+ */
47377
+ declare class PasswordSetupRequiredError extends MoonbaseError {
47378
+ constructor(detail?: string, title?: string, status?: number);
47379
+ }
47320
47380
 
47321
47381
  /**
47322
47382
  * Cleans up merchant-authored group IDs before they go on the wire.
@@ -47424,18 +47484,18 @@ declare const problemDetailsSchema: z.ZodObject<{
47424
47484
  title: string;
47425
47485
  type?: string | undefined;
47426
47486
  status?: number | undefined;
47487
+ errorType?: string | undefined;
47427
47488
  detail?: string | undefined;
47428
47489
  instance?: string | undefined;
47429
47490
  errors?: Record<string, string[]> | undefined;
47430
- errorType?: string | undefined;
47431
47491
  }, {
47432
47492
  title: string;
47433
47493
  type?: string | undefined;
47434
47494
  status?: number | undefined;
47495
+ errorType?: string | undefined;
47435
47496
  detail?: string | undefined;
47436
47497
  instance?: string | undefined;
47437
47498
  errors?: Record<string, string[]> | undefined;
47438
- errorType?: string | undefined;
47439
47499
  }>;
47440
47500
  type ProblemDetails = z.infer<typeof problemDetailsSchema>;
47441
47501
 
@@ -47501,4 +47561,4 @@ declare class MoonbaseClient {
47501
47561
  orders: OrderEndpoints;
47502
47562
  }
47503
47563
 
47504
- export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, Architecture, type BundleLineItem, CaptchaRequiredError, 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 ProductRelease, type PromotionDisplay, type Quantifiable, type RawPropertyArray, type RawPropertyObject, type RawPropertyValue, type SignUpOptions, type SignUpResult, type SingleOrMultiple, StoreClosedError, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontOfferTarget, type StorefrontProduct, type StorefrontPromotion, type StorefrontPromotionCta, type StorefrontPromotionTarget, type SubscribeInput, type SubscribeResponse, type Subscription, type SubscriptionCancellationFeedback, SubscriptionCancellationReason, SubscriptionStatus, type TaxEstimate, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type UserAccountConfirmedStatus, type Vendor, type VendorCaptcha, type VendorFeatures, type Voucher, accessTokenLifetime, imageWidths, isLocalStorageAvailable, isPromotionDisplay, isTransformableImageUrl, maxImageDimension, normalizeGroupIds, objectToQuery, parseOffSiteReferrer, problemDetailsSchema, promotionDisplays, resolveUtm, schemas, utmToObject };
47564
+ export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, Architecture, type BundleLineItem, CaptchaRequiredError, 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, PasswordSetupRequiredError, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type ProductRelease, type PromotionDisplay, type Quantifiable, type RawPropertyArray, type RawPropertyObject, type RawPropertyValue, type SignUpOptions, type SignUpResult, type SingleOrMultiple, StoreClosedError, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontOfferTarget, type StorefrontProduct, type StorefrontPromotion, type StorefrontPromotionCta, type StorefrontPromotionTarget, type SubscribeInput, type SubscribeResponse, type Subscription, type SubscriptionCancellationFeedback, SubscriptionCancellationReason, SubscriptionStatus, type TaxEstimate, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type UserAccountConfirmedStatus, type Vendor, type VendorCaptcha, type VendorFeatures, type Voucher, accessTokenLifetime, imageWidths, isLocalStorageAvailable, isPromotionDisplay, isTransformableImageUrl, maxImageDimension, normalizeGroupIds, objectToQuery, parseOffSiteReferrer, problemDetailsSchema, promotionDisplays, resolveUtm, schemas, utmToObject };
package/dist/index.d.ts CHANGED
@@ -1214,6 +1214,33 @@ declare class GroupEndpoints {
1214
1214
  join(groupId: string): Promise<void>;
1215
1215
  }
1216
1216
 
1217
+ /**
1218
+ * The password a customer chose at sign-up for an address that already had an account without
1219
+ * one, kept until the link Moonbase emails comes back. The server hands it back sealed, as
1220
+ * `pendingPasswordToken`, and confirming the account with it sets that password rather than
1221
+ * asking for another.
1222
+ *
1223
+ * Kept in `localStorage`, so the link finds it in whichever tab of this site it opens in, and
1224
+ * only in the browser that typed the password: whoever signs up with somebody else's address
1225
+ * gets the token, but never the emailed code it needs. Like the token store, every operation
1226
+ * degrades to memory when storage fails, in which case the link asks for the password again.
1227
+ *
1228
+ * Only ever filled from a sign-up response, never from a URL parameter or anything else a link
1229
+ * can carry: a token planted from a link would let an attacker's password ride on the victim's
1230
+ * own click.
1231
+ */
1232
+ declare class PendingPasswordStore {
1233
+ private readonly store;
1234
+ static readonly storageKey = "moonbase_pending_passwords";
1235
+ constructor(store?: IStore);
1236
+ get(email: string): string | null;
1237
+ set(email: string, token: string): void;
1238
+ remove(email: string): void;
1239
+ /** The entries still worth keeping. Drops the rest from storage as it goes. */
1240
+ private read;
1241
+ private write;
1242
+ }
1243
+
1217
1244
  declare const moneySchema: z.ZodObject<{
1218
1245
  currency: z.ZodString;
1219
1246
  amount: z.ZodNumber;
@@ -2020,6 +2047,17 @@ declare const pendingActivationSchema: z.ZodObject<{
2020
2047
  email: string;
2021
2048
  status: "activation_pending";
2022
2049
  }>;
2050
+ /** Sign-up's 409 for an address whose account has no password yet. See `PendingPasswordStore`. */
2051
+ declare const pendingPasswordProblemSchema: z.ZodObject<{
2052
+ errorType: z.ZodLiteral<"PasswordSetupRequired">;
2053
+ pendingPasswordToken: z.ZodString;
2054
+ }, "strip", z.ZodTypeAny, {
2055
+ errorType: "PasswordSetupRequired";
2056
+ pendingPasswordToken: string;
2057
+ }, {
2058
+ errorType: "PasswordSetupRequired";
2059
+ pendingPasswordToken: string;
2060
+ }>;
2023
2061
 
2024
2062
  declare const schemas$9_addressSchema: typeof addressSchema;
2025
2063
  declare const schemas$9_communicationPreferencesSchema: typeof communicationPreferencesSchema;
@@ -2028,11 +2066,12 @@ declare const schemas$9_connectionUrlSchema: typeof connectionUrlSchema;
2028
2066
  declare const schemas$9_identitySchema: typeof identitySchema;
2029
2067
  declare const schemas$9_ilokConnectedAccountSchema: typeof ilokConnectedAccountSchema;
2030
2068
  declare const schemas$9_pendingActivationSchema: typeof pendingActivationSchema;
2069
+ declare const schemas$9_pendingPasswordProblemSchema: typeof pendingPasswordProblemSchema;
2031
2070
  declare const schemas$9_userAccountConfirmedSchema: typeof userAccountConfirmedSchema;
2032
2071
  declare const schemas$9_userAccountConfirmedStatusSchema: typeof userAccountConfirmedStatusSchema;
2033
2072
  declare const schemas$9_userSchema: typeof userSchema;
2034
2073
  declare namespace schemas$9 {
2035
- export { schemas$9_addressSchema as addressSchema, schemas$9_communicationPreferencesSchema as communicationPreferencesSchema, schemas$9_connectedAccountSchema as connectedAccountSchema, schemas$9_connectionUrlSchema as connectionUrlSchema, schemas$9_identitySchema as identitySchema, schemas$9_ilokConnectedAccountSchema as ilokConnectedAccountSchema, schemas$9_pendingActivationSchema as pendingActivationSchema, schemas$9_userAccountConfirmedSchema as userAccountConfirmedSchema, schemas$9_userAccountConfirmedStatusSchema as userAccountConfirmedStatusSchema, schemas$9_userSchema as userSchema };
2074
+ export { schemas$9_addressSchema as addressSchema, schemas$9_communicationPreferencesSchema as communicationPreferencesSchema, schemas$9_connectedAccountSchema as connectedAccountSchema, schemas$9_connectionUrlSchema as connectionUrlSchema, schemas$9_identitySchema as identitySchema, schemas$9_ilokConnectedAccountSchema as ilokConnectedAccountSchema, schemas$9_pendingActivationSchema as pendingActivationSchema, schemas$9_pendingPasswordProblemSchema as pendingPasswordProblemSchema, schemas$9_userAccountConfirmedSchema as userAccountConfirmedSchema, schemas$9_userAccountConfirmedStatusSchema as userAccountConfirmedStatusSchema, schemas$9_userSchema as userSchema };
2036
2075
  }
2037
2076
 
2038
2077
  type CommunicationPreferences = z.infer<typeof communicationPreferencesSchema>;
@@ -2084,10 +2123,17 @@ declare class IdentityEndpoints {
2084
2123
  private api;
2085
2124
  private tokenStore;
2086
2125
  private logger;
2087
- constructor(api: MoonbaseApi, tokenStore: ITokenStore, logger: ILogger);
2126
+ private pendingPasswords;
2127
+ constructor(api: MoonbaseApi, tokenStore: ITokenStore, logger: ILogger, pendingPasswords: PendingPasswordStore);
2088
2128
  get(): Promise<User>;
2089
2129
  signIn(email: string, password: string): Promise<User>;
2090
2130
  signUp(name: string, email: string, password: string, address: Address | null | undefined, acceptedPrivacyPolicy: boolean, acceptedTermsAndConditions: boolean, communicationOptIn?: boolean, options?: SignUpOptions): Promise<SignUpResult>;
2131
+ /**
2132
+ * The address already has an account with no password, so the server emailed it a link and
2133
+ * handed back the password just typed, sealed, for that link to set once it is opened here.
2134
+ * Never thrown: the caller still gets the `PasswordSetupRequiredError` from the response.
2135
+ */
2136
+ private keepPendingPassword;
2091
2137
  /**
2092
2138
  * Signs the buyer out here at once, and ends the session on the server so its refresh
2093
2139
  * token stops working too. Resolves once the server has answered, and never rejects:
@@ -47317,6 +47363,20 @@ declare class MoonbaseError extends Error {
47317
47363
  declare class CaptchaRequiredError extends MoonbaseError {
47318
47364
  constructor(detail?: string, title?: string);
47319
47365
  }
47366
+ /**
47367
+ * The address already has an account, but one without a password: the store gave the customer a
47368
+ * license, or they bought something without one. Anyone can type any address into a form, so the
47369
+ * password they typed is not set from here. Moonbase emails the address a link to finish instead.
47370
+ * `message` is the API's own copy for the customer, safe to show as is.
47371
+ *
47372
+ * From `identity.signUp`, that link sets the password the customer just chose and signs them in,
47373
+ * provided they open it in this same browser. Anywhere else, it asks them for a password again.
47374
+ *
47375
+ * A `MoonbaseError` like any other refusal, so code that already handles those keeps working.
47376
+ */
47377
+ declare class PasswordSetupRequiredError extends MoonbaseError {
47378
+ constructor(detail?: string, title?: string, status?: number);
47379
+ }
47320
47380
 
47321
47381
  /**
47322
47382
  * Cleans up merchant-authored group IDs before they go on the wire.
@@ -47424,18 +47484,18 @@ declare const problemDetailsSchema: z.ZodObject<{
47424
47484
  title: string;
47425
47485
  type?: string | undefined;
47426
47486
  status?: number | undefined;
47487
+ errorType?: string | undefined;
47427
47488
  detail?: string | undefined;
47428
47489
  instance?: string | undefined;
47429
47490
  errors?: Record<string, string[]> | undefined;
47430
- errorType?: string | undefined;
47431
47491
  }, {
47432
47492
  title: string;
47433
47493
  type?: string | undefined;
47434
47494
  status?: number | undefined;
47495
+ errorType?: string | undefined;
47435
47496
  detail?: string | undefined;
47436
47497
  instance?: string | undefined;
47437
47498
  errors?: Record<string, string[]> | undefined;
47438
- errorType?: string | undefined;
47439
47499
  }>;
47440
47500
  type ProblemDetails = z.infer<typeof problemDetailsSchema>;
47441
47501
 
@@ -47501,4 +47561,4 @@ declare class MoonbaseClient {
47501
47561
  orders: OrderEndpoints;
47502
47562
  }
47503
47563
 
47504
- export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, Architecture, type BundleLineItem, CaptchaRequiredError, 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 ProductRelease, type PromotionDisplay, type Quantifiable, type RawPropertyArray, type RawPropertyObject, type RawPropertyValue, type SignUpOptions, type SignUpResult, type SingleOrMultiple, StoreClosedError, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontOfferTarget, type StorefrontProduct, type StorefrontPromotion, type StorefrontPromotionCta, type StorefrontPromotionTarget, type SubscribeInput, type SubscribeResponse, type Subscription, type SubscriptionCancellationFeedback, SubscriptionCancellationReason, SubscriptionStatus, type TaxEstimate, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type UserAccountConfirmedStatus, type Vendor, type VendorCaptcha, type VendorFeatures, type Voucher, accessTokenLifetime, imageWidths, isLocalStorageAvailable, isPromotionDisplay, isTransformableImageUrl, maxImageDimension, normalizeGroupIds, objectToQuery, parseOffSiteReferrer, problemDetailsSchema, promotionDisplays, resolveUtm, schemas, utmToObject };
47564
+ export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, Architecture, type BundleLineItem, CaptchaRequiredError, 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, PasswordSetupRequiredError, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type ProductRelease, type PromotionDisplay, type Quantifiable, type RawPropertyArray, type RawPropertyObject, type RawPropertyValue, type SignUpOptions, type SignUpResult, type SingleOrMultiple, StoreClosedError, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontOfferTarget, type StorefrontProduct, type StorefrontPromotion, type StorefrontPromotionCta, type StorefrontPromotionTarget, type SubscribeInput, type SubscribeResponse, type Subscription, type SubscriptionCancellationFeedback, SubscriptionCancellationReason, SubscriptionStatus, type TaxEstimate, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type UserAccountConfirmedStatus, type Vendor, type VendorCaptcha, type VendorFeatures, type Voucher, accessTokenLifetime, imageWidths, isLocalStorageAvailable, isPromotionDisplay, isTransformableImageUrl, maxImageDimension, normalizeGroupIds, objectToQuery, parseOffSiteReferrer, problemDetailsSchema, promotionDisplays, resolveUtm, schemas, utmToObject };
package/dist/index.js CHANGED
@@ -621,6 +621,12 @@ var CaptchaRequiredError = class extends MoonbaseError {
621
621
  this.name = "CaptchaRequiredError";
622
622
  }
623
623
  };
624
+ var PasswordSetupRequiredError = class extends MoonbaseError {
625
+ constructor(detail, title, status) {
626
+ super(title != null ? title : "Password setup required", detail, status);
627
+ this.name = "PasswordSetupRequiredError";
628
+ }
629
+ };
624
630
 
625
631
  // src/utils/problemDetails.ts
626
632
  import { z as z7 } from "zod";
@@ -644,6 +650,7 @@ function camelCase(str) {
644
650
  }).join("");
645
651
  }
646
652
  async function handleResponseProblem(response, logger) {
653
+ var _a;
647
654
  if (response.status === 404)
648
655
  throw new NotFoundError();
649
656
  if (response.status === 401) {
@@ -665,6 +672,8 @@ async function handleResponseProblem(response, logger) {
665
672
  throw new StoreClosedError(problemDetails.detail);
666
673
  if (problemDetails.errorType === "CaptchaRequired")
667
674
  throw new CaptchaRequiredError(problemDetails.detail, problemDetails.title);
675
+ if (problemDetails.errorType === "PasswordSetupRequired")
676
+ throw new PasswordSetupRequiredError(problemDetails.detail, problemDetails.title, (_a = problemDetails.status) != null ? _a : response.status);
668
677
  throw new MoonbaseError(
669
678
  problemDetails.title,
670
679
  problemDetails.detail,
@@ -683,6 +692,7 @@ __export(schemas_exports5, {
683
692
  identitySchema: () => identitySchema,
684
693
  ilokConnectedAccountSchema: () => ilokConnectedAccountSchema,
685
694
  pendingActivationSchema: () => pendingActivationSchema,
695
+ pendingPasswordProblemSchema: () => pendingPasswordProblemSchema,
686
696
  userAccountConfirmedSchema: () => userAccountConfirmedSchema,
687
697
  userAccountConfirmedStatusSchema: () => userAccountConfirmedStatusSchema,
688
698
  userSchema: () => userSchema
@@ -756,13 +766,18 @@ var pendingActivationSchema = z8.object({
756
766
  status: z8.literal("activation_pending"),
757
767
  email: z8.string()
758
768
  });
769
+ var pendingPasswordProblemSchema = z8.object({
770
+ errorType: z8.literal("PasswordSetupRequired"),
771
+ pendingPasswordToken: z8.string()
772
+ });
759
773
 
760
774
  // src/identity/endpoints.ts
761
775
  var IdentityEndpoints = class {
762
- constructor(api, tokenStore, logger) {
776
+ constructor(api, tokenStore, logger, pendingPasswords) {
763
777
  this.api = api;
764
778
  this.tokenStore = tokenStore;
765
779
  this.logger = logger;
780
+ this.pendingPasswords = pendingPasswords;
766
781
  }
767
782
  async get() {
768
783
  const response = await this.api.authenticatedFetch("/api/customer/meta/user", userSchema);
@@ -818,8 +833,11 @@ var IdentityEndpoints = class {
818
833
  groupIds: normalizeGroupIds(options == null ? void 0 : options.groupIds)
819
834
  })
820
835
  });
821
- if (response.status >= 400)
836
+ if (response.status >= 400) {
837
+ if (response.status === 409)
838
+ await this.keepPendingPassword(email, response.clone());
822
839
  await handleResponseProblem(response, this.logger);
840
+ }
823
841
  const data = await response.json();
824
842
  if (response.status === 202) {
825
843
  const parsed = pendingActivationSchema.parse(data);
@@ -835,6 +853,19 @@ var IdentityEndpoints = class {
835
853
  this.tokenStore.setUser(identity);
836
854
  return { status: "signed-in", user: userSchema.parse(identity) };
837
855
  }
856
+ /**
857
+ * The address already has an account with no password, so the server emailed it a link and
858
+ * handed back the password just typed, sealed, for that link to set once it is opened here.
859
+ * Never thrown: the caller still gets the `PasswordSetupRequiredError` from the response.
860
+ */
861
+ async keepPendingPassword(email, response) {
862
+ try {
863
+ const problem = pendingPasswordProblemSchema.safeParse(await response.json());
864
+ if (problem.success)
865
+ this.pendingPasswords.set(email, problem.data.pendingPasswordToken);
866
+ } catch (e) {
867
+ }
868
+ }
838
869
  /**
839
870
  * Signs the buyer out here at once, and ends the session on the server so its refresh
840
871
  * token stops working too. Resolves once the server has answered, and never rejects:
@@ -886,7 +917,13 @@ var IdentityEndpoints = class {
886
917
  await handleResponseProblem(response, this.logger);
887
918
  }
888
919
  async confirmAccount(email, code) {
889
- const response = await this.api.fetch(`/api/customer/identity/confirm-account?email=${encodeURIComponent(email)}&code=${encodeURIComponent(code.replaceAll(" ", "+"))}&scheme=JWT`, userAccountConfirmedSchema, { method: "POST" });
920
+ const pendingPasswordToken = this.pendingPasswords.get(email);
921
+ const response = await this.api.fetch(`/api/customer/identity/confirm-account?email=${encodeURIComponent(email)}&code=${encodeURIComponent(code.replaceAll(" ", "+"))}&scheme=JWT`, userAccountConfirmedSchema, {
922
+ method: "POST",
923
+ body: pendingPasswordToken ? { pendingPasswordToken } : void 0
924
+ });
925
+ if (pendingPasswordToken)
926
+ this.pendingPasswords.remove(email);
890
927
  const result = response.data;
891
928
  if (result.status === "SignedIn") {
892
929
  if (!result.accessToken || !result.refreshToken) {
@@ -1083,7 +1120,7 @@ var ProductEndpoints = class {
1083
1120
  import { z as z14 } from "zod";
1084
1121
 
1085
1122
  // package.json
1086
- var version = "3.8.0";
1123
+ var version = "3.9.0";
1087
1124
 
1088
1125
  // src/utils/client.ts
1089
1126
  function buildClientHeader(sdk) {
@@ -1091,6 +1128,11 @@ function buildClientHeader(sdk) {
1091
1128
  }
1092
1129
 
1093
1130
  // src/utils/api.ts
1131
+ function loggableBody(body) {
1132
+ if (!body || typeof body !== "object" || Array.isArray(body))
1133
+ return body;
1134
+ return Object.fromEntries(Object.entries(body).map(([key, value]) => [key, /password|token/i.test(key) && value != null ? "[redacted]" : value]));
1135
+ }
1094
1136
  function objectToQuery(obj) {
1095
1137
  return Object.entries(obj != null ? obj : {}).filter(([_, value]) => value !== void 0).map(([key, value]) => `${key}=${encodeURIComponent(value instanceof Date ? value.toISOString() : value)}`).join("&");
1096
1138
  }
@@ -1112,7 +1154,7 @@ var MoonbaseApi = class {
1112
1154
  const contentType = (_a = options == null ? void 0 : options.contentType) != null ? _a : "application/json";
1113
1155
  this.logger.debug("Making request to Moonbase API...", {
1114
1156
  path,
1115
- body: options == null ? void 0 : options.body
1157
+ body: loggableBody(options == null ? void 0 : options.body)
1116
1158
  });
1117
1159
  const startedAt = /* @__PURE__ */ new Date();
1118
1160
  const request = {
@@ -1761,6 +1803,50 @@ var InMemoryStore = class {
1761
1803
  }
1762
1804
  };
1763
1805
 
1806
+ // src/utils/pendingPasswords.ts
1807
+ var lifetime = 24 * 60 * 60 * 1e3;
1808
+ function normalizeEmail(email) {
1809
+ return email.trim().toLowerCase();
1810
+ }
1811
+ var _PendingPasswordStore = class _PendingPasswordStore {
1812
+ constructor(store) {
1813
+ this.store = store != null ? store : isLocalStorageAvailable() ? new LocalStorageStore() : new InMemoryStore();
1814
+ }
1815
+ get(email) {
1816
+ var _a, _b;
1817
+ return (_b = (_a = this.read()[normalizeEmail(email)]) == null ? void 0 : _a.token) != null ? _b : null;
1818
+ }
1819
+ set(email, token) {
1820
+ this.write({ ...this.read(), [normalizeEmail(email)]: { token, storedAt: Date.now() } });
1821
+ }
1822
+ remove(email) {
1823
+ const entries = this.read();
1824
+ delete entries[normalizeEmail(email)];
1825
+ this.write(entries);
1826
+ }
1827
+ /** The entries still worth keeping. Drops the rest from storage as it goes. */
1828
+ read() {
1829
+ const stored = this.store.get(_PendingPasswordStore.storageKey);
1830
+ if (!stored || typeof stored !== "object")
1831
+ return {};
1832
+ const now = Date.now();
1833
+ const fresh = Object.fromEntries(Object.entries(stored).filter(
1834
+ ([, entry]) => typeof (entry == null ? void 0 : entry.token) === "string" && typeof entry.storedAt === "number" && now - entry.storedAt < lifetime
1835
+ ));
1836
+ if (Object.keys(fresh).length !== Object.keys(stored).length)
1837
+ this.write(fresh);
1838
+ return fresh;
1839
+ }
1840
+ write(entries) {
1841
+ if (Object.keys(entries).length > 0)
1842
+ this.store.set(_PendingPasswordStore.storageKey, entries);
1843
+ else
1844
+ this.store.remove(_PendingPasswordStore.storageKey);
1845
+ }
1846
+ };
1847
+ _PendingPasswordStore.storageKey = "moonbase_pending_passwords";
1848
+ var PendingPasswordStore = _PendingPasswordStore;
1849
+
1764
1850
  // src/utils/tokenStore.ts
1765
1851
  var defaultAccessTokenLifetime = 15 * 60 * 1e3;
1766
1852
  var renewBeforeExpiry = 5 * 60 * 1e3;
@@ -1770,9 +1856,9 @@ function accessTokenLifetime(accessToken) {
1770
1856
  try {
1771
1857
  const payload = accessToken.split(".")[1].replaceAll("-", "+").replaceAll("_", "/");
1772
1858
  const claims = JSON.parse(atob(payload.padEnd(Math.ceil(payload.length / 4) * 4, "=")));
1773
- const lifetime = (Number(claims.exp) - Number(claims.iat)) * 1e3;
1774
- if (Number.isFinite(lifetime) && lifetime > 0 && lifetime <= 24 * 60 * 60 * 1e3)
1775
- return lifetime;
1859
+ const lifetime2 = (Number(claims.exp) - Number(claims.iat)) * 1e3;
1860
+ if (Number.isFinite(lifetime2) && lifetime2 > 0 && lifetime2 <= 24 * 60 * 60 * 1e3)
1861
+ return lifetime2;
1776
1862
  } catch (e) {
1777
1863
  }
1778
1864
  return defaultAccessTokenLifetime;
@@ -2714,7 +2800,7 @@ var MoonbaseClient = class {
2714
2800
  this.tokenStore = new TokenStore(configuration);
2715
2801
  this.api = new MoonbaseApi(this.configuration.endpoint, this.tokenStore, this.logger, this.configuration.sdk);
2716
2802
  this.storefront = new StorefrontEndpoints(this.api, this.configuration);
2717
- this.identity = new IdentityEndpoints(this.api, this.tokenStore, this.logger);
2803
+ this.identity = new IdentityEndpoints(this.api, this.tokenStore, this.logger, new PendingPasswordStore(configuration.store));
2718
2804
  this.communications = new CommunicationsEndpoints(this.api);
2719
2805
  this.groups = new GroupEndpoints(this.api);
2720
2806
  this.vouchers = new VoucherEndpoints(this.api);
@@ -2751,6 +2837,7 @@ export {
2751
2837
  NotFoundError,
2752
2838
  OfferUtils,
2753
2839
  OrderStatus,
2840
+ PasswordSetupRequiredError,
2754
2841
  Platform,
2755
2842
  StoreClosedError,
2756
2843
  SubscriptionCancellationReason,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@moonbase.sh/storefront-api",
3
3
  "type": "module",
4
- "version": "3.8.0",
4
+ "version": "3.9.0",
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",