@weaverse/next 0.1.0-alpha.9 → 1.0.1

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 (116) hide show
  1. package/README.md +161 -73
  2. package/dist/{chunk-6PMZ77RA.mjs → chunk-OSC5HR5V.mjs} +117 -8
  3. package/dist/chunk-OSC5HR5V.mjs.map +1 -0
  4. package/dist/client-boundary.js +1425 -0
  5. package/dist/client-boundary.js.map +1 -0
  6. package/dist/client-boundary.mjs +1395 -0
  7. package/dist/client-boundary.mjs.map +1 -0
  8. package/dist/index.js +292 -1003
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +90 -966
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/server.js +321 -91
  13. package/dist/server.js.map +1 -1
  14. package/dist/server.mjs +205 -28
  15. package/dist/server.mjs.map +1 -1
  16. package/dist/types/client-boundary.d.ts +25 -0
  17. package/dist/types/client-boundary.d.ts.map +1 -0
  18. package/dist/types/client.d.ts +16 -0
  19. package/dist/types/client.d.ts.map +1 -0
  20. package/dist/types/hooks.d.ts +20 -0
  21. package/dist/types/hooks.d.ts.map +1 -0
  22. package/dist/types/index.d.ts +33 -0
  23. package/dist/types/index.d.ts.map +1 -0
  24. package/dist/types/item.d.ts +60 -0
  25. package/dist/types/item.d.ts.map +1 -0
  26. package/dist/types/loader.d.ts +25 -0
  27. package/dist/types/loader.d.ts.map +1 -0
  28. package/dist/types/main.d.ts +11 -0
  29. package/dist/types/main.d.ts.map +1 -0
  30. package/dist/types/provider.d.ts +82 -0
  31. package/dist/types/provider.d.ts.map +1 -0
  32. package/dist/types/registry.d.ts +15 -0
  33. package/dist/types/registry.d.ts.map +1 -0
  34. package/dist/types/renderer.d.ts +21 -0
  35. package/dist/types/renderer.d.ts.map +1 -0
  36. package/dist/types/request-info.d.ts +19 -0
  37. package/dist/types/request-info.d.ts.map +1 -0
  38. package/dist/types/revalidate-item.d.ts +82 -0
  39. package/dist/types/revalidate-item.d.ts.map +1 -0
  40. package/dist/types/root-provider.d.ts +62 -0
  41. package/dist/types/root-provider.d.ts.map +1 -0
  42. package/dist/types/runtime.d.ts +113 -0
  43. package/dist/types/runtime.d.ts.map +1 -0
  44. package/dist/types/seo.d.ts +55 -0
  45. package/dist/types/seo.d.ts.map +1 -0
  46. package/dist/types/server/configs.d.ts +27 -0
  47. package/dist/types/server/configs.d.ts.map +1 -0
  48. package/dist/types/server/normalize-page-url.d.ts +19 -0
  49. package/dist/types/server/normalize-page-url.d.ts.map +1 -0
  50. package/dist/types/server/revalidate-handler.d.ts +55 -0
  51. package/dist/types/server/revalidate-handler.d.ts.map +1 -0
  52. package/dist/types/server/server-client.d.ts +21 -0
  53. package/dist/types/server/server-client.d.ts.map +1 -0
  54. package/dist/types/server.d.ts +19 -0
  55. package/dist/types/server.d.ts.map +1 -0
  56. package/dist/types/studio-bridge.d.ts +16 -0
  57. package/dist/types/studio-bridge.d.ts.map +1 -0
  58. package/dist/types/studio-connect.d.ts +27 -0
  59. package/dist/types/studio-connect.d.ts.map +1 -0
  60. package/dist/types/studio-router.d.ts +50 -0
  61. package/dist/types/studio-router.d.ts.map +1 -0
  62. package/dist/types/studio-script-src.d.ts +12 -0
  63. package/dist/types/studio-script-src.d.ts.map +1 -0
  64. package/dist/types/theme-settings-store.d.ts +18 -0
  65. package/dist/types/theme-settings-store.d.ts.map +1 -0
  66. package/dist/types/translate.d.ts +56 -0
  67. package/dist/types/translate.d.ts.map +1 -0
  68. package/dist/types/translation-context.d.ts +109 -0
  69. package/dist/types/translation-context.d.ts.map +1 -0
  70. package/dist/types/translation-store.d.ts +44 -0
  71. package/dist/types/translation-store.d.ts.map +1 -0
  72. package/dist/types/types.d.ts +665 -0
  73. package/dist/types/types.d.ts.map +1 -0
  74. package/dist/types/use-weaverse-next-studio.d.ts +34 -0
  75. package/dist/types/use-weaverse-next-studio.d.ts.map +1 -0
  76. package/dist/types/utils.d.ts +22 -0
  77. package/dist/types/utils.d.ts.map +1 -0
  78. package/package.json +12 -27
  79. package/src/client-boundary.ts +50 -0
  80. package/src/client.ts +102 -0
  81. package/src/hooks.ts +50 -0
  82. package/src/index.ts +143 -0
  83. package/src/item.ts +167 -0
  84. package/src/loader.ts +135 -0
  85. package/src/main.tsx +45 -0
  86. package/src/provider.tsx +223 -0
  87. package/src/registry.ts +63 -0
  88. package/src/renderer.tsx +100 -0
  89. package/src/request-info.ts +124 -0
  90. package/src/revalidate-item.ts +211 -0
  91. package/src/root-provider.tsx +180 -0
  92. package/src/runtime.ts +555 -0
  93. package/src/seo.ts +157 -0
  94. package/src/server/configs.ts +178 -0
  95. package/src/server/normalize-page-url.ts +73 -0
  96. package/src/server/revalidate-handler.ts +357 -0
  97. package/src/server/server-client.ts +728 -0
  98. package/src/server.ts +67 -0
  99. package/src/studio-bridge.tsx +82 -0
  100. package/src/studio-connect.tsx +88 -0
  101. package/src/studio-router.ts +85 -0
  102. package/src/studio-script-src.ts +128 -0
  103. package/src/theme-settings-store.ts +47 -0
  104. package/src/translate.ts +125 -0
  105. package/src/translation-context.tsx +182 -0
  106. package/src/translation-store.ts +69 -0
  107. package/src/types.ts +753 -0
  108. package/src/use-weaverse-next-studio.tsx +106 -0
  109. package/src/utils.ts +49 -0
  110. package/dist/chunk-6PMZ77RA.mjs.map +0 -1
  111. package/dist/index.d.mts +0 -580
  112. package/dist/index.d.ts +0 -580
  113. package/dist/seo-Dos9t22_.d.mts +0 -477
  114. package/dist/seo-Dos9t22_.d.ts +0 -477
  115. package/dist/server.d.mts +0 -99
  116. package/dist/server.d.ts +0 -99
