@moonbase.sh/storefront-api 0.4.26 → 0.4.31

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
@@ -53,6 +53,7 @@ __export(index_exports, {
53
53
  Platform: () => Platform,
54
54
  SubscriptionStatus: () => SubscriptionStatus,
55
55
  TokenStore: () => TokenStore,
56
+ objectToQuery: () => objectToQuery,
56
57
  problemDetailsSchema: () => problemDetailsSchema,
57
58
  schemas: () => schemas_exports3,
58
59
  utmToObject: () => utmToObject
@@ -251,6 +252,8 @@ var storefrontOfferSchema = import_zod3.z.object({
251
252
  });
252
253
  var storefrontSchema = import_zod3.z.object({
253
254
  suggestedCurrency: import_zod3.z.string(),
255
+ // Enabled currencies need to be optional since we may still have old, cached representations in browsers
256
+ enabledCurrencies: import_zod3.z.string().array().optional(),
254
257
  products: storefrontProductSchema.array(),
255
258
  bundles: storefrontBundleSchema.array(),
256
259
  // Offers need to be optional since we may still have old, cached representations in browsers
@@ -678,6 +681,132 @@ var ProductEndpoints = class {
678
681
  }
679
682
  };
680
683
 
684
+ // src/utils/api.ts
685
+ var import_cross_fetch2 = __toESM(require("cross-fetch"), 1);
686
+ function objectToQuery(obj) {
687
+ return Object.entries(obj != null ? obj : {}).filter(([_, value]) => value !== void 0).map(([key, value]) => `${key}=${encodeURIComponent(value instanceof Date ? value.toISOString() : value)}`).join("&");
688
+ }
689
+ var MoonbaseApi = class {
690
+ constructor(baseUrl, tokenStore, logger) {
691
+ this.baseUrl = baseUrl;
692
+ this.tokenStore = tokenStore;
693
+ this.logger = logger;
694
+ }
695
+ async authenticatedFetch(path, schema, options) {
696
+ if (!this.tokenStore.user)
697
+ throw new NotAuthenticatedError();
698
+ return await this.fetch(path, schema, options);
699
+ }
700
+ async fetch(path, schema, options) {
701
+ var _a;
702
+ const accessToken = await this.tokenStore.getAccessToken();
703
+ const contentType = (_a = options == null ? void 0 : options.contentType) != null ? _a : "application/json";
704
+ this.logger.debug("Making request to Moonbase API...", {
705
+ path,
706
+ body: options == null ? void 0 : options.body
707
+ });
708
+ const startedAt = /* @__PURE__ */ new Date();
709
+ const request = {
710
+ method: (options == null ? void 0 : options.method) || "GET",
711
+ mode: "cors",
712
+ headers: {
713
+ "Accept": "application/json",
714
+ "Content-Type": contentType,
715
+ // While this fetch can be anonymous, we add the token if we have it
716
+ ...accessToken ? { Authorization: `Bearer ${accessToken}` } : {},
717
+ // Force CORS on all calls
718
+ "x-mb-cors": "1"
719
+ },
720
+ body: (options == null ? void 0 : options.body) ? contentType !== "application/json" ? options.body : JSON.stringify(options.body) : void 0,
721
+ signal: options == null ? void 0 : options.abort,
722
+ redirect: "manual"
723
+ };
724
+ const response = await (0, import_cross_fetch2.default)(this.baseUrl + path, request);
725
+ const finishedAt = /* @__PURE__ */ new Date();
726
+ this.logger.debug("Received response from Moonbase", {
727
+ path,
728
+ status: response.status,
729
+ duration: finishedAt.getTime() - startedAt.getTime()
730
+ });
731
+ if (response.status >= 400) {
732
+ try {
733
+ await handleResponseProblem(response, this.logger);
734
+ } catch (err) {
735
+ this.reportRequestProblem(path, request, response, err);
736
+ throw err;
737
+ }
738
+ }
739
+ let json;
740
+ try {
741
+ json = schema ? await response.json() : null;
742
+ return {
743
+ data: schema ? schema.parse(json) : null,
744
+ headers: Object.fromEntries(response.headers.entries()),
745
+ status: response.status
746
+ };
747
+ } catch (err) {
748
+ this.logger.warn("Could not parse response", {
749
+ status: response.status,
750
+ path,
751
+ content: json || (response.bodyUsed ? "unknown" : await response.text()),
752
+ headers: Object.fromEntries(response.headers.entries()),
753
+ userAgent: window && window.navigator && window.navigator.userAgent,
754
+ err
755
+ });
756
+ this.reportParsingProblem(path, err, json || (response.bodyUsed ? "unknown" : await response.text()));
757
+ throw new MoonbaseError("Bad response", "Could not parse server response", response.status);
758
+ }
759
+ }
760
+ async reportParsingProblem(path, err, body) {
761
+ try {
762
+ await (0, import_cross_fetch2.default)(`${this.baseUrl}/api/customer/insights/error`, {
763
+ mode: "cors",
764
+ method: "POST",
765
+ headers: {
766
+ "Accept": "application/json",
767
+ "Content-Type": "application/json"
768
+ },
769
+ body: JSON.stringify({
770
+ title: "Parse error",
771
+ detail: `Could not parse response body`,
772
+ path,
773
+ origin: window == null ? void 0 : window.location.href,
774
+ userAgent: window && window.navigator && window.navigator.userAgent,
775
+ err,
776
+ body
777
+ })
778
+ });
779
+ } catch (e) {
780
+ }
781
+ }
782
+ async reportRequestProblem(path, request, response, err) {
783
+ try {
784
+ await (0, import_cross_fetch2.default)(`${this.baseUrl}/api/customer/insights/warn`, {
785
+ mode: "cors",
786
+ method: "POST",
787
+ headers: {
788
+ "Accept": "application/json",
789
+ "Content-Type": "application/json"
790
+ },
791
+ body: JSON.stringify({
792
+ title: "Request error",
793
+ detail: `Request failed with status ${response.status}`,
794
+ status: response.status,
795
+ request: {
796
+ ...request,
797
+ headers: void 0,
798
+ body: void 0
799
+ },
800
+ error: err,
801
+ path,
802
+ origin: window == null ? void 0 : window.location.href
803
+ })
804
+ });
805
+ } catch (e) {
806
+ }
807
+ }
808
+ };
809
+
681
810
  // src/inventory/subscriptions/endpoints.ts
682
811
  var import_zod13 = require("zod");
683
812
 
@@ -838,6 +967,8 @@ var subscriptionSchema = import_zod12.z.object({
838
967
  startedAt: import_zod12.z.coerce.date(),
839
968
  total: orderTotalSchema,
840
969
  cycleLength: import_zod12.z.nativeEnum(CycleLength),
970
+ paymentMethod: import_zod12.z.string().optional(),
971
+ embeddedUpdatePaymentUrl: import_zod12.z.string().optional(),
841
972
  content: import_zod12.z.discriminatedUnion("type", [
842
973
  import_zod12.z.object({
843
974
  type: import_zod12.z.literal("Product"),
@@ -862,8 +993,8 @@ var SubscriptionEndpoints = class {
862
993
  const response = await this.api.authenticatedFetch(nextUrl || "/api/customer/inventory/subscriptions", paged(subscriptionSchema));
863
994
  return response.data;
864
995
  }
865
- async getById(subscriptionId) {
866
- const response = await this.api.authenticatedFetch(`/api/customer/inventory/subscriptions/${subscriptionId}`, subscriptionSchema);
996
+ async getById(subscriptionId, options) {
997
+ const response = await this.api.authenticatedFetch(`/api/customer/inventory/subscriptions/${subscriptionId}?${objectToQuery(options)}`, subscriptionSchema);
867
998
  return response.data;
868
999
  }
869
1000
  async cancel(subscriptionId) {
@@ -954,129 +1085,6 @@ var StorefrontEndpoints = class {
954
1085
  }
955
1086
  };
956
1087
 
957
- // src/utils/api.ts
958
- var import_cross_fetch2 = __toESM(require("cross-fetch"), 1);
959
- var MoonbaseApi = class {
960
- constructor(baseUrl, tokenStore, logger) {
961
- this.baseUrl = baseUrl;
962
- this.tokenStore = tokenStore;
963
- this.logger = logger;
964
- }
965
- async authenticatedFetch(path, schema, options) {
966
- if (!this.tokenStore.user)
967
- throw new NotAuthenticatedError();
968
- return await this.fetch(path, schema, options);
969
- }
970
- async fetch(path, schema, options) {
971
- var _a;
972
- const accessToken = await this.tokenStore.getAccessToken();
973
- const contentType = (_a = options == null ? void 0 : options.contentType) != null ? _a : "application/json";
974
- this.logger.debug("Making request to Moonbase API...", {
975
- path,
976
- body: options == null ? void 0 : options.body
977
- });
978
- const startedAt = /* @__PURE__ */ new Date();
979
- const request = {
980
- method: (options == null ? void 0 : options.method) || "GET",
981
- mode: "cors",
982
- headers: {
983
- "Accept": "application/json",
984
- "Content-Type": contentType,
985
- // While this fetch can be anonymous, we add the token if we have it
986
- ...accessToken ? { Authorization: `Bearer ${accessToken}` } : {},
987
- // Force CORS on all calls
988
- "x-mb-cors": "1"
989
- },
990
- body: (options == null ? void 0 : options.body) ? contentType !== "application/json" ? options.body : JSON.stringify(options.body) : void 0,
991
- signal: options == null ? void 0 : options.abort,
992
- redirect: "manual"
993
- };
994
- const response = await (0, import_cross_fetch2.default)(this.baseUrl + path, request);
995
- const finishedAt = /* @__PURE__ */ new Date();
996
- this.logger.debug("Received response from Moonbase", {
997
- path,
998
- status: response.status,
999
- duration: finishedAt.getTime() - startedAt.getTime()
1000
- });
1001
- if (response.status >= 400) {
1002
- try {
1003
- await handleResponseProblem(response, this.logger);
1004
- } catch (err) {
1005
- this.reportRequestProblem(path, request, response, err);
1006
- throw err;
1007
- }
1008
- }
1009
- let json;
1010
- try {
1011
- json = schema ? await response.json() : null;
1012
- return {
1013
- data: schema ? schema.parse(json) : null,
1014
- headers: Object.fromEntries(response.headers.entries()),
1015
- status: response.status
1016
- };
1017
- } catch (err) {
1018
- this.logger.warn("Could not parse response", {
1019
- status: response.status,
1020
- path,
1021
- content: json || (response.bodyUsed ? "unknown" : await response.text()),
1022
- headers: Object.fromEntries(response.headers.entries()),
1023
- userAgent: window && window.navigator && window.navigator.userAgent,
1024
- err
1025
- });
1026
- this.reportParsingProblem(path, err, json || (response.bodyUsed ? "unknown" : await response.text()));
1027
- throw new MoonbaseError("Bad response", "Could not parse server response", response.status);
1028
- }
1029
- }
1030
- async reportParsingProblem(path, err, body) {
1031
- try {
1032
- await (0, import_cross_fetch2.default)(`${this.baseUrl}/api/customer/insights/error`, {
1033
- mode: "cors",
1034
- method: "POST",
1035
- headers: {
1036
- "Accept": "application/json",
1037
- "Content-Type": "application/json"
1038
- },
1039
- body: JSON.stringify({
1040
- title: "Parse error",
1041
- detail: `Could not parse response body`,
1042
- path,
1043
- origin: window == null ? void 0 : window.location.href,
1044
- userAgent: window && window.navigator && window.navigator.userAgent,
1045
- err,
1046
- body
1047
- })
1048
- });
1049
- } catch (e) {
1050
- }
1051
- }
1052
- async reportRequestProblem(path, request, response, err) {
1053
- try {
1054
- await (0, import_cross_fetch2.default)(`${this.baseUrl}/api/customer/insights/warn`, {
1055
- mode: "cors",
1056
- method: "POST",
1057
- headers: {
1058
- "Accept": "application/json",
1059
- "Content-Type": "application/json"
1060
- },
1061
- body: JSON.stringify({
1062
- title: "Request error",
1063
- detail: `Request failed with status ${response.status}`,
1064
- status: response.status,
1065
- request: {
1066
- ...request,
1067
- headers: void 0,
1068
- body: void 0
1069
- },
1070
- error: err,
1071
- path,
1072
- origin: window == null ? void 0 : window.location.href
1073
- })
1074
- });
1075
- } catch (e) {
1076
- }
1077
- }
1078
- };
1079
-
1080
1088
  // src/utils/tokenStore.ts
1081
1089
  var import_cross_fetch3 = __toESM(require("cross-fetch"), 1);
1082
1090
 
@@ -1356,10 +1364,16 @@ var OfferUtils = class {
1356
1364
  switch (offer.condition.type) {
1357
1365
  case "CartContainsItems":
1358
1366
  const relevantItems = order.items.filter(
1359
- (i) => i.type === "Product" && offer.condition.relevantItemVariations[`Product/${i.productId}`] && (offer.condition.relevantItemVariations[`Product/${i.productId}`].length === 0 || offer.condition.relevantItemVariations[`Product/${i.productId}`].includes(i.variationId)) || i.type === "Bundle" && offer.condition.relevantItemVariations[`Bundle/${i.bundleId}`] && (offer.condition.relevantItemVariations[`Bundle/${i.bundleId}`].length === 0 || offer.condition.relevantItemVariations[`Bundle/${i.bundleId}`].includes(i.variationId))
1367
+ (i) => i.type === "Product" && offer.condition.relevantItemVariations[`Product/${i.productId}`] && offer.condition.relevantItemVariations[`Product/${i.productId}`].includes(i.variationId) || i.type === "Bundle" && offer.condition.relevantItemVariations[`Bundle/${i.bundleId}`] && offer.condition.relevantItemVariations[`Bundle/${i.bundleId}`].includes(i.variationId)
1360
1368
  );
1361
- console.log("Relevant items for offer:", { offer, relevantItems });
1362
- return relevantItems.length >= offer.condition.minimumItems;
1369
+ const relevantReplacedItems = order.items.flatMap((i) => {
1370
+ var _a;
1371
+ return i.type === "Bundle" && offer.target.type === "Bundle" && offer.target.id === i.bundleId && offer.id === i.offerId ? (_a = i.replaced) != null ? _a : [] : [];
1372
+ }).filter((ref) => {
1373
+ const [productId, variationId] = ref.split("/");
1374
+ return offer.condition.relevantItemVariations[`Product/${productId}`] && offer.condition.relevantItemVariations[`Product/${productId}`].includes(variationId);
1375
+ });
1376
+ return relevantItems.length + relevantReplacedItems.length >= offer.condition.minimumItems;
1363
1377
  }
1364
1378
  console.warn("Unsupported offer condition found:", offer.condition);
1365
1379
  return false;
@@ -1417,6 +1431,7 @@ var MoonbaseClient = class {
1417
1431
  Platform,
1418
1432
  SubscriptionStatus,
1419
1433
  TokenStore,
1434
+ objectToQuery,
1420
1435
  problemDetailsSchema,
1421
1436
  schemas,
1422
1437
  utmToObject
package/dist/index.d.cts CHANGED
@@ -59,6 +59,7 @@ interface FetchOptions {
59
59
  contentType?: string;
60
60
  abort?: AbortSignal;
61
61
  }
62
+ declare function objectToQuery(obj?: Record<string, string | number | boolean | Date>): string;
62
63
  declare class MoonbaseApi {
63
64
  baseUrl: string;
64
65
  private tokenStore;
@@ -2084,6 +2085,8 @@ declare const subscriptionSchema: z.ZodObject<{
2084
2085
  };
2085
2086
  }>;
2086
2087
  cycleLength: z.ZodNativeEnum<typeof CycleLength>;
2088
+ paymentMethod: z.ZodOptional<z.ZodString>;
2089
+ embeddedUpdatePaymentUrl: z.ZodOptional<z.ZodString>;
2087
2090
  content: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2088
2091
  type: z.ZodLiteral<"Product">;
2089
2092
  quantity: z.ZodNumber;
@@ -4694,6 +4697,8 @@ declare const subscriptionSchema: z.ZodObject<{
4694
4697
  }[] | undefined;
4695
4698
  };
4696
4699
  };
4700
+ paymentMethod?: string | undefined;
4701
+ embeddedUpdatePaymentUrl?: string | undefined;
4697
4702
  }, {
4698
4703
  id: string;
4699
4704
  status: SubscriptionStatus;
@@ -4999,6 +5004,8 @@ declare const subscriptionSchema: z.ZodObject<{
4999
5004
  }[] | undefined;
5000
5005
  };
5001
5006
  };
5007
+ paymentMethod?: string | undefined;
5008
+ embeddedUpdatePaymentUrl?: string | undefined;
5002
5009
  }>;
5003
5010
 
5004
5011
  declare enum SubscriptionStatus {
@@ -5013,7 +5020,10 @@ declare class SubscriptionEndpoints {
5013
5020
  private readonly configuration;
5014
5021
  constructor(api: MoonbaseApi, configuration: MoonbaseConfiguration);
5015
5022
  get(nextUrl?: string): Promise<Page<Subscription>>;
5016
- getById(subscriptionId: string): Promise<Subscription>;
5023
+ getById(subscriptionId: string, options?: {
5024
+ toUpdatePaymentMethod?: boolean;
5025
+ returnUrl?: string;
5026
+ }): Promise<Subscription>;
5017
5027
  cancel(subscriptionId: string): Promise<Subscription>;
5018
5028
  renew(subscriptionId: string, returnUrl: string, embedded: boolean): Promise<{
5019
5029
  location: string;
@@ -19350,6 +19360,7 @@ declare class StorefrontEndpoints {
19350
19360
  }[] | null | undefined;
19351
19361
  }[] | undefined;
19352
19362
  }[];
19363
+ enabledCurrencies?: string[] | undefined;
19353
19364
  offers?: {
19354
19365
  id: string;
19355
19366
  discount: {
@@ -26726,6 +26737,7 @@ declare const storefrontOfferSchema: z.ZodObject<{
26726
26737
  }>;
26727
26738
  declare const storefrontSchema: z.ZodObject<{
26728
26739
  suggestedCurrency: z.ZodString;
26740
+ enabledCurrencies: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
26729
26741
  products: z.ZodArray<z.ZodObject<{
26730
26742
  id: z.ZodString;
26731
26743
  name: z.ZodString;
@@ -31142,6 +31154,7 @@ declare const storefrontSchema: z.ZodObject<{
31142
31154
  }[] | null | undefined;
31143
31155
  }[] | undefined;
31144
31156
  }[];
31157
+ enabledCurrencies?: string[] | undefined;
31145
31158
  offers?: {
31146
31159
  id: string;
31147
31160
  discount: {
@@ -31700,6 +31713,7 @@ declare const storefrontSchema: z.ZodObject<{
31700
31713
  }[] | null | undefined;
31701
31714
  }[] | undefined;
31702
31715
  }[];
31716
+ enabledCurrencies?: string[] | undefined;
31703
31717
  offers?: {
31704
31718
  id: string;
31705
31719
  discount: {
@@ -32075,4 +32089,4 @@ declare class MoonbaseClient {
32075
32089
  orders: OrderEndpoints;
32076
32090
  }
32077
32091
 
32078
- export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, type BundleLineItem, type CommunicationPreferences, type CompletedOrder, ConsoleLogger, CycleLength, type Discount, DiscountUtils, type Download, type DownloadManifest, type ILogger, type IRecurrence, type IStore, type ITokenStore, type Identity, InMemoryStore, type License, LicenseStatus, type LineItem, LocalStorageStore, LogLevel, type Money, type MoneyCollection, MoneyCollectionUtils, MoonbaseApi, MoonbaseClient, type MoonbaseConfiguration, MoonbaseError, NotAuthenticatedError, NotAuthorizedError, NotFoundError, type OfferCondition, OfferUtils, type OpenOrder, type Order, OrderStatus, type OwnedProduct, type Page, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type Quantifiable, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontProduct, type Subscription, SubscriptionStatus, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type Vendor, type Voucher, problemDetailsSchema, schemas, utmToObject };
32092
+ export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, type BundleLineItem, type CommunicationPreferences, type CompletedOrder, ConsoleLogger, CycleLength, type Discount, DiscountUtils, type Download, type DownloadManifest, type ILogger, type IRecurrence, type IStore, type ITokenStore, type Identity, InMemoryStore, type License, LicenseStatus, type LineItem, LocalStorageStore, LogLevel, type Money, type MoneyCollection, MoneyCollectionUtils, MoonbaseApi, MoonbaseClient, type MoonbaseConfiguration, MoonbaseError, NotAuthenticatedError, NotAuthorizedError, NotFoundError, type OfferCondition, OfferUtils, type OpenOrder, type Order, OrderStatus, type OwnedProduct, type Page, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type Quantifiable, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontProduct, type Subscription, SubscriptionStatus, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type Vendor, type Voucher, objectToQuery, problemDetailsSchema, schemas, utmToObject };
package/dist/index.d.ts CHANGED
@@ -59,6 +59,7 @@ interface FetchOptions {
59
59
  contentType?: string;
60
60
  abort?: AbortSignal;
61
61
  }
62
+ declare function objectToQuery(obj?: Record<string, string | number | boolean | Date>): string;
62
63
  declare class MoonbaseApi {
63
64
  baseUrl: string;
64
65
  private tokenStore;
@@ -2084,6 +2085,8 @@ declare const subscriptionSchema: z.ZodObject<{
2084
2085
  };
2085
2086
  }>;
2086
2087
  cycleLength: z.ZodNativeEnum<typeof CycleLength>;
2088
+ paymentMethod: z.ZodOptional<z.ZodString>;
2089
+ embeddedUpdatePaymentUrl: z.ZodOptional<z.ZodString>;
2087
2090
  content: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2088
2091
  type: z.ZodLiteral<"Product">;
2089
2092
  quantity: z.ZodNumber;
@@ -4694,6 +4697,8 @@ declare const subscriptionSchema: z.ZodObject<{
4694
4697
  }[] | undefined;
4695
4698
  };
4696
4699
  };
4700
+ paymentMethod?: string | undefined;
4701
+ embeddedUpdatePaymentUrl?: string | undefined;
4697
4702
  }, {
4698
4703
  id: string;
4699
4704
  status: SubscriptionStatus;
@@ -4999,6 +5004,8 @@ declare const subscriptionSchema: z.ZodObject<{
4999
5004
  }[] | undefined;
5000
5005
  };
5001
5006
  };
5007
+ paymentMethod?: string | undefined;
5008
+ embeddedUpdatePaymentUrl?: string | undefined;
5002
5009
  }>;
5003
5010
 
5004
5011
  declare enum SubscriptionStatus {
@@ -5013,7 +5020,10 @@ declare class SubscriptionEndpoints {
5013
5020
  private readonly configuration;
5014
5021
  constructor(api: MoonbaseApi, configuration: MoonbaseConfiguration);
5015
5022
  get(nextUrl?: string): Promise<Page<Subscription>>;
5016
- getById(subscriptionId: string): Promise<Subscription>;
5023
+ getById(subscriptionId: string, options?: {
5024
+ toUpdatePaymentMethod?: boolean;
5025
+ returnUrl?: string;
5026
+ }): Promise<Subscription>;
5017
5027
  cancel(subscriptionId: string): Promise<Subscription>;
5018
5028
  renew(subscriptionId: string, returnUrl: string, embedded: boolean): Promise<{
5019
5029
  location: string;
@@ -19350,6 +19360,7 @@ declare class StorefrontEndpoints {
19350
19360
  }[] | null | undefined;
19351
19361
  }[] | undefined;
19352
19362
  }[];
19363
+ enabledCurrencies?: string[] | undefined;
19353
19364
  offers?: {
19354
19365
  id: string;
19355
19366
  discount: {
@@ -26726,6 +26737,7 @@ declare const storefrontOfferSchema: z.ZodObject<{
26726
26737
  }>;
26727
26738
  declare const storefrontSchema: z.ZodObject<{
26728
26739
  suggestedCurrency: z.ZodString;
26740
+ enabledCurrencies: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
26729
26741
  products: z.ZodArray<z.ZodObject<{
26730
26742
  id: z.ZodString;
26731
26743
  name: z.ZodString;
@@ -31142,6 +31154,7 @@ declare const storefrontSchema: z.ZodObject<{
31142
31154
  }[] | null | undefined;
31143
31155
  }[] | undefined;
31144
31156
  }[];
31157
+ enabledCurrencies?: string[] | undefined;
31145
31158
  offers?: {
31146
31159
  id: string;
31147
31160
  discount: {
@@ -31700,6 +31713,7 @@ declare const storefrontSchema: z.ZodObject<{
31700
31713
  }[] | null | undefined;
31701
31714
  }[] | undefined;
31702
31715
  }[];
31716
+ enabledCurrencies?: string[] | undefined;
31703
31717
  offers?: {
31704
31718
  id: string;
31705
31719
  discount: {
@@ -32075,4 +32089,4 @@ declare class MoonbaseClient {
32075
32089
  orders: OrderEndpoints;
32076
32090
  }
32077
32091
 
32078
- export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, type BundleLineItem, type CommunicationPreferences, type CompletedOrder, ConsoleLogger, CycleLength, type Discount, DiscountUtils, type Download, type DownloadManifest, type ILogger, type IRecurrence, type IStore, type ITokenStore, type Identity, InMemoryStore, type License, LicenseStatus, type LineItem, LocalStorageStore, LogLevel, type Money, type MoneyCollection, MoneyCollectionUtils, MoonbaseApi, MoonbaseClient, type MoonbaseConfiguration, MoonbaseError, NotAuthenticatedError, NotAuthorizedError, NotFoundError, type OfferCondition, OfferUtils, type OpenOrder, type Order, OrderStatus, type OwnedProduct, type Page, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type Quantifiable, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontProduct, type Subscription, SubscriptionStatus, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type Vendor, type Voucher, problemDetailsSchema, schemas, utmToObject };
32092
+ export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, type BundleLineItem, type CommunicationPreferences, type CompletedOrder, ConsoleLogger, CycleLength, type Discount, DiscountUtils, type Download, type DownloadManifest, type ILogger, type IRecurrence, type IStore, type ITokenStore, type Identity, InMemoryStore, type License, LicenseStatus, type LineItem, LocalStorageStore, LogLevel, type Money, type MoneyCollection, MoneyCollectionUtils, MoonbaseApi, MoonbaseClient, type MoonbaseConfiguration, MoonbaseError, NotAuthenticatedError, NotAuthorizedError, NotFoundError, type OfferCondition, OfferUtils, type OpenOrder, type Order, OrderStatus, type OwnedProduct, type Page, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type Quantifiable, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontProduct, type Subscription, SubscriptionStatus, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type Vendor, type Voucher, objectToQuery, problemDetailsSchema, schemas, utmToObject };
package/dist/index.js CHANGED
@@ -196,6 +196,8 @@ var storefrontOfferSchema = z3.object({
196
196
  });
197
197
  var storefrontSchema = z3.object({
198
198
  suggestedCurrency: z3.string(),
199
+ // Enabled currencies need to be optional since we may still have old, cached representations in browsers
200
+ enabledCurrencies: z3.string().array().optional(),
199
201
  products: storefrontProductSchema.array(),
200
202
  bundles: storefrontBundleSchema.array(),
201
203
  // Offers need to be optional since we may still have old, cached representations in browsers
@@ -623,6 +625,132 @@ var ProductEndpoints = class {
623
625
  }
624
626
  };
625
627
 
628
+ // src/utils/api.ts
629
+ import fetch2 from "cross-fetch";
630
+ function objectToQuery(obj) {
631
+ return Object.entries(obj != null ? obj : {}).filter(([_, value]) => value !== void 0).map(([key, value]) => `${key}=${encodeURIComponent(value instanceof Date ? value.toISOString() : value)}`).join("&");
632
+ }
633
+ var MoonbaseApi = class {
634
+ constructor(baseUrl, tokenStore, logger) {
635
+ this.baseUrl = baseUrl;
636
+ this.tokenStore = tokenStore;
637
+ this.logger = logger;
638
+ }
639
+ async authenticatedFetch(path, schema, options) {
640
+ if (!this.tokenStore.user)
641
+ throw new NotAuthenticatedError();
642
+ return await this.fetch(path, schema, options);
643
+ }
644
+ async fetch(path, schema, options) {
645
+ var _a;
646
+ const accessToken = await this.tokenStore.getAccessToken();
647
+ const contentType = (_a = options == null ? void 0 : options.contentType) != null ? _a : "application/json";
648
+ this.logger.debug("Making request to Moonbase API...", {
649
+ path,
650
+ body: options == null ? void 0 : options.body
651
+ });
652
+ const startedAt = /* @__PURE__ */ new Date();
653
+ const request = {
654
+ method: (options == null ? void 0 : options.method) || "GET",
655
+ mode: "cors",
656
+ headers: {
657
+ "Accept": "application/json",
658
+ "Content-Type": contentType,
659
+ // While this fetch can be anonymous, we add the token if we have it
660
+ ...accessToken ? { Authorization: `Bearer ${accessToken}` } : {},
661
+ // Force CORS on all calls
662
+ "x-mb-cors": "1"
663
+ },
664
+ body: (options == null ? void 0 : options.body) ? contentType !== "application/json" ? options.body : JSON.stringify(options.body) : void 0,
665
+ signal: options == null ? void 0 : options.abort,
666
+ redirect: "manual"
667
+ };
668
+ const response = await fetch2(this.baseUrl + path, request);
669
+ const finishedAt = /* @__PURE__ */ new Date();
670
+ this.logger.debug("Received response from Moonbase", {
671
+ path,
672
+ status: response.status,
673
+ duration: finishedAt.getTime() - startedAt.getTime()
674
+ });
675
+ if (response.status >= 400) {
676
+ try {
677
+ await handleResponseProblem(response, this.logger);
678
+ } catch (err) {
679
+ this.reportRequestProblem(path, request, response, err);
680
+ throw err;
681
+ }
682
+ }
683
+ let json;
684
+ try {
685
+ json = schema ? await response.json() : null;
686
+ return {
687
+ data: schema ? schema.parse(json) : null,
688
+ headers: Object.fromEntries(response.headers.entries()),
689
+ status: response.status
690
+ };
691
+ } catch (err) {
692
+ this.logger.warn("Could not parse response", {
693
+ status: response.status,
694
+ path,
695
+ content: json || (response.bodyUsed ? "unknown" : await response.text()),
696
+ headers: Object.fromEntries(response.headers.entries()),
697
+ userAgent: window && window.navigator && window.navigator.userAgent,
698
+ err
699
+ });
700
+ this.reportParsingProblem(path, err, json || (response.bodyUsed ? "unknown" : await response.text()));
701
+ throw new MoonbaseError("Bad response", "Could not parse server response", response.status);
702
+ }
703
+ }
704
+ async reportParsingProblem(path, err, body) {
705
+ try {
706
+ await fetch2(`${this.baseUrl}/api/customer/insights/error`, {
707
+ mode: "cors",
708
+ method: "POST",
709
+ headers: {
710
+ "Accept": "application/json",
711
+ "Content-Type": "application/json"
712
+ },
713
+ body: JSON.stringify({
714
+ title: "Parse error",
715
+ detail: `Could not parse response body`,
716
+ path,
717
+ origin: window == null ? void 0 : window.location.href,
718
+ userAgent: window && window.navigator && window.navigator.userAgent,
719
+ err,
720
+ body
721
+ })
722
+ });
723
+ } catch (e) {
724
+ }
725
+ }
726
+ async reportRequestProblem(path, request, response, err) {
727
+ try {
728
+ await fetch2(`${this.baseUrl}/api/customer/insights/warn`, {
729
+ mode: "cors",
730
+ method: "POST",
731
+ headers: {
732
+ "Accept": "application/json",
733
+ "Content-Type": "application/json"
734
+ },
735
+ body: JSON.stringify({
736
+ title: "Request error",
737
+ detail: `Request failed with status ${response.status}`,
738
+ status: response.status,
739
+ request: {
740
+ ...request,
741
+ headers: void 0,
742
+ body: void 0
743
+ },
744
+ error: err,
745
+ path,
746
+ origin: window == null ? void 0 : window.location.href
747
+ })
748
+ });
749
+ } catch (e) {
750
+ }
751
+ }
752
+ };
753
+
626
754
  // src/inventory/subscriptions/endpoints.ts
627
755
  import { z as z13 } from "zod";
628
756
 
@@ -783,6 +911,8 @@ var subscriptionSchema = z12.object({
783
911
  startedAt: z12.coerce.date(),
784
912
  total: orderTotalSchema,
785
913
  cycleLength: z12.nativeEnum(CycleLength),
914
+ paymentMethod: z12.string().optional(),
915
+ embeddedUpdatePaymentUrl: z12.string().optional(),
786
916
  content: z12.discriminatedUnion("type", [
787
917
  z12.object({
788
918
  type: z12.literal("Product"),
@@ -807,8 +937,8 @@ var SubscriptionEndpoints = class {
807
937
  const response = await this.api.authenticatedFetch(nextUrl || "/api/customer/inventory/subscriptions", paged(subscriptionSchema));
808
938
  return response.data;
809
939
  }
810
- async getById(subscriptionId) {
811
- const response = await this.api.authenticatedFetch(`/api/customer/inventory/subscriptions/${subscriptionId}`, subscriptionSchema);
940
+ async getById(subscriptionId, options) {
941
+ const response = await this.api.authenticatedFetch(`/api/customer/inventory/subscriptions/${subscriptionId}?${objectToQuery(options)}`, subscriptionSchema);
812
942
  return response.data;
813
943
  }
814
944
  async cancel(subscriptionId) {
@@ -899,129 +1029,6 @@ var StorefrontEndpoints = class {
899
1029
  }
900
1030
  };
901
1031
 
902
- // src/utils/api.ts
903
- import fetch2 from "cross-fetch";
904
- var MoonbaseApi = class {
905
- constructor(baseUrl, tokenStore, logger) {
906
- this.baseUrl = baseUrl;
907
- this.tokenStore = tokenStore;
908
- this.logger = logger;
909
- }
910
- async authenticatedFetch(path, schema, options) {
911
- if (!this.tokenStore.user)
912
- throw new NotAuthenticatedError();
913
- return await this.fetch(path, schema, options);
914
- }
915
- async fetch(path, schema, options) {
916
- var _a;
917
- const accessToken = await this.tokenStore.getAccessToken();
918
- const contentType = (_a = options == null ? void 0 : options.contentType) != null ? _a : "application/json";
919
- this.logger.debug("Making request to Moonbase API...", {
920
- path,
921
- body: options == null ? void 0 : options.body
922
- });
923
- const startedAt = /* @__PURE__ */ new Date();
924
- const request = {
925
- method: (options == null ? void 0 : options.method) || "GET",
926
- mode: "cors",
927
- headers: {
928
- "Accept": "application/json",
929
- "Content-Type": contentType,
930
- // While this fetch can be anonymous, we add the token if we have it
931
- ...accessToken ? { Authorization: `Bearer ${accessToken}` } : {},
932
- // Force CORS on all calls
933
- "x-mb-cors": "1"
934
- },
935
- body: (options == null ? void 0 : options.body) ? contentType !== "application/json" ? options.body : JSON.stringify(options.body) : void 0,
936
- signal: options == null ? void 0 : options.abort,
937
- redirect: "manual"
938
- };
939
- const response = await fetch2(this.baseUrl + path, request);
940
- const finishedAt = /* @__PURE__ */ new Date();
941
- this.logger.debug("Received response from Moonbase", {
942
- path,
943
- status: response.status,
944
- duration: finishedAt.getTime() - startedAt.getTime()
945
- });
946
- if (response.status >= 400) {
947
- try {
948
- await handleResponseProblem(response, this.logger);
949
- } catch (err) {
950
- this.reportRequestProblem(path, request, response, err);
951
- throw err;
952
- }
953
- }
954
- let json;
955
- try {
956
- json = schema ? await response.json() : null;
957
- return {
958
- data: schema ? schema.parse(json) : null,
959
- headers: Object.fromEntries(response.headers.entries()),
960
- status: response.status
961
- };
962
- } catch (err) {
963
- this.logger.warn("Could not parse response", {
964
- status: response.status,
965
- path,
966
- content: json || (response.bodyUsed ? "unknown" : await response.text()),
967
- headers: Object.fromEntries(response.headers.entries()),
968
- userAgent: window && window.navigator && window.navigator.userAgent,
969
- err
970
- });
971
- this.reportParsingProblem(path, err, json || (response.bodyUsed ? "unknown" : await response.text()));
972
- throw new MoonbaseError("Bad response", "Could not parse server response", response.status);
973
- }
974
- }
975
- async reportParsingProblem(path, err, body) {
976
- try {
977
- await fetch2(`${this.baseUrl}/api/customer/insights/error`, {
978
- mode: "cors",
979
- method: "POST",
980
- headers: {
981
- "Accept": "application/json",
982
- "Content-Type": "application/json"
983
- },
984
- body: JSON.stringify({
985
- title: "Parse error",
986
- detail: `Could not parse response body`,
987
- path,
988
- origin: window == null ? void 0 : window.location.href,
989
- userAgent: window && window.navigator && window.navigator.userAgent,
990
- err,
991
- body
992
- })
993
- });
994
- } catch (e) {
995
- }
996
- }
997
- async reportRequestProblem(path, request, response, err) {
998
- try {
999
- await fetch2(`${this.baseUrl}/api/customer/insights/warn`, {
1000
- mode: "cors",
1001
- method: "POST",
1002
- headers: {
1003
- "Accept": "application/json",
1004
- "Content-Type": "application/json"
1005
- },
1006
- body: JSON.stringify({
1007
- title: "Request error",
1008
- detail: `Request failed with status ${response.status}`,
1009
- status: response.status,
1010
- request: {
1011
- ...request,
1012
- headers: void 0,
1013
- body: void 0
1014
- },
1015
- error: err,
1016
- path,
1017
- origin: window == null ? void 0 : window.location.href
1018
- })
1019
- });
1020
- } catch (e) {
1021
- }
1022
- }
1023
- };
1024
-
1025
1032
  // src/utils/tokenStore.ts
1026
1033
  import fetch3 from "cross-fetch";
1027
1034
 
@@ -1301,10 +1308,16 @@ var OfferUtils = class {
1301
1308
  switch (offer.condition.type) {
1302
1309
  case "CartContainsItems":
1303
1310
  const relevantItems = order.items.filter(
1304
- (i) => i.type === "Product" && offer.condition.relevantItemVariations[`Product/${i.productId}`] && (offer.condition.relevantItemVariations[`Product/${i.productId}`].length === 0 || offer.condition.relevantItemVariations[`Product/${i.productId}`].includes(i.variationId)) || i.type === "Bundle" && offer.condition.relevantItemVariations[`Bundle/${i.bundleId}`] && (offer.condition.relevantItemVariations[`Bundle/${i.bundleId}`].length === 0 || offer.condition.relevantItemVariations[`Bundle/${i.bundleId}`].includes(i.variationId))
1311
+ (i) => i.type === "Product" && offer.condition.relevantItemVariations[`Product/${i.productId}`] && offer.condition.relevantItemVariations[`Product/${i.productId}`].includes(i.variationId) || i.type === "Bundle" && offer.condition.relevantItemVariations[`Bundle/${i.bundleId}`] && offer.condition.relevantItemVariations[`Bundle/${i.bundleId}`].includes(i.variationId)
1305
1312
  );
1306
- console.log("Relevant items for offer:", { offer, relevantItems });
1307
- return relevantItems.length >= offer.condition.minimumItems;
1313
+ const relevantReplacedItems = order.items.flatMap((i) => {
1314
+ var _a;
1315
+ return i.type === "Bundle" && offer.target.type === "Bundle" && offer.target.id === i.bundleId && offer.id === i.offerId ? (_a = i.replaced) != null ? _a : [] : [];
1316
+ }).filter((ref) => {
1317
+ const [productId, variationId] = ref.split("/");
1318
+ return offer.condition.relevantItemVariations[`Product/${productId}`] && offer.condition.relevantItemVariations[`Product/${productId}`].includes(variationId);
1319
+ });
1320
+ return relevantItems.length + relevantReplacedItems.length >= offer.condition.minimumItems;
1308
1321
  }
1309
1322
  console.warn("Unsupported offer condition found:", offer.condition);
1310
1323
  return false;
@@ -1361,6 +1374,7 @@ export {
1361
1374
  Platform,
1362
1375
  SubscriptionStatus,
1363
1376
  TokenStore,
1377
+ objectToQuery,
1364
1378
  problemDetailsSchema,
1365
1379
  schemas_exports3 as schemas,
1366
1380
  utmToObject
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@moonbase.sh/storefront-api",
3
3
  "type": "module",
4
- "version": "0.4.26",
4
+ "version": "0.4.31",
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",