@01.software/sdk 0.29.0 → 0.31.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 (78) hide show
  1. package/README.md +331 -77
  2. package/dist/analytics/react.cjs +4 -1
  3. package/dist/analytics/react.cjs.map +1 -1
  4. package/dist/analytics/react.js +4 -1
  5. package/dist/analytics/react.js.map +1 -1
  6. package/dist/analytics.cjs +4 -1
  7. package/dist/analytics.cjs.map +1 -1
  8. package/dist/analytics.js +4 -1
  9. package/dist/analytics.js.map +1 -1
  10. package/dist/client.cjs +1541 -0
  11. package/dist/client.cjs.map +1 -0
  12. package/dist/client.d.cts +28 -0
  13. package/dist/client.d.ts +28 -0
  14. package/dist/client.js +1518 -0
  15. package/dist/client.js.map +1 -0
  16. package/dist/collection-client-ByzY3hWK.d.ts +218 -0
  17. package/dist/collection-client-DFXXz0vk.d.cts +218 -0
  18. package/dist/{const-DAjQYNuM.d.ts → const-AytzliEu.d.cts} +5 -7
  19. package/dist/{const-Dsixdi6z.d.cts → const-BGCP-OJL.d.ts} +5 -7
  20. package/dist/index-BGEhoDUs.d.cts +106 -0
  21. package/dist/index-BGEhoDUs.d.ts +106 -0
  22. package/dist/index.cjs +1006 -1615
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +11 -115
  25. package/dist/index.d.ts +11 -115
  26. package/dist/index.js +932 -1559
  27. package/dist/index.js.map +1 -1
  28. package/dist/metadata.cjs +91 -0
  29. package/dist/metadata.cjs.map +1 -0
  30. package/dist/metadata.d.cts +58 -0
  31. package/dist/metadata.d.ts +58 -0
  32. package/dist/metadata.js +68 -0
  33. package/dist/metadata.js.map +1 -0
  34. package/dist/{payload-types-Ci-ZA7aM.d.cts → payload-types-Wa4-eC6x.d.cts} +794 -532
  35. package/dist/{payload-types-Ci-ZA7aM.d.ts → payload-types-Wa4-eC6x.d.ts} +794 -532
  36. package/dist/query.cjs +1841 -0
  37. package/dist/query.cjs.map +1 -0
  38. package/dist/query.d.cts +244 -0
  39. package/dist/query.d.ts +244 -0
  40. package/dist/query.js +1836 -0
  41. package/dist/query.js.map +1 -0
  42. package/dist/realtime.cjs +4 -1
  43. package/dist/realtime.cjs.map +1 -1
  44. package/dist/realtime.d.cts +2 -2
  45. package/dist/realtime.d.ts +2 -2
  46. package/dist/realtime.js +4 -1
  47. package/dist/realtime.js.map +1 -1
  48. package/dist/{server-BINWywT8.d.cts → server-CrsPyqEc.d.cts} +14 -31
  49. package/dist/{server-BINWywT8.d.ts → server-CrsPyqEc.d.ts} +14 -31
  50. package/dist/server.cjs +430 -846
  51. package/dist/server.cjs.map +1 -1
  52. package/dist/server.d.cts +137 -7
  53. package/dist/server.d.ts +137 -7
  54. package/dist/server.js +430 -864
  55. package/dist/server.js.map +1 -1
  56. package/dist/{server-Cv0Q4dPQ.d.ts → types-BX2mqDf6.d.ts} +270 -743
  57. package/dist/{types-BWq_WlbB.d.ts → types-CVA10VC-.d.ts} +6 -2
  58. package/dist/{types-zKjATmDK.d.cts → types-CmLG-7RL.d.cts} +6 -2
  59. package/dist/{server-C0C8dtms.d.cts → types-DChFjQGz.d.cts} +270 -743
  60. package/dist/ui/canvas/server.cjs +7 -6
  61. package/dist/ui/canvas/server.cjs.map +1 -1
  62. package/dist/ui/canvas/server.d.cts +1 -3
  63. package/dist/ui/canvas/server.d.ts +1 -3
  64. package/dist/ui/canvas/server.js +7 -6
  65. package/dist/ui/canvas/server.js.map +1 -1
  66. package/dist/ui/canvas.cjs +11 -10
  67. package/dist/ui/canvas.cjs.map +1 -1
  68. package/dist/ui/canvas.d.cts +29 -6
  69. package/dist/ui/canvas.d.ts +29 -6
  70. package/dist/ui/canvas.js +11 -10
  71. package/dist/ui/canvas.js.map +1 -1
  72. package/dist/ui/form.d.cts +1 -1
  73. package/dist/ui/form.d.ts +1 -1
  74. package/dist/ui/video.d.cts +1 -1
  75. package/dist/ui/video.d.ts +1 -1
  76. package/dist/webhook.d.cts +3 -3
  77. package/dist/webhook.d.ts +3 -3
  78. package/package.json +84 -15
package/dist/server.cjs CHANGED
@@ -26,209 +26,11 @@ __export(server_exports, {
26
26
  ServerClient: () => ServerClient,
27
27
  ServerCollectionClient: () => ServerCollectionClient,
28
28
  ServerCommerceClient: () => ServerCommerceClient,
29
+ ServerPreviewClient: () => ServerPreviewClient,
29
30
  createServerClient: () => createServerClient
30
31
  });
31
32
  module.exports = __toCommonJS(server_exports);
32
33
 
