@01.software/sdk 0.12.1 → 0.13.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 (38) hide show
  1. package/README.md +94 -57
  2. package/dist/{const-CRjjFJ3o.d.ts → const-DSTPrI77.d.ts} +1 -1
  3. package/dist/{const-CZOY2tsf.d.cts → const-DqcpKgSA.d.cts} +1 -1
  4. package/dist/index.cjs +794 -504
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.cts +639 -439
  7. package/dist/index.d.ts +639 -439
  8. package/dist/index.js +794 -504
  9. package/dist/index.js.map +1 -1
  10. package/dist/{payload-types-D4IWd3ZB.d.cts → payload-types-DqX4iuTW.d.cts} +1 -1
  11. package/dist/{payload-types-D4IWd3ZB.d.ts → payload-types-DqX4iuTW.d.ts} +1 -1
  12. package/dist/realtime.cjs.map +1 -1
  13. package/dist/realtime.d.cts +2 -2
  14. package/dist/realtime.d.ts +2 -2
  15. package/dist/realtime.js.map +1 -1
  16. package/dist/{server-JR9TvKZ5.d.cts → server-DLdbWJVv.d.cts} +5 -3
  17. package/dist/{server-JR9TvKZ5.d.ts → server-DLdbWJVv.d.ts} +5 -3
  18. package/dist/ui/canvas/server.cjs +4 -4
  19. package/dist/ui/canvas/server.cjs.map +1 -1
  20. package/dist/ui/canvas/server.d.cts +1 -1
  21. package/dist/ui/canvas/server.d.ts +1 -1
  22. package/dist/ui/canvas/server.js +4 -4
  23. package/dist/ui/canvas/server.js.map +1 -1
  24. package/dist/ui/canvas.cjs +4 -4
  25. package/dist/ui/canvas.cjs.map +1 -1
  26. package/dist/ui/canvas.d.cts +2 -2
  27. package/dist/ui/canvas.d.ts +2 -2
  28. package/dist/ui/canvas.js +4 -4
  29. package/dist/ui/canvas.js.map +1 -1
  30. package/dist/ui/form.d.cts +1 -1
  31. package/dist/ui/form.d.ts +1 -1
  32. package/dist/ui/video.d.cts +1 -1
  33. package/dist/ui/video.d.ts +1 -1
  34. package/dist/{webhook-D_7bYIKj.d.ts → webhook-CX21PpBt.d.ts} +2 -2
  35. package/dist/{webhook-C1q3iC6W.d.cts → webhook-mXjcW86I.d.cts} +2 -2
  36. package/dist/webhook.d.cts +3 -3
  37. package/dist/webhook.d.ts +3 -3
  38. package/package.json +3 -3
package/dist/index.cjs CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
23
  ApiError: () => ApiError,
24
+ AuthError: () => AuthError,
24
25
  BaseApi: () => BaseApi,
25
26
  COLLECTIONS: () => COLLECTIONS,
26
27
  CartApi: () => CartApi,
