@01.software/sdk 0.32.0 → 0.34.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 (70) hide show
  1. package/README.md +253 -38
  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 +368 -24
  7. package/dist/client.cjs.map +1 -1
  8. package/dist/client.d.cts +7 -6
  9. package/dist/client.d.ts +7 -6
  10. package/dist/client.js +368 -24
  11. package/dist/client.js.map +1 -1
  12. package/dist/{collection-client-CORhppPb.d.cts → collection-client-CR2B8c1v.d.cts} +7 -3
  13. package/dist/{collection-client-DPGXnhoF.d.ts → collection-client-DkREjhQ9.d.ts} +7 -3
  14. package/dist/{const-DcY2_z9O.d.ts → const-BTvdrXtY.d.cts} +5 -5
  15. package/dist/{const-Brk2Ff0q.d.cts → const-CdqCauHQ.d.ts} +5 -5
  16. package/dist/index-CjA3U6X3.d.cts +186 -0
  17. package/dist/index-DK8_NXkh.d.ts +186 -0
  18. package/dist/index.cjs +1651 -260
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +74 -9
  21. package/dist/index.d.ts +74 -9
  22. package/dist/index.js +1651 -260
  23. package/dist/index.js.map +1 -1
  24. package/dist/{payload-types-DVK1QCeU.d.cts → payload-types-C7tb7Xbs.d.cts} +2115 -1833
  25. package/dist/{payload-types-DVK1QCeU.d.ts → payload-types-C7tb7Xbs.d.ts} +2115 -1833
  26. package/dist/query.cjs +194 -35
  27. package/dist/query.cjs.map +1 -1
  28. package/dist/query.d.cts +45 -18
  29. package/dist/query.d.ts +45 -18
  30. package/dist/query.js +194 -35
  31. package/dist/query.js.map +1 -1
  32. package/dist/realtime.cjs.map +1 -1
  33. package/dist/realtime.d.cts +2 -2
  34. package/dist/realtime.d.ts +2 -2
  35. package/dist/realtime.js.map +1 -1
  36. package/dist/{server-CrsPyqEc.d.cts → server-nXOezi4b.d.cts} +22 -6
  37. package/dist/{server-CrsPyqEc.d.ts → server-nXOezi4b.d.ts} +22 -6
  38. package/dist/server.cjs +474 -36
  39. package/dist/server.cjs.map +1 -1
  40. package/dist/server.d.cts +11 -179
  41. package/dist/server.d.ts +11 -179
  42. package/dist/server.js +474 -36
  43. package/dist/server.js.map +1 -1
  44. package/dist/{types-DUPC7Xn6.d.ts → types-1ylMrCuW.d.ts} +1 -1
  45. package/dist/{types-ByMrR_Z_.d.cts → types-Bx558PU6.d.cts} +1 -1
  46. package/dist/{types-CYMSBkJC.d.ts → types-Byo_Rty4.d.ts} +728 -75
  47. package/dist/{types-CAkWqIr6.d.cts → types-DDhtZI6E.d.cts} +728 -75
  48. package/dist/ui/canvas/server.cjs +231 -38
  49. package/dist/ui/canvas/server.cjs.map +1 -1
  50. package/dist/ui/canvas/server.d.cts +1 -1
  51. package/dist/ui/canvas/server.d.ts +1 -1
  52. package/dist/ui/canvas/server.js +221 -38
  53. package/dist/ui/canvas/server.js.map +1 -1
  54. package/dist/ui/canvas.cjs +320 -257
  55. package/dist/ui/canvas.cjs.map +1 -1
  56. package/dist/ui/canvas.d.cts +5 -19
  57. package/dist/ui/canvas.d.ts +5 -19
  58. package/dist/ui/canvas.js +323 -260
  59. package/dist/ui/canvas.js.map +1 -1
  60. package/dist/ui/form.d.cts +1 -1
  61. package/dist/ui/form.d.ts +1 -1
  62. package/dist/ui/video.d.cts +1 -1
  63. package/dist/ui/video.d.ts +1 -1
  64. package/dist/webhook.cjs +95 -0
  65. package/dist/webhook.cjs.map +1 -1
  66. package/dist/webhook.d.cts +20 -104
  67. package/dist/webhook.d.ts +20 -104
  68. package/dist/webhook.js +95 -0
  69. package/dist/webhook.js.map +1 -1
  70. package/package.json +4 -5
