@01.software/sdk 0.37.0 → 0.39.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.
Files changed (74) hide show
  1. package/README.md +189 -84
  2. package/dist/analytics/react.cjs.map +1 -1
  3. package/dist/analytics/react.js.map +1 -1
  4. package/dist/analytics.cjs.map +1 -1
  5. package/dist/analytics.js.map +1 -1
  6. package/dist/client.cjs +1286 -109
  7. package/dist/client.cjs.map +1 -1
  8. package/dist/client.d.cts +8 -7
  9. package/dist/client.d.ts +8 -7
  10. package/dist/client.js +1286 -109
  11. package/dist/client.js.map +1 -1
  12. package/dist/{collection-client-DyELGUcL.d.ts → collection-client-CaMgs5KE.d.ts} +18 -12
  13. package/dist/{collection-client-zOmnxwdA.d.cts → collection-client-DVfB0Em1.d.cts} +18 -12
  14. package/dist/const-6XHz_jej.d.ts +32 -0
  15. package/dist/const-B5KT72c7.d.cts +32 -0
  16. package/dist/errors.cjs +4 -1
  17. package/dist/errors.cjs.map +1 -1
  18. package/dist/errors.js +4 -1
  19. package/dist/errors.js.map +1 -1
  20. package/dist/{index-DRJs7QIh.d.cts → index-BOLQxveo.d.cts} +3 -3
  21. package/dist/{index-DTqoUZk_.d.ts → index-CSwR2HSg.d.ts} +3 -3
  22. package/dist/index.cjs +2861 -2714
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +9 -9
  25. package/dist/index.d.ts +9 -9
  26. package/dist/index.js +2861 -2714
  27. package/dist/index.js.map +1 -1
  28. package/dist/{payload-types-CREOjFNT.d.cts → payload-types-m3jjhxk9.d.cts} +418 -106
  29. package/dist/{payload-types-CREOjFNT.d.ts → payload-types-m3jjhxk9.d.ts} +418 -106
  30. package/dist/query.cjs +244 -1093
  31. package/dist/query.cjs.map +1 -1
  32. package/dist/query.d.cts +159 -34
  33. package/dist/query.d.ts +159 -34
  34. package/dist/query.js +244 -1093
  35. package/dist/query.js.map +1 -1
  36. package/dist/realtime.cjs +5 -1
  37. package/dist/realtime.cjs.map +1 -1
  38. package/dist/realtime.d.cts +2 -2
  39. package/dist/realtime.d.ts +2 -2
  40. package/dist/realtime.js +5 -1
  41. package/dist/realtime.js.map +1 -1
  42. package/dist/server.cjs +1191 -22
  43. package/dist/server.cjs.map +1 -1
  44. package/dist/server.d.cts +7 -7
  45. package/dist/server.d.ts +7 -7
  46. package/dist/server.js +1191 -22
  47. package/dist/server.js.map +1 -1
  48. package/dist/storefront-cache.cjs +144 -0
  49. package/dist/storefront-cache.cjs.map +1 -0
  50. package/dist/storefront-cache.d.cts +24 -0
  51. package/dist/storefront-cache.d.ts +24 -0
  52. package/dist/storefront-cache.js +121 -0
  53. package/dist/storefront-cache.js.map +1 -0
  54. package/dist/{types-DMvVHdb1.d.ts → types-BQo7UdI9.d.cts} +1608 -1215
  55. package/dist/{types-BWMUr3Zw.d.cts → types-CVf8sCZ-.d.ts} +1608 -1215
  56. package/dist/{types-CxzWHspI.d.ts → types-Cmrd1ezc.d.ts} +1 -15
  57. package/dist/{types-BkZNhuBh.d.cts → types-D0ubzQw0.d.cts} +1 -15
  58. package/dist/ui/canvas/server.cjs +5 -1
  59. package/dist/ui/canvas/server.cjs.map +1 -1
  60. package/dist/ui/canvas/server.js +5 -1
  61. package/dist/ui/canvas/server.js.map +1 -1
  62. package/dist/ui/canvas.cjs +5 -1
  63. package/dist/ui/canvas.cjs.map +1 -1
  64. package/dist/ui/canvas.js +5 -1
  65. package/dist/ui/canvas.js.map +1 -1
  66. package/dist/ui/form.d.cts +1 -1
  67. package/dist/ui/form.d.ts +1 -1
  68. package/dist/ui/video.d.cts +1 -1
  69. package/dist/ui/video.d.ts +1 -1
  70. package/dist/webhook.d.cts +4 -4
  71. package/dist/webhook.d.ts +4 -4
  72. package/package.json +11 -1
  73. package/dist/const-CK_FPaIn.d.cts +0 -32
  74. package/dist/const-Dqz05oaG.d.ts +0 -32
package/dist/client.js CHANGED
@@ -600,12 +600,35 @@ function productDetailCatalogQuery(params) {
600
600
  }
601
601
  return `/api/products/detail/catalog?${search}`;
602
602
  }
603
- function listingGroupsQuery(params) {
604
- return `/api/products/listing-groups?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
605
- }
606
603
  function listingGroupsCatalogQuery(params) {
607
604
  return `/api/products/listing-groups/catalog?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
608
605
  }
