@weaverse/next 0.1.0-alpha.8 → 1.0.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.
- package/README.md +155 -73
- package/dist/{chunk-6PMZ77RA.mjs → chunk-LH6AAEIK.mjs} +115 -8
- package/dist/chunk-LH6AAEIK.mjs.map +1 -0
- package/dist/index.js +260 -30
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +167 -46
- package/dist/index.mjs.map +1 -1
- package/dist/server.js +321 -91
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +205 -28
- package/dist/server.mjs.map +1 -1
- package/dist/types/client.d.ts +16 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/hooks.d.ts +20 -0
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/index.d.ts +34 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/item.d.ts +60 -0
- package/dist/types/item.d.ts.map +1 -0
- package/dist/types/loader.d.ts +25 -0
- package/dist/types/loader.d.ts.map +1 -0
- package/dist/types/main.d.ts +11 -0
- package/dist/types/main.d.ts.map +1 -0
- package/dist/types/provider.d.ts +82 -0
- package/dist/types/provider.d.ts.map +1 -0
- package/dist/types/registry.d.ts +15 -0
- package/dist/types/registry.d.ts.map +1 -0
- package/dist/types/renderer.d.ts +21 -0
- package/dist/types/renderer.d.ts.map +1 -0
- package/dist/types/request-info.d.ts +19 -0
- package/dist/types/request-info.d.ts.map +1 -0
- package/dist/types/revalidate-item.d.ts +82 -0
- package/dist/types/revalidate-item.d.ts.map +1 -0
- package/dist/types/root-provider.d.ts +62 -0
- package/dist/types/root-provider.d.ts.map +1 -0
- package/dist/types/runtime.d.ts +113 -0
- package/dist/types/runtime.d.ts.map +1 -0
- package/dist/types/seo.d.ts +55 -0
- package/dist/types/seo.d.ts.map +1 -0
- package/dist/types/server/configs.d.ts +27 -0
- package/dist/types/server/configs.d.ts.map +1 -0
- package/dist/types/server/normalize-page-url.d.ts +19 -0
- package/dist/types/server/normalize-page-url.d.ts.map +1 -0
- package/dist/types/server/revalidate-handler.d.ts +55 -0
- package/dist/types/server/revalidate-handler.d.ts.map +1 -0
- package/dist/types/server/server-client.d.ts +21 -0
- package/dist/types/server/server-client.d.ts.map +1 -0
- package/dist/types/server.d.ts +19 -0
- package/dist/types/server.d.ts.map +1 -0
- package/dist/types/studio-bridge.d.ts +16 -0
- package/dist/types/studio-bridge.d.ts.map +1 -0
- package/dist/types/studio-connect.d.ts +27 -0
- package/dist/types/studio-connect.d.ts.map +1 -0
- package/dist/types/studio-router.d.ts +50 -0
- package/dist/types/studio-router.d.ts.map +1 -0
- package/dist/types/studio-script-src.d.ts +12 -0
- package/dist/types/studio-script-src.d.ts.map +1 -0
- package/dist/types/theme-settings-store.d.ts +18 -0
- package/dist/types/theme-settings-store.d.ts.map +1 -0
- package/dist/types/translation-context.d.ts +156 -0
- package/dist/types/translation-context.d.ts.map +1 -0
- package/dist/types/translation-store.d.ts +44 -0
- package/dist/types/translation-store.d.ts.map +1 -0
- package/dist/types/types.d.ts +665 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/use-weaverse-next-studio.d.ts +34 -0
- package/dist/types/use-weaverse-next-studio.d.ts.map +1 -0
- package/dist/types/utils.d.ts +12 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/package.json +12 -8
- package/src/client.ts +102 -0
- package/src/hooks.ts +50 -0
- package/src/index.ts +153 -0
- package/src/item.ts +167 -0
- package/src/loader.ts +135 -0
- package/src/main.tsx +45 -0
- package/src/provider.tsx +225 -0
- package/src/registry.ts +63 -0
- package/src/renderer.tsx +100 -0
- package/src/request-info.ts +124 -0
- package/src/revalidate-item.ts +211 -0
- package/src/root-provider.tsx +182 -0
- package/src/runtime.ts +555 -0
- package/src/seo.ts +157 -0
- package/src/server/configs.ts +178 -0
- package/src/server/normalize-page-url.ts +73 -0
- package/src/server/revalidate-handler.ts +357 -0
- package/src/server/server-client.ts +728 -0
- package/src/server.ts +67 -0
- package/src/studio-bridge.tsx +82 -0
- package/src/studio-connect.tsx +88 -0
- package/src/studio-router.ts +85 -0
- package/src/studio-script-src.ts +128 -0
- package/src/theme-settings-store.ts +47 -0
- package/src/translation-context.tsx +299 -0
- package/src/translation-store.ts +69 -0
- package/src/types.ts +753 -0
- package/src/use-weaverse-next-studio.tsx +106 -0
- package/src/utils.ts +37 -0
- package/dist/chunk-6PMZ77RA.mjs.map +0 -1
- package/dist/index.d.mts +0 -517
- package/dist/index.d.ts +0 -517
- package/dist/seo-CpN6tC36.d.mts +0 -477
- package/dist/seo-CpN6tC36.d.ts +0 -477
- package/dist/server.d.mts +0 -99
- 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
|
|
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
|
|
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
|
-
|
|
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
|
|
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:
|
|
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
|
}
|