33
- // src/utils/types.ts
34
- var resolveRelation = (ref) => {
35
- if (typeof ref === "string" || typeof ref === "number" || ref === null || ref === void 0)
36
- return null;
37
- return ref;
38
- };
39
-
40
- // src/core/metadata/index.ts
41
- function extractSeo(doc) {
42
- const seo = doc.seo ?? {};
43
- const og = seo.openGraph ?? {};
44
- return {
45
- title: seo.title ?? doc.title ?? null,
46
- description: seo.description ?? null,
47
- noIndex: seo.noIndex ?? null,
48
- canonical: seo.canonical ?? null,
49
- openGraph: {
50
- title: og.title ?? null,
51
- description: og.description ?? null,
52
- image: og.image ?? null
53
- }
54
- };
55
- }
56
- function generateMetadata(input, options) {
57
- const title = input.title ?? void 0;
58
- const description = input.description ?? void 0;
59
- const ogTitle = input.openGraph?.title ?? title;
60
- const ogDescription = input.openGraph?.description ?? description;
61
- const image = resolveMetaImage(input.openGraph?.image);
62
- return {
63
- title,
64
- description,
65
- ...input.noIndex && { robots: { index: false, follow: false } },
66
- ...input.canonical && { alternates: { canonical: input.canonical } },
67
- openGraph: {
68
- ...ogTitle && { title: ogTitle },
69
- ...ogDescription && { description: ogDescription },
70
- ...options?.siteName && { siteName: options.siteName },
71
- ...image && { images: [image] }
72
- },
73
- twitter: {
74
- card: image ? "summary_large_image" : "summary",
75
- ...ogTitle && { title: ogTitle },
76
- ...ogDescription && { description: ogDescription },
77
- ...image && { images: [image.url] }
78
- }
79
- };
80
- }
81
- function resolveMetaImage(ref) {
82
- const image = resolveRelation(ref);
83
- if (!image) return null;
84
- const sized = image.sizes?.["1536"];
85
- const url = sized?.url || image.url;
86
- if (!url) return null;
87
- const width = sized?.url ? sized.width : image.width;
88
- const height = sized?.url ? sized.height : image.height;
89
- return {
90
- url,
91
- ...width && { width },
92
- ...height && { height },
93
- ...image.alt && { alt: image.alt }
94
- };
95
- }
96
-
97
- // src/core/collection/query-builder.ts
98
- var CollectionQueryBuilder = class {
99
- constructor(api, collection) {
100
- this.api = api;
101
- this.collection = collection;
102
- }
103
- /**
104
- * Find documents (list query)
105
- * GET /api/{collection}
106
- * @returns Payload CMS find response with docs array and pagination
107
- */
108
- async find(options) {
109
- return this.api.requestFind(
110
- `/api/${String(this.collection)}`,
111
- options
112
- );
113
- }
114
- /**
115
- * Find document by ID
116
- * GET /api/{collection}/{id}
117
- * @returns Document object directly (no wrapper)
118
- */
119
- async findById(id, options) {
120
- return this.api.requestFindById(
121
- `/api/${String(this.collection)}/${String(id)}`,
122
- options
123
- );
124
- }
125
- /**
126
- * Create a new document
127
- * POST /api/{collection}
128
- * @returns Payload CMS mutation response with doc and message
129
- */
130
- async create(data, options) {
131
- const endpoint = `/api/${String(this.collection)}`;
132
- if (options?.file) {
133
- return this.api.requestCreateWithFile(
134
- endpoint,
135
- data,
136
- options.file,
137
- options.filename
138
- );
139
- }
140
- return this.api.requestCreate(endpoint, data);
141
- }
142
- /**
143
- * Update a document by ID
144
- * PATCH /api/{collection}/{id}
145
- * @returns Payload CMS mutation response with doc and message
146
- */
147
- async update(id, data, options) {
148
- const endpoint = `/api/${String(this.collection)}/${String(id)}`;
149
- if (options?.file) {
150
- return this.api.requestUpdateWithFile(
151
- endpoint,
152
- data,
153
- options.file,
154
- options.filename
155
- );
156
- }
157
- return this.api.requestUpdate(endpoint, data);
158
- }
159
- /**
160
- * Count documents
161
- * GET /api/{collection}/count
162
- * @returns Count response with totalDocs
163
- */
164
- async count(options) {
165
- return this.api.requestCount(
166
- `/api/${String(this.collection)}/count`,
167
- options
168
- );
169
- }
170
- /**
171
- * Find first matching document and return its Next.js Metadata.
172
- * Applies depth: 1 (SEO image populate) and limit: 1 automatically.
173
- * @returns Metadata or null if no document matches
174
- */
175
- async findMetadata(options, metadataOptions) {
176
- const { docs } = await this.find({ ...options, limit: 1, depth: 1 });
177
- const doc = docs[0];
178
- if (!doc) return null;
179
- return generateMetadata(
180
- extractSeo(doc),
181
- metadataOptions
182
- );
183
- }
184
- /**
185
- * Find document by ID and return its Next.js Metadata.
186
- * Applies depth: 1 (SEO image populate) automatically.
187
- * @returns Metadata (throws on 404)
188
- */
189
- async findMetadataById(id, metadataOptions) {
190
- const doc = await this.findById(id, { depth: 1 });
191
- return generateMetadata(
192
- extractSeo(doc),
193
- metadataOptions
194
- );
195
- }
196
- /**
197
- * Update multiple documents (bulk update)
198
- * PATCH /api/{collection}
199
- * @returns Payload CMS find response with updated docs
200
- */
201
- async updateMany(where, data) {
202
- return this.api.requestUpdateMany(
203
- `/api/${String(this.collection)}`,
204
- { where, data }
205
- );
206
- }
207
- /**
208
- * Delete a document by ID
209
- * DELETE /api/{collection}/{id}
210
- * @returns Deleted document object directly (no wrapper)
211
- */
212
- async remove(id) {
213
- return this.api.requestDelete(
214
- `/api/${String(this.collection)}/${String(id)}`
215
- );
216
- }
217
- /**
218
- * Delete multiple documents (bulk delete)
219
- * DELETE /api/{collection}
220
- * @returns Payload CMS find response with deleted docs
221
- */
222
- async removeMany(where) {
223
- return this.api.requestDeleteMany(
224
- `/api/${String(this.collection)}`,
225
- { where }
226
- );
227
- }
228
- };
229
- var ServerCollectionQueryBuilder = class extends CollectionQueryBuilder {
230
- };
231
-
232
34
  // src/core/collection/http-client.ts
233
35
  var import_qs_esm = require("qs-esm");
234
36
 
@@ -276,8 +78,16 @@ var ValidationError = class extends SDKError {
276
78
  }
277
79
  };