606
+ function appendListingGroupsQuerySearchParams(search, options) {
607
+ if (options?.page != null) search.set("page", String(options.page));
608
+ if (options?.limit != null) search.set("limit", String(options.limit));
609
+ if (options?.sort != null) {
610
+ const sort = options.sort;
611
+ search.set(
612
+ "sort",
613
+ Array.isArray(sort) ? sort.join(",") : sort
614
+ );
615
+ }
616
+ if (options?.where != null) {
617
+ search.set("whereJson", JSON.stringify(options.where));
618
+ }
619
+ }
620
+ function listingGroupsQueryUrl(options) {
621
+ const search = new URLSearchParams();
622
+ appendListingGroupsQuerySearchParams(search, options);
623
+ const query = search.toString();
624
+ return `/api/products/listing-groups/query${query ? `?${query}` : ""}`;
625
+ }
626
+ function listingGroupsQueryCatalogUrl(options) {
627
+ const search = new URLSearchParams();
628
+ appendListingGroupsQuerySearchParams(search, options);
629
+ const query = search.toString();
630
+ return `/api/products/listing-groups/query/catalog${query ? `?${query}` : ""}`;
631
+ }
609
632
  function stockSnapshotQuery(params) {
610
633
  return `/api/products/stock?variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
611
634
  }
@@ -744,73 +767,27 @@ var HttpClient = class {
744
767
  }
745
768
  };
746
769
 
747
- // src/utils/types.ts
748
- function resolveRelation(ref) {
749
- if (typeof ref === "string" || typeof ref === "number" || ref === null || ref === void 0)
750
- return null;
751
- return ref;
752
- }
753
-
754
- // src/core/metadata/index.ts
755
- var OPEN_GRAPH_IMAGE_SIZE = "1200";
756
- var LEGACY_OPEN_GRAPH_IMAGE_SIZE = "1536";
757
- function extractSeo(doc) {
758
- const seo = doc.seo ?? {};
759
- const og = seo.openGraph ?? {};
760
- return {
761
- title: seo.title ?? doc.title ?? null,
762
- description: seo.description ?? null,
763
- noIndex: seo.noIndex ?? null,
764
- canonical: seo.canonical ?? null,
765
- openGraph: {
766
- title: og.title ?? null,
767
- description: og.description ?? null,
768
- image: og.image ?? null
769
- }
770
- };
771
- }
772
- function generateMetadata(input, options) {
773
- const title = input.title ?? void 0;
774
- const description = input.description ?? void 0;
775
- const ogTitle = input.openGraph?.title ?? title;
776
- const ogDescription = input.openGraph?.description ?? description;
777
- const image = resolveMetaImage(input.openGraph?.image);
778
- return {
779
- title,
780
- description,
781
- ...input.noIndex && { robots: { index: false, follow: false } },
782
- ...input.canonical && { alternates: { canonical: input.canonical } },
783
- openGraph: {
784
- ...ogTitle && { title: ogTitle },
785
- ...ogDescription && { description: ogDescription },
786
- ...options?.siteName && { siteName: options.siteName },
787
- ...image && { images: [image] }
788
- },
789
- twitter: {
790
- card: image ? "summary_large_image" : "summary",
791
- ...ogTitle && { title: ogTitle },
792
- ...ogDescription && { description: ogDescription },
793
- ...image && { images: [image.url] }
794
- }
795
- };
796
- }
797
- function resolveMetaImage(ref) {
798
- const image = resolveRelation(ref);
799
- if (!image) return null;
800
- const sized = image.sizes?.[OPEN_GRAPH_IMAGE_SIZE] ?? image.sizes?.[LEGACY_OPEN_GRAPH_IMAGE_SIZE];
801
- const url = sized?.url || image.url;
802
- if (!url) return null;
803
- const width = sized?.url ? sized.width : image.width;
804
- const height = sized?.url ? sized.height : image.height;
770
+ // src/core/collection/query-builder.ts
771
+ var PUBLIC_READ_DEPTH_ERROR = "Publishable collection reads require depth: 0. Use a shaped commerce endpoint or server client for populated data.";
772
+ var PUBLIC_READ_JOINS_ERROR = "Publishable collection reads require joins: false. Use a shaped commerce endpoint or server client for joined data.";
773
+ var PUBLIC_READ_POPULATE_ERROR = "Publishable collection reads do not support populate. Use a shaped commerce endpoint or server client for populated data.";
774
+ function withDefaultPublicReadOptions(options) {
775
+ const rawOptions = options;
776
+ if (rawOptions?.depth !== void 0 && rawOptions.depth !== 0) {
777
+ throw createValidationError(PUBLIC_READ_DEPTH_ERROR);
778
+ }
779
+ if (rawOptions?.joins !== void 0 && rawOptions.joins !== false) {
780
+ throw createValidationError(PUBLIC_READ_JOINS_ERROR);
781
+ }
782
+ if (rawOptions?.populate !== void 0) {
783
+ throw createValidationError(PUBLIC_READ_POPULATE_ERROR);
784
+ }
805
785
  return {
806
- url,
807
- ...width && { width },
808
- ...height && { height },
809
- ...image.alt && { alt: image.alt }
786
+ ...options,
787
+ depth: options?.depth ?? 0,
788
+ joins: options?.joins ?? false
810
789
  };
811
790
  }
812
-
813
- // src/core/collection/query-builder.ts
814
791
  var ReadOnlyCollectionQueryBuilder = class {
815
792
  constructor(api, collection) {
816
793
  this.api = api;
@@ -819,35 +796,19 @@ var ReadOnlyCollectionQueryBuilder = class {
819
796
  async find(options) {
820
797
  return this.api.requestFind(
821
798
  `/api/${String(this.collection)}`,
822
- options
799
+ withDefaultPublicReadOptions(options)
823
800
  );
824
801
  }
825
802
  async findById(id, options) {
826
803
  return this.api.requestFindById(
827
804
  `/api/${String(this.collection)}/${String(id)}`,
828
- options
805
+ withDefaultPublicReadOptions(options)
829
806
  );
830
807
  }
831
808
  async count(options) {
832
809
  return this.api.requestCount(
833
810
  `/api/${String(this.collection)}/count`,
834
- options
835
- );
836
- }
837
- async findMetadata(options, metadataOptions) {
838
- const { docs } = await this.find({ ...options, limit: 1, depth: 1 });
839
- const doc = docs[0];
840
- if (!doc) return null;
841
- return generateMetadata(
842
- extractSeo(doc),
843
- metadataOptions
844
- );
845
- }
846
- async findMetadataById(id, metadataOptions) {
847
- const doc = await this.findById(id, { depth: 1 });
848
- return generateMetadata(
849
- extractSeo(doc),
850
- metadataOptions
811
+ withDefaultPublicReadOptions(options)
851
812
  );
852
813
  }
853
814
  };
@@ -865,6 +826,21 @@ var ReadOnlyCollectionClient = class extends HttpClient {
865
826
  });
866
827
  return this.parseFindResponse(response);
867
828
  }
829
+ async requestFindEndpoint(endpoint, data) {
830
+ const response = await this.fetchWithTracking(endpoint, {
831
+ ...this.defaultOptions,
832
+ method: "POST",
833
+ body: data ? JSON.stringify(data) : void 0
834
+ });
835
+ return this.parseFindResponse(response);
836
+ }
837
+ async requestFindEndpointGet(endpoint) {
838
+ const response = await this.fetchWithTracking(endpoint, {
839
+ ...this.defaultOptions,
840
+ method: "GET"
841
+ });
842
+ return this.parseFindResponse(response);
843
+ }
868
844
  async requestFindById(endpoint, options) {
869
845
  const url = this.buildUrl(endpoint, options);
870
846
  const response = await this.fetchWithTracking(url, {
@@ -995,7 +971,8 @@ var CommunityClient = class extends CustomerScopedApi {
995
971
  const urlParams = new URLSearchParams();
996
972
  const sort = params?.sort ?? DEFAULT_POST_LIST_SORT;
997
973
  urlParams.set("sort", sort);
998
- if (params?.limit !== void 0) urlParams.set("limit", String(params.limit));
974
+ if (params?.limit !== void 0)
975
+ urlParams.set("limit", String(params.limit));
999
976
  if (params?.page !== void 0) urlParams.set("page", String(params.page));
1000
977
  if (params?.categoryId !== void 0) {
1001
978
  urlParams.set("where[categories][in]", params.categoryId);
@@ -1003,7 +980,7 @@ var CommunityClient = class extends CustomerScopedApi {
1003
980
  if (params?.tagId !== void 0) {
1004
981
  urlParams.set("where[tags][in]", params.tagId);
1005
982
  }
1006
- return `/api/posts?${urlParams.toString()}`;
983
+ return `/api/posts/public?${urlParams.toString()}`;
1007
984
  }
1008
985
  buildCommentsListQuery(params) {
1009
986
  const urlParams = new URLSearchParams();
@@ -1023,7 +1000,7 @@ var CommunityClient = class extends CustomerScopedApi {
1023
1000
  }
1024
1001
  if (params.limit !== void 0) urlParams.set("limit", String(params.limit));
1025
1002
  if (params.page !== void 0) urlParams.set("page", String(params.page));
1026
- return `/api/comments?${urlParams.toString()}`;
1003
+ return `/api/comments/public?${urlParams.toString()}`;
1027
1004
  }
1028
1005
  async execute(endpoint, method, body) {
1029
1006
  return this.request(endpoint, { method, body });
@@ -1033,7 +1010,11 @@ var CommunityClient = class extends CustomerScopedApi {
1033
1010
  return unwrapPayloadDoc(response);
1034
1011
  }
1035
1012
  createPost(params) {
1036
- return this.executeDoc("/api/posts", "POST", params);
1013
+ return this.executeDoc(
1014
+ "/api/posts",
1015
+ "POST",
1016
+ params
1017
+ );
1037
1018
  }
1038
1019
  /**
1039
1020
  * Public post feed. Server applies the same visibility contract as
@@ -1090,7 +1071,11 @@ var CommunityClient = class extends CustomerScopedApi {
1090
1071
  if (parentId !== void 0) {
1091
1072
  body.parent = parentId;
1092
1073
  }
1093
- return this.executeDoc("/api/comments", "POST", body);
1074
+ return this.executeDoc(
1075
+ "/api/comments",
1076
+ "POST",
1077
+ body
1078
+ );
1094
1079
  }
1095
1080
  /**
1096
1081
  * List comments for a post.
@@ -1159,10 +1144,14 @@ var CommunityClient = class extends CustomerScopedApi {
1159
1144
  400
1160
1145
  );
1161
1146
  }
1162
- return this.executeDoc("/api/reactions", "POST", {
1163
- post: postId,
1164
- type: reactionType
1165
- });
1147
+ return this.executeDoc(
1148
+ "/api/reactions",
1149
+ "POST",
1150
+ {
1151
+ post: postId,
1152
+ type: reactionType
1153
+ }
1154
+ );
1166
1155
  }
1167
1156
  removeReaction(params) {
1168
1157
  const { postId, type } = params;
@@ -1181,10 +1170,14 @@ var CommunityClient = class extends CustomerScopedApi {
1181
1170
  400
1182
1171
  );
1183
1172
  }
1184
- return this.executeDoc("/api/reactions", "POST", {
1185
- comment: commentId,
1186
- type: reactionType
1187
- });
1173
+ return this.executeDoc(
1174
+ "/api/reactions",
1175
+ "POST",
1176
+ {
1177
+ comment: commentId,
1178
+ type: reactionType
1179
+ }
1180
+ );
1188
1181
  }
1189
1182
  removeCommentReaction(params) {
1190
1183
  const { commentId, type } = params;
@@ -1213,9 +1206,13 @@ var CommunityClient = class extends CustomerScopedApi {
1213
1206
  }
1214
1207
  // Bookmarks
1215
1208
  addBookmark(params) {
1216
- return this.executeDoc("/api/bookmarks", "POST", {
1217
- post: params.postId
1218
- });
1209
+ return this.executeDoc(
1210
+ "/api/bookmarks",
1211
+ "POST",
1212
+ {
1213
+ post: params.postId
1214
+ }
1215
+ );
1219
1216
  }
1220
1217
  removeBookmark(params) {
1221
1218
  return this.execute(
@@ -1231,10 +1228,7 @@ var CommunityClient = class extends CustomerScopedApi {
1231
1228
  }
1232
1229
  // Profiles
1233
1230
  listProfileLists(params) {
1234
- return this.execute(
1235
- `/api/customer-profile-lists${this.buildQuery(params)}`,
1236
- "GET"
1237
- );
1231
+ return this.execute(`/api/customer-profile-lists${this.buildQuery(params)}`, "GET");
1238
1232
  }
1239
1233
  async getProfileList(params) {
1240
1234
  const query = "slug" in params ? `?where[slug][equals]=${encodeURIComponent(params.slug)}&limit=1` : `?where[id][equals]=${encodeURIComponent(params.id)}&limit=1`;
@@ -1250,6 +1244,55 @@ var CommunityClient = class extends CustomerScopedApi {
1250
1244
  }
1251
1245
  };
1252
1246
 
1247
+ // src/core/content/content-client.ts
1248
+ var PublicContentApi = class extends CustomerScopedApi {
1249
+ get(endpoint) {
1250
+ return this.request(endpoint, { method: "GET" });
1251
+ }
1252
+ };
1253
+ function appendCommonParams(search, options, defaultSort) {
1254
+ search.set("sort", options?.sort ?? defaultSort);
1255
+ if (options?.page != null) search.set("page", String(options.page));
1256
+ if (options?.limit != null) search.set("limit", String(options.limit));
1257
+ }
1258
+ function linksListPath(options) {
1259
+ const search = new URLSearchParams();
1260
+ appendCommonParams(search, options, "-publishedAt,-createdAt");
1261
+ if (options?.categoryId) search.set("categoryId", options.categoryId);
1262
+ if (options?.categorySlug) {
1263
+ search.set("categorySlug", options.categorySlug);
1264
+ }
1265
+ if (options?.tagId) search.set("tagId", options.tagId);
1266
+ if (options?.tagSlug) search.set("tagSlug", options.tagSlug);
1267
+ if (options?.featured != null) search.set("featured", String(options.featured));
1268
+ return `/api/links/storefront?${search}`;
1269
+ }
1270
+ function galleryItemsListPath(options) {
1271
+ const search = new URLSearchParams();
1272
+ appendCommonParams(search, options, "manual");
1273
+ if (options?.galleryId) search.set("galleryId", options.galleryId);
1274
+ if (options?.gallerySlug) search.set("gallerySlug", options.gallerySlug);
1275
+ return `/api/gallery-items/storefront?${search}`;
1276
+ }
1277
+ var ContentClient = class {
1278
+ constructor(options) {
1279
+ const api = new PublicContentApi("ContentClient", {
1280
+ publishableKey: options.publishableKey,
1281
+ apiUrl: options.apiUrl,
1282
+ onRequestId: options.onRequestId,
1283
+ requiresCredential: false
1284
+ });
1285
+ this.links = {
1286
+ list: (params) => api.get(linksListPath(params))
1287
+ };
1288
+ this.galleryItems = {
1289
+ list: (params) => api.get(
1290
+ galleryItemsListPath(params)
1291
+ )
1292
+ };
1293
+ }
1294
+ };
1295
+
1253
1296
  // src/core/customer/customer-auth.ts
1254
1297
  var DEFAULT_TIMEOUT2 = 15e3;
1255
1298
  function safeGetItem(key) {
@@ -1472,7 +1515,10 @@ var CartApi = class extends CustomerScopedApi {
1472
1515
  return this.request(endpoint, { method, body });
1473
1516
  }
1474
1517
  getCart(cartId) {
1475
- return this.execute(`/api/carts/${cartId}`, "GET");
1518
+ return this.execute(
1519
+ `/api/carts/${cartId}?depth=0&joins=false`,
1520
+ "GET"
1521
+ );
1476
1522
  }
1477
1523
  addItem(params) {
1478
1524
  return this.execute("/api/carts/add-item", "POST", params);
@@ -1502,6 +1548,1061 @@ var CartApi = class extends CustomerScopedApi {
1502
1548
  }
1503
1549
  };
1504
1550
 
1551
+ // src/utils/product-selection-media.ts
1552
+ function selectedSwatchMediaItemId(swatch) {
1553
+ if (!swatch || swatch.type !== "media") return null;
1554
+ const id = swatch.mediaItemId;
1555
+ if (id == null || id === "") return null;
1556
+ return String(id);
1557
+ }
1558
+ function getMediaId(value) {
1559
+ if (typeof value === "string" || typeof value === "number") {
1560
+ return String(value);
1561
+ }
1562
+ if (typeof value === "object" && value !== null && "id" in value) {
1563
+ const id = value.id;
1564
+ if (typeof id === "string" || typeof id === "number") return String(id);
1565
+ }
1566
+ return null;
1567
+ }
1568
+ function toPointerId(value) {
1569
+ return getMediaId(value);
1570
+ }
1571
+ function mediaArray(value) {
1572
+ if (!Array.isArray(value)) return [];
1573
+ return value.filter((entry) => entry != null);
1574
+ }
1575
+ function uniqueWithPrimaryFirst(primary, items) {
1576
+ const unique = /* @__PURE__ */ new Map();
1577
+ for (const item of items) {
1578
+ const id = getMediaId(item);
1579
+ const key = id ?? `inline:${unique.size}`;
1580
+ if (!unique.has(key)) unique.set(key, item);
1581
+ }
1582
+ if (primary) {
1583
+ const primaryId = getMediaId(primary);
1584
+ const prefixed = /* @__PURE__ */ new Map();
1585
+ const primaryKey = primaryId ?? "inline:primary";
1586
+ prefixed.set(primaryKey, primary);
1587
+ for (const [key, value] of unique.entries()) {
1588
+ if (!prefixed.has(key)) prefixed.set(key, value);
1589
+ }
1590
+ return Array.from(prefixed.values());
1591
+ }
1592
+ return Array.from(unique.values());
1593
+ }
1594
+ function buildPoolById(pool) {
1595
+ const poolById = /* @__PURE__ */ new Map();
1596
+ for (const item of pool) {
1597
+ const id = getMediaId(item);
1598
+ if (id) poolById.set(id, item);
1599
+ }
1600
+ return poolById;
1601
+ }
1602
+ function resolveVariantImageItems(variant, poolById) {
1603
+ if (!variant || !Array.isArray(variant.images)) return [];
1604
+ const resolved = [];
1605
+ for (const entry of variant.images) {
1606
+ if (entry == null) continue;
1607
+ if (typeof entry === "string" || typeof entry === "number") {
1608
+ const pooled = poolById.get(String(entry));
1609
+ if (pooled) resolved.push(pooled);
1610
+ continue;
1611
+ }
1612
+ const mediaId = getMediaId(entry);
1613
+ if (mediaId) {
1614
+ const pooled = poolById.get(mediaId);
1615
+ if (pooled) {
1616
+ resolved.push(pooled);
1617
+ }
1618
+ continue;
1619
+ }
1620
+ }
1621
+ return resolved;
1622
+ }
1623
+ function resolveOptionSwatchPrimary(selectedOptionValues, poolById) {
1624
+ if (!selectedOptionValues?.length) return null;
1625
+ for (const optionValue of selectedOptionValues) {
1626
+ const swatch = optionValue?.swatch;
1627
+ const swatchPointer = selectedSwatchMediaItemId(swatch);
1628
+ if (swatchPointer) {
1629
+ const pooled = poolById.get(swatchPointer);
1630
+ if (pooled) return pooled;
1631
+ }
1632
+ const inline = swatch?.inlineMedia;
1633
+ if (inline != null && typeof inline === "object") {
1634
+ return inline;
1635
+ }
1636
+ }
1637
+ return null;
1638
+ }
1639
+ function resolveProductSelectionMedia(input) {
1640
+ const pool = mediaArray(input.productMediaPool);
1641
+ const poolById = buildPoolById(pool);
1642
+ const selectedVariantImages = resolveVariantImageItems(
1643
+ input.selectedVariant,
1644
+ poolById
1645
+ );
1646
+ if (selectedVariantImages.length > 0) {
1647
+ const primaryImage = selectedVariantImages[0] ?? null;
1648
+ return {
1649
+ primaryImage,
1650
+ images: uniqueWithPrimaryFirst(primaryImage, selectedVariantImages),
1651
+ source: "variant_media_selected"
1652
+ };
1653
+ }
1654
+ if (input.selectedVariant == null && (input.matchingVariants?.length ?? 0) > 0) {
1655
+ const mergedMatchingImages = [];
1656
+ for (const matchingVariant of input.matchingVariants ?? []) {
1657
+ mergedMatchingImages.push(
1658
+ ...resolveVariantImageItems(matchingVariant, poolById)
1659
+ );
1660
+ }
1661
+ if (mergedMatchingImages.length > 0) {
1662
+ const primaryImage = mergedMatchingImages[0] ?? null;
1663
+ return {
1664
+ primaryImage,
1665
+ images: uniqueWithPrimaryFirst(primaryImage, mergedMatchingImages),
1666
+ source: "variant_media_matching"
1667
+ };
1668
+ }
1669
+ }
1670
+ const optionSwatchPrimary = resolveOptionSwatchPrimary(
1671
+ input.selectedOptionValues,
1672
+ poolById
1673
+ );
1674
+ if (optionSwatchPrimary) {
1675
+ return {
1676
+ primaryImage: optionSwatchPrimary,
1677
+ images: [optionSwatchPrimary],
1678
+ source: "option_swatch"
1679
+ };
1680
+ }
1681
+ return {
1682
+ primaryImage: null,
1683
+ images: [],
1684
+ source: "none"
1685
+ };
1686
+ }
1687
+ function resolveListingPrimaryImagePointer(input) {
1688
+ const pool = mediaArray(input.productMediaPool);
1689
+ const resolvedPointer = getMediaId(input.resolvedPrimary);
1690
+ if (resolvedPointer && input.resolvedSource !== "product_pool" && input.resolvedSource !== "none") {
1691
+ return resolvedPointer;
1692
+ }
1693
+ const poolById = buildPoolById(pool);
1694
+ const listingPointer = getMediaId(input.listingPrimaryImage);
1695
+ if (listingPointer && poolById.has(listingPointer)) {
1696
+ return listingPointer;
1697
+ }
1698
+ const primaryPointer = toPointerId(input.productPrimaryMediaItemId);
1699
+ if (primaryPointer && poolById.has(primaryPointer)) return primaryPointer;
1700
+ const thumbnailPointer = getMediaId(input.productThumbnail);
1701
+ if (thumbnailPointer && poolById.has(thumbnailPointer)) {
1702
+ return thumbnailPointer;
1703
+ }
1704
+ if (pool.length > 0) {
1705
+ const firstPoolId = getMediaId(pool[0]);
1706
+ if (firstPoolId) return firstPoolId;
1707
+ }
1708
+ return null;
1709
+ }
1710
+
1711
+ // src/utils/ecommerce.ts
1712
+ var DEFAULT_PRODUCT_SELECTION_URL_EMIT = "slug-compat";
1713
+ function resolveProductSelectionUrlEmit(emit) {
1714
+ return emit ?? DEFAULT_PRODUCT_SELECTION_URL_EMIT;
1715
+ }
1716
+ function appendSlugCompatSelectionParam(params, matrix, optionId, valueId) {
1717
+ const option = matrix.optionById.get(optionId);
1718
+ const value = matrix.valueById.get(valueId);
1719
+ if (!option?.slug || !value?.slug) return false;
1720
+ const slugMatches = option.values.filter(
1721
+ (candidate) => candidate.slug === value.slug
1722
+ );
1723
+ if (slugMatches.length !== 1) return false;
1724
+ params.append(`opt.${option.slug}`, value.slug);
1725
+ return true;
1726
+ }
1727
+ function appendCanonicalSelectionParam(params, optionId, valueId) {
1728
+ params.append(`opt.${optionId}`, valueId);
1729
+ }
1730
+ var ProductSelectionCodecError = class extends Error {
1731
+ constructor(message) {
1732
+ super(message);
1733
+ this.code = "ambiguous_product_selection_query";
1734
+ this.name = "ProductSelectionCodecError";
1735
+ }
1736
+ };
1737
+ function getRelationID(value) {
1738
+ if (typeof value === "string") return value;
1739
+ if (typeof value === "number") return String(value);
1740
+ if (value && typeof value === "object" && "id" in value) {
1741
+ const id = value.id;
1742
+ if (typeof id === "string") return id;
1743
+ if (typeof id === "number") return String(id);
1744
+ }
1745
+ return void 0;
1746
+ }
1747
+ function extractEntityId(value) {
1748
+ if (typeof value === "string") return value;
1749
+ if (typeof value === "number") return String(value);
1750
+ if (value && typeof value === "object" && "id" in value) {
1751
+ if (typeof value.id === "string") return value.id;
1752
+ if (typeof value.id === "number") return String(value.id);
1753
+ }
1754
+ return null;
1755
+ }
1756
+ function resolveGenericListingPrimaryImage(product, resolvedPrimary, resolvedSource) {
1757
+ return resolveListingPrimaryImagePointer({
1758
+ productMediaPool: product?.images ?? [],
1759
+ productPrimaryMediaItemId: getRelationID(
1760
+ product?.primaryMediaItemId ?? null
1761
+ ),
1762
+ productThumbnail: product?.thumbnail ?? null,
1763
+ listingPrimaryImage: product?.listing?.primaryImage ?? null,
1764
+ resolvedPrimary,
1765
+ resolvedSource
1766
+ });
1767
+ }
1768
+ function normalizeProductOptionValueSwatch(swatch) {
1769
+ if (swatch == null) return null;
1770
+ if (typeof swatch !== "object") return null;
1771
+ const raw = swatch;
1772
+ const mediaItemId = extractEntityId(raw.mediaItemId);
1773
+ const color = typeof raw.color === "string" ? raw.color.trim() : "";
1774
+ const hasColor = color.length > 0;
1775
+ if (raw.type === "media" || mediaItemId && raw.type !== "color") {
1776
+ if (!mediaItemId || hasColor) return null;
1777
+ return {
1778
+ type: "media",
1779
+ mediaItemId,
1780
+ color: null
1781
+ };
1782
+ }
1783
+ if (raw.type === "color" || hasColor) {
1784
+ if (mediaItemId || !hasColor) return null;
1785
+ return { type: "color", color, mediaItemId: null };
1786
+ }
1787
+ return null;
1788
+ }
1789
+ function matrixOrder(index) {
1790
+ return String(index).padStart(6, "0");
1791
+ }
1792
+ function buildProductOptionMatrixFromDetail(detail) {
1793
+ const normalizedOptions = detail.options.map((option, optionIndex) => ({
1794
+ id: String(option.id),
1795
+ title: option.title || String(option.id),
1796
+ slug: option.slug,
1797
+ order: matrixOrder(optionIndex),
1798
+ values: option.values.map((value, valueIndex) => ({
1799
+ id: String(value.id),
1800
+ optionId: String(option.id),
1801
+ optionSlug: option.slug,
1802
+ label: value.value || value.slug || String(value.id),
1803
+ slug: value.slug,
1804
+ swatch: normalizeProductOptionValueSwatch(value.swatch),
1805
+ order: matrixOrder(valueIndex)
1806
+ }))
1807
+ }));
1808
+ const optionById = new Map(
1809
+ normalizedOptions.map((option) => [option.id, option])
1810
+ );
1811
+ const optionBySlug = new Map(
1812
+ normalizedOptions.map((option) => [option.slug, option])
1813
+ );
1814
+ const valueById = /* @__PURE__ */ new Map();
1815
+ const valueToOptionId = /* @__PURE__ */ new Map();
1816
+ const valueToOptionSlug = /* @__PURE__ */ new Map();
1817
+ for (const option of normalizedOptions) {
1818
+ for (const value of option.values) {
1819
+ valueById.set(value.id, value);
1820
+ valueToOptionId.set(value.id, option.id);
1821
+ valueToOptionSlug.set(value.id, option.slug);
1822
+ }
1823
+ }
1824
+ const optionIds = normalizedOptions.map((option) => option.id);
1825
+ const optionSlugs = normalizedOptions.map((option) => option.slug);
1826
+ const normalizedVariants = detail.variants.map((variant) => {
1827
+ const optionValueByOptionId = /* @__PURE__ */ new Map();
1828
+ const optionValueByOptionSlug = /* @__PURE__ */ new Map();
1829
+ for (const rawValue of variant.optionValues) {
1830
+ const optionId = String(rawValue.optionId);
1831
+ const valueId = String(rawValue.valueId);
1832
+ const optionSlug = rawValue.optionSlug;
1833
+ if (!optionById.has(optionId)) continue;
1834
+ if (valueToOptionId.get(valueId) !== optionId) continue;
1835
+ if (optionValueByOptionId.has(optionId)) continue;
1836
+ optionValueByOptionId.set(optionId, valueId);
1837
+ if (optionSlug && !optionValueByOptionSlug.has(optionSlug)) {
1838
+ optionValueByOptionSlug.set(optionSlug, valueId);
1839
+ }
1840
+ }
1841
+ const optionValueIds = optionIds.map((optionId) => optionValueByOptionId.get(optionId)).filter((valueId) => Boolean(valueId));
1842
+ return {
1843
+ id: String(variant.id),
1844
+ optionValueIds,
1845
+ optionValueByOptionId,
1846
+ optionValueByOptionSlug,
1847
+ source: variant
1848
+ };
1849
+ });
1850
+ return {
1851
+ options: normalizedOptions,
1852
+ optionIds,
1853
+ optionSlugs,
1854
+ optionById,
1855
+ optionBySlug,
1856
+ valueById,
1857
+ valueToOptionId,
1858
+ valueToOptionSlug,
1859
+ variants: normalizedVariants
1860
+ };
1861
+ }
1862
+ function getVariantSelection(matrix, variantId) {
1863
+ if (variantId == null) return void 0;
1864
+ const id = String(variantId);
1865
+ return matrix.variants.find((variant) => variant.id === id);
1866
+ }
1867
+ function hasExplicitSelection(selection) {
1868
+ return Boolean(
1869
+ selection.variantId != null || selection.search || selection.valueIds || Object.keys(selection.byOptionId ?? {}).length > 0 || Object.keys(selection.byOptionSlug ?? {}).length > 0
1870
+ );
1871
+ }
1872
+ function assignSelectedValue(matrix, selectedByOptionId, optionId, valueId) {
1873
+ if (valueId == null) return false;
1874
+ const normalizedValueId = String(valueId);
1875
+ if (matrix.valueToOptionId.get(normalizedValueId) !== optionId) return false;
1876
+ selectedByOptionId.set(optionId, normalizedValueId);
1877
+ return true;
1878
+ }
1879
+ function assignSelectedValueSlugByOptionId(matrix, selectedByOptionId, optionId, valueSlug) {
1880
+ if (!valueSlug) return false;
1881
+ const option = matrix.optionById.get(optionId);
1882
+ if (!option) return false;
1883
+ const values = option.values.filter(
1884
+ (candidate) => candidate.slug === valueSlug
1885
+ );
1886
+ if (values.length > 1) {
1887
+ throw new ProductSelectionCodecError(
1888
+ `Ambiguous product selection value slug "${valueSlug}" for option "${optionId}". Use opt.<optionId>=<valueId>.`
1889
+ );
1890
+ }
1891
+ const value = values[0];
1892
+ if (!value) return false;
1893
+ selectedByOptionId.set(optionId, value.id);
1894
+ return true;
1895
+ }
1896
+ function assignSelectedValueSlugByOptionSlug(matrix, selectedByOptionId, optionSlug, valueSlug) {
1897
+ if (!valueSlug) return false;
1898
+ const option = matrix.optionBySlug.get(optionSlug);
1899
+ if (!option) return false;
1900
+ const values = option.values.filter(
1901
+ (candidate) => candidate.slug === valueSlug
1902
+ );
1903
+ if (values.length > 1) {
1904
+ throw new ProductSelectionCodecError(
1905
+ `Ambiguous product selection value slug "${valueSlug}" for option "${optionSlug}". Use opt.<optionId>=<valueId>.`
1906
+ );
1907
+ }
1908
+ const value = values[0];
1909
+ if (!value) return false;
1910
+ selectedByOptionId.set(option.id, value.id);
1911
+ return true;
1912
+ }
1913
+ function toSearchParams(search) {
1914
+ if (!search) return new URLSearchParams();
1915
+ if (search instanceof URLSearchParams) return new URLSearchParams(search);
1916
+ if (search instanceof URL) return new URLSearchParams(search.searchParams);
1917
+ const trimmed = search.trim();
1918
+ if (!trimmed) return new URLSearchParams();
1919
+ try {
1920
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed)) {
1921
+ return new URL(trimmed).searchParams;
1922
+ }
1923
+ } catch {
1924
+ return new URLSearchParams();
1925
+ }
1926
+ return new URLSearchParams(
1927
+ trimmed.startsWith("?") ? trimmed.slice(1) : trimmed
1928
+ );
1929
+ }
1930
+ function slugLike(value) {
1931
+ return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
1932
+ }
1933
+ function assertNoAmbiguousSelectionParams(matrix, params) {
1934
+ const knownSelectionKeys = /* @__PURE__ */ new Set();
1935
+ const hasVariantParam = params.has("variant");
1936
+ const hasOptionParams = Array.from(params.keys()).some(
1937
+ (key) => key.startsWith("opt.")
1938
+ );
1939
+ if (hasVariantParam && hasOptionParams) {
1940
+ throw new ProductSelectionCodecError(
1941
+ "Product selection URL cannot mix variant=<variantId> with opt.<optionId>=<valueId> params."
1942
+ );
1943
+ }
1944
+ for (const option of matrix.options) {
1945
+ knownSelectionKeys.add(slugLike(option.slug));
1946
+ knownSelectionKeys.add(slugLike(option.title));
1947
+ for (const value of option.values) {
1948
+ if (value.slug) knownSelectionKeys.add(slugLike(value.slug));
1949
+ }
1950
+ }
1951
+ for (const [key, value] of params.entries()) {
1952
+ if (key.startsWith("opt.")) {
1953
+ const optionToken = key.slice(4);
1954
+ if (!optionToken || !matrix.optionBySlug.has(optionToken) && !matrix.optionById.has(optionToken)) {
1955
+ throw new ProductSelectionCodecError(
1956
+ `Unknown product selection query parameter "${key}". Use opt.<optionId>=<valueId>.`
1957
+ );
1958
+ }
1959
+ if (!value) {
1960
+ throw new ProductSelectionCodecError(
1961
+ `Product selection query parameter "${key}" requires a value ID or compatibility value slug.`
1962
+ );
1963
+ }
1964
+ continue;
1965
+ }
1966
+ if (key === "variant") {
1967
+ if (!value) {
1968
+ throw new ProductSelectionCodecError(
1969
+ 'Product selection query parameter "variant" requires a variant ID.'
1970
+ );
1971
+ }
1972
+ if (!getVariantSelection(matrix, value)) {
1973
+ throw new ProductSelectionCodecError(
1974
+ `Unknown product selection variant "${value}".`
1975
+ );
1976
+ }
1977
+ continue;
1978
+ }
1979
+ const keyToken = slugLike(key);
1980
+ if (knownSelectionKeys.has(keyToken) || value === "" && knownSelectionKeys.has(keyToken)) {
1981
+ throw new ProductSelectionCodecError(
1982
+ `Ambiguous product selection query parameter "${key}". Use opt.<optionId>=<valueId>.`
1983
+ );
1984
+ }
1985
+ }
1986
+ }
1987
+ function emitCompatibilityOptionIdParam(options, event) {
1988
+ try {
1989
+ if (options?.onCompatibilityOptionIdParam) {
1990
+ options.onCompatibilityOptionIdParam(event);
1991
+ return;
1992
+ }
1993
+ options?.onLegacyOptionIdParam?.(event);
1994
+ } catch {
1995
+ }
1996
+ }
1997
+ function assignSearchSelection(matrix, selectedByOptionId, search, options) {
1998
+ if (!search) return null;
1999
+ const params = toSearchParams(search);
2000
+ assertNoAmbiguousSelectionParams(matrix, params);
2001
+ const variantParam = params.get("variant");
2002
+ if (variantParam != null) {
2003
+ const variantSelection = getVariantSelection(matrix, variantParam);
2004
+ if (!variantSelection) {
2005
+ throw new ProductSelectionCodecError(
2006
+ `Unknown product selection variant "${variantParam}".`
2007
+ );
2008
+ }
2009
+ for (const [optionId, valueId] of variantSelection.optionValueByOptionId) {
2010
+ selectedByOptionId.set(optionId, valueId);
2011
+ }
2012
+ return variantSelection.id;
2013
+ }
2014
+ for (const [key, valueToken] of params.entries()) {
2015
+ if (!key.startsWith("opt.")) continue;
2016
+ const optionToken = key.slice(4);
2017
+ const optionById = matrix.optionById.get(optionToken);
2018
+ if (optionById) {
2019
+ if (assignSelectedValue(
2020
+ matrix,
2021
+ selectedByOptionId,
2022
+ optionById.id,
2023
+ valueToken
2024
+ )) {
2025
+ continue;
2026
+ }
2027
+ const before = selectedByOptionId.get(optionById.id);
2028
+ if (assignSelectedValueSlugByOptionId(
2029
+ matrix,
2030
+ selectedByOptionId,
2031
+ optionById.id,
2032
+ valueToken
2033
+ ) && selectedByOptionId.get(optionById.id) !== before) {
2034
+ emitCompatibilityOptionIdParam(options, {
2035
+ optionId: optionById.id,
2036
+ optionSlug: optionById.slug,
2037
+ valueSlug: valueToken,
2038
+ searchParam: key
2039
+ });
2040
+ continue;
2041
+ }
2042
+ throw new ProductSelectionCodecError(
2043
+ `Unknown product selection value "${valueToken}" for option "${optionToken}". Use opt.<optionId>=<valueId>.`
2044
+ );
2045
+ }
2046
+ const optionBySlug = matrix.optionBySlug.get(optionToken);
2047
+ if (optionBySlug) {
2048
+ if (assignSelectedValueSlugByOptionSlug(
2049
+ matrix,
2050
+ selectedByOptionId,
2051
+ optionBySlug.slug,
2052
+ valueToken
2053
+ )) {
2054
+ continue;
2055
+ }
2056
+ if (matrix.valueById.has(valueToken)) {
2057
+ throw new ProductSelectionCodecError(
2058
+ `Unknown product selection value "${valueToken}" for option "${optionToken}". Use opt.<optionId>=<valueId>.`
2059
+ );
2060
+ }
2061
+ throw new ProductSelectionCodecError(
2062
+ `Unknown product selection value "${valueToken}" for option "${optionToken}". Use opt.<optionSlug>=<valueSlug> for compatibility URLs.`
2063
+ );
2064
+ }
2065
+ }
2066
+ return null;
2067
+ }
2068
+ function normalizeProductSelectionFromMatrix(matrix, selection = {}, options) {
2069
+ const selectedByOptionId = /* @__PURE__ */ new Map();
2070
+ const variantSelection = getVariantSelection(matrix, selection.variantId);
2071
+ const variantId = variantSelection?.id ?? null;
2072
+ if (variantSelection) {
2073
+ for (const [optionId, valueId] of variantSelection.optionValueByOptionId) {
2074
+ selectedByOptionId.set(optionId, valueId);
2075
+ }
2076
+ }
2077
+ for (const rawValueId of selection.valueIds ?? []) {
2078
+ const valueId = getRelationID(rawValueId);
2079
+ if (!valueId) continue;
2080
+ const optionId = matrix.valueToOptionId.get(valueId);
2081
+ if (!optionId) continue;
2082
+ selectedByOptionId.set(optionId, valueId);
2083
+ }
2084
+ const searchVariantId = assignSearchSelection(
2085
+ matrix,
2086
+ selectedByOptionId,
2087
+ selection.search,
2088
+ options
2089
+ );
2090
+ for (const [rawOptionId, rawSelection] of Object.entries(
2091
+ selection.byOptionId ?? {}
2092
+ )) {
2093
+ const optionId = String(rawOptionId);
2094
+ if (!matrix.optionById.has(optionId)) continue;
2095
+ if (rawSelection && typeof rawSelection === "object" && "valueId" in rawSelection && rawSelection.valueId != null) {
2096
+ assignSelectedValue(
2097
+ matrix,
2098
+ selectedByOptionId,
2099
+ optionId,
2100
+ rawSelection.valueId
2101
+ );
2102
+ continue;
2103
+ }
2104
+ if (typeof rawSelection === "string" || typeof rawSelection === "number") {
2105
+ assignSelectedValue(matrix, selectedByOptionId, optionId, rawSelection);
2106
+ continue;
2107
+ }
2108
+ if (rawSelection && typeof rawSelection === "object" && "valueSlug" in rawSelection) {
2109
+ assignSelectedValueSlugByOptionId(
2110
+ matrix,
2111
+ selectedByOptionId,
2112
+ optionId,
2113
+ rawSelection.valueSlug
2114
+ );
2115
+ }
2116
+ }
2117
+ for (const [rawOptionSlug, rawSelection] of Object.entries(
2118
+ selection.byOptionSlug ?? {}
2119
+ )) {
2120
+ const optionSlug = String(rawOptionSlug);
2121
+ if (!matrix.optionBySlug.has(optionSlug)) continue;
2122
+ if (rawSelection && typeof rawSelection === "object" && "valueId" in rawSelection && rawSelection.valueId != null) {
2123
+ const option = matrix.optionBySlug.get(optionSlug);
2124
+ if (option) {
2125
+ assignSelectedValue(
2126
+ matrix,
2127
+ selectedByOptionId,
2128
+ option.id,
2129
+ rawSelection.valueId
2130
+ );
2131
+ }
2132
+ continue;
2133
+ }
2134
+ if (rawSelection && typeof rawSelection === "object" && "valueSlug" in rawSelection) {
2135
+ assignSelectedValueSlugByOptionSlug(
2136
+ matrix,
2137
+ selectedByOptionId,
2138
+ optionSlug,
2139
+ rawSelection.valueSlug
2140
+ );
2141
+ continue;
2142
+ }
2143
+ if (typeof rawSelection === "string" || typeof rawSelection === "number") {
2144
+ assignSelectedValueSlugByOptionSlug(
2145
+ matrix,
2146
+ selectedByOptionId,
2147
+ optionSlug,
2148
+ String(rawSelection)
2149
+ );
2150
+ }
2151
+ }
2152
+ const byOptionId = Object.fromEntries(
2153
+ matrix.optionIds.map((optionId) => [optionId, selectedByOptionId.get(optionId)]).filter((entry) => Boolean(entry[1]))
2154
+ );
2155
+ const byOptionSlug = Object.fromEntries(
2156
+ matrix.options.map((option) => {
2157
+ const valueId = selectedByOptionId.get(option.id);
2158
+ const value = valueId ? matrix.valueById.get(valueId) : void 0;
2159
+ return [option.slug, value?.slug ?? void 0];
2160
+ }).filter((entry) => Boolean(entry[1]))
2161
+ );
2162
+ return {
2163
+ byOptionSlug,
2164
+ byOptionId,
2165
+ valueIds: matrix.optionIds.map((optionId) => byOptionId[optionId]).filter((valueId) => Boolean(valueId)),
2166
+ variantId: searchVariantId ?? variantId
2167
+ };
2168
+ }
2169
+ function stringifyProductSelection(detail, selection = {}, options) {
2170
+ const matrix = buildProductOptionMatrixFromDetail(detail);
2171
+ const normalized = normalizeProductSelectionFromMatrix(
2172
+ matrix,
2173
+ selection,
2174
+ options
2175
+ );
2176
+ const params = new URLSearchParams();
2177
+ if (hasExplicitSelection(selection)) {
2178
+ const matchingVariants = getMatchingVariantEntries(matrix, normalized);
2179
+ const exactVariant = getExactSelectedVariantEntry(
2180
+ matrix,
2181
+ normalized,
2182
+ matchingVariants
2183
+ );
2184
+ if (exactVariant) {
2185
+ params.set("variant", exactVariant.id);
2186
+ return params.toString();
2187
+ }
2188
+ }
2189
+ const emit = resolveProductSelectionUrlEmit(options?.emit);
2190
+ for (const optionId of matrix.optionIds) {
2191
+ const valueId = normalized.byOptionId[optionId];
2192
+ if (!valueId) continue;
2193
+ if (!matrix.optionById.has(optionId) || !matrix.valueById.has(valueId)) {
2194
+ continue;
2195
+ }
2196
+ if (emit === "slug-compat") {
2197
+ if (appendSlugCompatSelectionParam(params, matrix, optionId, valueId)) {
2198
+ continue;
2199
+ }
2200
+ }
2201
+ appendCanonicalSelectionParam(params, optionId, valueId);
2202
+ }
2203
+ return params.toString();
2204
+ }
2205
+ function selectedEntries(selection) {
2206
+ return Object.entries(selection.byOptionId);
2207
+ }
2208
+ function getMatchingVariantEntries(matrix, selection) {
2209
+ const entries = selectedEntries(selection);
2210
+ if (entries.length === 0) return matrix.variants;
2211
+ return matrix.variants.filter(
2212
+ (variant) => entries.every(
2213
+ ([optionId, valueId]) => variant.optionValueByOptionId.get(optionId) === valueId
2214
+ )
2215
+ );
2216
+ }
2217
+ function getExactSelectedVariantEntry(matrix, selection, matchingVariants) {
2218
+ if (matrix.optionIds.length === 0) {
2219
+ return getVariantSelection(matrix, selection.variantId) ?? (matchingVariants.length === 1 ? matchingVariants[0] ?? null : null);
2220
+ }
2221
+ const allOptionsSelected = matrix.optionIds.every(
2222
+ (optionId) => Boolean(selection.byOptionId[optionId])
2223
+ );
2224
+ if (!allOptionsSelected) return null;
2225
+ return matchingVariants.find(
2226
+ (variant) => matrix.optionIds.every(
2227
+ (optionId) => variant.optionValueByOptionId.get(optionId) === selection.byOptionId[optionId]
2228
+ )
2229
+ ) ?? null;
2230
+ }
2231
+ function isPresentMedia(value) {
2232
+ return value != null;
2233
+ }
2234
+ function mediaArray2(values) {
2235
+ if (!Array.isArray(values)) return [];
2236
+ return values.filter(isPresentMedia);
2237
+ }
2238
+ function getProductHrefSlug(product) {
2239
+ if ("product" in product && product.product?.slug) {
2240
+ return product.product.slug;
2241
+ }
2242
+ if ("slug" in product && product.slug) return product.slug;
2243
+ throw new ProductSelectionCodecError(
2244
+ "Product slug is required to build a product href."
2245
+ );
2246
+ }
2247
+ function joinProductPath(basePath, slug, trailingSlash) {
2248
+ const base = basePath.replace(/\/+$/, "");
2249
+ const encodedSlug = encodeURIComponent(slug);
2250
+ return `${base}/${encodedSlug}${trailingSlash ? "/" : ""}`;
2251
+ }
2252
+ function getProductHrefGroupSelection(group, matrix) {
2253
+ if (!group) return null;
2254
+ if (group.variantId != null) return { variantId: group.variantId };
2255
+ const optionId = group.optionId != null ? String(group.optionId) : group.optionSlug ? matrix?.optionBySlug.get(group.optionSlug)?.id : void 0;
2256
+ if (!optionId) return null;
2257
+ const option = matrix?.optionById.get(optionId);
2258
+ const optionValueId = group.optionValueId != null ? String(group.optionValueId) : group.optionValueSlug && option ? option.values.find((value) => value.slug === group.optionValueSlug)?.id : void 0;
2259
+ if (!optionValueId) return null;
2260
+ return { byOptionId: { [optionId]: optionValueId } };
2261
+ }
2262
+ function getProductHrefCodecOptions(options) {
2263
+ return options.emit != null ? { emit: options.emit } : void 0;
2264
+ }
2265
+ function appendGroupByOptionIdHrefParams(params, group, groupSelection, options) {
2266
+ const emit = resolveProductSelectionUrlEmit(options.emit);
2267
+ const byOptionId = groupSelection.byOptionId ?? {};
2268
+ const entries = Object.entries(byOptionId);
2269
+ if (entries.length === 0) return false;
2270
+ for (const [optionId, valueId] of entries) {
2271
+ const optionSlug = group?.optionSlug ?? options.matrix?.optionById.get(optionId)?.slug ?? null;
2272
+ const valueSlug = group?.optionValueSlug ?? options.matrix?.valueById.get(String(valueId))?.slug ?? null;
2273
+ if (emit === "slug-compat" && optionSlug && valueSlug && entries.length === 1) {
2274
+ params.set(`opt.${optionSlug}`, valueSlug);
2275
+ return true;
2276
+ }
2277
+ if (emit === "slug-compat" && options.matrix && appendSlugCompatSelectionParam(
2278
+ params,
2279
+ options.matrix,
2280
+ optionId,
2281
+ String(valueId)
2282
+ )) {
2283
+ continue;
2284
+ }
2285
+ appendCanonicalSelectionParam(params, optionId, String(valueId));
2286
+ }
2287
+ return params.size > 0;
2288
+ }
2289
+ function getPreferCompleteVariantFromHintSelection(group, options) {
2290
+ if (!options.preferCompleteVariantFromHint) return null;
2291
+ if (group?.optionValueId != null || group?.optionValueSlug) return null;
2292
+ const hintVariantId = group?.listing?.selectionHintVariant;
2293
+ if (hintVariantId == null) return null;
2294
+ return { variantId: hintVariantId };
2295
+ }
2296
+ function buildProductHref(product, group, options = {}) {
2297
+ const path = joinProductPath(
2298
+ options.basePath ?? "/products",
2299
+ getProductHrefSlug(product),
2300
+ options.trailingSlash ?? false
2301
+ );
2302
+ const params = new URLSearchParams();
2303
+ if (options.detail && options.selection) {
2304
+ const selection = stringifyProductSelection(
2305
+ options.detail,
2306
+ options.selection,
2307
+ getProductHrefCodecOptions(options)
2308
+ );
2309
+ return selection ? `${path}?${selection}` : path;
2310
+ }
2311
+ const preferVariantSelection = getPreferCompleteVariantFromHintSelection(
2312
+ group,
2313
+ options
2314
+ );
2315
+ if (preferVariantSelection) {
2316
+ if (options.detail) {
2317
+ const selection = stringifyProductSelection(
2318
+ options.detail,
2319
+ preferVariantSelection,
2320
+ getProductHrefCodecOptions(options)
2321
+ );
2322
+ return selection ? `${path}?${selection}` : path;
2323
+ }
2324
+ if (preferVariantSelection.variantId != null) {
2325
+ params.set("variant", String(preferVariantSelection.variantId));
2326
+ return `${path}?${params.toString()}`;
2327
+ }
2328
+ }
2329
+ const groupSelection = getProductHrefGroupSelection(group, options.matrix);
2330
+ if (groupSelection) {
2331
+ if (options.detail) {
2332
+ const selection = stringifyProductSelection(
2333
+ options.detail,
2334
+ groupSelection,
2335
+ getProductHrefCodecOptions(options)
2336
+ );
2337
+ return selection ? `${path}?${selection}` : path;
2338
+ }
2339
+ if (groupSelection.variantId != null) {
2340
+ params.set("variant", String(groupSelection.variantId));
2341
+ return `${path}?${params.toString()}`;
2342
+ }
2343
+ if (appendGroupByOptionIdHrefParams(params, group, groupSelection, options)) {
2344
+ return `${path}?${params.toString()}`;
2345
+ }
2346
+ }
2347
+ if (group?.optionValueSlug) {
2348
+ const optionSlug = group.optionSlug ?? (group.optionId != null ? options.matrix?.optionById.get(String(group.optionId))?.slug : void 0);
2349
+ if (optionSlug) {
2350
+ params.set(`opt.${optionSlug}`, group.optionValueSlug);
2351
+ }
2352
+ }
2353
+ return params.size > 0 ? `${path}?${params.toString()}` : path;
2354
+ }
2355
+ function compareVariantOrder(a, b) {
2356
+ const aOrder = Number(a._order ?? Number.MAX_SAFE_INTEGER);
2357
+ const bOrder = Number(b._order ?? Number.MAX_SAFE_INTEGER);
2358
+ if (Number.isFinite(aOrder) && Number.isFinite(bOrder) && aOrder !== bOrder) {
2359
+ return aOrder - bOrder;
2360
+ }
2361
+ const aId = String(getRelationID(a.id) ?? "");
2362
+ const bId = String(getRelationID(b.id) ?? "");
2363
+ return aId.localeCompare(bId);
2364
+ }
2365
+ function isVariantAvailableForSale(variant) {
2366
+ if (variant.isActive === false) return false;
2367
+ if (variant.isUnlimited) return true;
2368
+ return (variant.stock ?? 0) - (variant.reservedStock ?? 0) > 0;
2369
+ }
2370
+ function sortVariantsForMediaSelection(variants) {
2371
+ const orderedVariants = [...variants].sort(compareVariantOrder);
2372
+ const activeVariants = orderedVariants.filter(
2373
+ (variant) => variant.isActive !== false
2374
+ );
2375
+ const availableVariants = activeVariants.filter(isVariantAvailableForSale);
2376
+ const unavailableActiveVariants = activeVariants.filter(
2377
+ (variant) => !isVariantAvailableForSale(variant)
2378
+ );
2379
+ return [...availableVariants, ...unavailableActiveVariants];
2380
+ }
2381
+ function variantHasPoolMedia(variant, productMediaPool) {
2382
+ if (!variant?.images?.length) return false;
2383
+ return variant.images.some((image) => {
2384
+ const imageId = getRelationID(image);
2385
+ return Boolean(
2386
+ imageId && productMediaPool.some((poolItem) => getRelationID(poolItem) === imageId)
2387
+ );
2388
+ });
2389
+ }
2390
+ function getMinMax(values) {
2391
+ const numbers = values.filter(
2392
+ (value) => typeof value === "number"
2393
+ );
2394
+ if (numbers.length === 0) {
2395
+ return { min: null, max: null };
2396
+ }
2397
+ return {
2398
+ min: Math.min(...numbers),
2399
+ max: Math.max(...numbers)
2400
+ };
2401
+ }
2402
+ function buildProductListingProjection(product, variants) {
2403
+ const orderedVariants = [...variants].sort(compareVariantOrder);
2404
+ const activeVariants = orderedVariants.filter(
2405
+ (variant) => variant.isActive !== false
2406
+ );
2407
+ const availableVariants = activeVariants.filter(isVariantAvailableForSale);
2408
+ const selectionHintVariant = availableVariants[0] ?? activeVariants[0] ?? null;
2409
+ const { min: minPrice, max: maxPrice } = getMinMax(
2410
+ activeVariants.map((variant) => variant.price)
2411
+ );
2412
+ const { min: minCompareAtPrice, max: maxCompareAtPrice } = getMinMax(
2413
+ activeVariants.map((variant) => variant.compareAtPrice)
2414
+ );
2415
+ const productMediaPool = product?.images ?? [];
2416
+ const selectionHintHasPoolMedia = variantHasPoolMedia(
2417
+ selectionHintVariant,
2418
+ productMediaPool
2419
+ );
2420
+ const mediaSelectionVariants = sortVariantsForMediaSelection(variants);
2421
+ const resolvedProductMedia = resolveProductSelectionMedia({
2422
+ productMediaPool,
2423
+ productPrimaryMediaItemId: getRelationID(product?.primaryMediaItemId),
2424
+ selectedVariant: selectionHintVariant && selectionHintHasPoolMedia ? {
2425
+ id: selectionHintVariant.id,
2426
+ images: selectionHintVariant.images
2427
+ } : null,
2428
+ matchingVariants: selectionHintHasPoolMedia ? [] : mediaSelectionVariants
2429
+ });
2430
+ return {
2431
+ selectionHintVariant: getRelationID(selectionHintVariant?.id) ?? null,
2432
+ primaryImage: resolveGenericListingPrimaryImage(
2433
+ product,
2434
+ resolvedProductMedia.primaryImage,
2435
+ resolvedProductMedia.source
2436
+ ),
2437
+ minPrice,
2438
+ maxPrice,
2439
+ minCompareAtPrice,
2440
+ maxCompareAtPrice,
2441
+ isPriceRange: minPrice !== null && maxPrice !== null ? minPrice !== maxPrice : false,
2442
+ availableForSale: availableVariants.length > 0
2443
+ };
2444
+ }
2445
+ function buildProductListingCard(item, options = {}) {
2446
+ const product = item.product;
2447
+ const groups = item.groups;
2448
+ const variants = getProductListingCardVariants(item);
2449
+ const projectedListing = buildProductListingProjection(product, variants);
2450
+ const selectionHintVariant = getRelationID(
2451
+ product.listing && "selectionHintVariant" in product.listing ? product.listing.selectionHintVariant : null
2452
+ ) ?? projectedListing.selectionHintVariant;
2453
+ const representativeVariant = findListingCardRepresentativeVariant(
2454
+ variants,
2455
+ selectionHintVariant
2456
+ );
2457
+ const productMediaPool = mediaArray2(product.images);
2458
+ const representativeHasPoolMedia = Boolean(
2459
+ representativeVariant?.images?.some(
2460
+ (image) => productMediaPool.some(
2461
+ (poolItem) => getRelationID(poolItem) === getRelationID(image)
2462
+ )
2463
+ )
2464
+ );
2465
+ const resolvedPrimaryMedia = resolveProductSelectionMedia(
2466
+ {
2467
+ productMediaPool,
2468
+ productPrimaryMediaItemId: getRelationID(product.primaryMediaItemId),
2469
+ selectedVariant: representativeHasPoolMedia ? representativeVariant : null,
2470
+ matchingVariants: representativeHasPoolMedia ? [] : variants
2471
+ }
2472
+ );
2473
+ const listingPrimaryPointer = resolveListingPrimaryImagePointer({
2474
+ productMediaPool,
2475
+ productPrimaryMediaItemId: getRelationID(product.primaryMediaItemId),
2476
+ productThumbnail: product.thumbnail ?? null,
2477
+ listingPrimaryImage: product.listing?.primaryImage ?? null,
2478
+ resolvedPrimary: resolvedPrimaryMedia.primaryImage,
2479
+ resolvedSource: resolvedPrimaryMedia.source
2480
+ });
2481
+ const listingPrimaryMedia = listingPrimaryPointer ? productMediaPool.find(
2482
+ (item2) => getRelationID(item2) === listingPrimaryPointer
2483
+ ) ?? resolvedPrimaryMedia.primaryImage ?? null : null;
2484
+ const priceRange = resolveListingCardPriceRange(
2485
+ product,
2486
+ projectedListing,
2487
+ groups
2488
+ );
2489
+ const availableForSale = product.listing?.availableForSale != null ? product.listing.availableForSale : groups.length > 0 ? groups.some((group) => group.listing.availableForSale) : projectedListing.availableForSale;
2490
+ const swatches = groups.length > 1 ? groups.map((group) => buildListingSwatch(product, group, options)) : [];
2491
+ return {
2492
+ id: String(product.id),
2493
+ href: buildProductHref(
2494
+ { slug: product.slug },
2495
+ { listing: { selectionHintVariant } },
2496
+ options
2497
+ ),
2498
+ title: product.title,
2499
+ representativeVariant,
2500
+ primaryImage: listingPrimaryMedia,
2501
+ priceRange,
2502
+ availableForSale,
2503
+ swatches
2504
+ };
2505
+ }
2506
+ function getProductListingCardVariants(item) {
2507
+ const productVariants = item.product.variants?.docs;
2508
+ if (Array.isArray(productVariants) && productVariants.length > 0) {
2509
+ return productVariants;
2510
+ }
2511
+ const variants = [];
2512
+ const seen = /* @__PURE__ */ new Set();
2513
+ for (const group of item.groups) {
2514
+ for (const variant of group.variants) {
2515
+ const id = getRelationID(variant.id);
2516
+ if (id && seen.has(id)) continue;
2517
+ if (id) seen.add(id);
2518
+ variants.push(variant);
2519
+ }
2520
+ }
2521
+ return variants;
2522
+ }
2523
+ function findListingCardRepresentativeVariant(variants, representativeVariantId) {
2524
+ if (representativeVariantId == null) return null;
2525
+ return variants.find(
2526
+ (variant) => getRelationID(variant.id) === representativeVariantId
2527
+ ) ?? null;
2528
+ }
2529
+ function hasCompleteListingPriceProjection(listing) {
2530
+ return listing?.minPrice != null && listing?.maxPrice != null;
2531
+ }
2532
+ function listingDefinesCompareAtProjection(listing) {
2533
+ return "minCompareAtPrice" in listing || "maxCompareAtPrice" in listing;
2534
+ }
2535
+ function resolveListingCardPriceRange(product, projectedListing, groups) {
2536
+ const listing = product.listing;
2537
+ if (hasCompleteListingPriceProjection(listing)) {
2538
+ const groupRange = groups.length > 0 ? aggregateListingPriceRange(groups) : null;
2539
+ const definesCompareAt = listingDefinesCompareAtProjection(listing);
2540
+ return {
2541
+ minPrice: listing.minPrice,
2542
+ maxPrice: listing.maxPrice,
2543
+ minCompareAtPrice: definesCompareAt ? listing.minCompareAtPrice ?? null : groupRange?.minCompareAtPrice ?? projectedListing.minCompareAtPrice,
2544
+ maxCompareAtPrice: definesCompareAt ? listing.maxCompareAtPrice ?? null : groupRange?.maxCompareAtPrice ?? projectedListing.maxCompareAtPrice,
2545
+ isPriceRange: listing.isPriceRange ?? listing.minPrice !== listing.maxPrice
2546
+ };
2547
+ }
2548
+ if (groups.length > 0) {
2549
+ return aggregateListingPriceRange(groups);
2550
+ }
2551
+ return {
2552
+ minPrice: projectedListing.minPrice,
2553
+ maxPrice: projectedListing.maxPrice,
2554
+ minCompareAtPrice: projectedListing.minCompareAtPrice,
2555
+ maxCompareAtPrice: projectedListing.maxCompareAtPrice,
2556
+ isPriceRange: projectedListing.isPriceRange
2557
+ };
2558
+ }
2559
+ function aggregateListingPriceRange(groups) {
2560
+ const minPrice = minOfNullable(groups.map((g) => g.listing.minPrice));
2561
+ const maxPrice = maxOfNullable(groups.map((g) => g.listing.maxPrice));
2562
+ const minCompareAtPrice = minOfNullable(
2563
+ groups.map((g) => g.listing.minCompareAtPrice)
2564
+ );
2565
+ const maxCompareAtPrice = maxOfNullable(
2566
+ groups.map((g) => g.listing.maxCompareAtPrice)
2567
+ );
2568
+ const isPriceRange = minPrice !== null && maxPrice !== null && minPrice !== maxPrice;
2569
+ return {
2570
+ minPrice,
2571
+ maxPrice,
2572
+ minCompareAtPrice,
2573
+ maxCompareAtPrice,
2574
+ isPriceRange
2575
+ };
2576
+ }
2577
+ function buildListingSwatch(product, group, options) {
2578
+ return {
2579
+ optionId: group.optionId,
2580
+ optionValueId: group.optionValueId,
2581
+ label: group.optionValueLabel,
2582
+ swatch: group.optionValueSwatch ?? null,
2583
+ href: buildProductHref(
2584
+ { slug: product.slug },
2585
+ {
2586
+ optionId: group.optionId,
2587
+ optionSlug: group.optionSlug,
2588
+ optionValueId: group.optionValueId,
2589
+ optionValueSlug: group.optionValueSlug,
2590
+ listing: group.listing
2591
+ },
2592
+ options
2593
+ ),
2594
+ availableForSale: group.listing.availableForSale
2595
+ };
2596
+ }
2597
+ function minOfNullable(values) {
2598
+ const numbers = values.filter((v) => v !== null);
2599
+ return numbers.length === 0 ? null : Math.min(...numbers);
2600
+ }
2601
+ function maxOfNullable(values) {
2602
+ const numbers = values.filter((v) => v !== null);
2603
+ return numbers.length === 0 ? null : Math.max(...numbers);
2604
+ }
2605
+
1505
2606
  // src/core/api/product-api.ts
1506
2607
  var PRODUCT_DETAIL_UNAVAILABLE_REASONS = /* @__PURE__ */ new Set([
1507
2608
  "not_found",
@@ -1525,6 +2626,64 @@ function productDetailResultFromError(error) {
1525
2626
  if (!reason) return void 0;
1526
2627
  return { found: false, reason };
1527
2628
  }
2629
+ function nonEmpty(values) {
2630
+ return values?.length ? values : void 0;
2631
+ }
2632
+ function buildProductListingPageWhere(params) {
2633
+ const clauses = [];
2634
+ const search = params.search?.trim();
2635
+ if (search) {
2636
+ clauses.push({
2637
+ or: [
2638
+ { title: { like: search } },
2639
+ { slug: { like: search } },
2640
+ { handle: { like: search } }
2641
+ ]
2642
+ });
2643
+ }
2644
+ const filters = params.filters;
2645
+ const ids = nonEmpty(filters?.ids);
2646
+ if (ids) clauses.push({ id: { in: ids } });
2647
+ const slugs = nonEmpty(filters?.slugs);
2648
+ if (slugs) clauses.push({ slug: { in: slugs } });
2649
+ const handles = nonEmpty(filters?.handles);
2650
+ if (handles) clauses.push({ handle: { in: handles } });
2651
+ const categoryIds = nonEmpty(filters?.categoryIds);
2652
+ if (categoryIds) clauses.push({ categories: { in: categoryIds } });
2653
+ const tagIds = nonEmpty(filters?.tagIds);
2654
+ if (tagIds) clauses.push({ tags: { in: tagIds } });
2655
+ const minPrice = filters?.price?.min;
2656
+ if (minPrice != null) {
2657
+ clauses.push({ "listing.maxPrice": { greater_than_equal: minPrice } });
2658
+ }
2659
+ const maxPrice = filters?.price?.max;
2660
+ if (maxPrice != null) {
2661
+ clauses.push({ "listing.minPrice": { less_than_equal: maxPrice } });
2662
+ }
2663
+ if (filters?.availableForSale != null) {
2664
+ clauses.push({
2665
+ "listing.availableForSale": { equals: filters.availableForSale }
2666
+ });
2667
+ }
2668
+ if (clauses.length === 0) return void 0;
2669
+ if (clauses.length === 1) return clauses[0];
2670
+ return { and: clauses };
2671
+ }
2672
+ function buildProductListingPageUrl(params) {
2673
+ const options = {
2674
+ page: params.page,
2675
+ limit: params.limit,
2676
+ sort: params.sort,
2677
+ where: buildProductListingPageWhere(params)
2678
+ };
2679
+ return params.mode === "full" ? listingGroupsQueryUrl(options) : listingGroupsQueryCatalogUrl(options);
2680
+ }
2681
+ function withProductListingCards(response, options) {
2682
+ return {
2683
+ ...response,
2684
+ cards: response.docs.map((item) => buildProductListingCard(item, options))
2685
+ };
2686
+ }
1528
2687
 
1529
2688
  // src/core/api/order-api.ts
1530
2689
  function idempotencyRequestOptions(idempotencyKey) {
@@ -1567,8 +2726,20 @@ var CommerceClient = class {
1567
2726
  this.product = {
1568
2727
  stockCheck: (params) => api.post("/api/products/stock-check", params),
1569
2728
  stockSnapshot: (params) => api.get(stockSnapshotQuery(params)),
1570
- listingGroups: (params) => api.get(listingGroupsQuery(params)),
1571
- listingGroupsCatalog: (params) => api.get(listingGroupsCatalogQuery(params)),
2729
+ listingGroups: (params) => api.get(
2730
+ listingGroupsCatalogQuery(params)
2731
+ ),
2732
+ listingGroupsCatalog: (params) => api.get(
2733
+ listingGroupsCatalogQuery(params)
2734
+ ),
2735
+ listingPage: async (params = {}) => {
2736
+ const catalogParams = {
2737
+ ...params,
2738
+ mode: "catalog"
2739
+ };
2740
+ const response = await api.get(buildProductListingPageUrl(catalogParams));
2741
+ return withProductListingCards(response, catalogParams);
2742
+ },
1572
2743
  detail: async (params) => {
1573
2744
  try {
1574
2745
  const product = await api.get(productDetailQuery(params));
@@ -1773,6 +2944,11 @@ var Client = class {
1773
2944
  onUnauthorized,
1774
2945
  onRequestId
1775
2946
  });
2947
+ this.content = new ContentClient({
2948
+ publishableKey: this.config.publishableKey,
2949
+ apiUrl: this.config.apiUrl,
2950
+ onRequestId
2951
+ });
1776
2952
  this.events = new EventsClient({
1777
2953
  publishableKey: this.config.publishableKey,
1778
2954
  apiUrl: this.config.apiUrl,
@@ -1801,6 +2977,7 @@ function createClient(options) {
1801
2977
  }
1802
2978
  export {
1803
2979
  Client,
2980
+ ContentClient,
1804
2981
  createClient
1805
2982
  };
1806
2983
  //# sourceMappingURL=client.js.map