@01.software/sdk 0.12.1 → 0.14.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 (44) hide show
  1. package/README.md +102 -57
  2. package/dist/analytics.cjs +207 -0
  3. package/dist/analytics.cjs.map +1 -0
  4. package/dist/analytics.d.cts +20 -0
  5. package/dist/analytics.d.ts +20 -0
  6. package/dist/analytics.js +184 -0
  7. package/dist/analytics.js.map +1 -0
  8. package/dist/{const-CRjjFJ3o.d.ts → const-CigSm8e_.d.ts} +1 -1
  9. package/dist/{const-CZOY2tsf.d.cts → const-CxpAy8X_.d.cts} +1 -1
  10. package/dist/index.cjs +946 -485
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +640 -439
  13. package/dist/index.d.ts +640 -439
  14. package/dist/index.js +946 -485
  15. package/dist/index.js.map +1 -1
  16. package/dist/{payload-types-D4IWd3ZB.d.cts → payload-types-DH1fKdM3.d.cts} +94 -1
  17. package/dist/{payload-types-D4IWd3ZB.d.ts → payload-types-DH1fKdM3.d.ts} +94 -1
  18. package/dist/realtime.cjs.map +1 -1
  19. package/dist/realtime.d.cts +2 -2
  20. package/dist/realtime.d.ts +2 -2
  21. package/dist/realtime.js.map +1 -1
  22. package/dist/{server-JR9TvKZ5.d.cts → server-DLdbWJVv.d.cts} +5 -3
  23. package/dist/{server-JR9TvKZ5.d.ts → server-DLdbWJVv.d.ts} +5 -3
  24. package/dist/ui/canvas/server.cjs +4 -4
  25. package/dist/ui/canvas/server.cjs.map +1 -1
  26. package/dist/ui/canvas/server.d.cts +1 -1
  27. package/dist/ui/canvas/server.d.ts +1 -1
  28. package/dist/ui/canvas/server.js +4 -4
  29. package/dist/ui/canvas/server.js.map +1 -1
  30. package/dist/ui/canvas.cjs +4 -4
  31. package/dist/ui/canvas.cjs.map +1 -1
  32. package/dist/ui/canvas.d.cts +2 -2
  33. package/dist/ui/canvas.d.ts +2 -2
  34. package/dist/ui/canvas.js +4 -4
  35. package/dist/ui/canvas.js.map +1 -1
  36. package/dist/ui/form.d.cts +1 -1
  37. package/dist/ui/form.d.ts +1 -1
  38. package/dist/ui/video.d.cts +1 -1
  39. package/dist/ui/video.d.ts +1 -1
  40. package/dist/{webhook-D_7bYIKj.d.ts → webhook-CmJWfLjs.d.ts} +2 -2
  41. package/dist/{webhook-C1q3iC6W.d.cts → webhook-IX2MGQj2.d.cts} +2 -2
  42. package/dist/webhook.d.cts +3 -3
  43. package/dist/webhook.d.ts +3 -3
  44. package/package.json +11 -1
package/dist/index.js CHANGED
@@ -1,6 +1,206 @@
1
+ // src/utils/types.ts
2
+ var resolveRelation = (ref) => {
3
+ if (typeof ref === "string" || typeof ref === "number" || ref === null || ref === void 0)
4
+ return null;
5
+ return ref;
6
+ };
7
+
8
+ // src/core/metadata/index.ts
9
+ function extractSeo(doc) {
10
+ const seo = doc.seo ?? {};
11
+ const og = seo.openGraph ?? {};
12
+ return {
13
+ title: seo.title ?? doc.title ?? null,
14
+ description: seo.description ?? null,
15
+ noIndex: seo.noIndex ?? null,
16
+ canonical: seo.canonical ?? null,
17
+ openGraph: {
18
+ title: og.title ?? null,
19
+ description: og.description ?? null,
20
+ image: og.image ?? null
21
+ }
22
+ };
23
+ }
24
+ function generateMetadata(input, options) {
25
+ const title = input.title ?? void 0;
26
+ const description = input.description ?? void 0;
27
+ const ogTitle = input.openGraph?.title ?? title;
28
+ const ogDescription = input.openGraph?.description ?? description;
29
+ const image = resolveMetaImage(input.openGraph?.image);
30
+ return {
31
+ title,
32
+ description,
33
+ ...input.noIndex && { robots: { index: false, follow: false } },
34
+ ...input.canonical && { alternates: { canonical: input.canonical } },
35
+ openGraph: {
36
+ ...ogTitle && { title: ogTitle },
37
+ ...ogDescription && { description: ogDescription },
38
+ ...options?.siteName && { siteName: options.siteName },
39
+ ...image && { images: [image] }
40
+ },
41
+ twitter: {
42
+ card: image ? "summary_large_image" : "summary",
43
+ ...ogTitle && { title: ogTitle },
44
+ ...ogDescription && { description: ogDescription },
45
+ ...image && { images: [image.url] }
46
+ }
47
+ };
48
+ }
49
+ function resolveMetaImage(ref) {
50
+ const image = resolveRelation(ref);
51
+ if (!image) return null;
52
+ const sized = image.sizes?.["1536"];
53
+ const url = sized?.url || image.url;
54
+ if (!url) return null;
55
+ const width = sized?.url ? sized.width : image.width;
56
+ const height = sized?.url ? sized.height : image.height;
57
+ return {
58
+ url,
59
+ ...width && { width },
60
+ ...height && { height },
61
+ ...image.alt && { alt: image.alt }
62
+ };
63
+ }
64
+
65
+ // src/core/collection/query-builder.ts
66
+ var CollectionQueryBuilder = class {
67
+ constructor(api, collection) {
68
+ this.api = api;
69
+ this.collection = collection;
70
+ }
71
+ /**
72
+ * Find documents (list query)
73
+ * GET /api/{collection}
74
+ * @returns Payload CMS find response with docs array and pagination
75
+ */
76
+ async find(options) {
77
+ return this.api.requestFind(
78
+ `/api/${String(this.collection)}`,
79
+ options
80
+ );
81
+ }
82
+ /**
83
+ * Find document by ID
84
+ * GET /api/{collection}/{id}
85
+ * @returns Document object directly (no wrapper)
86
+ */
87
+ async findById(id, options) {
88
+ return this.api.requestFindById(
89
+ `/api/${String(this.collection)}/${String(id)}`,
90
+ options
91
+ );
92
+ }
93
+ /**
94
+ * Create a new document
95
+ * POST /api/{collection}
96
+ * @returns Payload CMS mutation response with doc and message
97
+ */
98
+ async create(data, options) {
99
+ const endpoint = `/api/${String(this.collection)}`;
100
+ if (options?.file) {
101
+ return this.api.requestCreateWithFile(
102
+ endpoint,
103
+ data,
104
+ options.file,
105
+ options.filename
106
+ );
107
+ }
108
+ return this.api.requestCreate(endpoint, data);
109
+ }
110
+ /**
111
+ * Update a document by ID
112
+ * PATCH /api/{collection}/{id}
113
+ * @returns Payload CMS mutation response with doc and message
114
+ */
115
+ async update(id, data, options) {
116
+ const endpoint = `/api/${String(this.collection)}/${String(id)}`;
117
+ if (options?.file) {
118
+ return this.api.requestUpdateWithFile(
119
+ endpoint,
120
+ data,
121
+ options.file,
122
+ options.filename
123
+ );
124
+ }
125
+ return this.api.requestUpdate(endpoint, data);
126
+ }
127
+ /**
128
+ * Count documents
129
+ * GET /api/{collection}/count
130
+ * @returns Count response with totalDocs
131
+ */
132
+ async count(options) {
133
+ return this.api.requestCount(
134
+ `/api/${String(this.collection)}/count`,
135
+ options
136
+ );
137
+ }
138
+ /**
139
+ * Find first matching document and return its Next.js Metadata.
140
+ * Applies depth: 1 (SEO image populate) and limit: 1 automatically.
141
+ * @returns Metadata or null if no document matches
142
+ */
143
+ async findMetadata(options, metadataOptions) {
144
+ const { docs } = await this.find({ ...options, limit: 1, depth: 1 });
145
+ const doc = docs[0];
146
+ if (!doc) return null;
147
+ return generateMetadata(
148
+ extractSeo(doc),
149
+ metadataOptions
150
+ );
151
+ }
152
+ /**
153
+ * Find document by ID and return its Next.js Metadata.
154
+ * Applies depth: 1 (SEO image populate) automatically.
155
+ * @returns Metadata (throws on 404)
156
+ */
157
+ async findMetadataById(id, metadataOptions) {
158
+ const doc = await this.findById(id, { depth: 1 });
159
+ return generateMetadata(
160
+ extractSeo(doc),
161
+ metadataOptions
162
+ );
163
+ }
164
+ /**
165
+ * Update multiple documents (bulk update)
166
+ * PATCH /api/{collection}
167
+ * @returns Payload CMS find response with updated docs
168
+ */
169
+ async updateMany(where, data) {
170
+ return this.api.requestUpdateMany(
171
+ `/api/${String(this.collection)}`,
172
+ { where, data }
173
+ );
174
+ }
175
+ /**
176
+ * Delete a document by ID
177
+ * DELETE /api/{collection}/{id}
178
+ * @returns Deleted document object directly (no wrapper)
179
+ */
180
+ async remove(id) {
181
+ return this.api.requestDelete(
182
+ `/api/${String(this.collection)}/${String(id)}`
183
+ );
184
+ }
185
+ /**
186
+ * Delete multiple documents (bulk delete)
187
+ * DELETE /api/{collection}
188
+ * @returns Payload CMS find response with deleted docs
189
+ */
190
+ async removeMany(where) {
191
+ return this.api.requestDeleteMany(
192
+ `/api/${String(this.collection)}`,
193
+ { where }
194
+ );
195
+ }
196
+ };
197
+
198
+ // src/core/collection/http-client.ts
199
+ import { stringify } from "qs-esm";
200
+
1
201
  // src/core/internal/errors/index.ts