package/dist/server.js CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var schema = require('@weaverse/schema');
4
+
3
5
  // src/seo.ts
4
6
  function hasOpenGraphContent(seo) {
5
7
  return Boolean(seo?.title || seo?.description || seo?.image || seo?.type);
@@ -7,6 +9,15 @@ function hasOpenGraphContent(seo) {
7
9
  function hasTwitterContent(seo) {
8
10
  return Boolean(seo?.title || seo?.description || seo?.image || seo?.cardType);
9
11
  }
12
+ function normalizeTwitterCard(cardType) {
13
+ return cardType === "summary_large_image" ? "summary_large_image" : "summary";
14
+ }
15
+ function normalizeOpenGraphType(type) {
16
+ if (type === "article" || type === "profile" || type === "video.other") {
17
+ return type;
18
+ }
19
+ return "website";
20
+ }
10
21
  function formatWeaverseNextSeoMetadata(seo) {
11
22
  let index = seo?.robots?.index !== false;
12
23
  let follow = seo?.robots?.follow !== false;
@@ -34,13 +45,13 @@ function formatWeaverseNextSeoMetadata(seo) {
34
45
  title: openGraph?.title,
35
46
  description: openGraph?.description,
36
47
  images: openGraph?.image ? [openGraph.image] : void 0,
37
- type: openGraph?.type || "website"
48
+ type: normalizeOpenGraphType(openGraph?.type)
38
49
  };
39
50
  }
40
51
  let twitter = seo.twitter;
41
52
  if (hasTwitterContent(twitter)) {
42
53
  metadata.twitter = {
43
- card: twitter?.cardType || "summary",
54
+ card: normalizeTwitterCard(twitter?.cardType),
44
55
  title: twitter?.title,
45
56
  description: twitter?.description,
46
57
  images: twitter?.image ? [twitter.image] : void 0
@@ -127,7 +138,6 @@ function getWeaverseNextConfigs(context, options = {}) {
127
138
  envProjectId: readEnv(env, "WEAVERSE_PROJECT_ID") || "",
128
139
  weaverseHost,
129
140
  weaverseApiBase,
130
- weaverseApiKey: lastParam(searchParams, "weaverseApiKey") || readEnv(env, "WEAVERSE_API_KEY") || "",
131
141
  weaverseVersion: lastParam(searchParams, "weaverseVersion") || options.weaverseVersion || "",
132
142
  isDesignMode,
133
143
  isPreviewMode,
@@ -140,6 +150,82 @@ function getWeaverseNextConfigs(context, options = {}) {
140
150
  };
141
151
  }
142
152
 
153
+ // src/request-info.ts
154
+ function toUrl2(value) {
155
+ return typeof value === "string" ? new URL(value, "http://localhost") : value;
156
+ }
157
+ function getSearchParamsFromContext(context) {
158
+ if (context?.searchParams) {
159
+ return new URLSearchParams(context.searchParams);
160
+ }
161
+ if (context?.url) {
162
+ let url = toUrl2(context.url);
163
+ return new URLSearchParams(url.searchParams);
164
+ }
165
+ return new URLSearchParams();
166
+ }
167
+ function withPathPrefix(pathname, i18n) {
168
+ let raw = typeof i18n?.pathPrefix === "string" ? i18n.pathPrefix : "";
169
+ let segments = raw.split("/").filter(Boolean);
170
+ let prefix = segments.length > 0 ? `/${segments.join("/")}` : "";
171
+ if (prefix === "" || pathname === prefix || pathname.startsWith(`${prefix}/`)) {
172
+ return pathname;
173
+ }
174
+ return pathname === "/" ? prefix : `${prefix}${pathname}`;
175
+ }
176
+ function getPathnameFromContext(context) {
177
+ if (context?.pathname) {
178
+ return withPathPrefix(context.pathname, context.i18n);
179
+ }
180
+ if (context?.url) {
181
+ let url = toUrl2(context.url);
182
+ return withPathPrefix(url.pathname || "/", context.i18n);
183
+ }
184
+ return "/";
185
+ }
186
+ function coerceQueryValue(value) {
187
+ if (value === "true") {
188
+ return true;
189
+ }
190
+ if (value === "false") {
191
+ return false;
192
+ }
193
+ return value;
194
+ }
195
+ function toQueryRecord(searchParams) {
196
+ let queries = {};
197
+ for (let [key, value] of searchParams.entries()) {
198
+ queries[key] = coerceQueryValue(value);
199
+ }
200
+ return queries;
201
+ }
202
+ var TRANSIENT_STUDIO_PARAMS = /* @__PURE__ */ new Set([
203
+ "weaverseDraftItem",
204
+ // Legacy name from the original design-mode draft-item spike. Keep it out of
205
+ // runtime requestInfo too, in case an older Builder bundle is in front of a
206
+ // newer Next storefront.
207
+ "__weaverseDraftItem"
208
+ ]);
209
+ function getRequestInfoSearchParams(context) {
210
+ let searchParams = new URLSearchParams(getSearchParamsFromContext(context));
211
+ for (let key of TRANSIENT_STUDIO_PARAMS) {
212
+ searchParams.delete(key);
213
+ }
214
+ return searchParams;
215
+ }
216
+ function buildWeaverseNextRequestInfo(context) {
217
+ let searchParams = getRequestInfoSearchParams(context);
218
+ let search = searchParams.toString();
219
+ return {
220
+ pathname: getPathnameFromContext(context),
221
+ search: search ? `?${search}` : "",
222
+ queries: toQueryRecord(searchParams),
223
+ ...context?.i18n ? { i18n: context.i18n } : {},
224
+ ...context?.pageType ? { pageType: context.pageType } : {},
225
+ ...context?.handle ? { handle: context.handle } : {}
226
+ };
227
+ }
228
+
143
229
  // src/server/normalize-page-url.ts
144
230
  var KEPT_PARAM_RE = /^(?:__revisionId|__weaverseDraftItem|isDesignMode|weaverse)/;
145
231
  var DATA_SUFFIX = ".data";
@@ -165,12 +251,49 @@ function normalizeNextPageUrl(url) {
165
251
  }
166
252
  function resolveRequestUrl(context) {
167
253
  if (context?.url) {
168
- return typeof context.url === "string" ? context.url : context.url.toString();
254
+ let raw = String(context.url);
255
+ let url = new URL(raw, "http://localhost");
256
+ let pathname2 = withPathPrefix(url.pathname, context.i18n);
257
+ if (pathname2 === url.pathname) {
258
+ return raw;
259
+ }
260
+ url.pathname = pathname2;
261
+ return url.toString();
169
262
  }
170
- let pathname = context?.pathname || "/";
263
+ let pathname = withPathPrefix(context?.pathname || "/", context?.i18n);
171
264
  let search = context?.searchParams ? new URLSearchParams(context.searchParams).toString() : "";
172
265
  return `http://localhost${pathname}${search ? `?${search}` : ""}`;
173
266
  }
267
+ var DENIED_ROUTE_CONTEXT_PARAMS = [
268
+ "weaverseprojectid",
269
+ "weaversehost",
270
+ "weaverseapikey",
271
+ "weaverseapibase",
272
+ "weaversepublicapibase",
273
+ "weaverseversion",
274
+ "projectid",
275
+ "weaversedraftitem",
276
+ "__weaversedraftitem",
277
+ "_rsc"
278
+ ];
279
+ var ROUTE_CONTEXT_I18N_KEYS = [
280
+ "country",
281
+ "label",
282
+ "language",
283
+ "locale",
284
+ "pathPrefix"
285
+ ];
286
+ function sanitizeRouteContextSearch(search) {
287
+ let params = new URLSearchParams(search);
288
+ let denied = new Set(DENIED_ROUTE_CONTEXT_PARAMS);
289
+ for (let key of [...new Set(params.keys())]) {
290
+ if (denied.has(key.toLowerCase())) {
291
+ params.delete(key);
292
+ }
293
+ }
294
+ let serialized = params.toString();
295
+ return serialized ? `?${serialized}` : "";
296
+ }
174
297
 
175
298
  // src/utils.ts
176
299
  function generateDataFromSchema(schema) {
@@ -200,6 +323,119 @@ var STATUS_BAD_REQUEST = 400;
200
323
  var STATUS_NOT_FOUND = 404;
201
324
  var STATUS_UNPROCESSABLE = 422;
202
325
  var STATUS_SERVER_ERROR = 500;
326
+ var MAX_PATHNAME_LENGTH = 2048;
327
+ var MAX_SEARCH_LENGTH = 8192;
328
+ var MAX_HANDLE_LENGTH = 512;
329
+ var MAX_I18N_FIELD_LENGTH = 256;
330
+ var CONTROL_CHAR_PATTERN = /[\u0000-\u001F\u007F]/;
331
+ function isValidPathname(pathname) {
332
+ if (!pathname || pathname.length > MAX_PATHNAME_LENGTH) {
333
+ return false;
334
+ }
335
+ if (pathname[0] !== "/" || pathname.startsWith("//")) {
336
+ return false;
337
+ }
338
+ if (pathname.includes("\\") || pathname.includes("?")) {
339
+ return false;
340
+ }
341
+ if (pathname.includes("#") || CONTROL_CHAR_PATTERN.test(pathname)) {
342
+ return false;
343
+ }
344
+ return true;
345
+ }
346
+ function isPlainObject(value) {
347
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
348
+ return false;
349
+ }
350
+ let proto = Object.getPrototypeOf(value);
351
+ return proto === Object.prototype || proto === null;
352
+ }
353
+ function sanitizeRouteContextI18n(input) {
354
+ if (input === void 0) {
355
+ return;
356
+ }
357
+ if (!isPlainObject(input)) {
358
+ return null;
359
+ }
360
+ let source = input;
361
+ let allowed = new Set(ROUTE_CONTEXT_I18N_KEYS);
362
+ for (let key of Object.keys(source)) {
363
+ if (!allowed.has(key)) {
364
+ return null;
365
+ }
366
+ }
367
+ let result = {};
368
+ for (let key of ROUTE_CONTEXT_I18N_KEYS) {
369
+ let value = source[key];
370
+ if (value === void 0) {
371
+ continue;
372
+ }
373
+ if (typeof value !== "string" || value.length > MAX_I18N_FIELD_LENGTH) {
374
+ return null;
375
+ }
376
+ result[key] = value;
377
+ }
378
+ return Object.keys(result).length ? result : void 0;
379
+ }
380
+ function reconstructRouteContext(request, routeContext) {
381
+ if (typeof routeContext !== "object" || routeContext === null || Array.isArray(routeContext)) {
382
+ return null;
383
+ }
384
+ let { pathname, search, handle, pageType, i18n } = routeContext;
385
+ if (typeof pathname !== "string" || !isValidPathname(pathname)) {
386
+ return null;
387
+ }
388
+ if (typeof search !== "string" || search.length > MAX_SEARCH_LENGTH) {
389
+ return null;
390
+ }
391
+ let rawSearch = search;
392
+ if (rawSearch.length && !rawSearch.startsWith("?")) {
393
+ return null;
394
+ }
395
+ let sanitizedI18n = sanitizeRouteContextI18n(i18n);
396
+ if (sanitizedI18n === null) {
397
+ return null;
398
+ }
399
+ let resolvedPageType;
400
+ if (pageType !== void 0) {
401
+ let parsed = schema.PageTypeSchema.safeParse(pageType);
402
+ if (!parsed.success) {
403
+ return null;
404
+ }
405
+ resolvedPageType = parsed.data;
406
+ }
407
+ let resolvedHandle;
408
+ if (handle !== void 0) {
409
+ if (typeof handle !== "string" || !handle || handle.length > MAX_HANDLE_LENGTH) {
410
+ return null;
411
+ }
412
+ resolvedHandle = handle;
413
+ }
414
+ let endpointUrl = new URL(request.url);
415
+ let routeUrl = new URL(endpointUrl.origin);
416
+ routeUrl.pathname = pathname;
417
+ routeUrl.search = sanitizeRouteContextSearch(rawSearch);
418
+ let canonicalPathname = routeUrl.pathname;
419
+ let searchParams = routeUrl.searchParams;
420
+ let lastParam2 = (key) => {
421
+ let values = searchParams.getAll(key);
422
+ return values.length ? values.at(-1) : void 0;
423
+ };
424
+ return {
425
+ pathname: canonicalPathname,
426
+ searchParams,
427
+ url: routeUrl,
428
+ // Headers come from the actual same-origin POST, never its JSON body.
429
+ headers: new Headers(request.headers),
430
+ ...sanitizedI18n ? { i18n: sanitizedI18n } : {},
431
+ ...resolvedPageType ? { pageType: resolvedPageType } : {},
432
+ ...resolvedHandle ? { handle: resolvedHandle } : {},
433
+ isDesignMode: lastParam2("isDesignMode") === "true",
434
+ isPreviewMode: lastParam2("isPreviewMode") === "true",
435
+ isRevisionPreview: searchParams.has("__revisionId"),
436
+ sectionType: lastParam2("sectionType") || void 0
437
+ };
438
+ }
203
439
  function json(body, status) {
204
440
  return new Response(JSON.stringify(body), {
205
441
  status,
@@ -233,9 +469,18 @@ function createWeaverseNextRevalidateHandler(config) {
233
469
  if (!draftItem) {
234
470
  return json({ error: "invalid-payload" }, STATUS_BAD_REQUEST);
235
471
  }
472
+ let requestContext;
473
+ let body = payload;
474
+ if (Object.hasOwn(body, "routeContext")) {
475
+ let reconstructed = reconstructRouteContext(request, body.routeContext);
476
+ if (!reconstructed) {
477
+ return json({ error: "invalid-route-context" }, STATUS_BAD_REQUEST);
478
+ }
479
+ requestContext = reconstructed;
480
+ }
236
481
  let client;
237
482
  try {
238
- client = await config.getClient(request);
483
+ client = await config.getClient(request, requestContext);
239
484
  } catch (error) {
240
485
  console.error("\u274C Revalidate handler getClient failed.", error);
241
486
  return json({ error: "client-init-failed" }, STATUS_SERVER_ERROR);
@@ -350,71 +595,6 @@ async function runWeaverseComponentLoaders(args) {
350
595
  return data;
351
596
  }
352
597
 
353
- // src/request-info.ts
354
- function toUrl2(value) {
355
- return typeof value === "string" ? new URL(value, "http://localhost") : value;
356
- }
357
- function getSearchParamsFromContext(context) {
358
- if (context?.searchParams) {
359
- return new URLSearchParams(context.searchParams);
360
- }
361
- if (context?.url) {
362
- let url = toUrl2(context.url);
363
- return new URLSearchParams(url.searchParams);
364
- }
365
- return new URLSearchParams();
366
- }
367
- function getPathnameFromContext(context) {
368
- if (context?.pathname) {
369
- return context.pathname;
370
- }
371
- if (context?.url) {
372
- let url = toUrl2(context.url);
373
- return url.pathname || "/";
374
- }
375
- return "/";
376
- }
377
- function coerceQueryValue(value) {
378
- if (value === "true") {
379
- return true;
380
- }
381
- if (value === "false") {
382
- return false;
383
- }
384
- return value;
385
- }
386
- function toQueryRecord(searchParams) {
387
- let queries = {};
388
- for (let [key, value] of searchParams.entries()) {
389
- queries[key] = coerceQueryValue(value);
390
- }
391
- return queries;
392
- }
393
- var TRANSIENT_STUDIO_PARAMS = /* @__PURE__ */ new Set([
394
- "weaverseDraftItem",
395
- // Legacy name from the original design-mode draft-item spike. Keep it out of
396
- // runtime requestInfo too, in case an older Builder bundle is in front of a
397
- // newer Next storefront.
398
- "__weaverseDraftItem"
399
- ]);
400
- function getRequestInfoSearchParams(context) {
401
- let searchParams = new URLSearchParams(getSearchParamsFromContext(context));
402
- for (let key of TRANSIENT_STUDIO_PARAMS) {
403
- searchParams.delete(key);
404
- }
405
- return searchParams;
406
- }
407
- function buildWeaverseNextRequestInfo(context) {
408
- let searchParams = getRequestInfoSearchParams(context);
409
- let search = searchParams.toString();
410
- return {
411
- pathname: getPathnameFromContext(context),
412
- search: search ? `?${search}` : "",
413
- queries: toQueryRecord(searchParams),
414
- ...context?.i18n ? { i18n: context.i18n } : {}
415
- };
416
- }
417
-
418
598
  // src/server/server-client.ts
419
599
  var DEFAULT_FETCH_TIMEOUT_MS = 1e4;
420
600
  var RANDOM_ID_RADIX = 36;
@@ -810,12 +990,58 @@ var NextServerClient = class {
810
990
  return null;
811
991
  }
812
992
  };
993
+ /**
994
+ * Resolve the request locale (e.g. `fr-ca`) used for merchant overrides.
995
+ * Unlike Hydrogen — which defaults to `en`/`us` because a Hydrogen
996
+ * storefront always has an i18n context — Next apps may not thread one
997
+ * through, so a missing language or country means "no explicit locale" and
998
+ * the translation fetch is skipped rather than guessed.
999
+ */
1000
+ _resolveOverridesLocale() {
1001
+ let i18n = this.requestContext?.i18n;
1002
+ let language = typeof i18n?.language === "string" ? i18n.language.trim() : "";
1003
+ let country = typeof i18n?.country === "string" ? i18n.country.trim() : "";
1004
+ if (!(language && country)) {
1005
+ return;
1006
+ }
1007
+ return `${language.toLowerCase()}-${country.toLowerCase()}`;
1008
+ }
1009
+ /**
1010
+ * Fetch locale-specific static-text overrides from the translation API.
1011
+ * Ported from Hydrogen's `fetchMerchantOverrides`: skipped entirely when the
1012
+ * theme has no `i18n` schema (nothing translatable) or when the request has
1013
+ * no explicit locale, and never allowed to fail theme settings.
1014
+ */
1015
+ async _fetchMerchantOverrides(projectId, options) {
1016
+ let { weaverseHost } = this._baseConfigs;
1017
+ if (!(asThemeSchema(this.themeSchema)?.i18n && projectId && weaverseHost)) {
1018
+ return;
1019
+ }
1020
+ let locale = this._resolveOverridesLocale();
1021
+ if (!locale) {
1022
+ return;
1023
+ }
1024
+ let url = `${weaverseHost}/api/translation/static?projectId=${projectId}&locale=${locale}`;
1025
+ try {
1026
+ let overrides = await this.fetchWithCache(url, {
1027
+ method: "GET",
1028
+ headers: { Accept: "application/json" },
1029
+ revalidate: options.revalidate,
1030
+ tags: options.tags
1031
+ });
1032
+ return typeof overrides === "object" && overrides !== null ? overrides : void 0;
1033
+ } catch (error) {
1034
+ console.warn(
1035
+ "[WeaverseNext] Unable to load merchant overrides, using theme defaults:",
1036
+ error instanceof Error ? error.message : String(error)
1037
+ );
1038
+ return;
1039
+ }
1040
+ }
813
1041
  loadThemeSettings = async (optionsInput = {}) => {
814
1042
  let options = optionsInput;
815
1043
  let themeSchema = asThemeSchema(this.themeSchema);
816
- let defaultThemeSettings = generateDataFromSchema(
817
- this.themeSchema
818
- );
1044
+ let defaultThemeSettings = generateDataFromSchema(this.themeSchema);
819
1045
  let staticContent = themeSchema?.i18n?.staticContent;
820
1046
  try {
821
1047
  let projectId = await this.resolveProjectId();
@@ -824,16 +1050,16 @@ var NextServerClient = class {
824
1050
  }
825
1051
  let { isDesignMode } = this._baseConfigs;
826
1052
  let url = `${this._baseConfigs.weaverseApiBase}/api/public/project_configs`;
827
- let result = await this.fetchWithCache(
828
- url,
829
- {
1053
+ let [result, merchantOverrides] = await Promise.all([
1054
+ this.fetchWithCache(url, {
830
1055
  method: "POST",
831
1056
  body: JSON.stringify({ projectId, isDesignMode }),
832
1057
  headers: JSON_HEADERS,
833
1058
  revalidate: options.revalidate,
834
1059
  tags: options.tags
835
- }
836
- );
1060
+ }),
1061
+ this._fetchMerchantOverrides(projectId, options)
1062
+ ]);
837
1063
  if (typeof result !== "object" || result === null) {
838
1064
  result = { theme: defaultThemeSettings };
839
1065
  }
@@ -847,21 +1073,25 @@ var NextServerClient = class {
847
1073
  if (staticContent) {
848
1074
  result.staticContent = staticContent;
849
1075
  }
1076
+ if (merchantOverrides) {
1077
+ result.merchantOverrides = merchantOverrides;
1078
+ }
850
1079
  if (isDesignMode) {
1080
+ let serializableSchema = themeSchema ? {
1081
+ ...themeSchema,
1082
+ settings: themeSchema.settings?.map((group) => ({
1083
+ ...group,
1084
+ inputs: group?.inputs?.map(
1085
+ (inputItem) => typeof inputItem?.condition === "function" ? {
1086
+ ...inputItem,
1087
+ condition: inputItem.condition.toString()
1088
+ } : inputItem
1089
+ )
1090
+ }))
1091
+ } : void 0;
851
1092
  result = {
852
1093
  ...result,
853
- schema: themeSchema ? {
854
- ...themeSchema,
855
- settings: themeSchema.settings?.map((group) => ({
856
- ...group,
857
- inputs: group?.inputs?.map(
858
- (inputItem) => typeof inputItem?.condition === "function" ? {
859
- ...inputItem,
860
- condition: inputItem.condition.toString()
861
- } : inputItem
862
- )
863
- }))
864
- } : void 0,
1094
+ schema: serializableSchema,
865
1095
  publicEnv: this._baseConfigs.publicEnv
866
1096
  };
867
1097
  }