@@ -28,20 +29,30 @@ __export(src_exports, {
28
29
  CollectionClient: () => CollectionClient,
29
30
  CollectionHooks: () => CollectionHooks,
30
31
  CollectionQueryBuilder: () => CollectionQueryBuilder,
32
+ CommerceClient: () => CommerceClient,
31
33
  CommunityClient: () => CommunityClient,
32
34
  ConfigError: () => ConfigError,
35
+ ConflictError: () => ConflictError,
33
36
  CustomerAuth: () => CustomerAuth,
34
37
  CustomerHooks: () => CustomerHooks,
38
+ CustomerNamespace: () => CustomerNamespace,
39
+ DiscountApi: () => DiscountApi,
35
40
  GoneError: () => GoneError,
36
41
  IMAGE_SIZES: () => IMAGE_SIZES,
42
+ ModerationApi: () => ModerationApi,
37
43
  NetworkError: () => NetworkError,
44
+ NotFoundError: () => NotFoundError,
38
45
  OrderApi: () => OrderApi,
46
+ PermissionError: () => PermissionError,
39
47
  ProductApi: () => ProductApi,
40
48
  QueryHooks: () => QueryHooks,
49
+ RateLimitError: () => RateLimitError,
41
50
  RealtimeConnection: () => RealtimeConnection,
42
51
  SDKError: () => SDKError,
43
52
  ServerClient: () => ServerClient,
53
+ ServerCommerceClient: () => ServerCommerceClient,
44
54
  ServiceUnavailableError: () => ServiceUnavailableError,
55
+ ShippingApi: () => ShippingApi,
45
56
  TimeoutError: () => TimeoutError,
46
57
  UsageLimitError: () => UsageLimitError,
47
58
  ValidationError: () => ValidationError,
@@ -49,7 +60,12 @@ __export(src_exports, {
49
60
  buildProductListingProjection: () => buildProductListingProjection,
50
61
  buildProductOptionMatrix: () => buildProductOptionMatrix,
51
62
  collectionKeys: () => collectionKeys,
63
+ createAuthError: () => createAuthError,
52
64
  createClient: () => createClient,
65
+ createConflictError: () => createConflictError,
66
+ createNotFoundError: () => createNotFoundError,
67
+ createPermissionError: () => createPermissionError,
68
+ createRateLimitError: () => createRateLimitError,
53
69
  createServerClient: () => createServerClient,
54
70
  createTypedWebhookHandler: () => createTypedWebhookHandler,
55
71
  customerKeys: () => customerKeys,
@@ -70,9 +86,14 @@ __export(src_exports, {
70
86
  getVideoThumbnail: () => getVideoThumbnail,
71
87
  handleWebhook: () => handleWebhook,
72
88
  isApiError: () => isApiError,
89
+ isAuthError: () => isAuthError,
73
90
  isConfigError: () => isConfigError,
91
+ isConflictError: () => isConflictError,
74
92
  isGoneError: () => isGoneError,
75
93
  isNetworkError: () => isNetworkError,
94
+ isNotFoundError: () => isNotFoundError,
95
+ isPermissionError: () => isPermissionError,
96
+ isRateLimitError: () => isRateLimitError,
76
97
  isSDKError: () => isSDKError,
77
98
  isServiceUnavailableError: () => isServiceUnavailableError,
78
99
  isTimeoutError: () => isTimeoutError,
@@ -86,9 +107,209 @@ __export(src_exports, {
86
107
  });
87
108
  module.exports = __toCommonJS(src_exports);
88
109
 
110
+ // src/utils/types.ts
111
+ var resolveRelation = (ref) => {
112
+ if (typeof ref === "string" || typeof ref === "number" || ref === null || ref === void 0)
113
+ return null;
114
+ return ref;
115
+ };
116
+
117
+ // src/core/metadata/index.ts
118
+ function extractSeo(doc) {
119
+ const seo = doc.seo ?? {};
120
+ const og = seo.openGraph ?? {};
121
+ return {
122
+ title: seo.title ?? doc.title ?? null,
123
+ description: seo.description ?? null,
124
+ noIndex: seo.noIndex ?? null,
125
+ canonical: seo.canonical ?? null,
126
+ openGraph: {
127
+ title: og.title ?? null,
128
+ description: og.description ?? null,
129
+ image: og.image ?? null
130
+ }
131
+ };
132
+ }
133
+ function generateMetadata(input, options) {
134
+ const title = input.title ?? void 0;
135
+ const description = input.description ?? void 0;
136
+ const ogTitle = input.openGraph?.title ?? title;
137
+ const ogDescription = input.openGraph?.description ?? description;
138
+ const image = resolveMetaImage(input.openGraph?.image);
139
+ return {
140
+ title,
141
+ description,
142
+ ...input.noIndex && { robots: { index: false, follow: false } },
143
+ ...input.canonical && { alternates: { canonical: input.canonical } },
144
+ openGraph: {
145
+ ...ogTitle && { title: ogTitle },
146
+ ...ogDescription && { description: ogDescription },
147
+ ...options?.siteName && { siteName: options.siteName },
148
+ ...image && { images: [image] }
149
+ },
150
+ twitter: {
151
+ card: image ? "summary_large_image" : "summary",
152
+ ...ogTitle && { title: ogTitle },
153
+ ...ogDescription && { description: ogDescription },
154
+ ...image && { images: [image.url] }
155
+ }
156
+ };
157
+ }
158
+ function resolveMetaImage(ref) {
159
+ const image = resolveRelation(ref);
160
+ if (!image) return null;
161
+ const sized = image.sizes?.["1536"];
162
+ const url = sized?.url || image.url;
163
+ if (!url) return null;
164
+ const width = sized?.url ? sized.width : image.width;
165
+ const height = sized?.url ? sized.height : image.height;
166
+ return {
167
+ url,
168
+ ...width && { width },
169
+ ...height && { height },
170
+ ...image.alt && { alt: image.alt }
171
+ };
172
+ }
173
+
174
+ // src/core/collection/query-builder.ts
175
+ var CollectionQueryBuilder = class {
176
+ constructor(api, collection) {
177
+ this.api = api;
178
+ this.collection = collection;
179
+ }
180
+ /**
181
+ * Find documents (list query)
182
+ * GET /api/{collection}
183
+ * @returns Payload CMS find response with docs array and pagination
184
+ */
185
+ async find(options) {
186
+ return this.api.requestFind(
187
+ `/api/${String(this.collection)}`,
188
+ options
189
+ );
190
+ }
191
+ /**
192
+ * Find document by ID
193
+ * GET /api/{collection}/{id}
194
+ * @returns Document object directly (no wrapper)
195
+ */
196
+ async findById(id, options) {
197
+ return this.api.requestFindById(
198
+ `/api/${String(this.collection)}/${String(id)}`,
199
+ options
200
+ );
201
+ }
202
+ /**
203
+ * Create a new document
204
+ * POST /api/{collection}
205
+ * @returns Payload CMS mutation response with doc and message
206
+ */
207
+ async create(data, options) {
208
+ const endpoint = `/api/${String(this.collection)}`;
209
+ if (options?.file) {
210
+ return this.api.requestCreateWithFile(
211
+ endpoint,
212
+ data,
213
+ options.file,
214
+ options.filename
215
+ );
216
+ }
217
+ return this.api.requestCreate(endpoint, data);
218
+ }
219
+ /**
220
+ * Update a document by ID
221
+ * PATCH /api/{collection}/{id}
222
+ * @returns Payload CMS mutation response with doc and message
223
+ */
224
+ async update(id, data, options) {
225
+ const endpoint = `/api/${String(this.collection)}/${String(id)}`;
226
+ if (options?.file) {
227
+ return this.api.requestUpdateWithFile(
228
+ endpoint,
229
+ data,
230
+ options.file,
231
+ options.filename
232
+ );
233
+ }
234
+ return this.api.requestUpdate(endpoint, data);
235
+ }
236
+ /**
237
+ * Count documents
238
+ * GET /api/{collection}/count
239
+ * @returns Count response with totalDocs
240
+ */
241
+ async count(options) {
242
+ return this.api.requestCount(
243
+ `/api/${String(this.collection)}/count`,
244
+ options
245
+ );
246
+ }
247
+ /**
248
+ * Find first matching document and return its Next.js Metadata.
249
+ * Applies depth: 1 (SEO image populate) and limit: 1 automatically.
250
+ * @returns Metadata or null if no document matches
251
+ */
252
+ async findMetadata(options, metadataOptions) {
253
+ const { docs } = await this.find({ ...options, limit: 1, depth: 1 });
254
+ const doc = docs[0];
255
+ if (!doc) return null;
256
+ return generateMetadata(
257
+ extractSeo(doc),
258
+ metadataOptions
259
+ );
260
+ }
261
+ /**
262
+ * Find document by ID and return its Next.js Metadata.
263
+ * Applies depth: 1 (SEO image populate) automatically.
264
+ * @returns Metadata (throws on 404)
265
+ */
266
+ async findMetadataById(id, metadataOptions) {
267
+ const doc = await this.findById(id, { depth: 1 });
268
+ return generateMetadata(
269
+ extractSeo(doc),
270
+ metadataOptions
271
+ );
272
+ }
273
+ /**
274
+ * Update multiple documents (bulk update)
275
+ * PATCH /api/{collection}
276
+ * @returns Payload CMS find response with updated docs
277
+ */
278
+ async updateMany(where, data) {
279
+ return this.api.requestUpdateMany(
280
+ `/api/${String(this.collection)}`,
281
+ { where, data }
282
+ );
283
+ }
284
+ /**
285
+ * Delete a document by ID
286
+ * DELETE /api/{collection}/{id}
287
+ * @returns Deleted document object directly (no wrapper)
288
+ */
289
+ async remove(id) {
290
+ return this.api.requestDelete(
291
+ `/api/${String(this.collection)}/${String(id)}`
292
+ );
293
+ }
294
+ /**
295
+ * Delete multiple documents (bulk delete)
296
+ * DELETE /api/{collection}
297
+ * @returns Payload CMS find response with deleted docs
298
+ */
299
+ async removeMany(where) {
300
+ return this.api.requestDeleteMany(
301
+ `/api/${String(this.collection)}`,
302
+ { where }
303
+ );
304
+ }
305
+ };
306
+
307
+ // src/core/collection/http-client.ts
308
+ var import_qs_esm = require("qs-esm");
309
+
89
310
  // src/core/internal/errors/index.ts
90
311
  var SDKError = class extends Error {
91
- constructor(code, message, status, details, userMessage, suggestion) {
312
+ constructor(code, message, status, details, userMessage, suggestion, requestId) {
92
313
  super(message);
93
314
  this.name = "SDKError";
94
315
  this.code = code;
@@ -96,6 +317,7 @@ var SDKError = class extends Error {
96
317
  this.details = details;
97
318
  this.userMessage = userMessage;
98
319
  this.suggestion = suggestion;
320
+ this.requestId = requestId;
99
321
  if (Error.captureStackTrace) {
100
322
  Error.captureStackTrace(this, new.target);
101
323
  }
@@ -111,7 +333,8 @@ var SDKError = class extends Error {
111
333
  status: this.status,
112
334
  details: this.details,
113
335
  userMessage: this.userMessage,
114
- suggestion: this.suggestion
336
+ suggestion: this.suggestion,
337
+ ...this.requestId !== void 0 && { requestId: this.requestId }
115
338
  };
116
339
  }
117
340
  };
@@ -178,6 +401,37 @@ var UsageLimitError = class extends SDKError {
178
401
  };
179
402
  }
180
403
  };
404
+ var AuthError = class extends SDKError {
405
+ constructor(message, details, userMessage, suggestion, requestId) {
406
+ super("auth_error", message, 401, details, userMessage, suggestion, requestId);
407
+ this.name = "AuthError";
408
+ }
409
+ };
410
+ var PermissionError = class extends SDKError {
411
+ constructor(message, details, userMessage, suggestion, requestId) {
412
+ super("permission_error", message, 403, details, userMessage, suggestion, requestId);
413
+ this.name = "PermissionError";
414
+ }
415
+ };
416
+ var NotFoundError = class extends SDKError {
417
+ constructor(message, details, userMessage, suggestion, requestId) {
418
+ super("not_found", message, 404, details, userMessage, suggestion, requestId);
419
+ this.name = "NotFoundError";
420
+ }
421
+ };
422
+ var ConflictError = class extends SDKError {
423
+ constructor(message, details, userMessage, suggestion, requestId) {
424
+ super("conflict", message, 409, details, userMessage, suggestion, requestId);
425
+ this.name = "ConflictError";
426
+ }
427
+ };
428
+ var RateLimitError = class extends SDKError {
429
+ constructor(message, retryAfter, details, userMessage, suggestion, requestId) {
430
+ super("rate_limit_exceeded", message, 429, details, userMessage, suggestion, requestId);
431
+ this.name = "RateLimitError";
432
+ this.retryAfter = retryAfter;
433
+ }
434
+ };
181
435
  function isSDKError(error) {
182
436
  return error instanceof SDKError;
183
437
  }
@@ -205,11 +459,32 @@ function isServiceUnavailableError(error) {
205
459
  function isUsageLimitError(error) {
206
460
  return error instanceof UsageLimitError;
207
461
  }
462
+ function isAuthError(error) {
463
+ return error instanceof AuthError;
464
+ }
465
+ function isPermissionError(error) {
466
+ return error instanceof PermissionError;
467
+ }
468
+ function isNotFoundError(error) {
469
+ return error instanceof NotFoundError;
470
+ }
471
+ function isConflictError(error) {
472
+ return error instanceof ConflictError;
473
+ }
474
+ function isRateLimitError(error) {
475
+ return error instanceof RateLimitError;
476
+ }
208
477
  var createNetworkError = (message, status, details, userMessage, suggestion) => new NetworkError(message, status, details, userMessage, suggestion);
478
+ var createValidationError = (message, details, userMessage, suggestion) => new ValidationError(message, details, userMessage, suggestion);
209
479
  var createApiError = (message, status, details, userMessage, suggestion) => new ApiError(message, status, details, userMessage, suggestion);
210
480
  var createConfigError = (message, details, userMessage, suggestion) => new ConfigError(message, details, userMessage, suggestion);
211
481
  var createTimeoutError = (message, details, userMessage, suggestion) => new TimeoutError(message, details, userMessage, suggestion);
212
482
  var createUsageLimitError = (message, usage, details, userMessage, suggestion) => new UsageLimitError(message, usage, details, userMessage, suggestion);
483
+ var createAuthError = (message, details, userMessage, suggestion, requestId) => new AuthError(message, details, userMessage, suggestion, requestId);
484
+ var createPermissionError = (message, details, userMessage, suggestion, requestId) => new PermissionError(message, details, userMessage, suggestion, requestId);
485
+ var createNotFoundError = (message, details, userMessage, suggestion, requestId) => new NotFoundError(message, details, userMessage, suggestion, requestId);
486
+ var createConflictError = (message, details, userMessage, suggestion, requestId) => new ConflictError(message, details, userMessage, suggestion, requestId);
487
+ var createRateLimitError = (message, retryAfter, details, userMessage, suggestion, requestId) => new RateLimitError(message, retryAfter, details, userMessage, suggestion, requestId);
213
488
 
214
489
  // src/core/client/types.ts
215
490
  function resolveApiUrl() {
@@ -252,6 +527,7 @@ async function parseErrorBody(response) {
252
527
  };
253
528
  try {
254
529
  const body = await response.json();
530
+ const reason = typeof body.reason === "string" ? body.reason : void 0;
255
531
  if (body.errors && Array.isArray(body.errors)) {
256
532
  const fieldErrors = [];
257
533
  for (const e of body.errors) {
@@ -273,6 +549,7 @@ async function parseErrorBody(response) {
273
549
  return {
274
550
  errorMessage: `HTTP ${response.status}: ${details}`,
275
551
  userMessage: details,
552
+ reason,
276
553
  errors: fieldErrors.length > 0 ? fieldErrors : body.errors
277
554
  };
278
555
  }
@@ -280,16 +557,18 @@ async function parseErrorBody(response) {
280
557
  if (typeof body.error === "string") {
281
558
  return {
282
559
  errorMessage: `HTTP ${response.status}: ${body.error}`,
283
- userMessage: body.error
560
+ userMessage: body.error,
561
+ reason
284
562
  };
285
563
  }
286
564
  if (body.message) {
287
565
  return {
288
566
  errorMessage: `HTTP ${response.status}: ${body.message}`,
289
- userMessage: body.message
567
+ userMessage: body.message,
568
+ reason
290
569
  };
291
570
  }
292
- return fallback;
571
+ return { ...fallback, reason };
293
572
  } catch {
294
573
  return fallback;
295
574
  }
@@ -297,11 +576,16 @@ async function parseErrorBody(response) {
297
576
  async function delay(ms) {
298
577
  return new Promise((resolve) => setTimeout(resolve, ms));
299
578
  }
579
+ function attachRequestId(err, id) {
580
+ if (id) err.requestId = id;
581
+ return err;
582
+ }
300
583
  async function httpFetch(url, options) {
301
584
  const {
302
585
  publishableKey,
303
586
  secretKey,
304
587
  customerToken,
588
+ tenantId,
305
589
  timeout = DEFAULT_TIMEOUT,
306
590
  debug,
307
591
  retry,
@@ -331,6 +615,9 @@ async function httpFetch(url, options) {
331
615
  if (authToken) {
332
616
  headers.set("Authorization", `Bearer ${authToken}`);
333
617
  }
618
+ if (tenantId) {
619
+ headers.set("X-Tenant-Id", tenantId);
620
+ }
334
621
  if (!headers.has("Content-Type") && requestInit.body && !(requestInit.body instanceof FormData)) {
335
622
  headers.set("Content-Type", "application/json");
336
623
  }
@@ -352,6 +639,7 @@ async function httpFetch(url, options) {
352
639
  signal: controller.signal
353
640
  });
354
641
  clearTimeout(timeoutId);
642
+ const requestId = response.headers.get("x-request-id") ?? void 0;
355
643
  debugLog(debug, "response", url, {
356
644
  status: response.status,
357
645
  statusText: response.statusText,
@@ -371,15 +659,19 @@ async function httpFetch(url, options) {
371
659
  response.headers.get("X-Usage-Remaining") || "0",
372
660
  10
373
661
  );
374
- throw createUsageLimitError(
375
- `Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,
376
- { limit, current, remaining },
377
- { url, method: requestInit.method || "GET", attempt: attempt + 1 },
378
- "Monthly API call limit exceeded. Please upgrade your plan.",
379
- "Upgrade your tenant plan to increase the monthly API call limit."
662
+ throw attachRequestId(
663
+ createUsageLimitError(
664
+ `Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,
665
+ { limit, current, remaining },
666
+ { url, method: requestInit.method || "GET", attempt: attempt + 1 },
667
+ "Monthly API call limit exceeded. Please upgrade your plan.",
668
+ "Upgrade your tenant plan to increase the monthly API call limit."
669
+ ),
670
+ requestId
380
671
  );
381
672
  }
382
- if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401) {
673
+ const parsed = await parseErrorBody(response);
674
+ if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && parsed.reason === "token_expired") {
383
675
  hasRetried401 = true;
384
676
  try {
385
677
  const newToken = await onUnauthorized();
@@ -390,29 +682,32 @@ async function httpFetch(url, options) {
390
682
  } catch {
391
683
  }
392
684
  }
685
+ const details = {
686
+ url,
687
+ method: requestInit.method || "GET",
688
+ attempt: attempt + 1
689
+ };
393
690
  if (NON_RETRYABLE_STATUSES.includes(response.status)) {
394
- const parsed2 = await parseErrorBody(response);
395
- const details = {
396
- url,
397
- method: requestInit.method || "GET",
398
- attempt: attempt + 1,
399
- ...parsed2.errors && { errors: parsed2.errors }
400
- };
401
- throw createNetworkError(
402
- parsed2.errorMessage,
691
+ throw attachRequestId(
692
+ createNetworkError(
693
+ parsed.errorMessage,
694
+ response.status,
695
+ { ...details, ...parsed.errors && { errors: parsed.errors } },
696
+ parsed.userMessage,
697
+ getErrorSuggestion(response.status)
698
+ ),
699
+ requestId
700
+ );
701
+ }
702
+ const error = attachRequestId(
703
+ createNetworkError(
704
+ parsed.errorMessage,
403
705
  response.status,
404
706
  details,
405
- parsed2.userMessage,
707
+ parsed.userMessage,
406
708
  getErrorSuggestion(response.status)
407
- );
408
- }
409
- const parsed = await parseErrorBody(response);
410
- const error = createNetworkError(
411
- parsed.errorMessage,
412
- response.status,
413
- { url, method: requestInit.method || "GET", attempt: attempt + 1 },
414
- parsed.userMessage,
415
- getErrorSuggestion(response.status)
709
+ ),
710
+ requestId
416
711
  );
417
712
  const method = (requestInit.method || "GET").toUpperCase();
418
713
  if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method) && retryConfig.retryableStatuses.includes(response.status)) {
@@ -460,417 +755,51 @@ async function httpFetch(url, options) {
460
755
  }
461
756
  if (error instanceof NetworkError || error instanceof TimeoutError) {
462
757
  if (isSafe && attempt < retryConfig.maxRetries && error.status && !NON_RETRYABLE_STATUSES.includes(error.status) && retryConfig.retryableStatuses.includes(error.status)) {
463
- lastError = error;
464
- await delay(retryConfig.retryDelay(attempt));
465
- continue;
466
- }
467
- throw error;
468
- }
469
- if (error instanceof SDKError) {
470
- throw error;
471
- }
472
- const unknownError = createNetworkError(
473
- error instanceof Error ? error.message : "An unknown network error occurred.",
474
- void 0,
475
- { url, originalError: error, attempt: attempt + 1 },
476
- "An unknown error occurred.",
477
- "Please try again later."
478
- );
479
- if (isSafe && attempt < retryConfig.maxRetries) {
480
- lastError = unknownError;
481
- await delay(retryConfig.retryDelay(attempt));
482
- continue;
483
- }
484
- throw unknownError;
485
- }
486
- }
487
- throw lastError ?? new NetworkError("Request failed after retries");
488
- }
489
-
490
- // src/core/api/parse-response.ts
491
- async function parseApiResponse(response, endpoint) {
492
- let data;
493
- try {
494
- data = await response.json();
495
- } catch {
496
- throw createApiError(
497
- `Invalid JSON response from ${endpoint}`,
498
- response.status,
499
- void 0,
500
- "Server returned an invalid response.",
501
- "Check if the API endpoint is available."
502
- );
503
- }
504
- if (data.error) {
505
- const errorMessage = typeof data.error === "string" ? data.error : "Unknown API error";
506
- throw createApiError(
507
- errorMessage,
508
- response.status,
509
- data,
510
- errorMessage,
511
- "An error occurred while processing the request."
512
- );
513
- }
514
- return data;
515
- }
516
-
517
- // src/core/api/base-api.ts
518
- var BaseApi = class {
519
- constructor(apiName, options) {
520
- if (!options.secretKey) {
521
- throw createConfigError(`secretKey is required for ${apiName}.`);
522
- }
523
- this.publishableKey = options.publishableKey ?? "";
524
- this.secretKey = options.secretKey;
525
- }
526
- async request(endpoint, body, options) {
527
- const method = options?.method ?? "POST";
528
- const response = await httpFetch(endpoint, {
529
- method,
530
- publishableKey: this.publishableKey,
531
- secretKey: this.secretKey,
532
- ...body !== void 0 && { body: JSON.stringify(body) },
533
- ...options?.headers && { headers: options.headers }
534
- });
535
- return parseApiResponse(response, endpoint);
536
- }
537
- };
538
-
539
- // src/core/api/order-api.ts
540
- var OrderApi = class extends BaseApi {
541
- constructor(options) {
542
- super("OrderApi", options);
543
- }
544
- createOrder(params) {
545
- return this.request("/api/orders/create", params);
546
- }
547
- updateOrder(params) {
548
- return this.request("/api/orders/update", params);
549
- }
550
- getOrder(params) {
551
- return this.request("/api/orders/get", params);
552
- }
553
- updateTransaction(params) {
554
- return this.request("/api/transactions/update", params);
555
- }
556
- checkout(params) {
557
- return this.request("/api/orders/checkout", params);
558
- }
559
- createFulfillment(params) {
560
- return this.request("/api/orders/create-fulfillment", params);
561
- }
562
- updateFulfillment(params) {
563
- return this.request("/api/orders/update-fulfillment", params);
564
- }
565
- returnWithRefund(params) {
566
- return this.request(
567
- "/api/returns/return-refund",
568
- params
569
- );
570
- }
571
- createReturn(params) {
572
- return this.request("/api/returns/create", params);
573
- }
574
- updateReturn(params) {
575
- return this.request("/api/returns/update", params);
576
- }
577
- validateDiscount(params) {
578
- return this.request(
579
- "/api/discounts/validate",
580
- params
581
- );
582
- }
583
- calculateShipping(params) {
584
- return this.request(
585
- "/api/shipping-policies/calculate",
586
- params
587
- );
588
- }
589
- };
590
-
591
- // src/core/api/cart-api.ts
592
- var CartApi = class {
593
- constructor(options) {
594
- if (!options.secretKey && !options.customerToken) {
595
- throw createConfigError(
596
- "Either secretKey or customerToken is required for CartApi."
597
- );
598
- }
599
- this.publishableKey = options.publishableKey ?? "";
600
- this.secretKey = options.secretKey;
601
- this.customerToken = options.customerToken;
602
- this.onUnauthorized = options.onUnauthorized;
603
- }
604
- async execute(endpoint, method, body) {
605
- const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
606
- const response = await httpFetch(endpoint, {
607
- method,
608
- publishableKey: this.publishableKey,
609
- secretKey: this.secretKey,
610
- customerToken: token ?? void 0,
611
- ...token && this.onUnauthorized && { onUnauthorized: this.onUnauthorized },
612
- ...body !== void 0 && { body: JSON.stringify(body) }
613
- });
614
- return parseApiResponse(response, endpoint);
615
- }
616
- getCart(cartId) {
617
- return this.execute(`/api/carts/${cartId}`, "GET");
618
- }
619
- addItem(params) {
620
- return this.execute("/api/carts/add-item", "POST", params);
621
- }
622
- updateItem(params) {
623
- return this.execute("/api/carts/update-item", "POST", params);
624
- }
625
- removeItem(params) {
626
- return this.execute(
627
- "/api/carts/remove-item",
628
- "POST",
629
- params
630
- );
631
- }
632
- applyDiscount(params) {
633
- return this.execute("/api/carts/apply-discount", "POST", params);
634
- }
635
- removeDiscount(params) {
636
- return this.execute("/api/carts/remove-discount", "POST", params);
637
- }
638
- clearCart(params) {
639
- return this.execute(
640
- "/api/carts/clear",
641
- "POST",
642
- params
643
- );
644
- }
645
- };
646
-
647
- // src/core/api/product-api.ts
648
- var ProductApi = class extends BaseApi {
649
- constructor(options) {
650
- super("ProductApi", options);
651
- }
652
- stockCheck(params) {
653
- return this.request("/api/products/stock-check", params);
654
- }
655
- listingGroups(params) {
656
- return this.request(
657
- "/api/products/listing-groups",
658
- params
659
- );
660
- }
661
- };
662
-
663
- // src/utils/types.ts
664
- var resolveRelation = (ref) => {
665
- if (typeof ref === "string" || typeof ref === "number" || ref === null || ref === void 0)
666
- return null;
667
- return ref;
668
- };
669
-
670
- // src/core/metadata/index.ts
671
- function extractSeo(doc) {
672
- const seo = doc.seo ?? {};
673
- const og = seo.openGraph ?? {};
674
- return {
675
- title: seo.title ?? doc.title ?? null,
676
- description: seo.description ?? null,
677
- noIndex: seo.noIndex ?? null,
678
- canonical: seo.canonical ?? null,
679
- openGraph: {
680
- title: og.title ?? null,
681
- description: og.description ?? null,
682
- image: og.image ?? null
683
- }
684
- };
685
- }
686
- function generateMetadata(input, options) {
687
- const title = input.title ?? void 0;
688
- const description = input.description ?? void 0;
689
- const ogTitle = input.openGraph?.title ?? title;
690
- const ogDescription = input.openGraph?.description ?? description;
691
- const image = resolveMetaImage(input.openGraph?.image);
692
- return {
693
- title,
694
- description,
695
- ...input.noIndex && { robots: { index: false, follow: false } },
696
- ...input.canonical && { alternates: { canonical: input.canonical } },
697
- openGraph: {
698
- ...ogTitle && { title: ogTitle },
699
- ...ogDescription && { description: ogDescription },
700
- ...options?.siteName && { siteName: options.siteName },
701
- ...image && { images: [image] }
702
- },
703
- twitter: {
704
- card: image ? "summary_large_image" : "summary",
705
- ...ogTitle && { title: ogTitle },
706
- ...ogDescription && { description: ogDescription },
707
- ...image && { images: [image.url] }
708
- }
709
- };
710
- }
711
- function resolveMetaImage(ref) {
712
- const image = resolveRelation(ref);
713
- if (!image) return null;
714
- const sized = image.sizes?.["1536"];
715
- const url = sized?.url || image.url;
716
- if (!url) return null;
717
- const width = sized?.url ? sized.width : image.width;
718
- const height = sized?.url ? sized.height : image.height;
719
- return {
720
- url,
721
- ...width && { width },
722
- ...height && { height },
723
- ...image.alt && { alt: image.alt }
724
- };
725
- }
726
-
727
- // src/core/collection/query-builder.ts
728
- var CollectionQueryBuilder = class {
729
- constructor(api, collection) {
730
- this.api = api;
731
- this.collection = collection;
732
- }
733
- /**
734
- * Find documents (list query)
735
- * GET /api/{collection}
736
- * @returns Payload CMS find response with docs array and pagination
737
- */
738
- async find(options) {
739
- return this.api.requestFind(
740
- `/api/${String(this.collection)}`,
741
- options
742
- );
743
- }
744
- /**
745
- * Find document by ID
746
- * GET /api/{collection}/{id}
747
- * @returns Document object directly (no wrapper)
748
- */
749
- async findById(id, options) {
750
- return this.api.requestFindById(
751
- `/api/${String(this.collection)}/${String(id)}`,
752
- options
753
- );
754
- }
755
- /**
756
- * Create a new document
757
- * POST /api/{collection}
758
- * @returns Payload CMS mutation response with doc and message
759
- */
760
- async create(data, options) {
761
- const endpoint = `/api/${String(this.collection)}`;
762
- if (options?.file) {
763
- return this.api.requestCreateWithFile(
764
- endpoint,
765
- data,
766
- options.file,
767
- options.filename
768
- );
769
- }
770
- return this.api.requestCreate(endpoint, data);
771
- }
772
- /**
773
- * Update a document by ID
774
- * PATCH /api/{collection}/{id}
775
- * @returns Payload CMS mutation response with doc and message
776
- */
777
- async update(id, data, options) {
778
- const endpoint = `/api/${String(this.collection)}/${String(id)}`;
779
- if (options?.file) {
780
- return this.api.requestUpdateWithFile(
781
- endpoint,
782
- data,
783
- options.file,
784
- options.filename
785
- );
786
- }
787
- return this.api.requestUpdate(endpoint, data);
788
- }
789
- /**
790
- * Count documents
791
- * GET /api/{collection}/count
792
- * @returns Count response with totalDocs
793
- */
794
- async count(options) {
795
- return this.api.requestCount(
796
- `/api/${String(this.collection)}/count`,
797
- options
798
- );
799
- }
800
- /**
801
- * Find first matching document and return its Next.js Metadata.
802
- * Applies depth: 1 (SEO image populate) and limit: 1 automatically.
803
- * @returns Metadata or null if no document matches
804
- */
805
- async findMetadata(options, metadataOptions) {
806
- const { docs } = await this.find({ ...options, limit: 1, depth: 1 });
807
- const doc = docs[0];
808
- if (!doc) return null;
809
- return generateMetadata(
810
- extractSeo(doc),
811
- metadataOptions
812
- );
813
- }
814
- /**
815
- * Find document by ID and return its Next.js Metadata.
816
- * Applies depth: 1 (SEO image populate) automatically.
817
- * @returns Metadata (throws on 404)
818
- */
819
- async findMetadataById(id, metadataOptions) {
820
- const doc = await this.findById(id, { depth: 1 });
821
- return generateMetadata(
822
- extractSeo(doc),
823
- metadataOptions
824
- );
825
- }
826
- /**
827
- * Update multiple documents (bulk update)
828
- * PATCH /api/{collection}
829
- * @returns Payload CMS find response with updated docs
830
- */
831
- async updateMany(where, data) {
832
- return this.api.requestUpdateMany(
833
- `/api/${String(this.collection)}`,
834
- { where, data }
835
- );
836
- }
837
- /**
838
- * Delete a document by ID
839
- * DELETE /api/{collection}/{id}
840
- * @returns Deleted document object directly (no wrapper)
841
- */
842
- async remove(id) {
843
- return this.api.requestDelete(
844
- `/api/${String(this.collection)}/${String(id)}`
845
- );
846
- }
847
- /**
848
- * Delete multiple documents (bulk delete)
849
- * DELETE /api/{collection}
850
- * @returns Payload CMS find response with deleted docs
851
- */
852
- async removeMany(where) {
853
- return this.api.requestDeleteMany(
854
- `/api/${String(this.collection)}`,
855
- { where }
856
- );
758
+ lastError = error;
759
+ await delay(retryConfig.retryDelay(attempt));
760
+ continue;
761
+ }
762
+ throw error;
763
+ }
764
+ if (error instanceof SDKError) {
765
+ throw error;
766
+ }
767
+ const unknownError = createNetworkError(
768
+ error instanceof Error ? error.message : "An unknown network error occurred.",
769
+ void 0,
770
+ { url, originalError: error, attempt: attempt + 1 },
771
+ "An unknown error occurred.",
772
+ "Please try again later."
773
+ );
774
+ if (isSafe && attempt < retryConfig.maxRetries) {
775
+ lastError = unknownError;
776
+ await delay(retryConfig.retryDelay(attempt));
777
+ continue;
778
+ }
779
+ throw unknownError;
780
+ }
857
781
  }
858
- };
782
+ throw lastError ?? new NetworkError("Request failed after retries");
783
+ }
859
784
 
860
785
  // src/core/collection/http-client.ts
861
- var import_qs_esm = require("qs-esm");
862
786
  var HttpClient = class {
863
- constructor(publishableKey, secretKey, getCustomerToken, onUnauthorized) {
787
+ constructor(publishableKey, secretKey, getCustomerToken, onUnauthorized, onRequestId, tenantId) {
864
788
  this.publishableKey = publishableKey;
865
789
  this.secretKey = secretKey;
790
+ this.tenantId = tenantId;
866
791
  this.getCustomerToken = getCustomerToken;
867
792
  this.onUnauthorized = onUnauthorized;
793
+ this.onRequestId = onRequestId;
868
794
  }
869
795
  get defaultOptions() {
870
796
  const opts = {
871
797
  publishableKey: this.publishableKey,
872
798
  secretKey: this.secretKey
873
799
  };
800
+ if (this.secretKey?.startsWith("pat01_") && this.tenantId) {
801
+ opts.tenantId = this.tenantId;
802
+ }
874
803
  const token = this.getCustomerToken?.();
875
804
  if (token) {
876
805
  opts.customerToken = token;
@@ -880,6 +809,17 @@ var HttpClient = class {
880
809
  }
881
810
  return opts;
882
811
  }
812
+ async fetchWithTracking(url, opts) {
813
+ try {
814
+ const response = await httpFetch(url, opts);
815
+ this.onRequestId?.(response.headers.get("x-request-id") ?? null);
816
+ return response;
817
+ } catch (err) {
818
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
819
+ this.onRequestId?.(id);
820
+ throw err;
821
+ }
822
+ }
883
823
  buildUrl(endpoint, options) {
884
824
  if (!options) return endpoint;
885
825
  const queryString = (0, import_qs_esm.stringify)(options, { addQueryPrefix: true });
@@ -996,7 +936,7 @@ var CollectionClient = class extends HttpClient {
996
936
  */
997
937
  async requestFind(endpoint, options) {
998
938
  const url = this.buildUrl(endpoint, options);
999
- const response = await httpFetch(url, {
939
+ const response = await this.fetchWithTracking(url, {
1000
940
  ...this.defaultOptions,
1001
941
  method: "GET"
1002
942
  });
@@ -1007,7 +947,7 @@ var CollectionClient = class extends HttpClient {
1007
947
  * POST /api/...custom-endpoint
1008
948
  */
1009
949
  async requestFindEndpoint(endpoint, data) {
1010
- const response = await httpFetch(endpoint, {
950
+ const response = await this.fetchWithTracking(endpoint, {
1011
951
  ...this.defaultOptions,
1012
952
  method: "POST",
1013
953
  body: data ? JSON.stringify(data) : void 0
@@ -1020,7 +960,7 @@ var CollectionClient = class extends HttpClient {
1020
960
  */
1021
961
  async requestFindById(endpoint, options) {
1022
962
  const url = this.buildUrl(endpoint, options);
1023
- const response = await httpFetch(url, {
963
+ const response = await this.fetchWithTracking(url, {
1024
964
  ...this.defaultOptions,
1025
965
  method: "GET"
1026
966
  });
@@ -1031,7 +971,7 @@ var CollectionClient = class extends HttpClient {
1031
971
  * POST /api/{collection}
1032
972
  */
1033
973
  async requestCreate(endpoint, data) {
1034
- const response = await httpFetch(endpoint, {
974
+ const response = await this.fetchWithTracking(endpoint, {
1035
975
  ...this.defaultOptions,
1036
976
  method: "POST",
1037
977
  body: data ? JSON.stringify(data) : void 0
@@ -1043,7 +983,7 @@ var CollectionClient = class extends HttpClient {
1043
983
  * PATCH /api/{collection}/{id}
1044
984
  */
1045
985
  async requestUpdate(endpoint, data) {
1046
- const response = await httpFetch(endpoint, {
986
+ const response = await this.fetchWithTracking(endpoint, {
1047
987
  ...this.defaultOptions,
1048
988
  method: "PATCH",
1049
989
  body: data ? JSON.stringify(data) : void 0
@@ -1056,7 +996,7 @@ var CollectionClient = class extends HttpClient {
1056
996
  */
1057
997
  async requestCount(endpoint, options) {
1058
998
  const url = this.buildUrl(endpoint, options);
1059
- const response = await httpFetch(url, {
999
+ const response = await this.fetchWithTracking(url, {
1060
1000
  ...this.defaultOptions,
1061
1001
  method: "GET"
1062
1002
  });
@@ -1067,7 +1007,7 @@ var CollectionClient = class extends HttpClient {
1067
1007
  * PATCH /api/{collection}
1068
1008
  */
1069
1009
  async requestUpdateMany(endpoint, data) {
1070
- const response = await httpFetch(endpoint, {
1010
+ const response = await this.fetchWithTracking(endpoint, {
1071
1011
  ...this.defaultOptions,
1072
1012
  method: "PATCH",
1073
1013
  body: JSON.stringify(data)
@@ -1079,7 +1019,7 @@ var CollectionClient = class extends HttpClient {
1079
1019
  * DELETE /api/{collection}/{id}
1080
1020
  */
1081
1021
  async requestDelete(endpoint) {
1082
- const response = await httpFetch(endpoint, {
1022
+ const response = await this.fetchWithTracking(endpoint, {
1083
1023
  ...this.defaultOptions,
1084
1024
  method: "DELETE"
1085
1025
  });
@@ -1090,7 +1030,7 @@ var CollectionClient = class extends HttpClient {
1090
1030
  * DELETE /api/{collection}
1091
1031
  */
1092
1032
  async requestDeleteMany(endpoint, data) {
1093
- const response = await httpFetch(endpoint, {
1033
+ const response = await this.fetchWithTracking(endpoint, {
1094
1034
  ...this.defaultOptions,
1095
1035
  method: "DELETE",
1096
1036
  body: JSON.stringify(data)
@@ -1102,7 +1042,7 @@ var CollectionClient = class extends HttpClient {
1102
1042
  * POST /api/{collection} (multipart/form-data)
1103
1043
  */
1104
1044
  async requestCreateWithFile(endpoint, data, file, filename) {
1105
- const response = await httpFetch(endpoint, {
1045
+ const response = await this.fetchWithTracking(endpoint, {
1106
1046
  ...this.defaultOptions,
1107
1047
  method: "POST",
1108
1048
  body: buildPayloadFormData(data, file, filename)
@@ -1114,7 +1054,7 @@ var CollectionClient = class extends HttpClient {
1114
1054
  * PATCH /api/{collection}/{id} (multipart/form-data)
1115
1055
  */
1116
1056
  async requestUpdateWithFile(endpoint, data, file, filename) {
1117
- const response = await httpFetch(endpoint, {
1057
+ const response = await this.fetchWithTracking(endpoint, {
1118
1058
  ...this.defaultOptions,
1119
1059
  method: "PATCH",
1120
1060
  body: buildPayloadFormData(data, file, filename)
@@ -1194,49 +1134,101 @@ var COLLECTIONS = [
1194
1134
  "community-bans"
1195
1135
  ];
1196
1136
 
1137
+ // src/core/api/parse-response.ts
1138
+ async function parseApiResponse(response, endpoint) {
1139
+ let data;
1140
+ try {
1141
+ data = await response.json();
1142
+ } catch {
1143
+ throw createApiError(
1144
+ `Invalid JSON response from ${endpoint}`,
1145
+ response.status,
1146
+ void 0,
1147
+ "Server returned an invalid response.",
1148
+ "Check if the API endpoint is available."
1149
+ );
1150
+ }
1151
+ if (data.error) {
1152
+ const errorMessage = typeof data.error === "string" ? data.error : "Unknown API error";
1153
+ const reason = typeof data.reason === "string" ? data.reason : void 0;
1154
+ const requestId = response.headers.get("x-request-id") ?? void 0;
1155
+ const retryAfterRaw = response.headers.get("Retry-After");
1156
+ const retryAfter = retryAfterRaw ? parseInt(retryAfterRaw, 10) || void 0 : void 0;
1157
+ if (reason === "validation_failed") {
1158
+ throw attachRequestId(createValidationError(errorMessage, data, errorMessage), requestId);
1159
+ }
1160
+ if (reason === "token_expired" || reason === "token_invalid" || reason === "key_invalid" || reason === "key_revoked") {
1161
+ throw attachRequestId(createAuthError(errorMessage, data, errorMessage), requestId);
1162
+ }
1163
+ if (reason === "forbidden") {
1164
+ throw attachRequestId(createPermissionError(errorMessage, data, errorMessage), requestId);
1165
+ }
1166
+ if (reason === "rate_limit_exceeded") {
1167
+ throw attachRequestId(createRateLimitError(errorMessage, retryAfter, data, errorMessage), requestId);
1168
+ }
1169
+ if (reason === "not_found") {
1170
+ throw attachRequestId(createNotFoundError(errorMessage, data, errorMessage), requestId);
1171
+ }
1172
+ if (reason === "conflict") {
1173
+ throw attachRequestId(createConflictError(errorMessage, data, errorMessage), requestId);
1174
+ }
1175
+ throw attachRequestId(
1176
+ createApiError(errorMessage, response.status, data, errorMessage, "An error occurred while processing the request."),
1177
+ requestId
1178
+ );
1179
+ }
1180
+ return data;
1181
+ }
1182
+
1197
1183
  // src/core/community/community-client.ts
1198
1184
  var CommunityClient = class {
1199
1185
  constructor(options) {
1200
1186
  this.publishableKey = options.publishableKey ?? "";
1201
1187
  this.secretKey = options.secretKey;
1188
+ this.tenantId = options.tenantId;
1202
1189
  this.customerToken = options.customerToken;
1203
1190
  this.onUnauthorized = options.onUnauthorized;
1191
+ this.onRequestId = options.onRequestId;
1192
+ }
1193
+ buildQuery(params) {
1194
+ if (!params) return "";
1195
+ const entries = Object.entries(params).filter((e) => e[1] !== void 0).map(([k, v]) => [k, String(v)]);
1196
+ return entries.length ? `?${new URLSearchParams(entries).toString()}` : "";
1204
1197
  }
1205
1198
  async execute(endpoint, method, body) {
1206
1199
  const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
1207
- const response = await httpFetch(endpoint, {
1208
- method,
1209
- publishableKey: this.publishableKey,
1210
- secretKey: this.secretKey,
1211
- customerToken: token ?? void 0,
1212
- ...token && this.onUnauthorized && { onUnauthorized: this.onUnauthorized },
1213
- ...body !== void 0 && { body: JSON.stringify(body) }
1214
- });
1215
- return parseApiResponse(response, endpoint);
1200
+ const tenantId = this.secretKey?.startsWith("pat01_") && this.tenantId ? this.tenantId : void 0;
1201
+ try {
1202
+ const response = await httpFetch(endpoint, {
1203
+ method,
1204
+ publishableKey: this.publishableKey,
1205
+ secretKey: this.secretKey,
1206
+ tenantId,
1207
+ customerToken: token ?? void 0,
1208
+ ...token && this.onUnauthorized && { onUnauthorized: this.onUnauthorized },
1209
+ ...body !== void 0 && { body: JSON.stringify(body) }
1210
+ });
1211
+ this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1212
+ return parseApiResponse(response, endpoint);
1213
+ } catch (err) {
1214
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
1215
+ this.onRequestId?.(id);
1216
+ throw err;
1217
+ }
1216
1218
  }
1217
1219
  // Threads
1218
1220
  createThread(params) {
1219
1221
  return this.execute("/api/threads", "POST", params);
1220
1222
  }
1221
1223
  getMyThreads(params) {
1222
- const query = params ? `?${new URLSearchParams(
1223
- Object.fromEntries(
1224
- Object.entries(params).map(([k, v]) => [k, String(v)])
1225
- )
1226
- ).toString()}` : "";
1227
1224
  return this.execute(
1228
- `/api/threads/my${query}`,
1225
+ `/api/threads/my${this.buildQuery(params)}`,
1229
1226
  "GET"
1230
1227
  );
1231
1228
  }
1232
1229
  getTrending(params) {
1233
- const query = params ? `?${new URLSearchParams(
1234
- Object.fromEntries(
1235
- Object.entries(params).map(([k, v]) => [k, String(v)])
1236
- )
1237
- ).toString()}` : "";
1238
1230
  return this.execute(
1239
- `/api/threads/trending${query}`,
1231
+ `/api/threads/trending${this.buildQuery(params)}`,
1240
1232
  "GET"
1241
1233
  );
1242
1234
  }
@@ -1352,26 +1344,56 @@ var CommunityClient = class {
1352
1344
  );
1353
1345
  }
1354
1346
  getMyBookmarks(params) {
1355
- const query = params ? `?${new URLSearchParams(
1356
- Object.fromEntries(
1357
- Object.entries(params).map(([k, v]) => [k, String(v)])
1358
- )
1359
- ).toString()}` : "";
1360
1347
  return this.execute(
1361
- `/api/bookmarks/my${query}`,
1348
+ `/api/bookmarks/my${this.buildQuery(params)}`,
1362
1349
  "GET"
1363
1350
  );
1364
1351
  }
1365
- // Moderation
1352
+ };
1353
+
1354
+ // src/core/api/base-api.ts
1355
+ var BaseApi = class {
1356
+ constructor(apiName, options) {
1357
+ if (!options.secretKey) {
1358
+ throw createConfigError(`secretKey is required for ${apiName}.`);
1359
+ }
1360
+ this.publishableKey = options.publishableKey ?? "";
1361
+ this.secretKey = options.secretKey;
1362
+ this.tenantId = options.tenantId;
1363
+ this.onRequestId = options.onRequestId;
1364
+ }
1365
+ async request(endpoint, body, options) {
1366
+ const method = options?.method ?? "POST";
1367
+ const tenantId = this.secretKey.startsWith("pat01_") && this.tenantId ? this.tenantId : void 0;
1368
+ try {
1369
+ const response = await httpFetch(endpoint, {
1370
+ method,
1371
+ publishableKey: this.publishableKey,
1372
+ secretKey: this.secretKey,
1373
+ tenantId,
1374
+ ...body !== void 0 && { body: JSON.stringify(body) },
1375
+ ...options?.headers && { headers: options.headers }
1376
+ });
1377
+ this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1378
+ return parseApiResponse(response, endpoint);
1379
+ } catch (err) {
1380
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
1381
+ this.onRequestId?.(id);
1382
+ throw err;
1383
+ }
1384
+ }
1385
+ };
1386
+
1387
+ // src/core/community/moderation-api.ts
1388
+ var ModerationApi = class extends BaseApi {
1389
+ constructor(options) {
1390
+ super("ModerationApi", options);
1391
+ }
1366
1392
  banCustomer(params) {
1367
- return this.execute("/api/community-bans/ban", "POST", params);
1393
+ return this.request("/api/community-bans/ban", params);
1368
1394
  }
1369
1395
  unbanCustomer(params) {
1370
- return this.execute(
1371
- "/api/community-bans/unban",
1372
- "DELETE",
1373
- params
1374
- );
1396
+ return this.request("/api/community-bans/unban", params);
1375
1397
  }
1376
1398
  };
1377
1399
 
@@ -1626,6 +1648,265 @@ var CustomerAuth = class {
1626
1648
  }
1627
1649
  };
1628
1650
 
1651
+ // src/core/customer/customer-namespace.ts
1652
+ var CustomerNamespace = class {
1653
+ constructor(publishableKey, options) {
1654
+ this.auth = new CustomerAuth(publishableKey, options);
1655
+ }
1656
+ };
1657
+
1658
+ // src/core/api/cart-api.ts
1659
+ var CartApi = class {
1660
+ constructor(options) {
1661
+ if (!options.secretKey && !options.customerToken) {
1662
+ throw createConfigError(
1663
+ "Either secretKey or customerToken is required for CartApi."
1664
+ );
1665
+ }
1666
+ this.publishableKey = options.publishableKey ?? "";
1667
+ this.secretKey = options.secretKey;
1668
+ this.tenantId = options.tenantId;
1669
+ this.customerToken = options.customerToken;
1670
+ this.onUnauthorized = options.onUnauthorized;
1671
+ this.onRequestId = options.onRequestId;
1672
+ }
1673
+ async execute(endpoint, method, body) {
1674
+ const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
1675
+ const tenantId = this.secretKey?.startsWith("pat01_") && this.tenantId ? this.tenantId : void 0;
1676
+ try {
1677
+ const response = await httpFetch(endpoint, {
1678
+ method,
1679
+ publishableKey: this.publishableKey,
1680
+ secretKey: this.secretKey,
1681
+ tenantId,
1682
+ customerToken: token ?? void 0,
1683
+ ...token && this.onUnauthorized && { onUnauthorized: this.onUnauthorized },
1684
+ ...body !== void 0 && { body: JSON.stringify(body) }
1685
+ });
1686
+ this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1687
+ return parseApiResponse(response, endpoint);
1688
+ } catch (err) {
1689
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
1690
+ this.onRequestId?.(id);
1691
+ throw err;
1692
+ }
1693
+ }
1694
+ getCart(cartId) {
1695
+ return this.execute(`/api/carts/${cartId}`, "GET");
1696
+ }
1697
+ addItem(params) {
1698
+ return this.execute("/api/carts/add-item", "POST", params);
1699
+ }
1700
+ updateItem(params) {
1701
+ return this.execute("/api/carts/update-item", "POST", params);
1702
+ }
1703
+ removeItem(params) {
1704
+ return this.execute(
1705
+ "/api/carts/remove-item",
1706
+ "POST",
1707
+ params
1708
+ );
1709
+ }
1710
+ applyDiscount(params) {
1711
+ return this.execute("/api/carts/apply-discount", "POST", params);
1712
+ }
1713
+ removeDiscount(params) {
1714
+ return this.execute("/api/carts/remove-discount", "POST", params);
1715
+ }
1716
+ clearCart(params) {
1717
+ return this.execute(
1718
+ "/api/carts/clear",
1719
+ "POST",
1720
+ params
1721
+ );
1722
+ }
1723
+ };
1724
+
1725
+ // src/core/commerce/commerce-client.ts
1726
+ var CommerceClient = class {
1727
+ constructor(options) {
1728
+ const cartApi = new CartApi({
1729
+ publishableKey: options.publishableKey,
1730
+ customerToken: options.customerToken,
1731
+ onUnauthorized: options.onUnauthorized,
1732
+ onRequestId: options.onRequestId
1733
+ });
1734
+ const execute = async (endpoint, body) => {
1735
+ const token = options.customerToken();
1736
+ try {
1737
+ const response = await httpFetch(endpoint, {
1738
+ method: "POST",
1739
+ publishableKey: options.publishableKey,
1740
+ customerToken: token ?? void 0,
1741
+ ...token && options.onUnauthorized && { onUnauthorized: options.onUnauthorized },
1742
+ body: JSON.stringify(body)
1743
+ });
1744
+ options.onRequestId?.(response.headers.get("x-request-id") ?? null);
1745
+ return parseApiResponse(response, endpoint);
1746
+ } catch (err) {
1747
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
1748
+ options.onRequestId?.(id);
1749
+ throw err;
1750
+ }
1751
+ };
1752
+ this.product = {
1753
+ stockCheck: (params) => execute("/api/products/stock-check", params),
1754
+ listingGroups: (params) => execute("/api/products/listing-groups", params)
1755
+ };
1756
+ this.cart = {
1757
+ get: cartApi.getCart.bind(cartApi),
1758
+ addItem: cartApi.addItem.bind(cartApi),
1759
+ updateItem: cartApi.updateItem.bind(cartApi),
1760
+ removeItem: cartApi.removeItem.bind(cartApi),
1761
+ applyDiscount: cartApi.applyDiscount.bind(cartApi),
1762
+ removeDiscount: cartApi.removeDiscount.bind(cartApi),
1763
+ clear: cartApi.clearCart.bind(cartApi)
1764
+ };
1765
+ this.orders = {
1766
+ checkout: (params) => execute("/api/orders/checkout", params),
1767
+ listMine: (params) => options.customerAuth.getMyOrders(params)
1768
+ };
1769
+ this.discounts = {
1770
+ validate: (params) => execute("/api/discounts/validate", params)
1771
+ };
1772
+ this.shipping = {
1773
+ calculate: (params) => execute("/api/shipping-policies/calculate", params)
1774
+ };
1775
+ }
1776
+ };
1777
+
1778
+ // src/core/api/product-api.ts
1779
+ var ProductApi = class extends BaseApi {
1780
+ constructor(options) {
1781
+ super("ProductApi", options);
1782
+ }
1783
+ /**
1784
+ * Check point-in-time stock availability for one or more product variants.
1785
+ * Results reflect available stock at the moment of the call and are not guaranteed
1786
+ * to remain available by the time an order is placed.
1787
+ */
1788
+ stockCheck(params) {
1789
+ return this.request("/api/products/stock-check", params);
1790
+ }
1791
+ listingGroups(params) {
1792
+ return this.request(
1793
+ "/api/products/listing-groups",
1794
+ params
1795
+ );
1796
+ }
1797
+ };
1798
+
1799
+ // src/core/api/discount-api.ts
1800
+ var DiscountApi = class extends BaseApi {
1801
+ constructor(options) {
1802
+ super("DiscountApi", options);
1803
+ }
1804
+ validate(params) {
1805
+ return this.request("/api/discounts/validate", params);
1806
+ }
1807
+ };
1808
+
1809
+ // src/core/api/shipping-api.ts
1810
+ var ShippingApi = class extends BaseApi {
1811
+ constructor(options) {
1812
+ super("ShippingApi", options);
1813
+ }
1814
+ calculate(params) {
1815
+ return this.request("/api/shipping-policies/calculate", params);
1816
+ }
1817
+ };
1818
+
1819
+ // src/core/api/order-api.ts
1820
+ var OrderApi = class extends BaseApi {
1821
+ constructor(options) {
1822
+ super("OrderApi", options);
1823
+ }
1824
+ createOrder(params) {
1825
+ return this.request("/api/orders/create", params);
1826
+ }
1827
+ updateOrder(params) {
1828
+ return this.request("/api/orders/update", params);
1829
+ }
1830
+ updateTransaction(params) {
1831
+ return this.request("/api/transactions/update", params);
1832
+ }
1833
+ checkout(params) {
1834
+ return this.request("/api/orders/checkout", params);
1835
+ }
1836
+ createFulfillment(params) {
1837
+ return this.request("/api/orders/create-fulfillment", params);
1838
+ }
1839
+ updateFulfillment(params) {
1840
+ return this.request("/api/orders/update-fulfillment", params);
1841
+ }
1842
+ bulkImportFulfillments(params) {
1843
+ return this.request(
1844
+ "/api/orders/bulk-import-fulfillments",
1845
+ params
1846
+ );
1847
+ }
1848
+ returnWithRefund(params) {
1849
+ return this.request(
1850
+ "/api/returns/return-refund",
1851
+ params
1852
+ );
1853
+ }
1854
+ createReturn(params) {
1855
+ return this.request("/api/returns/create", params);
1856
+ }
1857
+ updateReturn(params) {
1858
+ return this.request("/api/returns/update", params);
1859
+ }
1860
+ };
1861
+
1862
+ // src/core/commerce/server-commerce-client.ts
1863
+ var ServerCommerceClient = class {
1864
+ constructor(options) {
1865
+ const serverOptions = {
1866
+ publishableKey: options.publishableKey,
1867
+ secretKey: options.secretKey,
1868
+ tenantId: options.tenantId,
1869
+ onRequestId: options.onRequestId
1870
+ };
1871
+ const productApi = new ProductApi(serverOptions);
1872
+ const cartApi = new CartApi(serverOptions);
1873
+ const discountApi = new DiscountApi(serverOptions);
1874
+ const shippingApi = new ShippingApi(serverOptions);
1875
+ const orderApi = new OrderApi(serverOptions);
1876
+ this.product = {
1877
+ stockCheck: productApi.stockCheck.bind(productApi),
1878
+ listingGroups: productApi.listingGroups.bind(productApi)
1879
+ };
1880
+ this.cart = {
1881
+ get: cartApi.getCart.bind(cartApi),
1882
+ addItem: cartApi.addItem.bind(cartApi),
1883
+ updateItem: cartApi.updateItem.bind(cartApi),
1884
+ removeItem: cartApi.removeItem.bind(cartApi),
1885
+ applyDiscount: cartApi.applyDiscount.bind(cartApi),
1886
+ removeDiscount: cartApi.removeDiscount.bind(cartApi),
1887
+ clear: cartApi.clearCart.bind(cartApi)
1888
+ };
1889
+ this.orders = {
1890
+ checkout: orderApi.checkout.bind(orderApi),
1891
+ create: orderApi.createOrder.bind(orderApi),
1892
+ update: orderApi.updateOrder.bind(orderApi),
1893
+ updateTransaction: orderApi.updateTransaction.bind(orderApi),
1894
+ createFulfillment: orderApi.createFulfillment.bind(orderApi),
1895
+ updateFulfillment: orderApi.updateFulfillment.bind(orderApi),
1896
+ bulkImportFulfillments: orderApi.bulkImportFulfillments.bind(orderApi),
1897
+ createReturn: orderApi.createReturn.bind(orderApi),
1898
+ updateReturn: orderApi.updateReturn.bind(orderApi),
1899
+ returnWithRefund: orderApi.returnWithRefund.bind(orderApi)
1900
+ };
1901
+ this.discounts = {
1902
+ validate: discountApi.validate.bind(discountApi)
1903
+ };
1904
+ this.shipping = {
1905
+ calculate: shippingApi.calculate.bind(shippingApi)
1906
+ };
1907
+ }
1908
+ };
1909
+
1629
1910
  // src/core/query/get-query-client.ts
1630
1911
  var import_react_query = require("@tanstack/react-query");
1631
1912
  function makeQueryClient() {
@@ -2153,6 +2434,7 @@ var QueryHooks = class extends CollectionHooks {
2153
2434
  // src/core/client/client.ts
2154
2435
  var Client = class {
2155
2436
  constructor(options) {
2437
+ this.lastRequestId = null;
2156
2438
  const publishableKey = options.publishableKey;
2157
2439
  if (!publishableKey) {
2158
2440
  throw createConfigError("publishableKey is required.");
@@ -2164,43 +2446,47 @@ var Client = class {
2164
2446
  };
2165
2447
  this.state = { metadata };
2166
2448
  this.queryClient = getQueryClient();
2167
- this.customer = new CustomerAuth(
2449
+ this.customer = new CustomerNamespace(
2168
2450
  this.config.publishableKey,
2169
2451
  options.customer
2170
2452
  );
2171
2453
  const onUnauthorized = async () => {
2172
2454
  try {
2173
- const result = await this.customer.refreshToken();
2455
+ const result = await this.customer.auth.refreshToken();
2174
2456
  return result.token ?? null;
2175
2457
  } catch {
2176
2458
  return null;
2177
2459
  }
2178
2460
  };
2179
- this.cart = new CartApi({
2461
+ const onRequestId = (id) => {
2462
+ this.lastRequestId = id;
2463
+ };
2464
+ this.commerce = new CommerceClient({
2180
2465
  publishableKey: this.config.publishableKey,
2181
- customerToken: () => this.customer.getToken(),
2182
- onUnauthorized
2466
+ customerToken: () => this.customer.auth.getToken(),
2467
+ onUnauthorized,
2468
+ onRequestId,
2469
+ customerAuth: this.customer.auth
2183
2470
  });
2184
2471
  this.community = new CommunityClient({
2185
2472
  publishableKey: this.config.publishableKey,
2186
- customerToken: () => this.customer.getToken(),
2187
- onUnauthorized
2473
+ customerToken: () => this.customer.auth.getToken(),
2474
+ onUnauthorized,
2475
+ onRequestId
2188
2476
  });
2189
2477
  this.collections = new CollectionClient(
2190
2478
  this.config.publishableKey,
2191
2479
  void 0,
2192
- () => this.customer.getToken(),
2193
- onUnauthorized
2480
+ () => this.customer.auth.getToken(),
2481
+ onUnauthorized,
2482
+ onRequestId
2194
2483
  );
2195
2484
  this.query = new QueryHooks(
2196
2485
  this.queryClient,
2197
2486
  this.collections,
2198
- this.customer
2487
+ this.customer.auth
2199
2488
  );
2200
2489
  }
2201
- from(collection) {
2202
- return this.collections.from(collection);
2203
- }
2204
2490
  getState() {
2205
2491
  return { ...this.state };
2206
2492
  }
@@ -2215,6 +2501,7 @@ function createClient(options) {
2215
2501
  // src/core/client/client.server.ts
2216
2502
  var ServerClient = class {
2217
2503
  constructor(options) {
2504
+ this.lastRequestId = null;
2218
2505
  if (typeof window !== "undefined") {
2219
2506
  throw createConfigError(
2220
2507
  "ServerClient must not be used in a browser environment. This risks exposing your secretKey in client bundles. Use createClient() for browser code instead."
@@ -2234,32 +2521,35 @@ var ServerClient = class {
2234
2521
  userAgent: "Node.js"
2235
2522
  };
2236
2523
  this.state = { metadata };
2237
- this.api = new OrderApi({
2238
- publishableKey: this.config.publishableKey,
2239
- secretKey: this.config.secretKey
2240
- });
2241
- this.cart = new CartApi({
2242
- publishableKey: this.config.publishableKey,
2243
- secretKey: this.config.secretKey
2244
- });
2245
- this.community = new CommunityClient({
2246
- publishableKey: this.config.publishableKey,
2247
- secretKey: this.config.secretKey
2248
- });
2249
- this.product = new ProductApi({
2524
+ const onRequestId = (id) => {
2525
+ this.lastRequestId = id;
2526
+ };
2527
+ const serverOptions = {
2250
2528
  publishableKey: this.config.publishableKey,
2251
- secretKey: this.config.secretKey
2529
+ secretKey: this.config.secretKey,
2530
+ tenantId: this.config.tenantId,
2531
+ onRequestId
2532
+ };
2533
+ this.commerce = new ServerCommerceClient(serverOptions);
2534
+ const communityClient = new CommunityClient(serverOptions);
2535
+ const moderationApi = new ModerationApi(serverOptions);
2536
+ this.community = Object.assign(communityClient, {
2537
+ moderation: {
2538
+ banCustomer: moderationApi.banCustomer.bind(moderationApi),
2539
+ unbanCustomer: moderationApi.unbanCustomer.bind(moderationApi)
2540
+ }
2252
2541
  });
2253
2542
  this.collections = new CollectionClient(
2254
2543
  this.config.publishableKey,
2255
- this.config.secretKey
2544
+ this.config.secretKey,
2545
+ void 0,
2546
+ void 0,
2547
+ onRequestId,
2548
+ this.config.tenantId
2256
2549
  );
2257
2550
  this.queryClient = getQueryClient();
2258
2551
  this.query = new QueryHooks(this.queryClient, this.collections);
2259
2552
  }
2260
- from(collection) {
2261
- return this.collections.from(collection);
2262
- }
2263
2553
  getState() {
2264
2554
  return { ...this.state };
2265
2555
  }