package/dist/server.cjs CHANGED
@@ -22,6 +22,7 @@ var server_exports = {};
22
22
  __export(server_exports, {
23
23
  CollectionClient: () => CollectionClient,
24
24
  CommunityClient: () => CommunityClient,
25
+ EventsClient: () => EventsClient,
25
26
  ModerationApi: () => ModerationApi,
26
27
  ServerClient: () => ServerClient,
27
28
  ServerCollectionClient: () => ServerCollectionClient,
@@ -225,9 +226,12 @@ function resolveApiUrl(apiUrl) {
225
226
 
226
227
  // src/core/internal/utils/http.ts
227
228
  var DEFAULT_TIMEOUT = 3e4;
229
+ var STOREFRONT_BROWSER_TIMEOUT = 15e3;
228
230
  var DEFAULT_RETRYABLE_STATUSES = [408, 429, 500, 502, 503, 504];
229
231
  var NON_RETRYABLE_STATUSES = [400, 401, 403, 404, 409, 422];
230
232
  var SAFE_METHODS = ["GET", "HEAD", "OPTIONS"];
233
+ var DEFAULT_MAX_RETRIES = 3;
234
+ var STOREFRONT_BROWSER_MAX_RETRIES = 1;
231
235
  function debugLog(debug, type, message, data) {
232
236
  if (!debug) return;
233
237
  const shouldLog = debug === true || type === "request" && debug.logRequests || type === "response" && debug.logResponses || type === "error" && debug.logErrors;
@@ -420,15 +424,18 @@ async function httpFetch(url, options) {
420
424
  publishableKey,
421
425
  secretKey,
422
426
  customerToken,
423
- timeout = DEFAULT_TIMEOUT,
427
+ timeout: timeoutOption = DEFAULT_TIMEOUT,
424
428
  debug,
425
429
  retry,
426
430
  onUnauthorized,
427
431
  ...requestInit
428
432
  } = options || {};
429
433
  const baseUrl = resolveApiUrl(apiUrl);
434
+ const method = (requestInit.method || "GET").toUpperCase();
435
+ const isPublishableKeyBrowserGet = typeof window !== "undefined" && !secretKey && !customerToken && Boolean(publishableKey) && SAFE_METHODS.includes(method);
436
+ const timeout = timeoutOption === DEFAULT_TIMEOUT && isPublishableKeyBrowserGet ? STOREFRONT_BROWSER_TIMEOUT : timeoutOption;
430
437
  const retryConfig = {
431
- maxRetries: retry?.maxRetries ?? 3,
438
+ maxRetries: retry?.maxRetries ?? (isPublishableKeyBrowserGet ? STOREFRONT_BROWSER_MAX_RETRIES : DEFAULT_MAX_RETRIES),
432
439
  retryableStatuses: retry?.retryableStatuses ?? DEFAULT_RETRYABLE_STATUSES,
433
440
  retryDelay: retry?.retryDelay ?? ((attempt) => Math.min(1e3 * 2 ** attempt, 1e4))
434
441
  };
@@ -536,8 +543,8 @@ async function httpFetch(url, options) {
536
543
  ),
537
544
  requestId
538
545
  );
539
- const method = (requestInit.method || "GET").toUpperCase();
540
- if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method) && retryConfig.retryableStatuses.includes(response.status)) {
546
+ const method2 = (requestInit.method || "GET").toUpperCase();
547
+ if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method2) && retryConfig.retryableStatuses.includes(response.status)) {
541
548
  lastError = error;
542
549
  const retryDelay = retryConfig.retryDelay(attempt);
543
550
  debugLog(debug, "error", `Retrying in ${retryDelay}ms...`, error);
@@ -549,8 +556,8 @@ async function httpFetch(url, options) {
549
556
  return response;
550
557
  } catch (error) {
551
558
  debugLog(debug, "error", url, error);
552
- const method = (requestInit.method || "GET").toUpperCase();
553
- const isSafe = SAFE_METHODS.includes(method);
559
+ const method2 = (requestInit.method || "GET").toUpperCase();
560
+ const isSafe = SAFE_METHODS.includes(method2);
554
561
  if (error instanceof Error && error.name === "AbortError") {
555
562
  const timeoutError = createTimeoutError(
556
563
  `Request timed out after ${timeout}ms.`,
@@ -609,6 +616,35 @@ async function httpFetch(url, options) {
609
616
  throw lastError ?? new NetworkError("Request failed after retries");
610
617
  }
611
618
 
619
+ // src/core/internal/utils/query-string.ts
620
+ function productDetailQuery(params) {
621
+ const search = new URLSearchParams();
622
+ if ("slug" in params) {
623
+ search.set("slug", params.slug);
624
+ } else {
625
+ search.set("id", params.id);
626
+ }
627
+ return `/api/products/detail?${search}`;
628
+ }
629
+ function productDetailCatalogQuery(params) {
630
+ const search = new URLSearchParams();
631
+ if ("slug" in params) {
632
+ search.set("slug", params.slug);
633
+ } else {
634
+ search.set("id", params.id);
635
+ }
636
+ return `/api/products/detail/catalog?${search}`;
637
+ }
638
+ function listingGroupsQuery(params) {
639
+ return `/api/products/listing-groups?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
640
+ }
641
+ function listingGroupsCatalogQuery(params) {
642
+ return `/api/products/listing-groups/catalog?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
643
+ }
644
+ function stockSnapshotQuery(params) {
645
+ return `/api/products/stock?variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
646
+ }
647
+
612
648
  // src/core/collection/http-client.ts
613
649
  var HttpClient = class {
614
650
  constructor(publishableKey, secretKey, getCustomerToken, onUnauthorized, onRequestId, apiUrl) {
@@ -982,6 +1018,16 @@ var CollectionClient = class extends HttpClient {
982
1018
  });
983
1019
  return this.parseFindResponse(response);
984
1020
  }
1021
+ /**
1022
+ * Find-like response from a cacheable GET custom endpoint.
1023
+ */
1024
+ async requestFindEndpointGet(endpoint) {
1025
+ const response = await this.fetchWithTracking(endpoint, {
1026
+ ...this.defaultOptions,
1027
+ method: "GET"
1028
+ });
1029
+ return this.parseFindResponse(response);
1030
+ }
985
1031
  /**
986
1032
  * Find document by ID
987
1033
  * GET /api/{collection}/{id}
@@ -1143,6 +1189,8 @@ async function parseApiResponse(response, endpoint) {
1143
1189
  }
1144
1190
 
1145
1191
  // src/core/community/community-client.ts
1192
+ var DEFAULT_POST_LIST_SORT = "-lastActivityAt";
1193
+ var DEFAULT_COMMENT_LIST_SORT = "-createdAt";
1146
1194
  var CommunityClient = class {
1147
1195
  constructor(options) {
1148
1196
  this.publishableKey = requirePublishableKeyForSecret(
@@ -1161,6 +1209,40 @@ var CommunityClient = class {
1161
1209
  const entries = Object.entries(params).filter((e) => e[1] !== void 0).map(([k, v]) => [k, String(v)]);
1162
1210
  return entries.length ? `?${new URLSearchParams(entries).toString()}` : "";
1163
1211
  }
1212
+ buildPostsListQuery(params) {
1213
+ const urlParams = new URLSearchParams();
1214
+ const sort = params?.sort ?? DEFAULT_POST_LIST_SORT;
1215
+ urlParams.set("sort", sort);
1216
+ if (params?.limit !== void 0) urlParams.set("limit", String(params.limit));
1217
+ if (params?.page !== void 0) urlParams.set("page", String(params.page));
1218
+ if (params?.categoryId !== void 0) {
1219
+ urlParams.set("where[categories][in]", params.categoryId);
1220
+ }
1221
+ if (params?.tagId !== void 0) {
1222
+ urlParams.set("where[tags][in]", params.tagId);
1223
+ }
1224
+ return `/api/posts?${urlParams.toString()}`;
1225
+ }
1226
+ buildCommentsListQuery(params) {
1227
+ const urlParams = new URLSearchParams();
1228
+ const sort = params.sort ?? DEFAULT_COMMENT_LIST_SORT;
1229
+ urlParams.set("sort", sort);
1230
+ if (params.postId !== void 0) {
1231
+ urlParams.set("where[post][equals]", params.postId);
1232
+ }
1233
+ if (params.parentId !== void 0) {
1234
+ urlParams.set("where[parent][equals]", params.parentId);
1235
+ }
1236
+ if (params.rootComment !== void 0) {
1237
+ urlParams.set("where[rootComment][equals]", params.rootComment);
1238
+ }
1239
+ if (params.topLevelOnly) {
1240
+ urlParams.set("where[parent][exists]", "false");
1241
+ }
1242
+ if (params.limit !== void 0) urlParams.set("limit", String(params.limit));
1243
+ if (params.page !== void 0) urlParams.set("page", String(params.page));
1244
+ return `/api/comments?${urlParams.toString()}`;
1245
+ }
1164
1246
  async execute(endpoint, method, body) {
1165
1247
  const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
1166
1248
  try {
@@ -1184,6 +1266,28 @@ var CommunityClient = class {
1184
1266
  createPost(params) {
1185
1267
  return this.execute("/api/posts", "POST", params);
1186
1268
  }
1269
+ /**
1270
+ * Public post feed. Server applies the same visibility contract as
1271
+ * `communityPostRead` (published + visible + moderation-safe).
1272
+ */
1273
+ listPosts(params) {
1274
+ return this.execute(
1275
+ this.buildPostsListQuery(params),
1276
+ "GET"
1277
+ );
1278
+ }
1279
+ listPostCategories(params) {
1280
+ return this.execute(
1281
+ `/api/post-categories${this.buildQuery(params)}`,
1282
+ "GET"
1283
+ );
1284
+ }
1285
+ listPostTags(params) {
1286
+ return this.execute(
1287
+ `/api/post-tags${this.buildQuery(params)}`,
1288
+ "GET"
1289
+ );
1290
+ }
1187
1291
  getMyPosts(params) {
1188
1292
  return this.execute(
1189
1293
  `/api/posts/my${this.buildQuery(params)}`,
@@ -1219,16 +1323,37 @@ var CommunityClient = class {
1219
1323
  }
1220
1324
  return this.execute("/api/comments", "POST", body);
1221
1325
  }
1326
+ /**
1327
+ * List comments for a post.
1328
+ *
1329
+ * - Default: all visible comments on the post (any depth).
1330
+ * - `topLevelOnly: true`: only root comments (`parent` unset).
1331
+ * - `rootComment`: comments belonging to a thread rooted at that comment.
1332
+ */
1222
1333
  listComments(params) {
1223
- const { postId, page, limit, rootComment } = params;
1224
- const urlParams = new URLSearchParams();
1225
- urlParams.set("where[post][equals]", postId);
1226
- urlParams.set("sort", "-createdAt");
1227
- if (limit !== void 0) urlParams.set("limit", String(limit));
1228
- if (page !== void 0) urlParams.set("page", String(page));
1229
- if (rootComment !== void 0) urlParams.set("where[rootComment][equals]", rootComment);
1334
+ const { postId, page, limit, rootComment, topLevelOnly, sort } = params;
1230
1335
  return this.execute(
1231
- `/api/comments?${urlParams.toString()}`,
1336
+ this.buildCommentsListQuery({
1337
+ postId,
1338
+ page,
1339
+ limit,
1340
+ rootComment,
1341
+ topLevelOnly,
1342
+ sort
1343
+ }),
1344
+ "GET"
1345
+ );
1346
+ }
1347
+ /** Direct replies to a comment (`where[parent][equals]`). */
1348
+ listReplies(params) {
1349
+ const { commentId, page, limit, sort } = params;
1350
+ return this.execute(
1351
+ this.buildCommentsListQuery({
1352
+ parentId: commentId,
1353
+ page,
1354
+ limit,
1355
+ sort
1356
+ }),
1232
1357
  "GET"
1233
1358
  );
1234
1359
  }
@@ -1256,10 +1381,18 @@ var CommunityClient = class {
1256
1381
  }
1257
1382
  // Reactions
1258
1383
  addReaction(params) {
1259
- const { postId, type } = params;
1384
+ const { postId, typeSlug, type } = params;
1385
+ const reactionType = typeSlug ?? type;
1386
+ if (!reactionType) {
1387
+ throw new SDKError(
1388
+ "validation_failed",
1389
+ "addReaction requires typeSlug (or deprecated type)",
1390
+ 400
1391
+ );
1392
+ }
1260
1393
  return this.execute("/api/reactions", "POST", {
1261
1394
  post: postId,
1262
- type
1395
+ type: reactionType
1263
1396
  });
1264
1397
  }
1265
1398
  removeReaction(params) {
@@ -1270,10 +1403,18 @@ var CommunityClient = class {
1270
1403
  );
1271
1404
  }
1272
1405
  addCommentReaction(params) {
1273
- const { commentId, type } = params;
1406
+ const { commentId, typeSlug, type } = params;
1407
+ const reactionType = typeSlug ?? type;
1408
+ if (!reactionType) {
1409
+ throw new SDKError(
1410
+ "validation_failed",
1411
+ "addCommentReaction requires typeSlug (or deprecated type)",
1412
+ 400
1413
+ );
1414
+ }
1274
1415
  return this.execute("/api/reactions", "POST", {
1275
1416
  comment: commentId,
1276
- type
1417
+ type: reactionType
1277
1418
  });
1278
1419
  }
1279
1420
  removeCommentReaction(params) {
@@ -1289,6 +1430,12 @@ var CommunityClient = class {
1289
1430
  "GET"
1290
1431
  );
1291
1432
  }
1433
+ getCommentReactionSummary(params) {
1434
+ return this.execute(
1435
+ `/api/comments/${params.commentId}/reactions`,
1436
+ "GET"
1437
+ );
1438
+ }
1292
1439
  getReactionTypes() {
1293
1440
  return this.execute(
1294
1441
  "/api/reaction-types?limit=100",
@@ -1313,6 +1460,25 @@ var CommunityClient = class {
1313
1460
  "GET"
1314
1461
  );
1315
1462
  }
1463
+ // Profiles
1464
+ listProfileLists(params) {
1465
+ return this.execute(
1466
+ `/api/customer-profile-lists${this.buildQuery(params)}`,
1467
+ "GET"
1468
+ );
1469
+ }
1470
+ async getProfileList(params) {
1471
+ const query = "slug" in params ? `?where[slug][equals]=${encodeURIComponent(params.slug)}&limit=1` : `?where[id][equals]=${encodeURIComponent(params.id)}&limit=1`;
1472
+ const res = await this.execute(`/api/customer-profile-lists${query}`, "GET");
1473
+ return res.docs[0] ?? null;
1474
+ }
1475
+ updatePublicProfile(body) {
1476
+ return this.execute(
1477
+ "/api/customers/me/profile",
1478
+ "PATCH",
1479
+ body
1480
+ );
1481
+ }
1316
1482
  };
1317
1483
 
1318
1484
  // src/core/api/base-api.ts
@@ -1357,10 +1523,18 @@ var ModerationApi = class extends BaseApi {
1357
1523
  super("ModerationApi", options);
1358
1524
  }
1359
1525
  banCustomer(params) {
1360
- return this.request("/api/community-bans/ban", params);
1526
+ return this.request(
1527
+ "/api/community-bans/ban-bearer",
1528
+ params,
1529
+ { method: "POST" }
1530
+ );
1361
1531
  }
1362
1532
  unbanCustomer(params) {
1363
- return this.request("/api/community-bans/unban", params);
1533
+ return this.request(
1534
+ "/api/community-bans/unban-bearer",
1535
+ params,
1536
+ { method: "POST" }
1537
+ );
1364
1538
  }
1365
1539
  };
1366
1540
 
@@ -1435,6 +1609,59 @@ var CartApi = class {
1435
1609
  };
1436
1610
 
1437
1611
  // src/core/api/product-api.ts
1612
+ var PRODUCT_DETAIL_UNAVAILABLE_REASONS = /* @__PURE__ */ new Set([
1613
+ "not_found",
1614
+ "not_published",
1615
+ "feature_disabled"
1616
+ ]);
1617
+ function isRecord(value) {
1618
+ return typeof value === "object" && value !== null;
1619
+ }
1620
+ function readProductDetailUnavailableReason(value) {
1621
+ if (!isRecord(value)) return void 0;
1622
+ const directReason = value.reason ?? value.code;
1623
+ if (typeof directReason === "string" && PRODUCT_DETAIL_UNAVAILABLE_REASONS.has(directReason)) {
1624
+ return directReason;
1625
+ }
1626
+ return readProductDetailUnavailableReason(value.body);
1627
+ }
1628
+ function productDetailResultFromError(error) {
1629
+ if (!(error instanceof SDKError) || error.status !== 404) return void 0;
1630
+ const reason = readProductDetailUnavailableReason(error.details);
1631
+ if (!reason) return void 0;
1632
+ return { found: false, reason };
1633
+ }
1634
+ function rejectLegacyOptionValueSwatchColor(value) {
1635
+ if (Object.prototype.hasOwnProperty.call(
1636
+ value,
1637
+ "swatchColor"
1638
+ )) {
1639
+ throw new TypeError(
1640
+ 'Product upsert option values no longer accept legacy flat "swatchColor"; use nested "swatch" instead.'
1641
+ );
1642
+ }
1643
+ }
1644
+ function normalizeProductUpsertOptionValue(value) {
1645
+ rejectLegacyOptionValueSwatchColor(value);
1646
+ return value;
1647
+ }
1648
+ function normalizeProductUpsertParams(params) {
1649
+ const options = params.options ?? [];
1650
+ const variants = params.variants ?? [];
1651
+ if (!options.length) {
1652
+ return { ...params, options, variants };
1653
+ }
1654
+ return {
1655
+ ...params,
1656
+ options: options.map((option) => ({
1657
+ ...option,
1658
+ values: option.values.map(
1659
+ (value) => normalizeProductUpsertOptionValue(value)
1660
+ )
1661
+ })),
1662
+ variants
1663
+ };
1664
+ }
1438
1665
  var ProductApi = class extends BaseApi {
1439
1666
  constructor(options) {
1440
1667
  super("ProductApi", options);
@@ -1447,23 +1674,62 @@ var ProductApi = class extends BaseApi {
1447
1674
  stockCheck(params) {
1448
1675
  return this.request("/api/products/stock-check", params);
1449
1676
  }
1677
+ stockSnapshot(params) {
1678
+ return this.request(
1679
+ stockSnapshotQuery(params),
1680
+ void 0,
1681
+ { method: "GET" }
1682
+ );
1683
+ }
1450
1684
  listingGroups(params) {
1451
1685
  return this.request(
1452
- "/api/products/listing-groups",
1453
- params
1686
+ listingGroupsQuery(params),
1687
+ void 0,
1688
+ { method: "GET" }
1689
+ );
1690
+ }
1691
+ listingGroupsCatalog(params) {
1692
+ return this.request(
1693
+ listingGroupsCatalogQuery(params),
1694
+ void 0,
1695
+ { method: "GET" }
1454
1696
  );
1455
1697
  }
1456
1698
  /**
1457
1699
  * Fetch full product detail by slug or id.
1458
- * Returns `null` on 404 regardless of reason (`not_found` / `not_published` /
1459
- * `feature_disabled`). For the reason behind a null,
1460
- * inspect `client.lastRequestId` against backend logs.
1700
+ * Returns a discriminated result so storefronts can distinguish missing,
1701
+ * unpublished, and feature-disabled products.
1702
+ *
1703
+ * Only product-detail 404 responses carrying one of those allowlisted reasons
1704
+ * are mapped to `{ found: false, reason }`. Unknown or uncoded 404s, plus
1705
+ * permission/auth errors such as tenant mismatch, continue to throw typed SDK
1706
+ * errors instead of being collapsed into a storefront absence result.
1461
1707
  */
1462
1708
  async detail(params) {
1463
1709
  try {
1464
- return await this.request("/api/products/detail", params);
1710
+ const product = await this.request(
1711
+ productDetailQuery(params),
1712
+ void 0,
1713
+ { method: "GET" }
1714
+ );
1715
+ return { found: true, product };
1465
1716
  } catch (err) {
1466
- if (err instanceof NotFoundError) return null;
1717
+ const notFoundResult = productDetailResultFromError(err);
1718
+ if (notFoundResult) return notFoundResult;
1719
+ throw err;
1720
+ }
1721
+ }
1722
+ async detailCatalog(params) {
1723
+ try {
1724
+ const product = await this.request(
1725
+ productDetailCatalogQuery(params),
1726
+ void 0,
1727
+ { method: "GET" }
1728
+ );
1729
+ return { found: true, product };
1730
+ } catch (err) {
1731
+ const notFoundResult = productDetailResultFromError(err);
1732
+ if (notFoundResult?.found === false) return notFoundResult;
1467
1733
  throw err;
1468
1734
  }
1469
1735
  }
@@ -1474,7 +1740,10 @@ var ProductApi = class extends BaseApi {
1474
1740
  * `product-upsert` tool.
1475
1741
  */
1476
1742
  upsert(params) {
1477
- return this.request("/api/products/upsert", params);
1743
+ return this.request(
1744
+ "/api/products/upsert",
1745
+ normalizeProductUpsertParams(params)
1746
+ );
1478
1747
  }
1479
1748
  };
1480
1749
 
@@ -1499,12 +1768,24 @@ var ShippingApi = class extends BaseApi {
1499
1768
  };
1500
1769
 
1501
1770
  // src/core/api/order-api.ts
1771
+ function idempotencyRequestOptions(idempotencyKey) {
1772
+ return idempotencyKey ? { headers: { "X-Idempotency-Key": idempotencyKey } } : void 0;
1773
+ }
1774
+ function splitIdempotencyKey(params) {
1775
+ const { idempotencyKey, ...body } = params;
1776
+ return { body, idempotencyKey };
1777
+ }
1502
1778
  var OrderApi = class extends BaseApi {
1503
1779
  constructor(options) {
1504
1780
  super("OrderApi", options);
1505
1781
  }
1506
1782
  createOrder(params) {
1507
- return this.request("/api/orders/create", params);
1783
+ const { body, idempotencyKey } = splitIdempotencyKey(params);
1784
+ return this.request(
1785
+ "/api/orders/create",
1786
+ body,
1787
+ idempotencyRequestOptions(idempotencyKey)
1788
+ );
1508
1789
  }
1509
1790
  updateOrder(params) {
1510
1791
  return this.request("/api/orders/update", params);
@@ -1513,35 +1794,67 @@ var OrderApi = class extends BaseApi {
1513
1794
  return this.request("/api/transactions/update", params);
1514
1795
  }
1515
1796
  confirmPayment(params) {
1797
+ const { body, idempotencyKey } = splitIdempotencyKey(params);
1798
+ const headerKey = idempotencyKey ?? params.providerEventId;
1516
1799
  return this.request(
1517
1800
  "/api/orders/confirm-payment",
1518
- params,
1519
- params.providerEventId ? { headers: { "X-Idempotency-Key": params.providerEventId } } : void 0
1801
+ body,
1802
+ idempotencyRequestOptions(headerKey)
1803
+ );
1804
+ }
1805
+ cancelOrder(params) {
1806
+ const { idempotencyKey } = params;
1807
+ const body = {
1808
+ orderNumber: params.orderNumber,
1809
+ reasonCode: params.reasonCode,
1810
+ reasonDetail: params.reasonDetail
1811
+ };
1812
+ return this.request(
1813
+ "/api/orders/cancel",
1814
+ body,
1815
+ idempotencyKey ? { headers: { "X-Idempotency-Key": idempotencyKey } } : void 0
1520
1816
  );
1521
1817
  }
1522
1818
  checkout(params) {
1523
- return this.request("/api/orders/checkout", params);
1819
+ const { body, idempotencyKey } = splitIdempotencyKey(params);
1820
+ return this.request(
1821
+ "/api/orders/checkout",
1822
+ body,
1823
+ idempotencyRequestOptions(idempotencyKey)
1824
+ );
1524
1825
  }
1525
1826
  createFulfillment(params) {
1526
- return this.request("/api/orders/create-fulfillment", params);
1827
+ const { body, idempotencyKey } = splitIdempotencyKey(params);
1828
+ return this.request(
1829
+ "/api/orders/create-fulfillment",
1830
+ body,
1831
+ idempotencyRequestOptions(idempotencyKey)
1832
+ );
1527
1833
  }
1528
1834
  updateFulfillment(params) {
1529
1835
  return this.request("/api/orders/update-fulfillment", params);
1530
1836
  }
1531
1837
  bulkImportFulfillments(params) {
1532
1838
  return this.request(
1533
- "/api/orders/bulk-import-fulfillments",
1839
+ "/api/fulfillments/bulk-import",
1534
1840
  params
1535
1841
  );
1536
1842
  }
1537
1843
  returnWithRefund(params) {
1844
+ const { body, idempotencyKey } = splitIdempotencyKey(params);
1538
1845
  return this.request(
1539
1846
  "/api/returns/return-refund",
1540
- params
1847
+ body,
1848
+ idempotencyRequestOptions(idempotencyKey)
1541
1849
  );
1542
1850
  }
1543
1851
  createReturn(params) {
1544
- return this.request("/api/returns/create", params);
1852
+ const { body, idempotencyKey } = splitIdempotencyKey(params);
1853
+ return this.request(
1854
+ "/api/returns/create",
1855
+ body,
1856
+ idempotencyRequestOptions(idempotencyKey)
1857
+ );
1545
1858
  }
1546
1859
  updateReturn(params) {
1547
1860
  return this.request("/api/returns/update", params);
@@ -1643,6 +1956,7 @@ var ServerCommerceClient = class {
1643
1956
  update: orderApi.updateOrder.bind(orderApi),
1644
1957
  updateTransaction: orderApi.updateTransaction.bind(orderApi),
1645
1958
  confirmPayment: orderApi.confirmPayment.bind(orderApi),
1959
+ cancelOrder: orderApi.cancelOrder.bind(orderApi),
1646
1960
  createFulfillment: orderApi.createFulfillment.bind(orderApi),
1647
1961
  updateFulfillment: orderApi.updateFulfillment.bind(orderApi),
1648
1962
  bulkImportFulfillments: orderApi.bulkImportFulfillments.bind(orderApi),
@@ -1659,6 +1973,113 @@ var ServerCommerceClient = class {
1659
1973
  }
1660
1974
  };
1661
1975
 
1976
+ // src/core/events/events-client.ts
1977
+ var EventsClient = class {
1978
+ constructor(options) {
1979
+ const secretKey = options.secretKey;
1980
+ this.publishableKey = requirePublishableKeyForSecret(
1981
+ "EventsClient",
1982
+ options.publishableKey,
1983
+ secretKey
1984
+ );
1985
+ this.apiUrl = options.apiUrl;
1986
+ this.customerToken = options.customerToken;
1987
+ this.onUnauthorized = options.onUnauthorized;
1988
+ this.onRequestId = options.onRequestId;
1989
+ }
1990
+ getRange(params) {
1991
+ return this.execute(
1992
+ buildRangeEndpoint(params),
1993
+ "GET",
1994
+ void 0,
1995
+ { useCustomerAuth: false }
1996
+ );
1997
+ }
1998
+ register(params) {
1999
+ return this.execute(
2000
+ "/api/event-registrations/register",
2001
+ "POST",
2002
+ buildRegistrationRequestBody(params),
2003
+ { useCustomerAuth: true }
2004
+ );
2005
+ }
2006
+ getGuestRegistration(token) {
2007
+ return this.execute(
2008
+ "/api/event-registrations/guest/lookup",
2009
+ "POST",
2010
+ { token },
2011
+ { useCustomerAuth: false }
2012
+ );
2013
+ }
2014
+ cancelGuestRegistration(token, params = {}) {
2015
+ return this.execute(
2016
+ "/api/event-registrations/guest/cancel",
2017
+ "POST",
2018
+ buildGuestCancelRequestBody(token, params),
2019
+ { useCustomerAuth: false }
2020
+ );
2021
+ }
2022
+ async execute(endpoint, method, body, options = {}) {
2023
+ const useCustomerAuth = options.useCustomerAuth === true;
2024
+ const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
2025
+ try {
2026
+ const response = await httpFetch(endpoint, {
2027
+ method,
2028
+ apiUrl: this.apiUrl,
2029
+ publishableKey: this.publishableKey,
2030
+ ...useCustomerAuth && token ? { customerToken: token } : {},
2031
+ ...useCustomerAuth && token && this.onUnauthorized && { onUnauthorized: this.onUnauthorized },
2032
+ ...body !== void 0 && { body: JSON.stringify(body) }
2033
+ });
2034
+ this.onRequestId?.(response.headers.get("x-request-id") ?? null);
2035
+ return parseApiResponse(response, endpoint);
2036
+ } catch (err) {
2037
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
2038
+ this.onRequestId?.(id);
2039
+ throw err;
2040
+ }
2041
+ }
2042
+ };
2043
+ function buildRegistrationRequestBody(params) {
2044
+ return {
2045
+ event: params.event,
2046
+ occurrence: params.occurrence,
2047
+ ...params.quantity !== void 0 && { quantity: params.quantity },
2048
+ ...params.attendee !== void 0 && { attendee: params.attendee },
2049
+ ...params.answers !== void 0 && { answers: params.answers }
2050
+ };
2051
+ }
2052
+ function buildGuestCancelRequestBody(token, params) {
2053
+ return {
2054
+ token,
2055
+ ...params.reason !== void 0 && { reason: params.reason }
2056
+ };
2057
+ }
2058
+ function buildRangeEndpoint(params) {
2059
+ const urlParams = new URLSearchParams();
2060
+ urlParams.set("start", formatDateParam(params.start));
2061
+ urlParams.set("end", formatDateParam(params.end));
2062
+ if (params.limit !== void 0) urlParams.set("limit", String(params.limit));
2063
+ if (params.page !== void 0) urlParams.set("page", String(params.page));
2064
+ appendValues(urlParams, "calendar", params.calendar);
2065
+ appendValues(urlParams, "calendarSlug", params.calendarSlug);
2066
+ appendValues(urlParams, "category", params.category);
2067
+ appendValues(urlParams, "categorySlug", params.categorySlug);
2068
+ appendValues(urlParams, "tag", params.tag);
2069
+ appendValues(urlParams, "tagSlug", params.tagSlug);
2070
+ return `/api/event-occurrences/range?${urlParams.toString()}`;
2071
+ }
2072
+ function formatDateParam(value) {
2073
+ return value instanceof Date ? value.toISOString() : value;
2074
+ }
2075
+ function appendValues(params, key, value) {
2076
+ if (value === void 0) return;
2077
+ const values = Array.isArray(value) ? value : [value];
2078
+ for (const entry of values) {
2079
+ if (entry) params.append(key, entry);
2080
+ }
2081
+ }
2082
+
1662
2083
  // src/core/api/tenant-introspection-api.ts
1663
2084
  var TenantIntrospectionApi = class extends BaseApi {
1664
2085
  constructor(options) {
@@ -1745,6 +2166,23 @@ var ServerClient = class {
1745
2166
  this.config.apiUrl
1746
2167
  );
1747
2168
  }
2169
+ get events() {
2170
+ if (!this._events) {
2171
+ if (!this.config.publishableKey) {
2172
+ throw createConfigError(
2173
+ "publishableKey is required for server.events. It is sent as X-Publishable-Key for rate limiting and quota enforcement. Get it from Console > Settings > API Keys."
2174
+ );
2175
+ }
2176
+ this._events = new EventsClient({
2177
+ publishableKey: this.config.publishableKey,
2178
+ apiUrl: this.config.apiUrl,
2179
+ onRequestId: (id) => {
2180
+ this.lastRequestId = id;
2181
+ }
2182
+ });
2183
+ }
2184
+ return this._events;
2185
+ }
1748
2186
  getState() {
1749
2187
  return { ...this.state };
1750
2188
  }