2
202
  var SDKError = class extends Error {
3
- constructor(code, message, status, details, userMessage, suggestion) {
203
+ constructor(code, message, status, details, userMessage, suggestion, requestId) {
4
204
  super(message);
5
205
  this.name = "SDKError";
6
206
  this.code = code;
@@ -8,6 +208,7 @@ var SDKError = class extends Error {
8
208
  this.details = details;
9
209
  this.userMessage = userMessage;
10
210
  this.suggestion = suggestion;
211
+ this.requestId = requestId;
11
212
  if (Error.captureStackTrace) {
12
213
  Error.captureStackTrace(this, new.target);
13
214
  }
@@ -23,7 +224,8 @@ var SDKError = class extends Error {
23
224
  status: this.status,
24
225
  details: this.details,
25
226
  userMessage: this.userMessage,
26
- suggestion: this.suggestion
227
+ suggestion: this.suggestion,
228
+ ...this.requestId !== void 0 && { requestId: this.requestId }
27
229
  };
28
230
  }
29
231
  };
@@ -90,6 +292,37 @@ var UsageLimitError = class extends SDKError {
90
292
  };
91
293
  }
92
294
  };
295
+ var AuthError = class extends SDKError {
296
+ constructor(message, details, userMessage, suggestion, requestId) {
297
+ super("auth_error", message, 401, details, userMessage, suggestion, requestId);
298
+ this.name = "AuthError";
299
+ }
300
+ };
301
+ var PermissionError = class extends SDKError {
302
+ constructor(message, details, userMessage, suggestion, requestId) {
303
+ super("permission_error", message, 403, details, userMessage, suggestion, requestId);
304
+ this.name = "PermissionError";
305
+ }
306
+ };
307
+ var NotFoundError = class extends SDKError {
308
+ constructor(message, details, userMessage, suggestion, requestId) {
309
+ super("not_found", message, 404, details, userMessage, suggestion, requestId);
310
+ this.name = "NotFoundError";
311
+ }
312
+ };
313
+ var ConflictError = class extends SDKError {
314
+ constructor(message, details, userMessage, suggestion, requestId) {
315
+ super("conflict", message, 409, details, userMessage, suggestion, requestId);
316
+ this.name = "ConflictError";
317
+ }
318
+ };
319
+ var RateLimitError = class extends SDKError {
320
+ constructor(message, retryAfter, details, userMessage, suggestion, requestId) {
321
+ super("rate_limit_exceeded", message, 429, details, userMessage, suggestion, requestId);
322
+ this.name = "RateLimitError";
323
+ this.retryAfter = retryAfter;
324
+ }
325
+ };
93
326
  function isSDKError(error) {
94
327
  return error instanceof SDKError;
95
328
  }