278
80
  var ApiError = class extends SDKError {
279
- constructor(message, status, details, userMessage, suggestion) {
280
- super("API_ERROR", message, status, details, userMessage, suggestion);
81
+ constructor(message, status, details, userMessage, suggestion, requestId) {
82
+ super(
83
+ "API_ERROR",
84
+ message,
85
+ status,
86
+ details,
87
+ userMessage,
88
+ suggestion,
89
+ requestId
90
+ );
281
91
  this.name = "ApiError";
282
92
  }
283
93
  };
@@ -308,19 +118,43 @@ var UsageLimitError = class extends SDKError {
308
118
  };
309
119
  var AuthError = class extends SDKError {
310
120
  constructor(message, details, userMessage, suggestion, requestId) {
311
- super("auth_error", message, 401, details, userMessage, suggestion, requestId);
121
+ super(
122
+ "auth_error",
123
+ message,
124
+ 401,
125
+ details,
126
+ userMessage,
127
+ suggestion,
128
+ requestId
129
+ );
312
130
  this.name = "AuthError";
313
131
  }
314
132
  };
315
133
  var PermissionError = class extends SDKError {
316
134
  constructor(message, details, userMessage, suggestion, requestId) {
317
- super("permission_error", message, 403, details, userMessage, suggestion, requestId);
135
+ super(
136
+ "permission_error",
137
+ message,
138
+ 403,
139
+ details,
140
+ userMessage,
141
+ suggestion,
142
+ requestId
143
+ );
318
144
  this.name = "PermissionError";
319
145
  }
320
146
  };
321
147
  var NotFoundError = class extends SDKError {
322
148
  constructor(message, details, userMessage, suggestion, requestId) {
323
- super("not_found", message, 404, details, userMessage, suggestion, requestId);
149
+ super(
150
+ "not_found",
151
+ message,
152
+ 404,
153
+ details,
154
+ userMessage,
155
+ suggestion,
156
+ requestId
157
+ );
324
158
  this.name = "NotFoundError";
325
159
  }
326
160
  };
@@ -332,14 +166,22 @@ var ConflictError = class extends SDKError {
332
166
  };
333
167
  var RateLimitError = class extends SDKError {
334
168
  constructor(message, retryAfter, details, userMessage, suggestion, requestId) {
335
- super("rate_limit_exceeded", message, 429, details, userMessage, suggestion, requestId);
169
+ super(
170
+ "rate_limit_exceeded",
171
+ message,
172
+ 429,
173
+ details,
174
+ userMessage,
175
+ suggestion,
176
+ requestId
177
+ );
336
178
  this.name = "RateLimitError";
337
179
  this.retryAfter = retryAfter;
338
180
  }
339
181
  };
340
182
  var createNetworkError = (message, status, details, userMessage, suggestion) => new NetworkError(message, status, details, userMessage, suggestion);
341
183
  var createValidationError = (message, details, userMessage, suggestion, status) => new ValidationError(message, details, userMessage, suggestion, status);
342
- var createApiError = (message, status, details, userMessage, suggestion) => new ApiError(message, status, details, userMessage, suggestion);
184
+ var createApiError = (message, status, details, userMessage, suggestion, requestId) => new ApiError(message, status, details, userMessage, suggestion, requestId);
343
185
  var createConfigError = (message, details, userMessage, suggestion) => new ConfigError(message, details, userMessage, suggestion);
344
186
  var createTimeoutError = (message, details, userMessage, suggestion) => new TimeoutError(message, details, userMessage, suggestion);
345
187
  var createUsageLimitError = (message, usage, details, userMessage, suggestion) => new UsageLimitError(message, usage, details, userMessage, suggestion);
@@ -347,7 +189,14 @@ var createAuthError = (message, details, userMessage, suggestion, requestId) =>
347
189
  var createPermissionError = (message, details, userMessage, suggestion, requestId) => new PermissionError(message, details, userMessage, suggestion, requestId);
348
190
  var createNotFoundError = (message, details, userMessage, suggestion, requestId) => new NotFoundError(message, details, userMessage, suggestion, requestId);
349
191
  var createConflictError = (message, details, userMessage, suggestion, requestId) => new ConflictError(message, details, userMessage, suggestion, requestId);
350
- var createRateLimitError = (message, retryAfter, details, userMessage, suggestion, requestId) => new RateLimitError(message, retryAfter, details, userMessage, suggestion, requestId);
192
+ var createRateLimitError = (message, retryAfter, details, userMessage, suggestion, requestId) => new RateLimitError(
193
+ message,
194
+ retryAfter,
195
+ details,
196
+ userMessage,
197
+ suggestion,
198
+ requestId
199
+ );
351
200
 
352
201
  // src/core/internal/utils/credentials.ts
353
202
  function requirePublishableKeyForSecret(apiName, publishableKey, secretKey) {
@@ -360,7 +209,10 @@ function requirePublishableKeyForSecret(apiName, publishableKey, secretKey) {
360
209
  }
361
210
 
362
211
  // src/core/client/types.ts
363
- function resolveApiUrl() {
212
+ function resolveApiUrl(apiUrl) {
213
+ if (apiUrl) {
214
+ return apiUrl.replace(/\/$/, "");
215
+ }
364
216
  if (typeof process !== "undefined" && process.env) {
365
217
  const envUrl = process.env.SOFTWARE_API_URL || process.env.NEXT_PUBLIC_SOFTWARE_API_URL;
366
218
  if (envUrl) {
@@ -384,6 +236,22 @@ function debugLog(debug, type, message, data) {
384
236
  console.groupEnd();
385
237
  }
386
238
  }
239
+ function redactSensitiveHeader(value) {
240
+ const prefix = value.toLowerCase().startsWith("bearer ") ? "Bearer " : "";
241
+ return value.length > 20 ? `${prefix}...****${value.slice(-8)}` : "****";
242
+ }
243
+ function redactSensitiveHeaders(headers) {
244
+ const redacted = Object.fromEntries(headers.entries());
245
+ if (redacted.authorization) {
246
+ redacted.authorization = redactSensitiveHeader(redacted.authorization);
247
+ }
248
+ if (redacted["x-preview-token"]) {
249
+ redacted["x-preview-token"] = redactSensitiveHeader(
250
+ redacted["x-preview-token"]
251
+ );
252
+ }
253
+ return redacted;
254
+ }
387
255
  function getErrorSuggestion(status) {
388
256
  if (status === 400)
389
257
  return "The request data failed validation. Check field values and types.";
@@ -458,6 +326,12 @@ async function parseErrorBody(response) {
458
326
  return fallback;
459
327
  }
460
328
  }
329
+ function getParsedErrorSuggestion(status, parsed) {
330
+ if (status === 403 && parsed.reason === "origin_not_allowed") {
331
+ return "Add the request origin to the tenant Browser API origins, then retry the browser request.";
332
+ }
333
+ return getErrorSuggestion(status);
334
+ }
461
335
  async function delay(ms) {
462
336
  return new Promise((resolve) => setTimeout(resolve, ms));
463
337
  }
@@ -471,7 +345,7 @@ function createHttpStatusError(status, parsed, details, requestId) {
471
345
  ...parsed.errors && { errors: parsed.errors },
472
346
  ...parsed.body && { body: parsed.body }
473
347
  };
474
- const suggestion = getErrorSuggestion(status);
348
+ const suggestion = getParsedErrorSuggestion(status, parsed);
475
349
  if (status === 400 || status === 422) {
476
350
  return attachRequestId(
477
351
  createValidationError(
@@ -541,6 +415,7 @@ function createHttpStatusError(status, parsed, details, requestId) {
541
415
  }
542
416
  async function httpFetch(url, options) {
543
417
  const {
418
+ apiUrl,
544
419
  publishableKey,
545
420
  secretKey,
546
421
  customerToken,
@@ -550,7 +425,7 @@ async function httpFetch(url, options) {
550
425
  onUnauthorized,
551
426
  ...requestInit
552
427
  } = options || {};
553
- const baseUrl = resolveApiUrl();
428
+ const baseUrl = resolveApiUrl(apiUrl);
554
429
  const retryConfig = {
555
430
  maxRetries: retry?.maxRetries ?? 3,
556
431
  retryableStatuses: retry?.retryableStatuses ?? DEFAULT_RETRYABLE_STATUSES,
@@ -576,11 +451,7 @@ async function httpFetch(url, options) {
576
451
  if (!headers.has("Content-Type") && requestInit.body && !(requestInit.body instanceof FormData)) {
577
452
  headers.set("Content-Type", "application/json");
578
453
  }
579
- const redactedHeaders = Object.fromEntries(headers.entries());
580
- if (redactedHeaders["authorization"]) {
581
- const token = redactedHeaders["authorization"];
582
- redactedHeaders["authorization"] = token.length > 20 ? `Bearer ...****${token.slice(-8)}` : "****";
583
- }
454
+ const redactedHeaders = redactSensitiveHeaders(headers);
584
455
  debugLog(debug, "request", url, {
585
456
  method: requestInit.method || "GET",
586
457
  headers: redactedHeaders,
@@ -598,7 +469,7 @@ async function httpFetch(url, options) {
598
469
  debugLog(debug, "response", url, {
599
470
  status: response.status,
600
471
  statusText: response.statusText,
601
- headers: Object.fromEntries(response.headers.entries())
472
+ headers: redactSensitiveHeaders(response.headers)
602
473
  });
603
474
  if (!response.ok) {
604
475
  if (isUsageLimitExceededResponse(response)) {
@@ -739,7 +610,7 @@ async function httpFetch(url, options) {
739
610
 
740
611
  // src/core/collection/http-client.ts
741
612
  var HttpClient = class {
742
- constructor(publishableKey, secretKey, getCustomerToken, onUnauthorized, onRequestId) {
613
+ constructor(publishableKey, secretKey, getCustomerToken, onUnauthorized, onRequestId, apiUrl) {
743
614
  this.publishableKey = requirePublishableKeyForSecret(
744
615
  "CollectionClient",
745
616
  publishableKey,
@@ -749,9 +620,11 @@ var HttpClient = class {
749
620
  this.getCustomerToken = getCustomerToken;
750
621
  this.onUnauthorized = onUnauthorized;
751
622
  this.onRequestId = onRequestId;
623
+ this.apiUrl = apiUrl;
752
624
  }
753
625
  get defaultOptions() {
754
626
  const opts = {
627
+ apiUrl: this.apiUrl,
755
628
  publishableKey: this.publishableKey,
756
629
  secretKey: this.secretKey
757
630
  };
@@ -789,85 +662,284 @@ var HttpClient = class {
789
662
  }
790
663
  }
791
664
  /**
792
- * Parse Payload CMS find response (list query)
793
- * Returns native Payload response structure
665
+ * Parse Payload CMS find response (list query)
666
+ * Returns native Payload response structure
667
+ */
668
+ async parseFindResponse(response) {
669
+ const contentType = response.headers.get("content-type");
670
+ try {
671
+ this.assertJsonResponse(response);
672
+ const jsonData = await response.json();
673
+ if (jsonData.docs === void 0) {
674
+ throw createApiError("Invalid find response.", response.status, {
675
+ jsonData
676
+ });
677
+ }
678
+ return {
679
+ docs: jsonData.docs,
680
+ totalDocs: jsonData.totalDocs ?? 0,
681
+ limit: jsonData.limit || 20,
682
+ totalPages: jsonData.totalPages ?? 0,
683
+ page: jsonData.page || 1,
684
+ pagingCounter: jsonData.pagingCounter || 1,
685
+ hasPrevPage: jsonData.hasPrevPage ?? false,
686
+ hasNextPage: jsonData.hasNextPage ?? false,
687
+ prevPage: jsonData.prevPage ?? null,
688
+ nextPage: jsonData.nextPage ?? null
689
+ };
690
+ } catch (error) {
691
+ if (error instanceof SDKError) throw error;
692
+ throw createApiError("Failed to parse response.", response.status, {
693
+ contentType,
694
+ error: error instanceof Error ? error.message : error
695
+ });
696
+ }
697
+ }
698
+ /**
699
+ * Parse Payload CMS mutation response (create/update)
700
+ * Returns native Payload response structure
701
+ */
702
+ async parseMutationResponse(response) {
703
+ const contentType = response.headers.get("content-type");
704
+ try {
705
+ this.assertJsonResponse(response);
706
+ const jsonData = await response.json();
707
+ if (jsonData.doc === void 0) {
708
+ throw createApiError("Invalid mutation response.", response.status, {
709
+ jsonData
710
+ });
711
+ }
712
+ return {
713
+ message: jsonData.message || "",
714
+ doc: jsonData.doc,
715
+ errors: jsonData.errors
716
+ };
717
+ } catch (error) {
718
+ if (error instanceof SDKError) throw error;
719
+ throw createApiError("Failed to parse response.", response.status, {
720
+ contentType,
721
+ error: error instanceof Error ? error.message : error
722
+ });
723
+ }
724
+ }
725
+ /**
726
+ * Parse Payload CMS document response (findById/delete)
727
+ * Returns document directly without wrapper
728
+ */
729
+ async parseDocumentResponse(response) {
730
+ const contentType = response.headers.get("content-type");
731
+ try {
732
+ this.assertJsonResponse(response);
733
+ const jsonData = await response.json();
734
+ return jsonData;
735
+ } catch (error) {
736
+ if (error instanceof SDKError) throw error;
737
+ throw createApiError("Failed to parse response.", response.status, {
738
+ contentType,
739
+ error: error instanceof Error ? error.message : error
740
+ });
741
+ }
742
+ }
743
+ };
744
+
745
+ // src/utils/types.ts
746
+ var resolveRelation = (ref) => {
747
+ if (typeof ref === "string" || typeof ref === "number" || ref === null || ref === void 0)
748
+ return null;
749
+ return ref;
750
+ };
751
+
752
+ // src/core/metadata/index.ts
753
+ function extractSeo(doc) {
754
+ const seo = doc.seo ?? {};
755
+ const og = seo.openGraph ?? {};
756
+ return {
757
+ title: seo.title ?? doc.title ?? null,
758
+ description: seo.description ?? null,
759
+ noIndex: seo.noIndex ?? null,
760
+ canonical: seo.canonical ?? null,
761
+ openGraph: {
762
+ title: og.title ?? null,
763
+ description: og.description ?? null,
764
+ image: og.image ?? null
765
+ }
766
+ };
767
+ }
768
+ function generateMetadata(input, options) {
769
+ const title = input.title ?? void 0;
770
+ const description = input.description ?? void 0;
771
+ const ogTitle = input.openGraph?.title ?? title;
772
+ const ogDescription = input.openGraph?.description ?? description;
773
+ const image = resolveMetaImage(input.openGraph?.image);
774
+ return {
775
+ title,
776
+ description,
777
+ ...input.noIndex && { robots: { index: false, follow: false } },
778
+ ...input.canonical && { alternates: { canonical: input.canonical } },
779
+ openGraph: {
780
+ ...ogTitle && { title: ogTitle },
781
+ ...ogDescription && { description: ogDescription },
782
+ ...options?.siteName && { siteName: options.siteName },
783
+ ...image && { images: [image] }
784
+ },
785
+ twitter: {
786
+ card: image ? "summary_large_image" : "summary",
787
+ ...ogTitle && { title: ogTitle },
788
+ ...ogDescription && { description: ogDescription },
789
+ ...image && { images: [image.url] }
790
+ }
791
+ };
792
+ }
793
+ function resolveMetaImage(ref) {
794
+ const image = resolveRelation(ref);
795
+ if (!image) return null;
796
+ const sized = image.sizes?.["1536"];
797
+ const url = sized?.url || image.url;
798
+ if (!url) return null;
799
+ const width = sized?.url ? sized.width : image.width;
800
+ const height = sized?.url ? sized.height : image.height;
801
+ return {
802
+ url,
803
+ ...width && { width },
804
+ ...height && { height },
805
+ ...image.alt && { alt: image.alt }
806
+ };
807
+ }
808
+
809
+ // src/core/collection/query-builder.ts
810
+ var CollectionQueryBuilder = class {
811
+ constructor(api, collection) {
812
+ this.api = api;
813
+ this.collection = collection;
814
+ }
815
+ /**
816
+ * Find documents (list query)
817
+ * GET /api/{collection}
818
+ * @returns Payload CMS find response with docs array and pagination
819
+ */
820
+ async find(options) {
821
+ return this.api.requestFind(
822
+ `/api/${String(this.collection)}`,
823
+ options
824
+ );
825
+ }
826
+ /**
827
+ * Find document by ID
828
+ * GET /api/{collection}/{id}
829
+ * @returns Document object directly (no wrapper)
830
+ */
831
+ async findById(id, options) {
832
+ return this.api.requestFindById(
833
+ `/api/${String(this.collection)}/${String(id)}`,
834
+ options
835
+ );
836
+ }
837
+ /**
838
+ * Create a new document
839
+ * POST /api/{collection}
840
+ * @returns Payload CMS mutation response with doc and message
841
+ */
842
+ async create(data, options) {
843
+ const endpoint = `/api/${String(this.collection)}`;
844
+ if (options?.file) {
845
+ return this.api.requestCreateWithFile(
846
+ endpoint,
847
+ data,
848
+ options.file,
849
+ options.filename
850
+ );
851
+ }
852
+ return this.api.requestCreate(endpoint, data);
853
+ }
854
+ /**
855
+ * Update a document by ID
856
+ * PATCH /api/{collection}/{id}
857
+ * @returns Payload CMS mutation response with doc and message
858
+ */
859
+ async update(id, data, options) {
860
+ const endpoint = `/api/${String(this.collection)}/${String(id)}`;
861
+ if (options?.file) {
862
+ return this.api.requestUpdateWithFile(
863
+ endpoint,
864
+ data,
865
+ options.file,
866
+ options.filename
867
+ );
868
+ }
869
+ return this.api.requestUpdate(endpoint, data);
870
+ }
871
+ /**
872
+ * Count documents
873
+ * GET /api/{collection}/count
874
+ * @returns Count response with totalDocs
875
+ */
876
+ async count(options) {
877
+ return this.api.requestCount(
878
+ `/api/${String(this.collection)}/count`,
879
+ options
880
+ );
881
+ }
882
+ /**
883
+ * Find first matching document and return its Next.js Metadata.
884
+ * Applies depth: 1 (SEO image populate) and limit: 1 automatically.
885
+ * @returns Metadata or null if no document matches
886
+ */
887
+ async findMetadata(options, metadataOptions) {
888
+ const { docs } = await this.find({ ...options, limit: 1, depth: 1 });
889
+ const doc = docs[0];
890
+ if (!doc) return null;
891
+ return generateMetadata(
892
+ extractSeo(doc),
893
+ metadataOptions
894
+ );
895
+ }
896
+ /**
897
+ * Find document by ID and return its Next.js Metadata.
898
+ * Applies depth: 1 (SEO image populate) automatically.
899
+ * @returns Metadata (throws on 404)
900
+ */
901
+ async findMetadataById(id, metadataOptions) {
902
+ const doc = await this.findById(id, { depth: 1 });
903
+ return generateMetadata(
904
+ extractSeo(doc),
905
+ metadataOptions
906
+ );
907
+ }
908
+ /**
909
+ * Update multiple documents (bulk update)
910
+ * PATCH /api/{collection}
911
+ * @returns Payload CMS find response with updated docs
794
912
  */
795
- async parseFindResponse(response) {
796
- const contentType = response.headers.get("content-type");
797
- try {
798
- this.assertJsonResponse(response);
799
- const jsonData = await response.json();
800
- if (jsonData.docs === void 0) {
801
- throw createApiError("Invalid find response.", response.status, {
802
- jsonData
803
- });
804
- }
805
- return {
806
- docs: jsonData.docs,
807
- totalDocs: jsonData.totalDocs ?? 0,
808
- limit: jsonData.limit || 20,
809
- totalPages: jsonData.totalPages ?? 0,
810
- page: jsonData.page || 1,
811
- pagingCounter: jsonData.pagingCounter || 1,
812
- hasPrevPage: jsonData.hasPrevPage ?? false,
813
- hasNextPage: jsonData.hasNextPage ?? false,
814
- prevPage: jsonData.prevPage ?? null,
815
- nextPage: jsonData.nextPage ?? null
816
- };
817
- } catch (error) {
818
- if (error instanceof SDKError) throw error;
819
- throw createApiError("Failed to parse response.", response.status, {
820
- contentType,
821
- error: error instanceof Error ? error.message : error
822
- });
823
- }
913
+ async updateMany(where, data) {
914
+ return this.api.requestUpdateMany(
915
+ `/api/${String(this.collection)}`,
916
+ { where, data }
917
+ );
824
918
  }
825
919
  /**
826
- * Parse Payload CMS mutation response (create/update)
827
- * Returns native Payload response structure
920
+ * Delete a document by ID
921
+ * DELETE /api/{collection}/{id}
922
+ * @returns Deleted document object directly (no wrapper)
828
923
  */
829
- async parseMutationResponse(response) {
830
- const contentType = response.headers.get("content-type");
831
- try {
832
- this.assertJsonResponse(response);
833
- const jsonData = await response.json();
834
- if (jsonData.doc === void 0) {
835
- throw createApiError("Invalid mutation response.", response.status, {
836
- jsonData
837
- });
838
- }
839
- return {
840
- message: jsonData.message || "",
841
- doc: jsonData.doc,
842
- errors: jsonData.errors
843
- };
844
- } catch (error) {
845
- if (error instanceof SDKError) throw error;
846
- throw createApiError("Failed to parse response.", response.status, {
847
- contentType,
848
- error: error instanceof Error ? error.message : error
849
- });
850
- }
924
+ async remove(id) {
925
+ return this.api.requestDelete(
926
+ `/api/${String(this.collection)}/${String(id)}`
927
+ );
851
928
  }
852
929
  /**
853
- * Parse Payload CMS document response (findById/delete)
854
- * Returns document directly without wrapper
930
+ * Delete multiple documents (bulk delete)
931
+ * DELETE /api/{collection}
932
+ * @returns Payload CMS find response with deleted docs
855
933
  */
856
- async parseDocumentResponse(response) {
857
- const contentType = response.headers.get("content-type");
858
- try {
859
- this.assertJsonResponse(response);
860
- const jsonData = await response.json();
861
- return jsonData;
862
- } catch (error) {
863
- if (error instanceof SDKError) throw error;
864
- throw createApiError("Failed to parse response.", response.status, {
865
- contentType,
866
- error: error instanceof Error ? error.message : error
867
- });
868
- }
934
+ async removeMany(where) {
935
+ return this.api.requestDeleteMany(
936
+ `/api/${String(this.collection)}`,
937
+ { where }
938
+ );
869
939
  }
870
940
  };
941
+ var ServerCollectionQueryBuilder = class extends CollectionQueryBuilder {
942
+ };
871
943
 
872
944
  // src/core/collection/collection-client.ts
873
945
  function buildPayloadFormData(data, file, filename) {
@@ -1046,7 +1118,7 @@ async function parseApiResponse(response, endpoint) {
1046
1118
  if (reason === "validation_failed") {
1047
1119
  throw attachRequestId(createValidationError(errorMessage, data, errorMessage), requestId);
1048
1120
  }
1049
- if (reason === "token_expired" || reason === "token_invalid" || reason === "key_invalid" || reason === "key_revoked") {
1121
+ if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
1050
1122
  throw attachRequestId(createAuthError(errorMessage, data, errorMessage), requestId);
1051
1123
  }
1052
1124
  if (reason === "forbidden") {
@@ -1078,6 +1150,7 @@ var CommunityClient = class {
1078
1150
  options.secretKey
1079
1151
  );
1080
1152
  this.secretKey = options.secretKey;
1153
+ this.apiUrl = options.apiUrl;
1081
1154
  this.customerToken = options.customerToken;
1082
1155
  this.onUnauthorized = options.onUnauthorized;
1083
1156
  this.onRequestId = options.onRequestId;
@@ -1092,6 +1165,7 @@ var CommunityClient = class {
1092
1165
  try {
1093
1166
  const response = await httpFetch(endpoint, {
1094
1167
  method,
1168
+ apiUrl: this.apiUrl,
1095
1169
  publishableKey: this.publishableKey,
1096
1170
  secretKey: this.secretKey,
1097
1171
  customerToken: token ?? void 0,
@@ -1252,6 +1326,7 @@ var BaseApi = class {
1252
1326
  options.secretKey
1253
1327
  );
1254
1328
  this.secretKey = options.secretKey;
1329
+ this.apiUrl = options.apiUrl;
1255
1330
  this.onRequestId = options.onRequestId;
1256
1331
  }
1257
1332
  async request(endpoint, body, options) {
@@ -1259,6 +1334,7 @@ var BaseApi = class {
1259
1334
  try {
1260
1335
  const response = await httpFetch(endpoint, {
1261
1336
  method,
1337
+ apiUrl: this.apiUrl,
1262
1338
  publishableKey: this.publishableKey,
1263
1339
  secretKey: this.secretKey,
1264
1340
  ...body !== void 0 && { body: JSON.stringify(body) },
@@ -1301,6 +1377,7 @@ var CartApi = class {
1301
1377
  options.secretKey
1302
1378
  );
1303
1379
  this.secretKey = options.secretKey;
1380
+ this.apiUrl = options.apiUrl;
1304
1381
  this.customerToken = options.customerToken;
1305
1382
  this.onUnauthorized = options.onUnauthorized;
1306
1383
  this.onRequestId = options.onRequestId;
@@ -1310,6 +1387,7 @@ var CartApi = class {
1310
1387
  try {
1311
1388
  const response = await httpFetch(endpoint, {
1312
1389
  method,
1390
+ apiUrl: this.apiUrl,
1313
1391
  publishableKey: this.publishableKey,
1314
1392
  secretKey: this.secretKey,
1315
1393
  customerToken: token ?? void 0,
@@ -1469,7 +1547,61 @@ var OrderApi = class extends BaseApi {
1469
1547
  }
1470
1548
  };
1471
1549
 
1550
+ // src/core/preview/server-preview-client.ts
1551
+ var ServerPreviewClient = class extends BaseApi {
1552
+ constructor(options) {
1553
+ super("ServerPreviewClient", options);
1554
+ }
1555
+ async detail(params, options) {
1556
+ let response;
1557
+ try {
1558
+ response = await httpFetch("/api/preview/detail", {
1559
+ method: "POST",
1560
+ apiUrl: this.apiUrl,
1561
+ publishableKey: this.publishableKey,
1562
+ secretKey: this.secretKey,
1563
+ body: JSON.stringify(params),
1564
+ headers: { "X-Preview-Token": options.previewToken }
1565
+ });
1566
+ } catch (err) {
1567
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
1568
+ this.onRequestId?.(id);
1569
+ if (err instanceof NotFoundError) return null;
1570
+ throw err;
1571
+ }
1572
+ const requestId = response.headers.get("x-request-id") ?? null;
1573
+ this.onRequestId?.(requestId);
1574
+ try {
1575
+ return await response.json();
1576
+ } catch (err) {
1577
+ if (err instanceof SyntaxError) {
1578
+ throw createApiError(
1579
+ "Invalid JSON response from /api/preview/detail",
1580
+ 200,
1581
+ void 0,
1582
+ "Server returned an invalid response.",
1583
+ "Check if the API endpoint is available.",
1584
+ requestId ?? void 0
1585
+ );
1586
+ }
1587
+ throw err;
1588
+ }
1589
+ }
1590
+ };
1591
+
1472
1592
  // src/core/commerce/server-commerce-client.ts
1593
+ var PreviewProductApi = class extends ProductApi {
1594
+ constructor(options) {
1595
+ super(options);
1596
+ this.previewApi = new ServerPreviewClient(options);
1597
+ }
1598
+ async previewDetail(params, options) {
1599
+ return this.previewApi.detail(
1600
+ { collection: "products", id: params.id },
1601
+ options
1602
+ );
1603
+ }
1604
+ };
1473
1605
  var ServerCommerceClient = class {
1474
1606
  constructor(options) {
1475
1607
  const publishableKey = requirePublishableKeyForSecret(
@@ -1480,9 +1612,10 @@ var ServerCommerceClient = class {
1480
1612
  const serverOptions = {
1481
1613
  publishableKey,
1482
1614
  secretKey: options.secretKey,
1615
+ apiUrl: options.apiUrl,
1483
1616
  onRequestId: options.onRequestId
1484
1617
  };
1485
- const productApi = new ProductApi(serverOptions);
1618
+ const productApi = new PreviewProductApi(serverOptions);
1486
1619
  const cartApi = new CartApi(serverOptions);
1487
1620
  const discountApi = new DiscountApi(serverOptions);
1488
1621
  const shippingApi = new ShippingApi(serverOptions);
@@ -1491,6 +1624,7 @@ var ServerCommerceClient = class {
1491
1624
  stockCheck: productApi.stockCheck.bind(productApi),
1492
1625
  listingGroups: productApi.listingGroups.bind(productApi),
1493
1626
  detail: productApi.detail.bind(productApi),
1627
+ previewDetail: productApi.previewDetail.bind(productApi),
1494
1628
  upsert: productApi.upsert.bind(productApi)
1495
1629
  };
1496
1630
  this.cart = {
@@ -1524,560 +1658,6 @@ var ServerCommerceClient = class {
1524
1658
  }
1525
1659
  };
1526
1660
 
1527
- // src/core/query/get-query-client.ts
1528
- var import_react_query = require("@tanstack/react-query");
1529
- function makeQueryClient() {
1530
- return new import_react_query.QueryClient({
1531
- defaultOptions: {
1532
- queries: {
1533
- // Infinite staleTime: server-fetched data persists until explicitly invalidated.
1534
- // For browser clients needing fresher data, override per-query:
1535
- // useQuery({ ..., staleTime: 5 * 60 * 1000 })
1536
- staleTime: Number.POSITIVE_INFINITY,
1537
- refetchOnWindowFocus: false
1538
- },
1539
- dehydrate: {
1540
- shouldDehydrateQuery: (query) => (0, import_react_query.defaultShouldDehydrateQuery)(query) || query.state.status === "pending",
1541
- shouldRedactErrors: () => false
1542
- }
1543
- }
1544
- });
1545
- }
1546
- var browserQueryClient;
1547
- function getQueryClient() {
1548
- if (import_react_query.isServer) {
1549
- return makeQueryClient();
1550
- }
1551
- if (!browserQueryClient) {
1552
- browserQueryClient = makeQueryClient();
1553
- }
1554
- return browserQueryClient;
1555
- }
1556
-
1557
- // src/core/query/query-hooks.ts
1558
- var import_react_query4 = require("@tanstack/react-query");
1559
-
1560
- // src/core/query/collection-hooks.ts
1561
- var import_react_query2 = require("@tanstack/react-query");
1562
-
1563
- // src/core/query/query-keys.ts
1564
- function collectionKeys(collection) {
1565
- return {
1566
- all: [collection],
1567
- lists: () => [collection, "list"],
1568
- list: (options) => [collection, "list", options],
1569
- details: () => [collection, "detail"],
1570
- detail: (id, options) => [collection, "detail", id, options],
1571
- infinites: () => [collection, "infinite"],
1572
- infinite: (options) => [collection, "infinite", options]
1573
- };
1574
- }
1575
- var customerKeys = {
1576
- all: ["customer"],
1577
- me: () => ["customer", "me"]
1578
- };
1579
- var productKeys = {
1580
- listingGroups: (options) => ["products", "listing-groups", "list", options],
1581
- listingGroupsInfinite: (options) => ["products", "listing-groups", "infinite", options],
1582
- detail: (params) => ["products", "detail", params],
1583
- detailAll: () => ["products", "detail"]
1584
- };
1585
-
1586
- // src/core/query/collection-hooks.ts
1587
- var PRODUCT_DETAIL_INVALIDATING_COLLECTIONS = /* @__PURE__ */ new Set([
1588
- "products",
1589
- "product-variants",
1590
- "product-options",
1591
- "product-option-values",
1592
- "product-categories",
1593
- "product-tags",
1594
- "product-collections",
1595
- "brands",
1596
- "brand-logos",
1597
- "images"
1598
- ]);
1599
- var DEFAULT_PAGE_SIZE = 20;
1600
- var CollectionHooks = class {
1601
- constructor(queryClient, collectionClient) {
1602
- this.queryClient = queryClient;
1603
- this.collectionClient = collectionClient;
1604
- }
1605
- // ===== useQuery =====
1606
- useQuery(params, options) {
1607
- const { collection, options: queryOptions } = params;
1608
- const { placeholderData, ...restOptions } = options ?? {};
1609
- return (0, import_react_query2.useQuery)({
1610
- queryKey: collectionKeys(collection).list(queryOptions),
1611
- queryFn: async () => {
1612
- return await this.collectionClient.from(collection).find(queryOptions);
1613
- },
1614
- ...restOptions,
1615
- // NonFunctionGuard<T> incompatible with generic union types — safe cast
1616
- ...placeholderData !== void 0 && {
1617
- placeholderData
1618
- }
1619
- });
1620
- }
1621
- // ===== useSuspenseQuery =====
1622
- useSuspenseQuery(params, options) {
1623
- const { collection, options: queryOptions } = params;
1624
- return (0, import_react_query2.useSuspenseQuery)({
1625
- queryKey: collectionKeys(collection).list(queryOptions),
1626
- queryFn: async () => {
1627
- return await this.collectionClient.from(collection).find(queryOptions);
1628
- },
1629
- ...options
1630
- });
1631
- }
1632
- // ===== useQueryById =====
1633
- useQueryById(params, options) {
1634
- const { collection, id, options: queryOptions } = params;
1635
- const { placeholderData, ...restOptions } = options ?? {};
1636
- return (0, import_react_query2.useQuery)({
1637
- queryKey: collectionKeys(collection).detail(id, queryOptions),
1638
- queryFn: async () => {
1639
- return await this.collectionClient.from(collection).findById(id, queryOptions);
1640
- },
1641
- ...restOptions,
1642
- // NonFunctionGuard<T> incompatible with generic union types — safe cast
1643
- ...placeholderData !== void 0 && {
1644
- placeholderData
1645
- }
1646
- });
1647
- }
1648
- // ===== useSuspenseQueryById =====
1649
- useSuspenseQueryById(params, options) {
1650
- const { collection, id, options: queryOptions } = params;
1651
- return (0, import_react_query2.useSuspenseQuery)({
1652
- queryKey: collectionKeys(collection).detail(id, queryOptions),
1653
- queryFn: async () => {
1654
- return await this.collectionClient.from(collection).findById(id, queryOptions);
1655
- },
1656
- ...options
1657
- });
1658
- }
1659
- // ===== useInfiniteQuery =====
1660
- useInfiniteQuery(params, options) {
1661
- const {
1662
- collection,
1663
- options: queryOptions,
1664
- pageSize = DEFAULT_PAGE_SIZE
1665
- } = params;
1666
- return (0, import_react_query2.useInfiniteQuery)({
1667
- queryKey: collectionKeys(collection).infinite(queryOptions),
1668
- queryFn: async ({ pageParam }) => {
1669
- const response = await this.collectionClient.from(collection).find({ ...queryOptions, page: pageParam, limit: pageSize });
1670
- return response;
1671
- },
1672
- initialPageParam: 1,
1673
- getNextPageParam: (lastPage) => {
1674
- return lastPage.hasNextPage ? lastPage.nextPage : void 0;
1675
- },
1676
- ...options
1677
- });
1678
- }
1679
- // ===== useSuspenseInfiniteQuery =====
1680
- useSuspenseInfiniteQuery(params, options) {
1681
- const {
1682
- collection,
1683
- options: queryOptions,
1684
- pageSize = DEFAULT_PAGE_SIZE
1685
- } = params;
1686
- return (0, import_react_query2.useSuspenseInfiniteQuery)({
1687
- queryKey: collectionKeys(collection).infinite(queryOptions),
1688
- queryFn: async ({ pageParam }) => {
1689
- const response = await this.collectionClient.from(collection).find({ ...queryOptions, page: pageParam, limit: pageSize });
1690
- return response;
1691
- },
1692
- initialPageParam: 1,
1693
- getNextPageParam: (lastPage) => {
1694
- return lastPage.hasNextPage ? lastPage.nextPage : void 0;
1695
- },
1696
- ...options
1697
- });
1698
- }
1699
- // ===== prefetchQuery =====
1700
- async prefetchQuery(params, options) {
1701
- const { collection, options: queryOptions } = params;
1702
- return this.queryClient.prefetchQuery({
1703
- queryKey: collectionKeys(collection).list(queryOptions),
1704
- queryFn: async () => {
1705
- return await this.collectionClient.from(collection).find(queryOptions);
1706
- },
1707
- ...options
1708
- });
1709
- }
1710
- // ===== prefetchQueryById =====
1711
- async prefetchQueryById(params, options) {
1712
- const { collection, id, options: queryOptions } = params;
1713
- return this.queryClient.prefetchQuery({
1714
- queryKey: collectionKeys(collection).detail(id, queryOptions),
1715
- queryFn: async () => {
1716
- return await this.collectionClient.from(collection).findById(id, queryOptions);
1717
- },
1718
- ...options
1719
- });
1720
- }
1721
- // ===== prefetchInfiniteQuery =====
1722
- async prefetchInfiniteQuery(params, options) {
1723
- const {
1724
- collection,
1725
- options: queryOptions,
1726
- pageSize = DEFAULT_PAGE_SIZE
1727
- } = params;
1728
- return this.queryClient.prefetchInfiniteQuery({
1729
- queryKey: collectionKeys(collection).infinite(queryOptions),
1730
- queryFn: async ({ pageParam }) => {
1731
- const response = await this.collectionClient.from(collection).find({ ...queryOptions, page: pageParam, limit: pageSize });
1732
- return response;
1733
- },
1734
- initialPageParam: 1,
1735
- getNextPageParam: (lastPage) => {
1736
- return lastPage.hasNextPage ? lastPage.nextPage : void 0;
1737
- },
1738
- pages: options?.pages ?? 1,
1739
- staleTime: options?.staleTime
1740
- });
1741
- }
1742
- // ===== Mutation Hooks =====
1743
- useCreate(params, options) {
1744
- const { collection } = params;
1745
- return (0, import_react_query2.useMutation)({
1746
- mutationFn: async (variables) => {
1747
- return await this.collectionClient.from(collection).create(
1748
- variables.data,
1749
- variables.file ? { file: variables.file, filename: variables.filename } : void 0
1750
- );
1751
- },
1752
- onSuccess: (data) => {
1753
- this.queryClient.invalidateQueries({
1754
- queryKey: collectionKeys(collection).all
1755
- });
1756
- if (PRODUCT_DETAIL_INVALIDATING_COLLECTIONS.has(collection)) {
1757
- this.queryClient.invalidateQueries({ queryKey: ["products", "detail"] });
1758
- }
1759
- options?.onSuccess?.(data);
1760
- },
1761
- onError: options?.onError,
1762
- onSettled: options?.onSettled
1763
- });
1764
- }
1765
- useUpdate(params, options) {
1766
- const { collection } = params;
1767
- return (0, import_react_query2.useMutation)({
1768
- mutationFn: async (variables) => {
1769
- return await this.collectionClient.from(collection).update(
1770
- variables.id,
1771
- variables.data,
1772
- variables.file ? { file: variables.file, filename: variables.filename } : void 0
1773
- );
1774
- },
1775
- onSuccess: (data) => {
1776
- this.queryClient.invalidateQueries({
1777
- queryKey: collectionKeys(collection).all
1778
- });
1779
- if (PRODUCT_DETAIL_INVALIDATING_COLLECTIONS.has(collection)) {
1780
- this.queryClient.invalidateQueries({ queryKey: ["products", "detail"] });
1781
- }
1782
- options?.onSuccess?.(data);
1783
- },
1784
- onError: options?.onError,
1785
- onSettled: options?.onSettled
1786
- });
1787
- }
1788
- useRemove(params, options) {
1789
- const { collection } = params;
1790
- return (0, import_react_query2.useMutation)({
1791
- mutationFn: async (id) => {
1792
- return await this.collectionClient.from(collection).remove(id);
1793
- },
1794
- onSuccess: (data) => {
1795
- this.queryClient.invalidateQueries({
1796
- queryKey: collectionKeys(collection).all
1797
- });
1798
- if (PRODUCT_DETAIL_INVALIDATING_COLLECTIONS.has(collection)) {
1799
- this.queryClient.invalidateQueries({ queryKey: ["products", "detail"] });
1800
- }
1801
- options?.onSuccess?.(data);
1802
- },
1803
- onError: options?.onError,
1804
- onSettled: options?.onSettled
1805
- });
1806
- }
1807
- // ===== Cache Utilities =====
1808
- invalidateQueries(collection, type) {
1809
- const queryKey = type ? [collection, type] : [collection];
1810
- return this.queryClient.invalidateQueries({ queryKey });
1811
- }
1812
- getQueryData(collection, type, idOrOptions, options) {
1813
- if (type === "list") {
1814
- return this.queryClient.getQueryData(
1815
- collectionKeys(collection).list(idOrOptions)
1816
- );
1817
- }
1818
- return this.queryClient.getQueryData(
1819
- collectionKeys(collection).detail(idOrOptions, options)
1820
- );
1821
- }
1822
- setQueryData(collection, type, dataOrId, dataOrOptions, options) {
1823
- if (type === "list") {
1824
- this.queryClient.setQueryData(
1825
- collectionKeys(collection).list(dataOrOptions),
1826
- dataOrId
1827
- );
1828
- } else {
1829
- this.queryClient.setQueryData(
1830
- collectionKeys(collection).detail(dataOrId, options),
1831
- dataOrOptions
1832
- );
1833
- }
1834
- }
1835
- };
1836
-
1837
- // src/core/query/customer-hooks.ts
1838
- var import_react_query3 = require("@tanstack/react-query");
1839
- function createMutation(mutationFn, callbacks, onSuccessExtra) {
1840
- return (0, import_react_query3.useMutation)({
1841
- mutationFn,
1842
- onSuccess: (data) => {
1843
- onSuccessExtra?.(data);
1844
- callbacks?.onSuccess?.(data);
1845
- },
1846
- onError: callbacks?.onError,
1847
- onSettled: callbacks?.onSettled
1848
- });
1849
- }
1850
- var CustomerHooks = class {
1851
- constructor(queryClient, customerAuth) {
1852
- this.invalidateMe = () => {
1853
- this.queryClient.invalidateQueries({ queryKey: customerKeys.me() });
1854
- };
1855
- this.queryClient = queryClient;
1856
- this.customerAuth = customerAuth;
1857
- }
1858
- ensureCustomerAuth() {
1859
- if (!this.customerAuth) {
1860
- throw createConfigError(
1861
- "Customer hooks require Client. Use createClient() instead of createServerClient()."
1862
- );
1863
- }
1864
- return this.customerAuth;
1865
- }
1866
- // ===== useCustomerMe =====
1867
- useCustomerMe(options) {
1868
- return (0, import_react_query3.useQuery)({
1869
- queryKey: customerKeys.me(),
1870
- queryFn: async () => {
1871
- return await this.ensureCustomerAuth().me();
1872
- },
1873
- ...options,
1874
- enabled: (options?.enabled ?? true) && !!this.customerAuth?.isAuthenticated()
1875
- });
1876
- }
1877
- // ===== Mutations =====
1878
- useCustomerLogin(options) {
1879
- return createMutation(
1880
- (data) => this.ensureCustomerAuth().login(data),
1881
- options,
1882
- this.invalidateMe
1883
- );
1884
- }
1885
- useCustomerRegister(options) {
1886
- return createMutation(
1887
- (data) => this.ensureCustomerAuth().register(data),
1888
- options
1889
- );
1890
- }
1891
- useCustomerLogout(options) {
1892
- return (0, import_react_query3.useMutation)({
1893
- mutationFn: async () => {
1894
- this.ensureCustomerAuth().logout();
1895
- },
1896
- onSuccess: () => {
1897
- this.queryClient.removeQueries({ queryKey: customerKeys.all });
1898
- options?.onSuccess?.();
1899
- },
1900
- onError: options?.onError,
1901
- onSettled: options?.onSettled
1902
- });
1903
- }
1904
- useCustomerForgotPassword(options) {
1905
- return createMutation(
1906
- (email) => this.ensureCustomerAuth().forgotPassword(email).then(() => {
1907
- }),
1908
- options
1909
- );
1910
- }
1911
- useCustomerResetPassword(options) {
1912
- return createMutation(
1913
- (data) => this.ensureCustomerAuth().resetPassword(data.token, data.password).then(() => {
1914
- }),
1915
- options
1916
- );
1917
- }
1918
- useCustomerRefreshToken(options) {
1919
- return createMutation(
1920
- () => this.ensureCustomerAuth().refreshToken(),
1921
- options,
1922
- this.invalidateMe
1923
- );
1924
- }
1925
- useCustomerUpdateProfile(options) {
1926
- return createMutation(
1927
- (data) => this.ensureCustomerAuth().updateProfile(data),
1928
- options,
1929
- this.invalidateMe
1930
- );
1931
- }
1932
- useCustomerChangePassword(options) {
1933
- return createMutation(
1934
- (data) => this.ensureCustomerAuth().changePassword(data.currentPassword, data.newPassword).then(() => {
1935
- }),
1936
- options
1937
- );
1938
- }
1939
- // ===== Customer Cache Utilities =====
1940
- invalidateCustomerQueries() {
1941
- return this.queryClient.invalidateQueries({ queryKey: customerKeys.all });
1942
- }
1943
- getCustomerData() {
1944
- return this.queryClient.getQueryData(customerKeys.me());
1945
- }
1946
- setCustomerData(data) {
1947
- this.queryClient.setQueryData(customerKeys.me(), data);
1948
- }
1949
- };
1950
-
1951
- // src/core/query/query-hooks.ts
1952
- var QueryHooks = class extends CollectionHooks {
1953
- constructor(queryClient, collectionClient, customerAuth, commerceClient) {
1954
- super(queryClient, collectionClient);
1955
- // --- Customer hooks delegation ---
1956
- this.useCustomerMe = (...args) => this._customer.useCustomerMe(...args);
1957
- this.useCustomerLogin = (...args) => this._customer.useCustomerLogin(...args);
1958
- this.useCustomerRegister = (...args) => this._customer.useCustomerRegister(...args);
1959
- this.useCustomerLogout = (...args) => this._customer.useCustomerLogout(...args);
1960
- this.useCustomerForgotPassword = (...args) => this._customer.useCustomerForgotPassword(...args);
1961
- this.useCustomerResetPassword = (...args) => this._customer.useCustomerResetPassword(...args);
1962
- this.useCustomerRefreshToken = (...args) => this._customer.useCustomerRefreshToken(...args);
1963
- this.useCustomerUpdateProfile = (...args) => this._customer.useCustomerUpdateProfile(...args);
1964
- this.useCustomerChangePassword = (...args) => this._customer.useCustomerChangePassword(...args);
1965
- // --- Customer cache delegation ---
1966
- this.invalidateCustomerQueries = () => this._customer.invalidateCustomerQueries();
1967
- this.getCustomerData = () => this._customer.getCustomerData();
1968
- this.setCustomerData = (data) => this._customer.setCustomerData(data);
1969
- this._customer = new CustomerHooks(queryClient, customerAuth);
1970
- this._commerce = commerceClient;
1971
- }
1972
- useProductListingGroupsQuery(params, options) {
1973
- const queryOptions = params.options;
1974
- const { placeholderData, ...restOptions } = options ?? {};
1975
- return (0, import_react_query4.useQuery)({
1976
- queryKey: productKeys.listingGroups(queryOptions),
1977
- queryFn: async () => this.collectionClient.requestFindEndpoint(
1978
- "/api/products/listing-groups/query",
1979
- { options: queryOptions }
1980
- ),
1981
- ...restOptions,
1982
- ...placeholderData !== void 0 && {
1983
- placeholderData
1984
- }
1985
- });
1986
- }
1987
- useSuspenseProductListingGroupsQuery(params, options) {
1988
- const queryOptions = params.options;
1989
- return (0, import_react_query4.useSuspenseQuery)({
1990
- queryKey: productKeys.listingGroups(queryOptions),
1991
- queryFn: async () => this.collectionClient.requestFindEndpoint(
1992
- "/api/products/listing-groups/query",
1993
- { options: queryOptions }
1994
- ),
1995
- ...options
1996
- });
1997
- }
1998
- useInfiniteProductListingGroupsQuery(params, options) {
1999
- const {
2000
- options: queryOptions,
2001
- pageSize = 20
2002
- } = params;
2003
- return (0, import_react_query4.useInfiniteQuery)({
2004
- queryKey: productKeys.listingGroupsInfinite(queryOptions),
2005
- queryFn: async ({ pageParam }) => this.collectionClient.requestFindEndpoint(
2006
- "/api/products/listing-groups/query",
2007
- {
2008
- options: { ...queryOptions, page: pageParam, limit: pageSize }
2009
- }
2010
- ),
2011
- initialPageParam: 1,
2012
- getNextPageParam: (lastPage) => lastPage.hasNextPage ? lastPage.nextPage : void 0,
2013
- ...options
2014
- });
2015
- }
2016
- useSuspenseInfiniteProductListingGroupsQuery(params, options) {
2017
- const {
2018
- options: queryOptions,
2019
- pageSize = 20
2020
- } = params;
2021
- return (0, import_react_query4.useSuspenseInfiniteQuery)({
2022
- queryKey: productKeys.listingGroupsInfinite(queryOptions),
2023
- queryFn: async ({ pageParam }) => this.collectionClient.requestFindEndpoint(
2024
- "/api/products/listing-groups/query",
2025
- {
2026
- options: { ...queryOptions, page: pageParam, limit: pageSize }
2027
- }
2028
- ),
2029
- initialPageParam: 1,
2030
- getNextPageParam: (lastPage) => lastPage.hasNextPage ? lastPage.nextPage : void 0,
2031
- ...options
2032
- });
2033
- }
2034
- async prefetchProductListingGroupsQuery(params, options) {
2035
- const queryOptions = params.options;
2036
- return this.queryClient.prefetchQuery({
2037
- queryKey: productKeys.listingGroups(queryOptions),
2038
- queryFn: async () => this.collectionClient.requestFindEndpoint(
2039
- "/api/products/listing-groups/query",
2040
- { options: queryOptions }
2041
- ),
2042
- ...options
2043
- });
2044
- }
2045
- async prefetchInfiniteProductListingGroupsQuery(params, options) {
2046
- const {
2047
- options: queryOptions,
2048
- pageSize = 20
2049
- } = params;
2050
- return this.queryClient.prefetchInfiniteQuery({
2051
- queryKey: productKeys.listingGroupsInfinite(queryOptions),
2052
- queryFn: async ({ pageParam }) => this.collectionClient.requestFindEndpoint(
2053
- "/api/products/listing-groups/query",
2054
- {
2055
- options: { ...queryOptions, page: pageParam, limit: pageSize }
2056
- }
2057
- ),
2058
- initialPageParam: 1,
2059
- getNextPageParam: (lastPage) => lastPage.hasNextPage ? lastPage.nextPage : void 0,
2060
- pages: options?.pages ?? 1,
2061
- staleTime: options?.staleTime
2062
- });
2063
- }
2064
- useProductDetail(params, options) {
2065
- const discriminator = "slug" in params ? params.slug : params.id;
2066
- const enabled = options?.enabled !== false && Boolean(discriminator);
2067
- return (0, import_react_query4.useQuery)({
2068
- queryKey: productKeys.detail(params),
2069
- queryFn: () => this._commerce.product.detail(params),
2070
- enabled
2071
- });
2072
- }
2073
- useProductDetailBySlug(slug, options) {
2074
- return this.useProductDetail({ slug }, options);
2075
- }
2076
- useProductDetailById(id, options) {
2077
- return this.useProductDetail({ id }, options);
2078
- }
2079
- };
2080
-
2081
1661
  // src/core/client/client.server.ts
2082
1662
  var ServerClient = class {
2083
1663
  constructor(options) {
@@ -2107,9 +1687,14 @@ var ServerClient = class {
2107
1687
  const serverOptions = {
2108
1688
  publishableKey: this.config.publishableKey,
2109
1689
  secretKey: this.config.secretKey,
1690
+ apiUrl: this.config.apiUrl,
2110
1691
  onRequestId
2111
1692
  };
2112
1693
  this.commerce = new ServerCommerceClient(serverOptions);
1694
+ const previewApi = new ServerPreviewClient(serverOptions);
1695
+ this.preview = {
1696
+ detail: previewApi.detail.bind(previewApi)
1697
+ };
2113
1698
  const communityClient = new CommunityClient(serverOptions);
2114
1699
  const moderationApi = new ModerationApi(serverOptions);
2115
1700
  this.community = Object.assign(communityClient, {
@@ -2123,10 +1708,9 @@ var ServerClient = class {
2123
1708
  this.config.secretKey,
2124
1709
  void 0,
2125
1710
  void 0,
2126
- onRequestId
1711
+ onRequestId,
1712
+ this.config.apiUrl
2127
1713
  );
2128
- this.queryClient = getQueryClient();
2129
- this.query = new QueryHooks(this.queryClient, this.collections, void 0, this.commerce);
2130
1714
  }
2131
1715
  getState() {
2132
1716
  return { ...this.state };