@@ -117,11 +350,32 @@ function isServiceUnavailableError(error) {
117
350
  function isUsageLimitError(error) {
118
351
  return error instanceof UsageLimitError;
119
352
  }
353
+ function isAuthError(error) {
354
+ return error instanceof AuthError;
355
+ }
356
+ function isPermissionError(error) {
357
+ return error instanceof PermissionError;
358
+ }
359
+ function isNotFoundError(error) {
360
+ return error instanceof NotFoundError;
361
+ }
362
+ function isConflictError(error) {
363
+ return error instanceof ConflictError;
364
+ }
365
+ function isRateLimitError(error) {
366
+ return error instanceof RateLimitError;
367
+ }
120
368
  var createNetworkError = (message, status, details, userMessage, suggestion) => new NetworkError(message, status, details, userMessage, suggestion);
369
+ var createValidationError = (message, details, userMessage, suggestion) => new ValidationError(message, details, userMessage, suggestion);
121
370
  var createApiError = (message, status, details, userMessage, suggestion) => new ApiError(message, status, details, userMessage, suggestion);
122
371
  var createConfigError = (message, details, userMessage, suggestion) => new ConfigError(message, details, userMessage, suggestion);
123
372
  var createTimeoutError = (message, details, userMessage, suggestion) => new TimeoutError(message, details, userMessage, suggestion);
124
373
  var createUsageLimitError = (message, usage, details, userMessage, suggestion) => new UsageLimitError(message, usage, details, userMessage, suggestion);
374
+ var createAuthError = (message, details, userMessage, suggestion, requestId) => new AuthError(message, details, userMessage, suggestion, requestId);
375
+ var createPermissionError = (message, details, userMessage, suggestion, requestId) => new PermissionError(message, details, userMessage, suggestion, requestId);
376
+ var createNotFoundError = (message, details, userMessage, suggestion, requestId) => new NotFoundError(message, details, userMessage, suggestion, requestId);
377
+ var createConflictError = (message, details, userMessage, suggestion, requestId) => new ConflictError(message, details, userMessage, suggestion, requestId);
378
+ var createRateLimitError = (message, retryAfter, details, userMessage, suggestion, requestId) => new RateLimitError(message, retryAfter, details, userMessage, suggestion, requestId);
125
379
 
126
380
  // src/core/client/types.ts
127
381
  function resolveApiUrl() {
@@ -164,6 +418,7 @@ async function parseErrorBody(response) {
164
418
  };
165
419
  try {
166
420
  const body = await response.json();
421
+ const reason = typeof body.reason === "string" ? body.reason : void 0;
167
422
  if (body.errors && Array.isArray(body.errors)) {
168
423
  const fieldErrors = [];
169
424
  for (const e of body.errors) {
@@ -185,6 +440,7 @@ async function parseErrorBody(response) {
185
440
  return {
186
441
  errorMessage: `HTTP ${response.status}: ${details}`,
187
442
  userMessage: details,
443
+ reason,
188
444
  errors: fieldErrors.length > 0 ? fieldErrors : body.errors
189
445
  };
190
446
  }
@@ -192,16 +448,18 @@ async function parseErrorBody(response) {
192
448
  if (typeof body.error === "string") {
193
449
  return {
194
450
  errorMessage: `HTTP ${response.status}: ${body.error}`,
195
- userMessage: body.error
451
+ userMessage: body.error,
452
+ reason
196
453
  };
197
454
  }
198
455
  if (body.message) {
199
456
  return {
200
457
  errorMessage: `HTTP ${response.status}: ${body.message}`,
201
- userMessage: body.message
458
+ userMessage: body.message,
459
+ reason
202
460
  };
203
461
  }
204
- return fallback;
462
+ return { ...fallback, reason };
205
463
  } catch {
206
464
  return fallback;
207
465
  }
@@ -209,11 +467,16 @@ async function parseErrorBody(response) {
209
467
  async function delay(ms) {
210
468
  return new Promise((resolve) => setTimeout(resolve, ms));
211
469
  }
470
+ function attachRequestId(err, id) {
471
+ if (id) err.requestId = id;
472
+ return err;
473
+ }
212
474
  async function httpFetch(url, options) {
213
475
  const {
214
476
  publishableKey,
215
477
  secretKey,
216
478
  customerToken,
479
+ tenantId,
217
480
  timeout = DEFAULT_TIMEOUT,
218
481
  debug,
219
482
  retry,
@@ -243,6 +506,9 @@ async function httpFetch(url, options) {
243
506
  if (authToken) {
244
507
  headers.set("Authorization", `Bearer ${authToken}`);
245
508
  }
509
+ if (tenantId) {
510
+ headers.set("X-Tenant-Id", tenantId);
511
+ }
246
512
  if (!headers.has("Content-Type") && requestInit.body && !(requestInit.body instanceof FormData)) {
247
513
  headers.set("Content-Type", "application/json");
248
514
  }
@@ -264,6 +530,7 @@ async function httpFetch(url, options) {
264
530
  signal: controller.signal
265
531
  });
266
532
  clearTimeout(timeoutId);
533
+ const requestId = response.headers.get("x-request-id") ?? void 0;
267
534
  debugLog(debug, "response", url, {
268
535
  status: response.status,
269
536
  statusText: response.statusText,
@@ -283,15 +550,19 @@ async function httpFetch(url, options) {
283
550
  response.headers.get("X-Usage-Remaining") || "0",
284
551
  10
285
552
  );
286
- throw createUsageLimitError(
287
- `Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,
288
- { limit, current, remaining },
289
- { url, method: requestInit.method || "GET", attempt: attempt + 1 },
290
- "Monthly API call limit exceeded. Please upgrade your plan.",
291
- "Upgrade your tenant plan to increase the monthly API call limit."
553
+ throw attachRequestId(
554
+ createUsageLimitError(
555
+ `Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,
556
+ { limit, current, remaining },
557
+ { url, method: requestInit.method || "GET", attempt: attempt + 1 },
558
+ "Monthly API call limit exceeded. Please upgrade your plan.",
559
+ "Upgrade your tenant plan to increase the monthly API call limit."
560
+ ),
561
+ requestId
292
562
  );
293
563
  }
294
- if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401) {
564
+ const parsed = await parseErrorBody(response);
565
+ if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && parsed.reason === "token_expired") {
295
566
  hasRetried401 = true;
296
567
  try {
297
568
  const newToken = await onUnauthorized();
@@ -302,29 +573,32 @@ async function httpFetch(url, options) {
302
573
  } catch {
303
574
  }
304
575
  }
576
+ const details = {
577
+ url,
578
+ method: requestInit.method || "GET",
579
+ attempt: attempt + 1
580
+ };
305
581
  if (NON_RETRYABLE_STATUSES.includes(response.status)) {
306
- const parsed2 = await parseErrorBody(response);
307
- const details = {
308
- url,
309
- method: requestInit.method || "GET",
310
- attempt: attempt + 1,
311
- ...parsed2.errors && { errors: parsed2.errors }
312
- };
313
- throw createNetworkError(
314
- parsed2.errorMessage,
582
+ throw attachRequestId(
583
+ createNetworkError(
584
+ parsed.errorMessage,
585
+ response.status,
586
+ { ...details, ...parsed.errors && { errors: parsed.errors } },
587
+ parsed.userMessage,
588
+ getErrorSuggestion(response.status)
589
+ ),
590
+ requestId
591
+ );
592
+ }
593
+ const error = attachRequestId(
594
+ createNetworkError(
595
+ parsed.errorMessage,
315
596
  response.status,
316
597
  details,
317
- parsed2.userMessage,
598
+ parsed.userMessage,
318
599
  getErrorSuggestion(response.status)
319
- );
320
- }
321
- const parsed = await parseErrorBody(response);
322
- const error = createNetworkError(
323
- parsed.errorMessage,
324
- response.status,
325
- { url, method: requestInit.method || "GET", attempt: attempt + 1 },
326
- parsed.userMessage,
327
- getErrorSuggestion(response.status)
600
+ ),
601
+ requestId
328
602
  );
329
603
  const method = (requestInit.method || "GET").toUpperCase();
330
604
  if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method) && retryConfig.retryableStatuses.includes(response.status)) {
@@ -399,390 +673,24 @@ async function httpFetch(url, options) {
399
673
  throw lastError ?? new NetworkError("Request failed after retries");
400
674
  }
401
675
 
402
- // src/core/api/parse-response.ts
403
- async function parseApiResponse(response, endpoint) {
404
- let data;
405
- try {
406
- data = await response.json();
407
- } catch {
408
- throw createApiError(
409
- `Invalid JSON response from ${endpoint}`,
410
- response.status,
411
- void 0,
412
- "Server returned an invalid response.",
413
- "Check if the API endpoint is available."
414
- );
415
- }
416
- if (data.error) {
417
- const errorMessage = typeof data.error === "string" ? data.error : "Unknown API error";
418
- throw createApiError(
419
- errorMessage,
420
- response.status,
421
- data,
422
- errorMessage,
423
- "An error occurred while processing the request."
424
- );
425
- }
426
- return data;
427
- }
428
-
429
- // src/core/api/base-api.ts
430
- var BaseApi = class {
431
- constructor(apiName, options) {
432
- if (!options.secretKey) {
433
- throw createConfigError(`secretKey is required for ${apiName}.`);
434
- }
435
- this.publishableKey = options.publishableKey ?? "";
436
- this.secretKey = options.secretKey;
437
- }
438
- async request(endpoint, body, options) {
439
- const method = options?.method ?? "POST";
440
- const response = await httpFetch(endpoint, {
441
- method,
442
- publishableKey: this.publishableKey,
443
- secretKey: this.secretKey,
444
- ...body !== void 0 && { body: JSON.stringify(body) },
445
- ...options?.headers && { headers: options.headers }
446
- });
447
- return parseApiResponse(response, endpoint);
448
- }
449
- };
450
-
451
- // src/core/api/order-api.ts
452
- var OrderApi = class extends BaseApi {
453
- constructor(options) {
454
- super("OrderApi", options);
455
- }
456
- createOrder(params) {
457
- return this.request("/api/orders/create", params);
458
- }
459
- updateOrder(params) {
460
- return this.request("/api/orders/update", params);
461
- }
462
- getOrder(params) {
463
- return this.request("/api/orders/get", params);
464
- }
465
- updateTransaction(params) {
466
- return this.request("/api/transactions/update", params);
467
- }
468
- checkout(params) {
469
- return this.request("/api/orders/checkout", params);
470
- }
471
- createFulfillment(params) {
472
- return this.request("/api/orders/create-fulfillment", params);
473
- }
474
- updateFulfillment(params) {
475
- return this.request("/api/orders/update-fulfillment", params);
476
- }
477
- returnWithRefund(params) {
478
- return this.request(
479
- "/api/returns/return-refund",
480
- params
481
- );
482
- }
483
- createReturn(params) {
484
- return this.request("/api/returns/create", params);
485
- }
486
- updateReturn(params) {
487
- return this.request("/api/returns/update", params);
488
- }
489
- validateDiscount(params) {
490
- return this.request(
491
- "/api/discounts/validate",
492
- params
493
- );
494
- }
495
- calculateShipping(params) {
496
- return this.request(
497
- "/api/shipping-policies/calculate",
498
- params
499
- );
500
- }
501
- };
502
-
503
- // src/core/api/cart-api.ts
504
- var CartApi = class {
505
- constructor(options) {
506
- if (!options.secretKey && !options.customerToken) {
507
- throw createConfigError(
508
- "Either secretKey or customerToken is required for CartApi."
509
- );
510
- }
511
- this.publishableKey = options.publishableKey ?? "";
512
- this.secretKey = options.secretKey;
513
- this.customerToken = options.customerToken;
514
- this.onUnauthorized = options.onUnauthorized;
515
- }
516
- async execute(endpoint, method, body) {
517
- const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
518
- const response = await httpFetch(endpoint, {
519
- method,
520
- publishableKey: this.publishableKey,
521
- secretKey: this.secretKey,
522
- customerToken: token ?? void 0,
523
- ...token && this.onUnauthorized && { onUnauthorized: this.onUnauthorized },
524
- ...body !== void 0 && { body: JSON.stringify(body) }
525
- });
526
- return parseApiResponse(response, endpoint);
527
- }
528
- getCart(cartId) {
529
- return this.execute(`/api/carts/${cartId}`, "GET");
530
- }
531
- addItem(params) {
532
- return this.execute("/api/carts/add-item", "POST", params);
533
- }
534
- updateItem(params) {
535
- return this.execute("/api/carts/update-item", "POST", params);
536
- }
537
- removeItem(params) {
538
- return this.execute(
539
- "/api/carts/remove-item",
540
- "POST",
541
- params
542
- );
543
- }
544
- applyDiscount(params) {
545
- return this.execute("/api/carts/apply-discount", "POST", params);
546
- }
547
- removeDiscount(params) {
548
- return this.execute("/api/carts/remove-discount", "POST", params);
549
- }
550
- clearCart(params) {
551
- return this.execute(
552
- "/api/carts/clear",
553
- "POST",
554
- params
555
- );
556
- }
557
- };
558
-
559
- // src/core/api/product-api.ts
560
- var ProductApi = class extends BaseApi {
561
- constructor(options) {
562
- super("ProductApi", options);
563
- }
564
- stockCheck(params) {
565
- return this.request("/api/products/stock-check", params);
566
- }
567
- listingGroups(params) {
568
- return this.request(
569
- "/api/products/listing-groups",
570
- params
571
- );
572
- }
573
- };
574
-
575
- // src/utils/types.ts
576
- var resolveRelation = (ref) => {
577
- if (typeof ref === "string" || typeof ref === "number" || ref === null || ref === void 0)
578
- return null;
579
- return ref;
580
- };
581
-
582
- // src/core/metadata/index.ts
583
- function extractSeo(doc) {
584
- const seo = doc.seo ?? {};
585
- const og = seo.openGraph ?? {};
586
- return {
587
- title: seo.title ?? doc.title ?? null,
588
- description: seo.description ?? null,
589
- noIndex: seo.noIndex ?? null,
590
- canonical: seo.canonical ?? null,
591
- openGraph: {
592
- title: og.title ?? null,
593
- description: og.description ?? null,
594
- image: og.image ?? null
595
- }
596
- };
597
- }
598
- function generateMetadata(input, options) {
599
- const title = input.title ?? void 0;
600
- const description = input.description ?? void 0;
601
- const ogTitle = input.openGraph?.title ?? title;
602
- const ogDescription = input.openGraph?.description ?? description;
603
- const image = resolveMetaImage(input.openGraph?.image);
604
- return {
605
- title,
606
- description,
607
- ...input.noIndex && { robots: { index: false, follow: false } },
608
- ...input.canonical && { alternates: { canonical: input.canonical } },
609
- openGraph: {
610
- ...ogTitle && { title: ogTitle },
611
- ...ogDescription && { description: ogDescription },
612
- ...options?.siteName && { siteName: options.siteName },
613
- ...image && { images: [image] }
614
- },
615
- twitter: {
616
- card: image ? "summary_large_image" : "summary",
617
- ...ogTitle && { title: ogTitle },
618
- ...ogDescription && { description: ogDescription },
619
- ...image && { images: [image.url] }
620
- }
621
- };
622
- }
623
- function resolveMetaImage(ref) {
624
- const image = resolveRelation(ref);
625
- if (!image) return null;
626
- const sized = image.sizes?.["1536"];
627
- const url = sized?.url || image.url;
628
- if (!url) return null;
629
- const width = sized?.url ? sized.width : image.width;
630
- const height = sized?.url ? sized.height : image.height;
631
- return {
632
- url,
633
- ...width && { width },
634
- ...height && { height },
635
- ...image.alt && { alt: image.alt }
636
- };
637
- }
638
-
639
- // src/core/collection/query-builder.ts
640
- var CollectionQueryBuilder = class {
641
- constructor(api, collection) {
642
- this.api = api;
643
- this.collection = collection;
644
- }
645
- /**
646
- * Find documents (list query)
647
- * GET /api/{collection}
648
- * @returns Payload CMS find response with docs array and pagination
649
- */
650
- async find(options) {
651
- return this.api.requestFind(
652
- `/api/${String(this.collection)}`,
653
- options
654
- );
655
- }
656
- /**
657
- * Find document by ID
658
- * GET /api/{collection}/{id}
659
- * @returns Document object directly (no wrapper)
660
- */
661
- async findById(id, options) {
662
- return this.api.requestFindById(
663
- `/api/${String(this.collection)}/${String(id)}`,
664
- options
665
- );
666
- }
667
- /**
668
- * Create a new document
669
- * POST /api/{collection}
670
- * @returns Payload CMS mutation response with doc and message
671
- */
672
- async create(data, options) {
673
- const endpoint = `/api/${String(this.collection)}`;
674
- if (options?.file) {
675
- return this.api.requestCreateWithFile(
676
- endpoint,
677
- data,
678
- options.file,
679
- options.filename
680
- );
681
- }
682
- return this.api.requestCreate(endpoint, data);
683
- }
684
- /**
685
- * Update a document by ID
686
- * PATCH /api/{collection}/{id}
687
- * @returns Payload CMS mutation response with doc and message
688
- */
689
- async update(id, data, options) {
690
- const endpoint = `/api/${String(this.collection)}/${String(id)}`;
691
- if (options?.file) {
692
- return this.api.requestUpdateWithFile(
693
- endpoint,
694
- data,
695
- options.file,
696
- options.filename
697
- );
698
- }
699
- return this.api.requestUpdate(endpoint, data);
700
- }
701
- /**
702
- * Count documents
703
- * GET /api/{collection}/count
704
- * @returns Count response with totalDocs
705
- */
706
- async count(options) {
707
- return this.api.requestCount(
708
- `/api/${String(this.collection)}/count`,
709
- options
710
- );
711
- }
712
- /**
713
- * Find first matching document and return its Next.js Metadata.
714
- * Applies depth: 1 (SEO image populate) and limit: 1 automatically.
715
- * @returns Metadata or null if no document matches
716
- */
717
- async findMetadata(options, metadataOptions) {
718
- const { docs } = await this.find({ ...options, limit: 1, depth: 1 });
719
- const doc = docs[0];
720
- if (!doc) return null;
721
- return generateMetadata(
722
- extractSeo(doc),
723
- metadataOptions
724
- );
725
- }
726
- /**
727
- * Find document by ID and return its Next.js Metadata.
728
- * Applies depth: 1 (SEO image populate) automatically.
729
- * @returns Metadata (throws on 404)
730
- */
731
- async findMetadataById(id, metadataOptions) {
732
- const doc = await this.findById(id, { depth: 1 });
733
- return generateMetadata(
734
- extractSeo(doc),
735
- metadataOptions
736
- );
737
- }
738
- /**
739
- * Update multiple documents (bulk update)
740
- * PATCH /api/{collection}
741
- * @returns Payload CMS find response with updated docs
742
- */
743
- async updateMany(where, data) {
744
- return this.api.requestUpdateMany(
745
- `/api/${String(this.collection)}`,
746
- { where, data }
747
- );
748
- }
749
- /**
750
- * Delete a document by ID
751
- * DELETE /api/{collection}/{id}
752
- * @returns Deleted document object directly (no wrapper)
753
- */
754
- async remove(id) {
755
- return this.api.requestDelete(
756
- `/api/${String(this.collection)}/${String(id)}`
757
- );
758
- }
759
- /**
760
- * Delete multiple documents (bulk delete)
761
- * DELETE /api/{collection}
762
- * @returns Payload CMS find response with deleted docs
763
- */
764
- async removeMany(where) {
765
- return this.api.requestDeleteMany(
766
- `/api/${String(this.collection)}`,
767
- { where }
768
- );
769
- }
770
- };
771
-
772
- // src/core/collection/http-client.ts
773
- import { stringify } from "qs-esm";
774
- var HttpClient = class {
775
- constructor(publishableKey, secretKey, getCustomerToken, onUnauthorized) {
776
- this.publishableKey = publishableKey;
777
- this.secretKey = secretKey;
778
- this.getCustomerToken = getCustomerToken;
779
- this.onUnauthorized = onUnauthorized;
676
+ // src/core/collection/http-client.ts
677
+ var HttpClient = class {
678
+ constructor(publishableKey, secretKey, getCustomerToken, onUnauthorized, onRequestId, tenantId) {
679
+ this.publishableKey = publishableKey;
680
+ this.secretKey = secretKey;
681
+ this.tenantId = tenantId;
682
+ this.getCustomerToken = getCustomerToken;
683
+ this.onUnauthorized = onUnauthorized;
684
+ this.onRequestId = onRequestId;
780
685
  }
781
686
  get defaultOptions() {
782
687
  const opts = {
783
688
  publishableKey: this.publishableKey,
784
689
  secretKey: this.secretKey
785
690
  };
691
+ if (this.secretKey?.startsWith("pat01_") && this.tenantId) {
692
+ opts.tenantId = this.tenantId;
693
+ }
786
694
  const token = this.getCustomerToken?.();
787
695
  if (token) {
788
696
  opts.customerToken = token;
@@ -792,6 +700,17 @@ var HttpClient = class {
792
700
  }
793
701
  return opts;
794
702
  }
703
+ async fetchWithTracking(url, opts) {
704
+ try {
705
+ const response = await httpFetch(url, opts);
706
+ this.onRequestId?.(response.headers.get("x-request-id") ?? null);
707
+ return response;
708
+ } catch (err) {
709
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
710
+ this.onRequestId?.(id);
711
+ throw err;
712
+ }
713
+ }
795
714
  buildUrl(endpoint, options) {
796
715
  if (!options) return endpoint;
797
716
  const queryString = stringify(options, { addQueryPrefix: true });
@@ -908,7 +827,7 @@ var CollectionClient = class extends HttpClient {
908
827
  */
909
828
  async requestFind(endpoint, options) {
910
829
  const url = this.buildUrl(endpoint, options);
911
- const response = await httpFetch(url, {
830
+ const response = await this.fetchWithTracking(url, {
912
831
  ...this.defaultOptions,
913
832
  method: "GET"
914
833
  });
@@ -919,7 +838,7 @@ var CollectionClient = class extends HttpClient {
919
838
  * POST /api/...custom-endpoint
920
839
  */
921
840
  async requestFindEndpoint(endpoint, data) {
922
- const response = await httpFetch(endpoint, {
841
+ const response = await this.fetchWithTracking(endpoint, {
923
842
  ...this.defaultOptions,
924
843
  method: "POST",
925
844
  body: data ? JSON.stringify(data) : void 0
@@ -932,7 +851,7 @@ var CollectionClient = class extends HttpClient {
932
851
  */
933
852
  async requestFindById(endpoint, options) {
934
853
  const url = this.buildUrl(endpoint, options);
935
- const response = await httpFetch(url, {
854
+ const response = await this.fetchWithTracking(url, {
936
855
  ...this.defaultOptions,
937
856
  method: "GET"
938
857
  });
@@ -943,7 +862,7 @@ var CollectionClient = class extends HttpClient {
943
862
  * POST /api/{collection}
944
863
  */
945
864
  async requestCreate(endpoint, data) {
946
- const response = await httpFetch(endpoint, {
865
+ const response = await this.fetchWithTracking(endpoint, {
947
866
  ...this.defaultOptions,
948
867
  method: "POST",
949
868
  body: data ? JSON.stringify(data) : void 0
@@ -955,7 +874,7 @@ var CollectionClient = class extends HttpClient {
955
874
  * PATCH /api/{collection}/{id}
956
875
  */
957
876
  async requestUpdate(endpoint, data) {
958
- const response = await httpFetch(endpoint, {
877
+ const response = await this.fetchWithTracking(endpoint, {
959
878
  ...this.defaultOptions,
960
879
  method: "PATCH",
961
880
  body: data ? JSON.stringify(data) : void 0
@@ -968,7 +887,7 @@ var CollectionClient = class extends HttpClient {
968
887
  */
969
888
  async requestCount(endpoint, options) {
970
889
  const url = this.buildUrl(endpoint, options);
971
- const response = await httpFetch(url, {
890
+ const response = await this.fetchWithTracking(url, {
972
891
  ...this.defaultOptions,
973
892
  method: "GET"
974
893
  });
@@ -979,7 +898,7 @@ var CollectionClient = class extends HttpClient {
979
898
  * PATCH /api/{collection}
980
899
  */
981
900
  async requestUpdateMany(endpoint, data) {
982
- const response = await httpFetch(endpoint, {
901
+ const response = await this.fetchWithTracking(endpoint, {
983
902
  ...this.defaultOptions,
984
903
  method: "PATCH",
985
904
  body: JSON.stringify(data)
@@ -991,7 +910,7 @@ var CollectionClient = class extends HttpClient {
991
910
  * DELETE /api/{collection}/{id}
992
911
  */
993
912
  async requestDelete(endpoint) {
994
- const response = await httpFetch(endpoint, {
913
+ const response = await this.fetchWithTracking(endpoint, {
995
914
  ...this.defaultOptions,
996
915
  method: "DELETE"
997
916
  });
@@ -1002,7 +921,7 @@ var CollectionClient = class extends HttpClient {
1002
921
  * DELETE /api/{collection}
1003
922
  */
1004
923
  async requestDeleteMany(endpoint, data) {
1005
- const response = await httpFetch(endpoint, {
924
+ const response = await this.fetchWithTracking(endpoint, {
1006
925
  ...this.defaultOptions,
1007
926
  method: "DELETE",
1008
927
  body: JSON.stringify(data)
@@ -1014,7 +933,7 @@ var CollectionClient = class extends HttpClient {
1014
933
  * POST /api/{collection} (multipart/form-data)
1015
934
  */
1016
935
  async requestCreateWithFile(endpoint, data, file, filename) {
1017
- const response = await httpFetch(endpoint, {
936
+ const response = await this.fetchWithTracking(endpoint, {
1018
937
  ...this.defaultOptions,
1019
938
  method: "POST",
1020
939
  body: buildPayloadFormData(data, file, filename)
@@ -1026,7 +945,7 @@ var CollectionClient = class extends HttpClient {
1026
945
  * PATCH /api/{collection}/{id} (multipart/form-data)
1027
946
  */
1028
947
  async requestUpdateWithFile(endpoint, data, file, filename) {
1029
- const response = await httpFetch(endpoint, {
948
+ const response = await this.fetchWithTracking(endpoint, {
1030
949
  ...this.defaultOptions,
1031
950
  method: "PATCH",
1032
951
  body: buildPayloadFormData(data, file, filename)
@@ -1106,49 +1025,101 @@ var COLLECTIONS = [
1106
1025
  "community-bans"
1107
1026
  ];
1108
1027
 
1028
+ // src/core/api/parse-response.ts
1029
+ async function parseApiResponse(response, endpoint) {
1030
+ let data;
1031
+ try {
1032
+ data = await response.json();
1033
+ } catch {
1034
+ throw createApiError(
1035
+ `Invalid JSON response from ${endpoint}`,
1036
+ response.status,
1037
+ void 0,
1038
+ "Server returned an invalid response.",
1039
+ "Check if the API endpoint is available."
1040
+ );
1041
+ }
1042
+ if (data.error) {
1043
+ const errorMessage = typeof data.error === "string" ? data.error : "Unknown API error";
1044
+ const reason = typeof data.reason === "string" ? data.reason : void 0;
1045
+ const requestId = response.headers.get("x-request-id") ?? void 0;
1046
+ const retryAfterRaw = response.headers.get("Retry-After");
1047
+ const retryAfter = retryAfterRaw ? parseInt(retryAfterRaw, 10) || void 0 : void 0;
1048
+ if (reason === "validation_failed") {
1049
+ throw attachRequestId(createValidationError(errorMessage, data, errorMessage), requestId);
1050
+ }
1051
+ if (reason === "token_expired" || reason === "token_invalid" || reason === "key_invalid" || reason === "key_revoked") {
1052
+ throw attachRequestId(createAuthError(errorMessage, data, errorMessage), requestId);
1053
+ }
1054
+ if (reason === "forbidden") {
1055
+ throw attachRequestId(createPermissionError(errorMessage, data, errorMessage), requestId);
1056
+ }
1057
+ if (reason === "rate_limit_exceeded") {
1058
+ throw attachRequestId(createRateLimitError(errorMessage, retryAfter, data, errorMessage), requestId);
1059
+ }
1060
+ if (reason === "not_found") {
1061
+ throw attachRequestId(createNotFoundError(errorMessage, data, errorMessage), requestId);
1062
+ }
1063
+ if (reason === "conflict") {
1064
+ throw attachRequestId(createConflictError(errorMessage, data, errorMessage), requestId);
1065
+ }
1066
+ throw attachRequestId(
1067
+ createApiError(errorMessage, response.status, data, errorMessage, "An error occurred while processing the request."),
1068
+ requestId
1069
+ );
1070
+ }
1071
+ return data;
1072
+ }
1073
+
1109
1074
  // src/core/community/community-client.ts
1110
1075
  var CommunityClient = class {
1111
1076
  constructor(options) {
1112
1077
  this.publishableKey = options.publishableKey ?? "";
1113
1078
  this.secretKey = options.secretKey;
1079
+ this.tenantId = options.tenantId;
1114
1080
  this.customerToken = options.customerToken;
1115
1081
  this.onUnauthorized = options.onUnauthorized;
1082
+ this.onRequestId = options.onRequestId;
1083
+ }
1084
+ buildQuery(params) {
1085
+ if (!params) return "";
1086
+ const entries = Object.entries(params).filter((e) => e[1] !== void 0).map(([k, v]) => [k, String(v)]);
1087
+ return entries.length ? `?${new URLSearchParams(entries).toString()}` : "";
1116
1088
  }
1117
1089
  async execute(endpoint, method, body) {
1118
1090
  const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
1119
- const response = await httpFetch(endpoint, {
1120
- method,
1121
- publishableKey: this.publishableKey,
1122
- secretKey: this.secretKey,
1123
- customerToken: token ?? void 0,
1124
- ...token && this.onUnauthorized && { onUnauthorized: this.onUnauthorized },
1125
- ...body !== void 0 && { body: JSON.stringify(body) }
1126
- });
1127
- return parseApiResponse(response, endpoint);
1091
+ const tenantId = this.secretKey?.startsWith("pat01_") && this.tenantId ? this.tenantId : void 0;
1092
+ try {
1093
+ const response = await httpFetch(endpoint, {
1094
+ method,
1095
+ publishableKey: this.publishableKey,
1096
+ secretKey: this.secretKey,
1097
+ tenantId,
1098
+ customerToken: token ?? void 0,
1099
+ ...token && this.onUnauthorized && { onUnauthorized: this.onUnauthorized },
1100
+ ...body !== void 0 && { body: JSON.stringify(body) }
1101
+ });
1102
+ this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1103
+ return parseApiResponse(response, endpoint);
1104
+ } catch (err) {
1105
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
1106
+ this.onRequestId?.(id);
1107
+ throw err;
1108
+ }
1128
1109
  }
1129
1110
  // Threads
1130
1111
  createThread(params) {
1131
1112
  return this.execute("/api/threads", "POST", params);
1132
1113
  }
1133
1114
  getMyThreads(params) {
1134
- const query = params ? `?${new URLSearchParams(
1135
- Object.fromEntries(
1136
- Object.entries(params).map(([k, v]) => [k, String(v)])
1137
- )
1138
- ).toString()}` : "";
1139
1115
  return this.execute(
1140
- `/api/threads/my${query}`,
1116
+ `/api/threads/my${this.buildQuery(params)}`,
1141
1117
  "GET"
1142
1118
  );
1143
1119
  }
1144
1120
  getTrending(params) {
1145
- const query = params ? `?${new URLSearchParams(
1146
- Object.fromEntries(
1147
- Object.entries(params).map(([k, v]) => [k, String(v)])
1148
- )
1149
- ).toString()}` : "";
1150
1121
  return this.execute(
1151
- `/api/threads/trending${query}`,
1122
+ `/api/threads/trending${this.buildQuery(params)}`,
1152
1123
  "GET"
1153
1124
  );
1154
1125
  }
@@ -1264,26 +1235,56 @@ var CommunityClient = class {
1264
1235
  );
1265
1236
  }
1266
1237
  getMyBookmarks(params) {
1267
- const query = params ? `?${new URLSearchParams(
1268
- Object.fromEntries(
1269
- Object.entries(params).map(([k, v]) => [k, String(v)])
1270
- )
1271
- ).toString()}` : "";
1272
1238
  return this.execute(
1273
- `/api/bookmarks/my${query}`,
1239
+ `/api/bookmarks/my${this.buildQuery(params)}`,
1274
1240
  "GET"
1275
1241
  );
1276
1242
  }
1277
- // Moderation
1243
+ };
1244
+
1245
+ // src/core/api/base-api.ts
1246
+ var BaseApi = class {
1247
+ constructor(apiName, options) {
1248
+ if (!options.secretKey) {
1249
+ throw createConfigError(`secretKey is required for ${apiName}.`);
1250
+ }
1251
+ this.publishableKey = options.publishableKey ?? "";
1252
+ this.secretKey = options.secretKey;
1253
+ this.tenantId = options.tenantId;
1254
+ this.onRequestId = options.onRequestId;
1255
+ }
1256
+ async request(endpoint, body, options) {
1257
+ const method = options?.method ?? "POST";
1258
+ const tenantId = this.secretKey.startsWith("pat01_") && this.tenantId ? this.tenantId : void 0;
1259
+ try {
1260
+ const response = await httpFetch(endpoint, {
1261
+ method,
1262
+ publishableKey: this.publishableKey,
1263
+ secretKey: this.secretKey,
1264
+ tenantId,
1265
+ ...body !== void 0 && { body: JSON.stringify(body) },
1266
+ ...options?.headers && { headers: options.headers }
1267
+ });
1268
+ this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1269
+ return parseApiResponse(response, endpoint);
1270
+ } catch (err) {
1271
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
1272
+ this.onRequestId?.(id);
1273
+ throw err;
1274
+ }
1275
+ }
1276
+ };
1277
+
1278
+ // src/core/community/moderation-api.ts
1279
+ var ModerationApi = class extends BaseApi {
1280
+ constructor(options) {
1281
+ super("ModerationApi", options);
1282
+ }
1278
1283
  banCustomer(params) {
1279
- return this.execute("/api/community-bans/ban", "POST", params);
1284
+ return this.request("/api/community-bans/ban", params);
1280
1285
  }
1281
1286
  unbanCustomer(params) {
1282
- return this.execute(
1283
- "/api/community-bans/unban",
1284
- "DELETE",
1285
- params
1286
- );
1287
+ return this.request("/api/community-bans/unban", params);
1287
1288
  }
1288
1289
  };
1289
1290
 
@@ -1538,6 +1539,265 @@ var CustomerAuth = class {
1538
1539
  }
1539
1540
  };
1540
1541
 
1542
+ // src/core/customer/customer-namespace.ts
1543
+ var CustomerNamespace = class {
1544
+ constructor(publishableKey, options) {
1545
+ this.auth = new CustomerAuth(publishableKey, options);
1546
+ }
1547
+ };
1548
+
1549
+ // src/core/api/cart-api.ts
1550
+ var CartApi = class {
1551
+ constructor(options) {
1552
+ if (!options.secretKey && !options.customerToken) {
1553
+ throw createConfigError(
1554
+ "Either secretKey or customerToken is required for CartApi."
1555
+ );
1556
+ }
1557
+ this.publishableKey = options.publishableKey ?? "";
1558
+ this.secretKey = options.secretKey;
1559
+ this.tenantId = options.tenantId;
1560
+ this.customerToken = options.customerToken;
1561
+ this.onUnauthorized = options.onUnauthorized;
1562
+ this.onRequestId = options.onRequestId;
1563
+ }
1564
+ async execute(endpoint, method, body) {
1565
+ const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
1566
+ const tenantId = this.secretKey?.startsWith("pat01_") && this.tenantId ? this.tenantId : void 0;
1567
+ try {
1568
+ const response = await httpFetch(endpoint, {
1569
+ method,
1570
+ publishableKey: this.publishableKey,
1571
+ secretKey: this.secretKey,
1572
+ tenantId,
1573
+ customerToken: token ?? void 0,
1574
+ ...token && this.onUnauthorized && { onUnauthorized: this.onUnauthorized },
1575
+ ...body !== void 0 && { body: JSON.stringify(body) }
1576
+ });
1577
+ this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1578
+ return parseApiResponse(response, endpoint);
1579
+ } catch (err) {
1580
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
1581
+ this.onRequestId?.(id);
1582
+ throw err;
1583
+ }
1584
+ }
1585
+ getCart(cartId) {
1586
+ return this.execute(`/api/carts/${cartId}`, "GET");
1587
+ }
1588
+ addItem(params) {
1589
+ return this.execute("/api/carts/add-item", "POST", params);
1590
+ }
1591
+ updateItem(params) {
1592
+ return this.execute("/api/carts/update-item", "POST", params);
1593
+ }
1594
+ removeItem(params) {
1595
+ return this.execute(
1596
+ "/api/carts/remove-item",
1597
+ "POST",
1598
+ params
1599
+ );
1600
+ }
1601
+ applyDiscount(params) {
1602
+ return this.execute("/api/carts/apply-discount", "POST", params);
1603
+ }
1604
+ removeDiscount(params) {
1605
+ return this.execute("/api/carts/remove-discount", "POST", params);
1606
+ }
1607
+ clearCart(params) {
1608
+ return this.execute(
1609
+ "/api/carts/clear",
1610
+ "POST",
1611
+ params
1612
+ );
1613
+ }
1614
+ };
1615
+
1616
+ // src/core/commerce/commerce-client.ts
1617
+ var CommerceClient = class {
1618
+ constructor(options) {
1619
+ const cartApi = new CartApi({
1620
+ publishableKey: options.publishableKey,
1621
+ customerToken: options.customerToken,
1622
+ onUnauthorized: options.onUnauthorized,
1623
+ onRequestId: options.onRequestId
1624
+ });
1625
+ const execute = async (endpoint, body) => {
1626
+ const token = options.customerToken();
1627
+ try {
1628
+ const response = await httpFetch(endpoint, {
1629
+ method: "POST",
1630
+ publishableKey: options.publishableKey,
1631
+ customerToken: token ?? void 0,
1632
+ ...token && options.onUnauthorized && { onUnauthorized: options.onUnauthorized },
1633
+ body: JSON.stringify(body)
1634
+ });
1635
+ options.onRequestId?.(response.headers.get("x-request-id") ?? null);
1636
+ return parseApiResponse(response, endpoint);
1637
+ } catch (err) {
1638
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
1639
+ options.onRequestId?.(id);
1640
+ throw err;
1641
+ }
1642
+ };
1643
+ this.product = {
1644
+ stockCheck: (params) => execute("/api/products/stock-check", params),
1645
+ listingGroups: (params) => execute("/api/products/listing-groups", params)
1646
+ };
1647
+ this.cart = {
1648
+ get: cartApi.getCart.bind(cartApi),
1649
+ addItem: cartApi.addItem.bind(cartApi),
1650
+ updateItem: cartApi.updateItem.bind(cartApi),
1651
+ removeItem: cartApi.removeItem.bind(cartApi),
1652
+ applyDiscount: cartApi.applyDiscount.bind(cartApi),
1653
+ removeDiscount: cartApi.removeDiscount.bind(cartApi),
1654
+ clear: cartApi.clearCart.bind(cartApi)
1655
+ };
1656
+ this.orders = {
1657
+ checkout: (params) => execute("/api/orders/checkout", params),
1658
+ listMine: (params) => options.customerAuth.getMyOrders(params)
1659
+ };
1660
+ this.discounts = {
1661
+ validate: (params) => execute("/api/discounts/validate", params)
1662
+ };
1663
+ this.shipping = {
1664
+ calculate: (params) => execute("/api/shipping-policies/calculate", params)
1665
+ };
1666
+ }
1667
+ };
1668
+
1669
+ // src/core/api/product-api.ts
1670
+ var ProductApi = class extends BaseApi {
1671
+ constructor(options) {
1672
+ super("ProductApi", options);
1673
+ }
1674
+ /**
1675
+ * Check point-in-time stock availability for one or more product variants.
1676
+ * Results reflect available stock at the moment of the call and are not guaranteed
1677
+ * to remain available by the time an order is placed.
1678
+ */
1679
+ stockCheck(params) {
1680
+ return this.request("/api/products/stock-check", params);
1681
+ }
1682
+ listingGroups(params) {
1683
+ return this.request(
1684
+ "/api/products/listing-groups",
1685
+ params
1686
+ );
1687
+ }
1688
+ };
1689
+
1690
+ // src/core/api/discount-api.ts
1691
+ var DiscountApi = class extends BaseApi {
1692
+ constructor(options) {
1693
+ super("DiscountApi", options);
1694
+ }
1695
+ validate(params) {
1696
+ return this.request("/api/discounts/validate", params);
1697
+ }
1698
+ };
1699
+
1700
+ // src/core/api/shipping-api.ts
1701
+ var ShippingApi = class extends BaseApi {
1702
+ constructor(options) {
1703
+ super("ShippingApi", options);
1704
+ }
1705
+ calculate(params) {
1706
+ return this.request("/api/shipping-policies/calculate", params);
1707
+ }
1708
+ };
1709
+
1710
+ // src/core/api/order-api.ts
1711
+ var OrderApi = class extends BaseApi {
1712
+ constructor(options) {
1713
+ super("OrderApi", options);
1714
+ }
1715
+ createOrder(params) {
1716
+ return this.request("/api/orders/create", params);
1717
+ }
1718
+ updateOrder(params) {
1719
+ return this.request("/api/orders/update", params);
1720
+ }
1721
+ updateTransaction(params) {
1722
+ return this.request("/api/transactions/update", params);
1723
+ }
1724
+ checkout(params) {
1725
+ return this.request("/api/orders/checkout", params);
1726
+ }
1727
+ createFulfillment(params) {
1728
+ return this.request("/api/orders/create-fulfillment", params);
1729
+ }
1730
+ updateFulfillment(params) {
1731
+ return this.request("/api/orders/update-fulfillment", params);
1732
+ }
1733
+ bulkImportFulfillments(params) {
1734
+ return this.request(
1735
+ "/api/orders/bulk-import-fulfillments",
1736
+ params
1737
+ );
1738
+ }
1739
+ returnWithRefund(params) {
1740
+ return this.request(
1741
+ "/api/returns/return-refund",
1742
+ params
1743
+ );
1744
+ }
1745
+ createReturn(params) {
1746
+ return this.request("/api/returns/create", params);
1747
+ }
1748
+ updateReturn(params) {
1749
+ return this.request("/api/returns/update", params);
1750
+ }
1751
+ };
1752
+
1753
+ // src/core/commerce/server-commerce-client.ts
1754
+ var ServerCommerceClient = class {
1755
+ constructor(options) {
1756
+ const serverOptions = {
1757
+ publishableKey: options.publishableKey,
1758
+ secretKey: options.secretKey,
1759
+ tenantId: options.tenantId,
1760
+ onRequestId: options.onRequestId
1761
+ };
1762
+ const productApi = new ProductApi(serverOptions);
1763
+ const cartApi = new CartApi(serverOptions);
1764
+ const discountApi = new DiscountApi(serverOptions);
1765
+ const shippingApi = new ShippingApi(serverOptions);
1766
+ const orderApi = new OrderApi(serverOptions);
1767
+ this.product = {
1768
+ stockCheck: productApi.stockCheck.bind(productApi),
1769
+ listingGroups: productApi.listingGroups.bind(productApi)
1770
+ };
1771
+ this.cart = {
1772
+ get: cartApi.getCart.bind(cartApi),
1773
+ addItem: cartApi.addItem.bind(cartApi),
1774
+ updateItem: cartApi.updateItem.bind(cartApi),
1775
+ removeItem: cartApi.removeItem.bind(cartApi),
1776
+ applyDiscount: cartApi.applyDiscount.bind(cartApi),
1777
+ removeDiscount: cartApi.removeDiscount.bind(cartApi),
1778
+ clear: cartApi.clearCart.bind(cartApi)
1779
+ };
1780
+ this.orders = {
1781
+ checkout: orderApi.checkout.bind(orderApi),
1782
+ create: orderApi.createOrder.bind(orderApi),
1783
+ update: orderApi.updateOrder.bind(orderApi),
1784
+ updateTransaction: orderApi.updateTransaction.bind(orderApi),
1785
+ createFulfillment: orderApi.createFulfillment.bind(orderApi),
1786
+ updateFulfillment: orderApi.updateFulfillment.bind(orderApi),
1787
+ bulkImportFulfillments: orderApi.bulkImportFulfillments.bind(orderApi),
1788
+ createReturn: orderApi.createReturn.bind(orderApi),
1789
+ updateReturn: orderApi.updateReturn.bind(orderApi),
1790
+ returnWithRefund: orderApi.returnWithRefund.bind(orderApi)
1791
+ };
1792
+ this.discounts = {
1793
+ validate: discountApi.validate.bind(discountApi)
1794
+ };
1795
+ this.shipping = {
1796
+ calculate: shippingApi.calculate.bind(shippingApi)
1797
+ };
1798
+ }
1799
+ };
1800
+
1541
1801
  // src/core/query/get-query-client.ts
1542
1802
  import {
1543
1803
  isServer,
@@ -2083,6 +2343,7 @@ var QueryHooks = class extends CollectionHooks {
2083
2343
  // src/core/client/client.ts
2084
2344
  var Client = class {
2085
2345
  constructor(options) {
2346
+ this.lastRequestId = null;
2086
2347
  const publishableKey = options.publishableKey;
2087
2348
  if (!publishableKey) {
2088
2349
  throw createConfigError("publishableKey is required.");
@@ -2094,43 +2355,47 @@ var Client = class {
2094
2355
  };
2095
2356
  this.state = { metadata };
2096
2357
  this.queryClient = getQueryClient();
2097
- this.customer = new CustomerAuth(
2358
+ this.customer = new CustomerNamespace(
2098
2359
  this.config.publishableKey,
2099
2360
  options.customer
2100
2361
  );
2101
2362
  const onUnauthorized = async () => {
2102
2363
  try {
2103
- const result = await this.customer.refreshToken();
2364
+ const result = await this.customer.auth.refreshToken();
2104
2365
  return result.token ?? null;
2105
2366
  } catch {
2106
2367
  return null;
2107
2368
  }
2108
2369
  };
2109
- this.cart = new CartApi({
2370
+ const onRequestId = (id) => {
2371
+ this.lastRequestId = id;
2372
+ };
2373
+ this.commerce = new CommerceClient({
2110
2374
  publishableKey: this.config.publishableKey,
2111
- customerToken: () => this.customer.getToken(),
2112
- onUnauthorized
2375
+ customerToken: () => this.customer.auth.getToken(),
2376
+ onUnauthorized,
2377
+ onRequestId,
2378
+ customerAuth: this.customer.auth
2113
2379
  });
2114
2380
  this.community = new CommunityClient({
2115
2381
  publishableKey: this.config.publishableKey,
2116
- customerToken: () => this.customer.getToken(),
2117
- onUnauthorized
2382
+ customerToken: () => this.customer.auth.getToken(),
2383
+ onUnauthorized,
2384
+ onRequestId
2118
2385
  });
2119
2386
  this.collections = new CollectionClient(
2120
2387
  this.config.publishableKey,
2121
2388
  void 0,
2122
- () => this.customer.getToken(),
2123
- onUnauthorized
2389
+ () => this.customer.auth.getToken(),
2390
+ onUnauthorized,
2391
+ onRequestId
2124
2392
  );
2125
2393
  this.query = new QueryHooks(
2126
2394
  this.queryClient,
2127
2395
  this.collections,
2128
- this.customer
2396
+ this.customer.auth
2129
2397
  );
2130
2398
  }
2131
- from(collection) {
2132
- return this.collections.from(collection);
2133
- }
2134
2399
  getState() {
2135
2400
  return { ...this.state };
2136
2401
  }
@@ -2145,6 +2410,7 @@ function createClient(options) {
2145
2410
  // src/core/client/client.server.ts
2146
2411
  var ServerClient = class {
2147
2412
  constructor(options) {
2413
+ this.lastRequestId = null;
2148
2414
  if (typeof window !== "undefined") {
2149
2415
  throw createConfigError(
2150
2416
  "ServerClient must not be used in a browser environment. This risks exposing your secretKey in client bundles. Use createClient() for browser code instead."
@@ -2164,32 +2430,35 @@ var ServerClient = class {
2164
2430
  userAgent: "Node.js"
2165
2431
  };
2166
2432
  this.state = { metadata };
2167
- this.api = new OrderApi({
2168
- publishableKey: this.config.publishableKey,
2169
- secretKey: this.config.secretKey
2170
- });
2171
- this.cart = new CartApi({
2172
- publishableKey: this.config.publishableKey,
2173
- secretKey: this.config.secretKey
2174
- });
2175
- this.community = new CommunityClient({
2176
- publishableKey: this.config.publishableKey,
2177
- secretKey: this.config.secretKey
2178
- });
2179
- this.product = new ProductApi({
2433
+ const onRequestId = (id) => {
2434
+ this.lastRequestId = id;
2435
+ };
2436
+ const serverOptions = {
2180
2437
  publishableKey: this.config.publishableKey,
2181
- secretKey: this.config.secretKey
2438
+ secretKey: this.config.secretKey,
2439
+ tenantId: this.config.tenantId,
2440
+ onRequestId
2441
+ };
2442
+ this.commerce = new ServerCommerceClient(serverOptions);
2443
+ const communityClient = new CommunityClient(serverOptions);
2444
+ const moderationApi = new ModerationApi(serverOptions);
2445
+ this.community = Object.assign(communityClient, {
2446
+ moderation: {
2447
+ banCustomer: moderationApi.banCustomer.bind(moderationApi),
2448
+ unbanCustomer: moderationApi.unbanCustomer.bind(moderationApi)
2449
+ }
2182
2450
  });
2183
2451
  this.collections = new CollectionClient(
2184
2452
  this.config.publishableKey,
2185
- this.config.secretKey
2453
+ this.config.secretKey,
2454
+ void 0,
2455
+ void 0,
2456
+ onRequestId,
2457
+ this.config.tenantId
2186
2458
  );
2187
2459
  this.queryClient = getQueryClient();
2188
2460
  this.query = new QueryHooks(this.queryClient, this.collections);
2189
2461
  }
2190
- from(collection) {
2191
- return this.collections.from(collection);
2192
- }
2193
2462
  getState() {
2194
2463
  return { ...this.state };
2195
2464
  }
@@ -2766,8 +3035,179 @@ function getVideoStreamUrl(playbackId) {
2766
3035
  function getVideoMp4Url(playbackId, resolution = "high") {
2767
3036
  return `${MUX_STREAM_BASE}/${playbackId}/${resolution}.mp4`;
2768
3037
  }
3038
+
3039
+ // src/analytics.ts
3040
+ function createAnalytics(config) {
3041
+ if (typeof window === "undefined") {
3042
+ return { pageview() {
3043
+ }, track() {
3044
+ }, destroy() {
3045
+ } };
3046
+ }
3047
+ const endpoint = config.endpoint ?? `${resolveApiUrl()}/api/analytics/collect`;
3048
+ const respectDnt = config.respectDnt !== false;
3049
+ function isDntActive() {
3050
+ if (!respectDnt) return false;
3051
+ const nav = navigator;
3052
+ return nav.doNotTrack === "1" || nav.globalPrivacyControl === true;
3053
+ }
3054
+ let lastPath = null;
3055
+ let lastAt = 0;
3056
+ const autoTrack = config.autoTrack !== false;
3057
+ const originalPushState = history.pushState;
3058
+ const originalReplaceState = history.replaceState;
3059
+ let destroyed = false;
3060
+ function newEventId() {
3061
+ return typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : String(Date.now()) + String(Math.random());
3062
+ }
3063
+ function sendBeaconOrFetch(body) {
3064
+ try {
3065
+ if (typeof navigator.sendBeacon === "function") {
3066
+ const blob = new Blob([body], { type: "text/plain" });
3067
+ const sent = navigator.sendBeacon(endpoint, blob);
3068
+ if (sent) return;
3069
+ }
3070
+ fetch(endpoint, {
3071
+ method: "POST",
3072
+ keepalive: true,
3073
+ headers: { "Content-Type": "application/json" },
3074
+ body
3075
+ }).catch(() => {
3076
+ });
3077
+ } catch {
3078
+ }
3079
+ }
3080
+ function sendPageview(pathname) {
3081
+ if (isDntActive()) return;
3082
+ const doc = document;
3083
+ if (doc.prerendering === true || document.visibilityState === "prerender") return;
3084
+ const now = Date.now();
3085
+ if (pathname === lastPath && now - lastAt < 500) return;
3086
+ lastPath = pathname;
3087
+ lastAt = now;
3088
+ const body = JSON.stringify({
3089
+ publishableKey: config.publishableKey,
3090
+ pathname,
3091
+ referrer: document.referrer || "",
3092
+ eventId: newEventId()
3093
+ });
3094
+ sendBeaconOrFetch(body);
3095
+ }
3096
+ function trackCurrentPath() {
3097
+ if (destroyed) return;
3098
+ sendPageview(location.pathname);
3099
+ }
3100
+ function patchedPushState(data, unused, url) {
3101
+ originalPushState.apply(this, [data, unused, url]);
3102
+ if (!destroyed) setTimeout(trackCurrentPath, 0);
3103
+ }
3104
+ function patchedReplaceState(data, unused, url) {
3105
+ originalReplaceState.apply(this, [data, unused, url]);
3106
+ if (!destroyed) setTimeout(trackCurrentPath, 0);
3107
+ }
3108
+ if (autoTrack) {
3109
+ history.pushState = patchedPushState;
3110
+ history.replaceState = patchedReplaceState;
3111
+ window.addEventListener("popstate", trackCurrentPath);
3112
+ if (document.readyState === "complete") {
3113
+ trackCurrentPath();
3114
+ } else {
3115
+ window.addEventListener("load", trackCurrentPath, { once: true });
3116
+ }
3117
+ }
3118
+ const isProduction = (() => {
3119
+ try {
3120
+ const hostname = location.hostname;
3121
+ return hostname !== "localhost" && hostname !== "127.0.0.1" && !hostname.endsWith(".local");
3122
+ } catch {
3123
+ return true;
3124
+ }
3125
+ })();
3126
+ const warnedReasons = /* @__PURE__ */ new Set();
3127
+ function devWarn(name, reason) {
3128
+ if (isProduction) return;
3129
+ if (warnedReasons.has(reason)) return;
3130
+ warnedReasons.add(reason);
3131
+ console.warn(`[01 analytics] dropped event ${name}: ${reason}`);
3132
+ }
3133
+ const EVENT_NAME_RE = /^[a-zA-Z][a-zA-Z0-9_:-]{0,49}$/;
3134
+ const RESERVED_PREFIXES = ["__", "_pv_"];
3135
+ function validateEventName(name) {
3136
+ if (!name || typeof name !== "string") return "name-empty";
3137
+ for (const prefix of RESERVED_PREFIXES) {
3138
+ if (name.startsWith(prefix)) return "name-reserved";
3139
+ }
3140
+ if (!EVENT_NAME_RE.test(name)) return "name-regex";
3141
+ return null;
3142
+ }
3143
+ const PROP_KEY_RE = /^[a-zA-Z_][a-zA-Z0-9_]{0,31}$/;
3144
+ function validateEventProps(props) {
3145
+ if (props === void 0 || props === null) return null;
3146
+ if (typeof props !== "object" || Array.isArray(props)) return "props-value-type";
3147
+ const keys = Object.keys(props);
3148
+ if (keys.length > 10) return "props-too-many-keys";
3149
+ for (const k of keys) {
3150
+ const v = props[k];
3151
+ if (!PROP_KEY_RE.test(k)) return "props-key-regex";
3152
+ if (typeof v === "string") {
3153
+ if (v.length > 80) return "props-value-too-long";
3154
+ } else if (typeof v === "number") {
3155
+ if (!isFinite(v)) return "props-value-not-finite";
3156
+ } else if (typeof v === "boolean") {
3157
+ } else {
3158
+ return "props-value-type";
3159
+ }
3160
+ }
3161
+ return null;
3162
+ }
3163
+ return {
3164
+ pageview(path) {
3165
+ if (destroyed) return;
3166
+ sendPageview(path ?? location.pathname);
3167
+ },
3168
+ track(name, props) {
3169
+ if (destroyed) return;
3170
+ if (isDntActive()) return;
3171
+ const doc = document;
3172
+ if (doc.prerendering === true || document.visibilityState === "prerender") return;
3173
+ const nameErr = validateEventName(name);
3174
+ if (nameErr) {
3175
+ devWarn(name, nameErr);
3176
+ return;
3177
+ }
3178
+ if (props !== void 0) {
3179
+ const propsErr = validateEventProps(props);
3180
+ if (propsErr) {
3181
+ devWarn(name, propsErr);
3182
+ return;
3183
+ }
3184
+ }
3185
+ const body = JSON.stringify({
3186
+ publishableKey: config.publishableKey,
3187
+ pathname: location.pathname,
3188
+ referrer: document.referrer || "",
3189
+ eventId: newEventId(),
3190
+ eventName: name,
3191
+ eventProps: props
3192
+ });
3193
+ sendBeaconOrFetch(body);
3194
+ },
3195
+ destroy() {
3196
+ if (destroyed) return;
3197
+ destroyed = true;
3198
+ if (autoTrack) {
3199
+ history.pushState = originalPushState;
3200
+ history.replaceState = originalReplaceState;
3201
+ window.removeEventListener("popstate", trackCurrentPath);
3202
+ }
3203
+ lastPath = null;
3204
+ lastAt = 0;
3205
+ }
3206
+ };
3207
+ }
2769
3208
  export {
2770
3209
  ApiError,
3210
+ AuthError,
2771
3211
  BaseApi,
2772
3212
  COLLECTIONS,
2773
3213
  CartApi,
@@ -2775,20 +3215,30 @@ export {
2775
3215
  CollectionClient,
2776
3216
  CollectionHooks,
2777
3217
  CollectionQueryBuilder,
3218
+ CommerceClient,
2778
3219
  CommunityClient,
2779
3220
  ConfigError,
3221
+ ConflictError,
2780
3222
  CustomerAuth,
2781
3223
  CustomerHooks,
3224
+ CustomerNamespace,
3225
+ DiscountApi,
2782
3226
  GoneError,
2783
3227
  IMAGE_SIZES,
3228
+ ModerationApi,
2784
3229
  NetworkError,
3230
+ NotFoundError,
2785
3231
  OrderApi,
3232
+ PermissionError,
2786
3233
  ProductApi,
2787
3234
  QueryHooks,
3235
+ RateLimitError,
2788
3236
  RealtimeConnection,
2789
3237
  SDKError,
2790
3238
  ServerClient,
3239
+ ServerCommerceClient,
2791
3240
  ServiceUnavailableError,
3241
+ ShippingApi,
2792
3242
  TimeoutError,
2793
3243
  UsageLimitError,
2794
3244
  ValidationError,
@@ -2796,7 +3246,13 @@ export {
2796
3246
  buildProductListingProjection,
2797
3247
  buildProductOptionMatrix,
2798
3248
  collectionKeys,
3249
+ createAnalytics,
3250
+ createAuthError,
2799
3251
  createClient,
3252
+ createConflictError,
3253
+ createNotFoundError,
3254
+ createPermissionError,
3255
+ createRateLimitError,
2800
3256
  createServerClient,
2801
3257
  createTypedWebhookHandler,
2802
3258
  customerKeys,
@@ -2817,9 +3273,14 @@ export {
2817
3273
  getVideoThumbnail,
2818
3274
  handleWebhook,
2819
3275
  isApiError,
3276
+ isAuthError,
2820
3277
  isConfigError,
3278
+ isConflictError,
2821
3279
  isGoneError,
2822
3280
  isNetworkError,
3281
+ isNotFoundError,
3282
+ isPermissionError,
3283
+ isRateLimitError,
2823
3284
  isSDKError,
2824
3285
  isServiceUnavailableError,
2825
3286
  isTimeoutError,