@weaverse/hydrogen 5.23.0 → 6.0.0-beta.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/dist/index.js +29 -2271
- package/dist/index.mjs +4 -2213
- package/dist/internal.js +64 -0
- package/dist/internal.js.map +1 -0
- package/dist/internal.mjs +16 -0
- package/dist/internal.mjs.map +1 -0
- package/dist/next-server.js +14 -0
- package/dist/next-server.mjs +2 -0
- package/dist/next.js +119 -0
- package/dist/next.mjs +5 -0
- package/dist/react-router.js +68 -0
- package/dist/react-router.mjs +5 -0
- package/dist/react.js +26 -0
- package/dist/react.mjs +2 -0
- package/dist/translation-store-BpPWqZ0B.js +548 -0
- package/dist/translation-store-BpPWqZ0B.js.map +1 -0
- package/dist/translation-store-C42QdI0e.mjs +441 -0
- package/dist/translation-store-C42QdI0e.mjs.map +1 -0
- package/dist/types/WeaverseHydrogenRoot.d.ts +8 -8
- package/dist/types/WeaverseHydrogenRoot.d.ts.map +1 -1
- package/dist/types/components/index.d.ts +2 -2
- package/dist/types/components/main.d.ts +2 -2
- package/dist/types/hooks/translation-context.d.ts +2 -8
- package/dist/types/hooks/translation-context.d.ts.map +1 -1
- package/dist/types/index.d.ts +12 -33
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/internal.d.ts +24 -0
- package/dist/types/internal.d.ts.map +1 -0
- package/dist/types/next-server.d.ts +8 -0
- package/dist/types/next-server.d.ts.map +1 -0
- package/dist/types/next.d.ts +12 -0
- package/dist/types/next.d.ts.map +1 -0
- package/dist/types/react-router.d.ts +18 -0
- package/dist/types/react-router.d.ts.map +1 -0
- package/dist/types/react.d.ts +11 -0
- package/dist/types/react.d.ts.map +1 -0
- package/dist/types/seo.d.ts +4 -4
- package/dist/types/seo.d.ts.map +1 -1
- package/dist/types/types.d.ts +126 -67
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +4 -5
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/nested-key.d.ts +9 -0
- package/dist/types/utils/nested-key.d.ts.map +1 -0
- package/dist/types/utils/normalize-page-url.d.ts +1 -1
- package/dist/types/utils/product-options.d.ts +18 -0
- package/dist/types/utils/product-options.d.ts.map +1 -0
- package/dist/types/utils/translation-store.d.ts.map +1 -1
- package/dist/types/utils/use-studio.d.ts +1 -1
- package/dist/types/utils/use-studio.d.ts.map +1 -1
- package/dist/types/utils/use-theme-settings-store.d.ts +8 -8
- package/dist/types/utils/use-theme-settings-store.d.ts.map +1 -1
- package/dist/types/weaverse-client.d.ts +15 -16
- package/dist/types/weaverse-client.d.ts.map +1 -1
- package/dist/weaverse-client-Clu3u7md.mjs +1966 -0
- package/dist/weaverse-client-Clu3u7md.mjs.map +1 -0
- package/dist/weaverse-client-yC4TYuVV.js +2073 -0
- package/dist/weaverse-client-yC4TYuVV.js.map +1 -0
- package/package.json +44 -20
- package/readme.md +76 -23
- package/src/WeaverseHydrogenRoot.tsx +18 -15
- package/src/components/index.ts +2 -2
- package/src/components/main.tsx +2 -2
- package/src/hooks/translation-context.tsx +3 -28
- package/src/index.ts +42 -81
- package/src/internal.ts +64 -0
- package/src/next-server.ts +13 -0
- package/src/next.ts +35 -0
- package/src/react-router.ts +52 -0
- package/src/react.ts +16 -0
- package/src/seo.ts +5 -5
- package/src/types.ts +158 -73
- package/src/utils/index.ts +15 -14
- package/src/utils/nested-key.ts +28 -0
- package/src/utils/normalize-page-url.ts +1 -1
- package/src/utils/product-options.ts +28 -0
- package/src/utils/use-studio.ts +1 -1
- package/src/utils/use-theme-settings-store.ts +7 -7
- package/src/weaverse-client.ts +313 -148
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,2275 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
var main_default = Main;
|
|
24
|
-
var schema = schema$1.createSchema({
|
|
25
|
-
type: "main",
|
|
26
|
-
title: "Main"
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
// src/components/index.ts
|
|
30
|
-
var defaultComponents = [
|
|
31
|
-
{
|
|
32
|
-
default: main_default,
|
|
33
|
-
schema
|
|
34
|
-
}
|
|
35
|
-
];
|
|
36
|
-
function getNestedKey(obj, path, fallback) {
|
|
37
|
-
const keys = path.split(".");
|
|
38
|
-
let current = obj;
|
|
39
|
-
for (const key of keys) {
|
|
40
|
-
if (current == null || typeof current !== "object") {
|
|
41
|
-
return fallback;
|
|
42
|
-
}
|
|
43
|
-
current = current[key];
|
|
44
|
-
}
|
|
45
|
-
if (typeof current === "string") {
|
|
46
|
-
return current;
|
|
47
|
-
}
|
|
48
|
-
return fallback;
|
|
49
|
-
}
|
|
50
|
-
function interpolate(template, variables) {
|
|
51
|
-
if (!variables) {
|
|
52
|
-
return template;
|
|
53
|
-
}
|
|
54
|
-
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
|
|
55
|
-
const value = variables[key];
|
|
56
|
-
return value === void 0 ? match : String(value);
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
var TranslationContext = react$1.createContext(null);
|
|
60
|
-
TranslationContext.displayName = "WeaverseTranslationContext";
|
|
61
|
-
function createTranslate(sources) {
|
|
62
|
-
const { staticContent, merchantOverrides, designOverrides, externalT } = sources;
|
|
63
|
-
return (key, variables) => {
|
|
64
|
-
if (externalT) {
|
|
65
|
-
const external = externalT(key, variables);
|
|
66
|
-
if (external && external !== key) {
|
|
67
|
-
return external;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
const design = designOverrides && Object.hasOwn(designOverrides, key) ? designOverrides[key] : void 0;
|
|
71
|
-
const override = merchantOverrides ? getNestedKey(merchantOverrides, key) : void 0;
|
|
72
|
-
const staticValue = getNestedKey(staticContent, key);
|
|
73
|
-
const raw = design ?? override ?? staticValue ?? key;
|
|
74
|
-
return interpolate(raw, variables);
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
var EMPTY = {};
|
|
78
|
-
var NOOP_SUBSCRIBE = () => () => {
|
|
79
|
-
};
|
|
80
|
-
var NOOP_SNAPSHOT = () => EMPTY;
|
|
81
|
-
function TranslationProvider({
|
|
82
|
-
staticContent,
|
|
83
|
-
merchantOverrides,
|
|
84
|
-
t: externalT,
|
|
85
|
-
translationStore,
|
|
86
|
-
themeTextStore,
|
|
87
|
-
children
|
|
88
|
-
}) {
|
|
89
|
-
const store = translationStore ?? themeTextStore ?? null;
|
|
90
|
-
const designOverrides = react.useSafeExternalStore(
|
|
91
|
-
store?.subscribe ?? NOOP_SUBSCRIBE,
|
|
92
|
-
store?.getSnapshot ?? NOOP_SNAPSHOT,
|
|
93
|
-
store?.getServerSnapshot ?? NOOP_SNAPSHOT
|
|
94
|
-
);
|
|
95
|
-
const value = react$1.useMemo(
|
|
96
|
-
() => ({
|
|
97
|
-
t: createTranslate({
|
|
98
|
-
staticContent,
|
|
99
|
-
merchantOverrides,
|
|
100
|
-
designOverrides,
|
|
101
|
-
externalT
|
|
102
|
-
}),
|
|
103
|
-
translationStore: store,
|
|
104
|
-
// Deprecated alias — same instance, kept for backward compatibility.
|
|
105
|
-
themeTextStore: store,
|
|
106
|
-
merchantOverrides: merchantOverrides ?? null
|
|
107
|
-
}),
|
|
108
|
-
[staticContent, merchantOverrides, designOverrides, externalT, store]
|
|
109
|
-
);
|
|
110
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TranslationContext.Provider, { value, children });
|
|
111
|
-
}
|
|
112
|
-
function useTranslation() {
|
|
113
|
-
const ctx = react$1.useContext(TranslationContext);
|
|
114
|
-
if (!ctx) {
|
|
115
|
-
throw new Error(
|
|
116
|
-
"useTranslation must be used within <TranslationProvider>. Wrap your app with withWeaverse()."
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
return ctx;
|
|
120
|
-
}
|
|
121
|
-
var ThemeTextProvider = TranslationProvider;
|
|
122
|
-
var useThemeText = useTranslation;
|
|
123
|
-
function createFlatDataContext(matches) {
|
|
124
|
-
const context = {};
|
|
125
|
-
for (const match of matches) {
|
|
126
|
-
if (match.data && typeof match.data === "object") {
|
|
127
|
-
context[match.id] = match.data;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return context;
|
|
131
|
-
}
|
|
132
|
-
function useWeaverseDataContext() {
|
|
133
|
-
const matches = reactRouter.useMatches();
|
|
134
|
-
return createFlatDataContext(matches);
|
|
135
|
-
}
|
|
136
|
-
function createWeaverseDataContext(matches) {
|
|
137
|
-
return createFlatDataContext(matches);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// src/seo.ts
|
|
141
|
-
function formatMetaDescriptors(seo) {
|
|
142
|
-
if (!seo) {
|
|
143
|
-
return [{ name: "robots", content: "index,follow" }];
|
|
144
|
-
}
|
|
145
|
-
let descriptors = [];
|
|
146
|
-
if (seo.title) {
|
|
147
|
-
descriptors.push({ title: seo.title });
|
|
148
|
-
}
|
|
149
|
-
if (seo.description) {
|
|
150
|
-
descriptors.push({ name: "description", content: seo.description });
|
|
151
|
-
}
|
|
152
|
-
if (seo.keywords) {
|
|
153
|
-
descriptors.push({ name: "keywords", content: seo.keywords });
|
|
154
|
-
}
|
|
155
|
-
if (seo.canonicalUrl) {
|
|
156
|
-
descriptors.push({
|
|
157
|
-
tagName: "link",
|
|
158
|
-
rel: "canonical",
|
|
159
|
-
href: seo.canonicalUrl
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
let og = seo.openGraph;
|
|
163
|
-
if (og && (og.title || og.description || og.image || og.type)) {
|
|
164
|
-
if (og.title) {
|
|
165
|
-
descriptors.push({ property: "og:title", content: og.title });
|
|
166
|
-
}
|
|
167
|
-
if (og.description) {
|
|
168
|
-
descriptors.push({ property: "og:description", content: og.description });
|
|
169
|
-
}
|
|
170
|
-
if (og.image) {
|
|
171
|
-
descriptors.push({ property: "og:image", content: og.image });
|
|
172
|
-
}
|
|
173
|
-
descriptors.push({ property: "og:type", content: og.type || "website" });
|
|
174
|
-
}
|
|
175
|
-
let tw = seo.twitter;
|
|
176
|
-
if (tw && (tw.title || tw.description || tw.image || tw.cardType)) {
|
|
177
|
-
descriptors.push({
|
|
178
|
-
name: "twitter:card",
|
|
179
|
-
content: tw.cardType || "summary"
|
|
180
|
-
});
|
|
181
|
-
if (tw.title) {
|
|
182
|
-
descriptors.push({ name: "twitter:title", content: tw.title });
|
|
183
|
-
}
|
|
184
|
-
if (tw.description) {
|
|
185
|
-
descriptors.push({ name: "twitter:description", content: tw.description });
|
|
186
|
-
}
|
|
187
|
-
if (tw.image) {
|
|
188
|
-
descriptors.push({ name: "twitter:image", content: tw.image });
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
let index = seo.robots?.index !== false;
|
|
192
|
-
let follow = seo.robots?.follow !== false;
|
|
193
|
-
descriptors.push({
|
|
194
|
-
name: "robots",
|
|
195
|
-
content: `${index ? "index" : "noindex"},${follow ? "follow" : "nofollow"}`
|
|
196
|
-
});
|
|
197
|
-
return descriptors;
|
|
198
|
-
}
|
|
199
|
-
function getWeaverseSeoMeta(data) {
|
|
200
|
-
if (!data) {
|
|
201
|
-
return formatMetaDescriptors(null);
|
|
202
|
-
}
|
|
203
|
-
let page = "items" in data && "id" in data ? data : data.page ?? null;
|
|
204
|
-
return formatMetaDescriptors(page?.seo ?? null);
|
|
205
|
-
}
|
|
206
|
-
function isProjectIdFunction(projectId) {
|
|
207
|
-
return typeof projectId === "function";
|
|
208
|
-
}
|
|
209
|
-
var WeaverseError = class _WeaverseError extends Error {
|
|
210
|
-
/** Machine-readable error code. */
|
|
211
|
-
code;
|
|
212
|
-
/** HTTP status associated with the failure, when available. */
|
|
213
|
-
statusCode;
|
|
214
|
-
/** Structured diagnostic details for logging and error handling. */
|
|
215
|
-
context;
|
|
216
|
-
/** Creates a Weaverse request error with a stable code and diagnostics. */
|
|
217
|
-
constructor(message, code = "WEAVERSE_ERROR", statusCode, context) {
|
|
218
|
-
super(message);
|
|
219
|
-
this.name = "WeaverseError";
|
|
220
|
-
this.code = code;
|
|
221
|
-
this.statusCode = statusCode;
|
|
222
|
-
this.context = context;
|
|
223
|
-
if (Error.captureStackTrace) {
|
|
224
|
-
Error.captureStackTrace(this, _WeaverseError);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
function isWithCacheFetchResponse(response) {
|
|
229
|
-
return typeof response === "object" && response !== null && "data" in response && "response" in response;
|
|
230
|
-
}
|
|
231
|
-
function isFetchProjectPayload(payload) {
|
|
232
|
-
return typeof payload === "object" && payload !== null && "page" in payload && "project" in payload && "pageAssignment" in payload;
|
|
233
|
-
}
|
|
234
|
-
function hasError(response) {
|
|
235
|
-
return typeof response === "object" && response !== null && "error" in response && typeof response.error === "string";
|
|
236
|
-
}
|
|
237
|
-
function isThemeSettingsResponse(data) {
|
|
238
|
-
if (typeof data !== "object" || data === null) {
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
const record = data;
|
|
242
|
-
return "theme" in record && typeof record.theme === "object" && record.theme !== null;
|
|
243
|
-
}
|
|
244
|
-
function isValidHydrogenSchema(schema2) {
|
|
245
|
-
return schema$1.isValidSchema(schema2);
|
|
246
|
-
}
|
|
247
|
-
function hasWeaverseStudio(window2) {
|
|
248
|
-
return "weaverseStudio" in window2 && typeof window2.weaverseStudio === "object";
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// src/utils/studio-script-src.ts
|
|
252
|
-
var DEFAULT_WEAVERSE_HOST = "https://studio.weaverse.io";
|
|
253
|
-
var TRUSTED_STUDIO_DOMAINS = ["weaverse.io", "weaverse.dev"];
|
|
254
|
-
function isLoopbackHostname(hostname) {
|
|
255
|
-
return hostname === "localhost" || hostname === "127.0.0.1" || hostname.endsWith(".localhost");
|
|
256
|
-
}
|
|
257
|
-
function isTrustedStudioHost(host, options) {
|
|
258
|
-
let parsed;
|
|
259
|
-
try {
|
|
260
|
-
parsed = new URL(host);
|
|
261
|
-
} catch {
|
|
262
|
-
return false;
|
|
263
|
-
}
|
|
264
|
-
let { hostname, protocol } = parsed;
|
|
265
|
-
if (options?.allowLoopback && isLoopbackHostname(hostname)) {
|
|
266
|
-
return protocol === "http:" || protocol === "https:";
|
|
267
|
-
}
|
|
268
|
-
if (protocol !== "https:") {
|
|
269
|
-
return false;
|
|
270
|
-
}
|
|
271
|
-
return TRUSTED_STUDIO_DOMAINS.some(
|
|
272
|
-
(domain) => hostname === domain || hostname.endsWith(`.${domain}`)
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
function getStudioScriptSrc(mode) {
|
|
276
|
-
let {
|
|
277
|
-
isDesignMode,
|
|
278
|
-
isPreviewMode,
|
|
279
|
-
isRevisionPreview,
|
|
280
|
-
weaverseHost,
|
|
281
|
-
weaverseVersion
|
|
282
|
-
} = mode;
|
|
283
|
-
let base = `${weaverseHost}/static/studio/hydrogen`;
|
|
284
|
-
let version = `?v=${weaverseVersion}`;
|
|
285
|
-
if (isRevisionPreview || isPreviewMode) {
|
|
286
|
-
return `${base}/preview.js${version}`;
|
|
287
|
-
}
|
|
288
|
-
if (isDesignMode) {
|
|
289
|
-
return `${base}/index.js${version}`;
|
|
290
|
-
}
|
|
291
|
-
return null;
|
|
292
|
-
}
|
|
293
|
-
function resolveStudioScriptSrc(search, storefrontHostname = "") {
|
|
294
|
-
let params = new URLSearchParams(search);
|
|
295
|
-
let last = (key) => params.getAll(key).at(-1);
|
|
296
|
-
let host = last("weaverseHost");
|
|
297
|
-
if (host) {
|
|
298
|
-
let allowLoopback = isLoopbackHostname(storefrontHostname);
|
|
299
|
-
if (!isTrustedStudioHost(host, { allowLoopback })) {
|
|
300
|
-
return null;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
return getStudioScriptSrc({
|
|
304
|
-
isDesignMode: last("isDesignMode") === "true",
|
|
305
|
-
isPreviewMode: last("isPreviewMode") === "true",
|
|
306
|
-
isRevisionPreview: params.has("__revisionId"),
|
|
307
|
-
weaverseHost: host || DEFAULT_WEAVERSE_HOST,
|
|
308
|
-
weaverseVersion: last("weaverseVersion") || ""
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// src/utils/index.ts
|
|
313
|
-
var warnedTypes = /* @__PURE__ */ new Set();
|
|
314
|
-
function logOnce(type, message) {
|
|
315
|
-
if (!warnedTypes.has(type)) {
|
|
316
|
-
console.warn(message);
|
|
317
|
-
warnedTypes.add(type);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
function deepMergeArrays(target, source) {
|
|
321
|
-
return [...target, ...source];
|
|
322
|
-
}
|
|
323
|
-
function mergeInspectorSettings(settings, inspector, type) {
|
|
324
|
-
if (!inspector?.length) {
|
|
325
|
-
return settings;
|
|
326
|
-
}
|
|
327
|
-
if (!settings?.length) {
|
|
328
|
-
return inspector;
|
|
329
|
-
}
|
|
330
|
-
console.info(
|
|
331
|
-
`Schema "${type}": Both 'settings' and 'inspector' found. Using 'settings' with 'inspector' as fallback.`
|
|
332
|
-
);
|
|
333
|
-
return deepMergeArrays(settings, inspector);
|
|
334
|
-
}
|
|
335
|
-
function getRequestQueries(request, options) {
|
|
336
|
-
let url = new URL(request.url);
|
|
337
|
-
let queries = {};
|
|
338
|
-
for (let [key, value] of url.searchParams.entries()) {
|
|
339
|
-
if (options?.allowedKeys && !options.allowedKeys.includes(key)) {
|
|
340
|
-
continue;
|
|
341
|
-
}
|
|
342
|
-
if (value === "true") {
|
|
343
|
-
queries[key] = true;
|
|
344
|
-
} else if (value === "false") {
|
|
345
|
-
queries[key] = false;
|
|
346
|
-
} else {
|
|
347
|
-
queries[key] = value;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
return queries;
|
|
351
|
-
}
|
|
352
|
-
function getWeaverseConfigs(request, env) {
|
|
353
|
-
let queries = getRequestQueries(request);
|
|
354
|
-
let {
|
|
355
|
-
WEAVERSE_PROJECT_ID,
|
|
356
|
-
WEAVERSE_API_KEY,
|
|
357
|
-
WEAVERSE_HOST,
|
|
358
|
-
WEAVERSE_PUBLIC_API_BASE,
|
|
359
|
-
PUBLIC_STORE_DOMAIN,
|
|
360
|
-
PUBLIC_STOREFRONT_API_TOKEN
|
|
361
|
-
} = env || {};
|
|
362
|
-
let envFromProcess = typeof process !== "undefined" && process.env || {};
|
|
363
|
-
let {
|
|
364
|
-
weaverseProjectId,
|
|
365
|
-
weaverseHost,
|
|
366
|
-
isDesignMode,
|
|
367
|
-
isPreviewMode,
|
|
368
|
-
sectionType,
|
|
369
|
-
weaverseVersion,
|
|
370
|
-
weaverseApiKey
|
|
371
|
-
} = queries;
|
|
372
|
-
let url = new URL(request.url);
|
|
373
|
-
let isRevisionPreview = url.searchParams.has("__revisionId");
|
|
374
|
-
let configuredWeaverseHost = WEAVERSE_HOST || envFromProcess.WEAVERSE_HOST;
|
|
375
|
-
let trustedUrlHost = typeof weaverseHost === "string" && isTrustedStudioHost(weaverseHost) ? weaverseHost : "";
|
|
376
|
-
let resolvedWeaverseHost = trustedUrlHost || configuredWeaverseHost || "https://studio.weaverse.io";
|
|
377
|
-
let resolvedWeaverseApiBase = trustedUrlHost ? trustedUrlHost : WEAVERSE_PUBLIC_API_BASE || envFromProcess.WEAVERSE_PUBLIC_API_BASE || (configuredWeaverseHost && configuredWeaverseHost !== "https://studio.weaverse.io" ? configuredWeaverseHost : "https://api.weaverse.io");
|
|
378
|
-
return {
|
|
379
|
-
projectId: weaverseProjectId || WEAVERSE_PROJECT_ID || envFromProcess.WEAVERSE_PROJECT_ID || "",
|
|
380
|
-
weaverseHost: resolvedWeaverseHost,
|
|
381
|
-
weaverseApiBase: resolvedWeaverseApiBase,
|
|
382
|
-
weaversePublicApiBase: resolvedWeaverseApiBase,
|
|
383
|
-
weaverseApiKey: weaverseApiKey || WEAVERSE_API_KEY || envFromProcess.WEAVERSE_API_KEY || "",
|
|
384
|
-
weaverseVersion: weaverseVersion || "",
|
|
385
|
-
isDesignMode,
|
|
386
|
-
isPreviewMode,
|
|
387
|
-
isRevisionPreview,
|
|
388
|
-
sectionType: sectionType || "",
|
|
389
|
-
publicEnv: {
|
|
390
|
-
PUBLIC_STORE_DOMAIN: PUBLIC_STORE_DOMAIN || "",
|
|
391
|
-
PUBLIC_STOREFRONT_API_TOKEN: PUBLIC_STOREFRONT_API_TOKEN || ""
|
|
392
|
-
}
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
var schemaDefaultsCache = /* @__PURE__ */ new WeakMap();
|
|
396
|
-
function generateDataFromSchema(schema2) {
|
|
397
|
-
const cached = schemaDefaultsCache.get(schema2);
|
|
398
|
-
if (cached) {
|
|
399
|
-
return cached;
|
|
400
|
-
}
|
|
401
|
-
let data = {};
|
|
402
|
-
let inspectorGroups = [];
|
|
403
|
-
const isComponentSchema = (s) => "type" in s && typeof s.type === "string";
|
|
404
|
-
if (isComponentSchema(schema2)) {
|
|
405
|
-
if (schema2.settings) {
|
|
406
|
-
inspectorGroups = schema2.settings;
|
|
407
|
-
}
|
|
408
|
-
if (schema2.inspector) {
|
|
409
|
-
if (schema2.settings?.length) {
|
|
410
|
-
inspectorGroups = mergeInspectorSettings(
|
|
411
|
-
schema2.settings,
|
|
412
|
-
schema2.inspector,
|
|
413
|
-
schema2.type || "unknown"
|
|
414
|
-
);
|
|
415
|
-
} else {
|
|
416
|
-
inspectorGroups = schema2.inspector;
|
|
417
|
-
if (schema2.type) {
|
|
418
|
-
logOnce(
|
|
419
|
-
schema2.type,
|
|
420
|
-
`\u26A0\uFE0F Schema "${schema2.type}": The 'inspector' property is deprecated. Please use 'settings' instead.`
|
|
421
|
-
);
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
} else {
|
|
426
|
-
if (schema2.settings) {
|
|
427
|
-
inspectorGroups = schema2.settings;
|
|
428
|
-
}
|
|
429
|
-
if (schema2.inspector) {
|
|
430
|
-
if (schema2.settings?.length) {
|
|
431
|
-
inspectorGroups = mergeInspectorSettings(
|
|
432
|
-
schema2.settings,
|
|
433
|
-
schema2.inspector,
|
|
434
|
-
"Theme Schema"
|
|
435
|
-
);
|
|
436
|
-
} else {
|
|
437
|
-
inspectorGroups = schema2.inspector;
|
|
438
|
-
logOnce(
|
|
439
|
-
"ThemeSchema",
|
|
440
|
-
`\u26A0\uFE0F Theme Schema: The 'inspector' property is deprecated. Please use 'settings' instead.`
|
|
441
|
-
);
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
if (inspectorGroups?.length) {
|
|
446
|
-
for (let group of inspectorGroups) {
|
|
447
|
-
for (let input of group.inputs) {
|
|
448
|
-
let { name, defaultValue } = input;
|
|
449
|
-
if (name && defaultValue !== null && defaultValue !== void 0) {
|
|
450
|
-
data[name] = defaultValue;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
schemaDefaultsCache.set(schema2, data);
|
|
456
|
-
return data;
|
|
457
|
-
}
|
|
458
|
-
function recursivelyAddDataItem(type, components, items, initData) {
|
|
459
|
-
let component = components.find((c) => c.schema.type === type);
|
|
460
|
-
if (!component) {
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
let childIds = [];
|
|
464
|
-
let id = crypto.randomUUID();
|
|
465
|
-
let { children, ...data } = component.schema?.presets || {};
|
|
466
|
-
if (children) {
|
|
467
|
-
for (let c of children) {
|
|
468
|
-
let { type: type2, children: children2, ...data2 } = c;
|
|
469
|
-
let childId = recursivelyAddDataItem(type2, components, items, data2);
|
|
470
|
-
childIds.push({ id: childId });
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
items.push({
|
|
474
|
-
data: { ...data, ...initData },
|
|
475
|
-
id,
|
|
476
|
-
type,
|
|
477
|
-
children: childIds
|
|
478
|
-
});
|
|
479
|
-
return id;
|
|
480
|
-
}
|
|
481
|
-
function getPreviewData(type, components, weaverseHost) {
|
|
482
|
-
let items = [];
|
|
483
|
-
return {
|
|
484
|
-
project: { id: "x", weaverseShopId: "shop-id", name: "Section Preview" },
|
|
485
|
-
configs: {
|
|
486
|
-
projectId: "x",
|
|
487
|
-
weaverseHost,
|
|
488
|
-
isDesignMode: false,
|
|
489
|
-
isPreviewMode: true,
|
|
490
|
-
requestInfo: {
|
|
491
|
-
i18n: {
|
|
492
|
-
label: "United States (USD $)",
|
|
493
|
-
language: "EN",
|
|
494
|
-
country: "US",
|
|
495
|
-
currency: "USD",
|
|
496
|
-
pathPrefix: ""
|
|
497
|
-
},
|
|
498
|
-
queries: {},
|
|
499
|
-
pathname: "/",
|
|
500
|
-
search: ""
|
|
501
|
-
}
|
|
502
|
-
},
|
|
503
|
-
page: {
|
|
504
|
-
id: "weaverse-preview-page",
|
|
505
|
-
name: "Preview section",
|
|
506
|
-
rootId: "1",
|
|
507
|
-
items: [
|
|
508
|
-
{
|
|
509
|
-
data: {},
|
|
510
|
-
id: "1",
|
|
511
|
-
type: "main",
|
|
512
|
-
children: [{ id: recursivelyAddDataItem(type, components, items) }]
|
|
513
|
-
},
|
|
514
|
-
...items
|
|
515
|
-
]
|
|
516
|
-
}
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
// src/utils/translation-store.ts
|
|
521
|
-
var TranslationStore = class {
|
|
522
|
-
/** Current flat translation overrides keyed by dot-path. */
|
|
523
|
-
overrides = {};
|
|
524
|
-
listeners = /* @__PURE__ */ new Set();
|
|
525
|
-
/** Replaces all overrides and notifies subscribers. */
|
|
526
|
-
setOverrides = (overrides) => {
|
|
527
|
-
this.overrides = { ...overrides };
|
|
528
|
-
this.emit();
|
|
529
|
-
};
|
|
530
|
-
/** Merges changed overrides and notifies subscribers. */
|
|
531
|
-
updateOverrides = (newOverrides) => {
|
|
532
|
-
this.overrides = { ...this.overrides, ...newOverrides };
|
|
533
|
-
this.emit();
|
|
534
|
-
};
|
|
535
|
-
/** Returns the current client snapshot for `useSyncExternalStore`. */
|
|
536
|
-
getSnapshot = () => this.overrides;
|
|
537
|
-
/** Returns the current server snapshot for `useSyncExternalStore`. */
|
|
538
|
-
getServerSnapshot = () => this.overrides;
|
|
539
|
-
/** Subscribes to override changes and returns an unsubscribe callback. */
|
|
540
|
-
subscribe = (callback) => {
|
|
541
|
-
this.listeners.add(callback);
|
|
542
|
-
return () => {
|
|
543
|
-
this.listeners.delete(callback);
|
|
544
|
-
};
|
|
545
|
-
};
|
|
546
|
-
emit = () => {
|
|
547
|
-
for (const listener of Array.from(this.listeners)) {
|
|
548
|
-
try {
|
|
549
|
-
listener();
|
|
550
|
-
} catch (error) {
|
|
551
|
-
console.error("TranslationStore: Listener error", error);
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
};
|
|
555
|
-
};
|
|
556
|
-
var ThemeTextStore = TranslationStore;
|
|
557
|
-
|
|
558
|
-
// src/utils/pick-weaverse-data.ts
|
|
559
|
-
function pickWeaverseData(dataProp, ownLoaderData, matches) {
|
|
560
|
-
if (dataProp !== void 0) {
|
|
561
|
-
return dataProp;
|
|
562
|
-
}
|
|
563
|
-
if (hasWeaverseData(ownLoaderData)) {
|
|
564
|
-
return ownLoaderData.weaverseData;
|
|
565
|
-
}
|
|
566
|
-
for (let i = matches.length - 1; i >= 0; i--) {
|
|
567
|
-
const loaderData = matches[i].loaderData;
|
|
568
|
-
if (hasWeaverseData(loaderData)) {
|
|
569
|
-
return loaderData.weaverseData;
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
return null;
|
|
573
|
-
}
|
|
574
|
-
function hasWeaverseData(value) {
|
|
575
|
-
if (typeof value !== "object" || value === null || !("weaverseData" in value)) {
|
|
576
|
-
return false;
|
|
577
|
-
}
|
|
578
|
-
return value.weaverseData !== void 0;
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// src/utils/studio-request-info.ts
|
|
582
|
-
function getBrowserLocation() {
|
|
583
|
-
if (typeof window === "undefined") {
|
|
584
|
-
return;
|
|
585
|
-
}
|
|
586
|
-
return window.location;
|
|
587
|
-
}
|
|
588
|
-
function getQueriesFromSearch(search) {
|
|
589
|
-
let queries = {};
|
|
590
|
-
let params = new URLSearchParams(search);
|
|
591
|
-
for (let [key, value] of params.entries()) {
|
|
592
|
-
if (value === "true") {
|
|
593
|
-
queries[key] = true;
|
|
594
|
-
} else if (value === "false") {
|
|
595
|
-
queries[key] = false;
|
|
596
|
-
} else {
|
|
597
|
-
queries[key] = value;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
return queries;
|
|
601
|
-
}
|
|
602
|
-
function normalizeRequestInfo(params, browserLocation = getBrowserLocation()) {
|
|
603
|
-
if (!browserLocation) {
|
|
604
|
-
return params;
|
|
605
|
-
}
|
|
606
|
-
let { pathname, search } = browserLocation;
|
|
607
|
-
if (params.requestInfo.pathname === pathname && params.requestInfo.search === search) {
|
|
608
|
-
return params;
|
|
609
|
-
}
|
|
610
|
-
return {
|
|
611
|
-
...params,
|
|
612
|
-
requestInfo: {
|
|
613
|
-
...params.requestInfo,
|
|
614
|
-
pathname,
|
|
615
|
-
queries: getQueriesFromSearch(search),
|
|
616
|
-
search
|
|
617
|
-
}
|
|
618
|
-
};
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
// src/utils/is-same-loader-payload.ts
|
|
622
|
-
function isJsonOmitted(value) {
|
|
623
|
-
return value === void 0 || typeof value === "function" || typeof value === "symbol";
|
|
624
|
-
}
|
|
625
|
-
function isObjectLike(value) {
|
|
626
|
-
return value !== null && typeof value === "object";
|
|
627
|
-
}
|
|
628
|
-
function isThenable(value) {
|
|
629
|
-
return typeof value.then === "function";
|
|
630
|
-
}
|
|
631
|
-
function isPlainObject(value) {
|
|
632
|
-
const proto = Object.getPrototypeOf(value);
|
|
633
|
-
return proto === Object.prototype || proto === null;
|
|
634
|
-
}
|
|
635
|
-
function toJsonValue(value) {
|
|
636
|
-
return typeof value.toJSON === "function" ? value.toJSON() : value;
|
|
637
|
-
}
|
|
638
|
-
function toFiniteOrNull(value) {
|
|
639
|
-
return typeof value === "number" && !Number.isFinite(value) ? null : value;
|
|
640
|
-
}
|
|
641
|
-
function isSameLoaderPayload(left, right) {
|
|
642
|
-
const activePairs = [];
|
|
643
|
-
function isSame(rawA, rawB) {
|
|
644
|
-
if (Object.is(rawA, rawB)) {
|
|
645
|
-
return true;
|
|
646
|
-
}
|
|
647
|
-
const a = toFiniteOrNull(rawA);
|
|
648
|
-
const b = toFiniteOrNull(rawB);
|
|
649
|
-
if (a === b) {
|
|
650
|
-
return true;
|
|
651
|
-
}
|
|
652
|
-
if (!(isObjectLike(a) && isObjectLike(b))) {
|
|
653
|
-
return false;
|
|
654
|
-
}
|
|
655
|
-
if (isThenable(a) || isThenable(b)) {
|
|
656
|
-
return false;
|
|
657
|
-
}
|
|
658
|
-
for (let index = 0; index < activePairs.length; index += 2) {
|
|
659
|
-
if (activePairs[index] === a && activePairs[index + 1] === b) {
|
|
660
|
-
return true;
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
activePairs.push(a, b);
|
|
664
|
-
try {
|
|
665
|
-
return isSameOpenPair(a, b);
|
|
666
|
-
} finally {
|
|
667
|
-
activePairs.length -= 2;
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
function isSameOpenPair(a, b) {
|
|
671
|
-
const aJson = toJsonValue(a);
|
|
672
|
-
const bJson = toJsonValue(b);
|
|
673
|
-
if (aJson !== a || bJson !== b) {
|
|
674
|
-
return isSame(aJson, bJson);
|
|
675
|
-
}
|
|
676
|
-
if (Array.isArray(a) !== Array.isArray(b)) {
|
|
677
|
-
return false;
|
|
678
|
-
}
|
|
679
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
680
|
-
return isSameArray(a, b);
|
|
681
|
-
}
|
|
682
|
-
if (!(isPlainObject(a) && isPlainObject(b))) {
|
|
683
|
-
return false;
|
|
684
|
-
}
|
|
685
|
-
return isSameObject(a, b);
|
|
686
|
-
}
|
|
687
|
-
function isSameArray(a, b) {
|
|
688
|
-
if (a.length !== b.length) {
|
|
689
|
-
return false;
|
|
690
|
-
}
|
|
691
|
-
for (let index = 0; index < a.length; index++) {
|
|
692
|
-
const aItem = isJsonOmitted(a[index]) ? null : a[index];
|
|
693
|
-
const bItem = isJsonOmitted(b[index]) ? null : b[index];
|
|
694
|
-
if (!isSame(aItem, bItem)) {
|
|
695
|
-
return false;
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
return true;
|
|
699
|
-
}
|
|
700
|
-
function isSameObject(a, b) {
|
|
701
|
-
let aKeyCount = 0;
|
|
702
|
-
for (const key of Object.keys(a)) {
|
|
703
|
-
if (isJsonOmitted(a[key])) {
|
|
704
|
-
continue;
|
|
705
|
-
}
|
|
706
|
-
aKeyCount++;
|
|
707
|
-
if (!isSame(a[key], b[key])) {
|
|
708
|
-
return false;
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
let bKeyCount = 0;
|
|
712
|
-
for (const key of Object.keys(b)) {
|
|
713
|
-
if (!isJsonOmitted(b[key])) {
|
|
714
|
-
bKeyCount++;
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
return aKeyCount === bKeyCount;
|
|
718
|
-
}
|
|
719
|
-
return isSame(left, right);
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
// src/utils/sync-reused-instance.ts
|
|
723
|
-
function syncReusedInstance(weaverse, params) {
|
|
724
|
-
weaverse.requestInfo = params.requestInfo;
|
|
725
|
-
weaverse.internal = params.internal;
|
|
726
|
-
let dataChanged = !isSameLoaderPayload(weaverse.data, params.data);
|
|
727
|
-
let contextChanged = !isSameLoaderPayload(
|
|
728
|
-
weaverse.dataContext ?? null,
|
|
729
|
-
params.dataContext ?? null
|
|
730
|
-
);
|
|
731
|
-
if (contextChanged) {
|
|
732
|
-
weaverse.dataContext = params.dataContext ?? null;
|
|
733
|
-
}
|
|
734
|
-
if (dataChanged) {
|
|
735
|
-
weaverse.setProjectData(params.data);
|
|
736
|
-
} else if (contextChanged) {
|
|
737
|
-
for (const { id } of params.data?.items || []) {
|
|
738
|
-
weaverse.itemInstances.get(id)?.setData({});
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
if (dataChanged || contextChanged) {
|
|
742
|
-
weaverse.triggerUpdate();
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
var ThemeSettingsStore = class {
|
|
746
|
-
/** Current merged theme setting values. */
|
|
747
|
-
settings = {};
|
|
748
|
-
/** Theme schema exposed to Studio, when available. */
|
|
749
|
-
schema;
|
|
750
|
-
/** Storefront-safe environment values, when available. */
|
|
751
|
-
publicEnv;
|
|
752
|
-
listeners = /* @__PURE__ */ new Set();
|
|
753
|
-
hasWarnedListenerCount = false;
|
|
754
|
-
isDestroyed = false;
|
|
755
|
-
/** Creates a theme settings store from root-loader theme data. */
|
|
756
|
-
constructor(data) {
|
|
757
|
-
const { theme, schema: schema2, publicEnv } = data || {};
|
|
758
|
-
this.settings = { ...theme };
|
|
759
|
-
this.schema = schema2;
|
|
760
|
-
this.publicEnv = publicEnv;
|
|
761
|
-
if (react.isBrowser) {
|
|
762
|
-
window.__weaverseThemeSettingsStore = this;
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
/** Merges setting changes into the current snapshot and notifies subscribers. */
|
|
766
|
-
updateThemeSettings = (newSettings) => {
|
|
767
|
-
if (this.isDestroyed) {
|
|
768
|
-
console.warn("ThemeSettingsStore: Cannot update destroyed store");
|
|
769
|
-
return;
|
|
770
|
-
}
|
|
771
|
-
this.settings = {
|
|
772
|
-
...this.settings,
|
|
773
|
-
...newSettings
|
|
774
|
-
};
|
|
775
|
-
this.emit();
|
|
776
|
-
};
|
|
777
|
-
/** Returns the current client snapshot for `useSyncExternalStore`. */
|
|
778
|
-
getSnapshot = () => this.settings;
|
|
779
|
-
/** Returns the current server snapshot for `useSyncExternalStore`. */
|
|
780
|
-
getServerSnapshot = () => this.settings;
|
|
781
|
-
/** Subscribes to setting changes and returns an unsubscribe callback. */
|
|
782
|
-
subscribe = (callback) => {
|
|
783
|
-
if (this.isDestroyed) {
|
|
784
|
-
console.warn("ThemeSettingsStore: Cannot subscribe to destroyed store");
|
|
785
|
-
return () => {
|
|
786
|
-
};
|
|
787
|
-
}
|
|
788
|
-
this.listeners.add(callback);
|
|
789
|
-
if (!this.hasWarnedListenerCount && this.listeners.size > 500) {
|
|
790
|
-
this.hasWarnedListenerCount = true;
|
|
791
|
-
console.warn(
|
|
792
|
-
`ThemeSettingsStore: ${this.listeners.size} listeners detected. This may indicate a performance issue. Consider using fewer useThemeSettings() calls.`
|
|
793
|
-
);
|
|
794
|
-
}
|
|
795
|
-
return () => {
|
|
796
|
-
this.listeners.delete(callback);
|
|
797
|
-
};
|
|
798
|
-
};
|
|
799
|
-
emit = () => {
|
|
800
|
-
if (this.isDestroyed) {
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
|
-
const currentListeners = Array.from(this.listeners);
|
|
804
|
-
for (const listener of currentListeners) {
|
|
805
|
-
try {
|
|
806
|
-
listener();
|
|
807
|
-
} catch (error) {
|
|
808
|
-
console.error("ThemeSettingsStore: Listener error", error);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
};
|
|
812
|
-
/** Clears subscribers and detaches the browser-global store reference. */
|
|
813
|
-
destroy = () => {
|
|
814
|
-
if (this.isDestroyed) {
|
|
815
|
-
return;
|
|
816
|
-
}
|
|
817
|
-
this.listeners.clear();
|
|
818
|
-
this.isDestroyed = true;
|
|
819
|
-
if (react.isBrowser && window.__weaverseThemeSettingsStore === this) {
|
|
820
|
-
window.__weaverseThemeSettingsStore = void 0;
|
|
821
|
-
}
|
|
822
|
-
};
|
|
823
|
-
};
|
|
824
|
-
var ThemeSettingsStoreContext = react$1.createContext(null);
|
|
825
|
-
ThemeSettingsStoreContext.displayName = "ThemeSettingsStoreContext";
|
|
826
|
-
function useCreateThemeSettingsStore() {
|
|
827
|
-
const data = reactRouter.useRouteLoaderData("root");
|
|
828
|
-
const storeRef = react$1.useRef(null);
|
|
829
|
-
if (!storeRef.current) {
|
|
830
|
-
storeRef.current = new ThemeSettingsStore(data?.weaverseTheme);
|
|
831
|
-
}
|
|
832
|
-
const theme = data?.weaverseTheme?.theme;
|
|
833
|
-
react$1.useEffect(() => {
|
|
834
|
-
if (storeRef.current && theme) {
|
|
835
|
-
storeRef.current.updateThemeSettings(theme);
|
|
836
|
-
}
|
|
837
|
-
}, [theme]);
|
|
838
|
-
return storeRef.current;
|
|
839
|
-
}
|
|
840
|
-
function useThemeSettingsStore() {
|
|
841
|
-
const fromContext = react$1.useContext(ThemeSettingsStoreContext);
|
|
842
|
-
const data = reactRouter.useRouteLoaderData("root");
|
|
843
|
-
const fallbackRef = react$1.useRef(null);
|
|
844
|
-
if (!(fallbackRef.current || fromContext)) {
|
|
845
|
-
fallbackRef.current = new ThemeSettingsStore(data?.weaverseTheme);
|
|
846
|
-
}
|
|
847
|
-
const store = fromContext ?? fallbackRef.current;
|
|
848
|
-
const theme = data?.weaverseTheme?.theme;
|
|
849
|
-
react$1.useEffect(() => {
|
|
850
|
-
if (!fromContext && theme) {
|
|
851
|
-
store.updateThemeSettings(theme);
|
|
852
|
-
}
|
|
853
|
-
}, [fromContext, store, theme]);
|
|
854
|
-
return store;
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
// src/utils/use-studio.ts
|
|
858
|
-
var STUDIO_READY_POLL_MS = 50;
|
|
859
|
-
var STUDIO_READY_TIMEOUT_MS = 5e3;
|
|
860
|
-
function waitForStudio() {
|
|
861
|
-
return new Promise((resolve) => {
|
|
862
|
-
let startedAt = Date.now();
|
|
863
|
-
function check() {
|
|
864
|
-
if (hasWeaverseStudio(window)) {
|
|
865
|
-
return resolve(window.weaverseStudio);
|
|
866
|
-
}
|
|
867
|
-
if (Date.now() - startedAt >= STUDIO_READY_TIMEOUT_MS) {
|
|
868
|
-
console.warn("[Weaverse] Studio script did not initialize in time");
|
|
869
|
-
return resolve(null);
|
|
870
|
-
}
|
|
871
|
-
setTimeout(check, STUDIO_READY_POLL_MS);
|
|
872
|
-
}
|
|
873
|
-
check();
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
function useStudioConnect() {
|
|
877
|
-
let { search } = reactRouter.useLocation();
|
|
878
|
-
react$1.useEffect(() => {
|
|
879
|
-
let hostname = typeof window === "undefined" ? "" : window.location.hostname;
|
|
880
|
-
let src = resolveStudioScriptSrc(search, hostname);
|
|
881
|
-
if (src) {
|
|
882
|
-
react.loadScript(src).catch(console.error);
|
|
883
|
-
}
|
|
884
|
-
}, [search]);
|
|
885
|
-
}
|
|
886
|
-
function useStudio(weaverse) {
|
|
887
|
-
let { revalidate } = reactRouter.useRevalidator();
|
|
888
|
-
let navigation = reactRouter.useNavigation();
|
|
889
|
-
let { pathname, search } = reactRouter.useLocation();
|
|
890
|
-
let navigate = reactRouter.useNavigate();
|
|
891
|
-
let themeSettingsStore = useThemeSettingsStore();
|
|
892
|
-
let { translationStore, themeTextStore, merchantOverrides } = useTranslation();
|
|
893
|
-
let {
|
|
894
|
-
isDesignMode,
|
|
895
|
-
weaverseHost,
|
|
896
|
-
weaverseVersion,
|
|
897
|
-
isPreviewMode,
|
|
898
|
-
isRevisionPreview
|
|
899
|
-
} = weaverse;
|
|
900
|
-
react$1.useEffect(() => {
|
|
901
|
-
if (navigation.state !== "idle") {
|
|
902
|
-
return;
|
|
903
|
-
}
|
|
904
|
-
let src = getStudioScriptSrc({
|
|
905
|
-
isDesignMode,
|
|
906
|
-
isPreviewMode,
|
|
907
|
-
isRevisionPreview,
|
|
908
|
-
weaverseHost,
|
|
909
|
-
weaverseVersion
|
|
910
|
-
});
|
|
911
|
-
if (!src) {
|
|
912
|
-
return;
|
|
913
|
-
}
|
|
914
|
-
if (isRevisionPreview || isPreviewMode) {
|
|
915
|
-
react.loadScript(src).catch(console.error);
|
|
916
|
-
} else {
|
|
917
|
-
weaverse.internal = {
|
|
918
|
-
...weaverse.internal,
|
|
919
|
-
navigate,
|
|
920
|
-
revalidate,
|
|
921
|
-
merchantOverrides,
|
|
922
|
-
themeSettingsStore,
|
|
923
|
-
translationStore,
|
|
924
|
-
// Deprecated alias for existing Studio bridge integrations.
|
|
925
|
-
themeTextStore
|
|
926
|
-
};
|
|
927
|
-
react.loadScript(src).then(waitForStudio).then((studio) => studio?.init(weaverse)).catch(console.error);
|
|
928
|
-
}
|
|
929
|
-
}, [pathname, search, navigation.state]);
|
|
930
|
-
}
|
|
931
|
-
var WeaverseHydrogenItem = class extends react.WeaverseItemStore {
|
|
932
|
-
/**
|
|
933
|
-
* Cached merged snapshot (base + translations).
|
|
934
|
-
* Reset to `null` whenever `_store` or the item's translation entry changes.
|
|
935
|
-
*/
|
|
936
|
-
_cachedSnapshot = null;
|
|
937
|
-
_snapshotStoreRef = null;
|
|
938
|
-
_snapshotTranslationRef = null;
|
|
939
|
-
/** Creates an item store from serialized component data and its owner. */
|
|
940
|
-
constructor(initialData, weaverse) {
|
|
941
|
-
super(initialData, weaverse);
|
|
942
|
-
const { data, ...rest } = initialData;
|
|
943
|
-
if (!this.Element?.schema) {
|
|
944
|
-
console.error("Element is missing schema or not found!");
|
|
945
|
-
return;
|
|
946
|
-
}
|
|
947
|
-
const schemaData = generateDataFromSchema(this.Element.schema);
|
|
948
|
-
Object.assign(this._store, schemaData, data, rest);
|
|
949
|
-
}
|
|
950
|
-
/** Registered component definition for this item's type. */
|
|
951
|
-
get Element() {
|
|
952
|
-
return super.Element;
|
|
953
|
-
}
|
|
954
|
-
/**
|
|
955
|
-
* Override setData to flatten serialized `data` the same way the constructor
|
|
956
|
-
* does. Core's `initProject()` reuses item stores keyed by item id (identical
|
|
957
|
-
* ids across locales), and the inherited setData only shallow-merges the raw
|
|
958
|
-
* item — fresh settings would land under `_store.data` while the stale
|
|
959
|
-
* flattened values keep rendering.
|
|
960
|
-
*
|
|
961
|
-
* Schema defaults are re-applied ahead of incoming settings because a
|
|
962
|
-
* serialized payload can omit fields — or the optional `data` object itself —
|
|
963
|
-
* when values equal schema defaults. The stored nested `data` is also replaced
|
|
964
|
-
* so the public serialized state does not retain the previous locale payload.
|
|
965
|
-
*
|
|
966
|
-
* An empty update is the context-only refresh from `syncReusedInstance`: swap
|
|
967
|
-
* the store reference so memoized subscribers re-render, and leave the
|
|
968
|
-
* settings untouched.
|
|
969
|
-
*/
|
|
970
|
-
setData = (update) => {
|
|
971
|
-
let source = update ?? {};
|
|
972
|
-
let { data, ...rest } = source;
|
|
973
|
-
let isEmptyUpdate = Object.keys(source).length === 0;
|
|
974
|
-
if (isEmptyUpdate) {
|
|
975
|
-
this._store = { ...this._store };
|
|
976
|
-
} else {
|
|
977
|
-
let type = source.type ?? this._store.type;
|
|
978
|
-
let schema2 = this.weaverse.elementRegistry.get(type)?.schema;
|
|
979
|
-
let isSerializedItem = "id" in source && "type" in source;
|
|
980
|
-
let shouldNormalize = data !== void 0 || isSerializedItem;
|
|
981
|
-
if (schema2 && shouldNormalize) {
|
|
982
|
-
let { data: _previousData, ...store } = this._store;
|
|
983
|
-
let schemaData = generateDataFromSchema(schema2);
|
|
984
|
-
this._store = {
|
|
985
|
-
...store,
|
|
986
|
-
...data === void 0 ? {} : { data },
|
|
987
|
-
...schemaData,
|
|
988
|
-
...data,
|
|
989
|
-
...rest
|
|
990
|
-
};
|
|
991
|
-
} else {
|
|
992
|
-
this._store = { ...this._store, ...source };
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
this.triggerUpdate();
|
|
996
|
-
return this.data;
|
|
997
|
-
};
|
|
998
|
-
/**
|
|
999
|
-
* Override getSnapShot to merge translation data when in translation mode.
|
|
1000
|
-
* Memoizes the result: returns the same object reference as long as
|
|
1001
|
-
* both `_store` and the translation entry haven't changed.
|
|
1002
|
-
* This is critical for `useSyncExternalStore` stability.
|
|
1003
|
-
*/
|
|
1004
|
-
getSnapShot = () => {
|
|
1005
|
-
const base = this._store;
|
|
1006
|
-
const translations = this.weaverse.translationMap?.[this._id];
|
|
1007
|
-
if (!translations) {
|
|
1008
|
-
return base;
|
|
1009
|
-
}
|
|
1010
|
-
if (this._cachedSnapshot && this._snapshotStoreRef === base && this._snapshotTranslationRef === translations) {
|
|
1011
|
-
return this._cachedSnapshot;
|
|
1012
|
-
}
|
|
1013
|
-
const merged = { ...base };
|
|
1014
|
-
for (const [key, entry] of Object.entries(translations)) {
|
|
1015
|
-
if (entry.translatedValue !== void 0) {
|
|
1016
|
-
merged[key] = entry.translatedValue;
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
this._cachedSnapshot = merged;
|
|
1020
|
-
this._snapshotStoreRef = base;
|
|
1021
|
-
this._snapshotTranslationRef = translations;
|
|
1022
|
-
return merged;
|
|
1023
|
-
};
|
|
1024
|
-
};
|
|
1025
|
-
react.Weaverse.ItemConstructor = WeaverseHydrogenItem;
|
|
1026
|
-
var WeaverseHydrogen = class extends react.Weaverse {
|
|
1027
|
-
/** Identifier of the rendered page. */
|
|
1028
|
-
pageId;
|
|
1029
|
-
/** Runtime services and project metadata exposed to integrations. */
|
|
1030
|
-
internal;
|
|
1031
|
-
/** Normalized URL and locale information for the current request. */
|
|
1032
|
-
requestInfo;
|
|
1033
|
-
/** Identifier of the project supplying the page. */
|
|
1034
|
-
projectId;
|
|
1035
|
-
/** Origin used for Studio assets and editor communication. */
|
|
1036
|
-
weaverseHost;
|
|
1037
|
-
/** Base URL used for public content API requests. */
|
|
1038
|
-
weaverseApiBase;
|
|
1039
|
-
/**
|
|
1040
|
-
* API key read from environment/configuration for storefront requests or
|
|
1041
|
-
* supplied by Studio requests while editing and previewing.
|
|
1042
|
-
*/
|
|
1043
|
-
weaverseApiKey;
|
|
1044
|
-
/** Studio asset version supplied by the preview request. */
|
|
1045
|
-
weaverseVersion;
|
|
1046
|
-
/** Whether the page is running inside the visual editor. */
|
|
1047
|
-
isDesignMode;
|
|
1048
|
-
/** Whether a single component preview is being rendered. */
|
|
1049
|
-
isPreviewMode;
|
|
1050
|
-
/** Whether a saved page revision is being previewed. */
|
|
1051
|
-
isRevisionPreview;
|
|
1052
|
-
/** Component type requested by section preview mode. */
|
|
1053
|
-
sectionType;
|
|
1054
|
-
// ─── Translation sidecar (design mode only) ────────────────────────
|
|
1055
|
-
/**
|
|
1056
|
-
* Translation map received from the builder in design mode.
|
|
1057
|
-
* Keyed by item ID, each entry maps field names to translated values.
|
|
1058
|
-
* `WeaverseHydrogenItem.getSnapShot()` merges these into the data
|
|
1059
|
-
* returned to components, so translations render without monkey-patching.
|
|
1060
|
-
*/
|
|
1061
|
-
translationMap = {};
|
|
1062
|
-
/** Locale code for the active translation sidecar. */
|
|
1063
|
-
translationLocale = "";
|
|
1064
|
-
/** Builder language identifier for the active translation sidecar. */
|
|
1065
|
-
translationLanguageId = "";
|
|
1066
|
-
/** Creates a page runtime from resolved loader data and request settings. */
|
|
1067
|
-
constructor(params) {
|
|
1068
|
-
const { internal, pageId, requestInfo, ...coreParams } = params;
|
|
1069
|
-
super({ ...coreParams });
|
|
1070
|
-
this.internal = internal;
|
|
1071
|
-
this.pageId = pageId;
|
|
1072
|
-
this.requestInfo = requestInfo;
|
|
1073
|
-
this.projectId = params.projectId;
|
|
1074
|
-
this.weaverseHost = params.weaverseHost;
|
|
1075
|
-
this.weaverseApiBase = params.weaverseApiBase;
|
|
1076
|
-
this.weaverseApiKey = params.weaverseApiKey;
|
|
1077
|
-
this.weaverseVersion = params.weaverseVersion || "";
|
|
1078
|
-
this.isDesignMode = params.isDesignMode ?? false;
|
|
1079
|
-
this.isPreviewMode = params.isPreviewMode ?? false;
|
|
1080
|
-
this.isRevisionPreview = params.isRevisionPreview ?? false;
|
|
1081
|
-
this.sectionType = params.sectionType || "";
|
|
1082
|
-
this.extractTranslationSidecar();
|
|
1083
|
-
}
|
|
1084
|
-
/**
|
|
1085
|
-
* Extract translation sidecar data from `this.data` (the page data).
|
|
1086
|
-
* The builder attaches `translationMap`, `translationLocale`, and
|
|
1087
|
-
* `translationLanguageId` to the page data in design mode.
|
|
1088
|
-
*/
|
|
1089
|
-
extractTranslationSidecar = () => {
|
|
1090
|
-
const pageData = this.data;
|
|
1091
|
-
if (pageData?.translationMap) {
|
|
1092
|
-
this.translationMap = pageData.translationMap;
|
|
1093
|
-
this.translationLocale = pageData.translationLocale || "";
|
|
1094
|
-
this.translationLanguageId = pageData.translationLanguageId || "";
|
|
1095
|
-
}
|
|
1096
|
-
};
|
|
1097
|
-
/**
|
|
1098
|
-
* Set the translation sidecar data.
|
|
1099
|
-
* Called by the studio bridge when translation data arrives or changes.
|
|
1100
|
-
* Triggers a re-render of all items so translated snapshots are recalculated.
|
|
1101
|
-
*/
|
|
1102
|
-
setTranslationSidecar = (translationMap, locale, languageId) => {
|
|
1103
|
-
this.translationMap = translationMap;
|
|
1104
|
-
this.translationLocale = locale;
|
|
1105
|
-
this.translationLanguageId = languageId;
|
|
1106
|
-
this.refreshAllItems();
|
|
1107
|
-
};
|
|
1108
|
-
/**
|
|
1109
|
-
* Update a single translation entry for a specific item field.
|
|
1110
|
-
* Used by the studio bridge when the user edits a translatable field.
|
|
1111
|
-
*/
|
|
1112
|
-
updateTranslation = (itemId, key, originalValue, translatedValue) => {
|
|
1113
|
-
if (!this.translationMap[itemId]) {
|
|
1114
|
-
this.translationMap[itemId] = {};
|
|
1115
|
-
}
|
|
1116
|
-
this.translationMap[itemId] = {
|
|
1117
|
-
...this.translationMap[itemId],
|
|
1118
|
-
[key]: { originalValue, translatedValue }
|
|
1119
|
-
};
|
|
1120
|
-
const instance = this.itemInstances.get(itemId);
|
|
1121
|
-
if (instance) {
|
|
1122
|
-
instance.triggerUpdate();
|
|
1123
|
-
}
|
|
1124
|
-
};
|
|
1125
|
-
/**
|
|
1126
|
-
* Collect all translation changes across all weaverse instances.
|
|
1127
|
-
* Used by the save flow to persist translation edits.
|
|
1128
|
-
*/
|
|
1129
|
-
getTranslationChanges = () => {
|
|
1130
|
-
const entries = [];
|
|
1131
|
-
const languageId = this.translationLanguageId;
|
|
1132
|
-
if (!(this.translationLocale && languageId)) {
|
|
1133
|
-
return;
|
|
1134
|
-
}
|
|
1135
|
-
for (const [itemId, fields] of Object.entries(this.translationMap)) {
|
|
1136
|
-
for (const [key, entry] of Object.entries(fields)) {
|
|
1137
|
-
entries.push({
|
|
1138
|
-
itemId,
|
|
1139
|
-
key: `data.${key}`,
|
|
1140
|
-
originalValue: entry.originalValue,
|
|
1141
|
-
translatedValue: entry.translatedValue
|
|
1142
|
-
});
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
if (entries.length === 0) {
|
|
1146
|
-
return;
|
|
1147
|
-
}
|
|
1148
|
-
return { languageId, entries };
|
|
1149
|
-
};
|
|
1150
|
-
/**
|
|
1151
|
-
* Override setProjectData to re-extract translation sidecar from new page data.
|
|
1152
|
-
*/
|
|
1153
|
-
setProjectData = (data) => {
|
|
1154
|
-
this.data = data;
|
|
1155
|
-
this.extractTranslationSidecar();
|
|
1156
|
-
this.initProject();
|
|
1157
|
-
};
|
|
1158
|
-
};
|
|
1159
|
-
function createWeaverseInstance(params) {
|
|
1160
|
-
const normalizedParams = normalizeRequestInfo(params);
|
|
1161
|
-
if (react.isBrowser) {
|
|
1162
|
-
window.__weaverses = window.__weaverses || {};
|
|
1163
|
-
const existing = window.__weaverses[normalizedParams.pageId];
|
|
1164
|
-
const isReused = existing?.requestInfo?.pathname === normalizedParams.requestInfo.pathname && existing?.requestInfo?.search === normalizedParams.requestInfo.search;
|
|
1165
|
-
const weaverse = isReused ? existing : new WeaverseHydrogen(normalizedParams);
|
|
1166
|
-
window.__weaverses[normalizedParams.pageId] = weaverse;
|
|
1167
|
-
if (weaverse.isDesignMode) {
|
|
1168
|
-
weaverse.requestInfo = normalizedParams.requestInfo;
|
|
1169
|
-
if (hasWeaverseStudio(window)) {
|
|
1170
|
-
window.weaverseStudio.refreshStudio(normalizedParams);
|
|
1171
|
-
}
|
|
1172
|
-
} else if (isReused) {
|
|
1173
|
-
syncReusedInstance(weaverse, normalizedParams);
|
|
1174
|
-
}
|
|
1175
|
-
return weaverse;
|
|
1176
|
-
}
|
|
1177
|
-
return new WeaverseHydrogen(normalizedParams);
|
|
1178
|
-
}
|
|
1179
|
-
var StudioBridge = react$1.memo(({ context }) => {
|
|
1180
|
-
useStudio(context);
|
|
1181
|
-
return null;
|
|
1182
|
-
});
|
|
1183
|
-
var StudioConnect = react$1.memo(() => {
|
|
1184
|
-
useStudioConnect();
|
|
1185
|
-
return null;
|
|
1186
|
-
});
|
|
1187
|
-
var registeredComponentLists = /* @__PURE__ */ new WeakSet();
|
|
1188
|
-
function RenderRoot(props) {
|
|
1189
|
-
const { data, components, dataContext } = props;
|
|
1190
|
-
if (!registeredComponentLists.has(components)) {
|
|
1191
|
-
for (const comp of [...components, ...defaultComponents]) {
|
|
1192
|
-
if (comp?.schema?.type) {
|
|
1193
|
-
registerComponent({
|
|
1194
|
-
type: comp.schema.type,
|
|
1195
|
-
Component: comp.default,
|
|
1196
|
-
schema: comp.schema,
|
|
1197
|
-
loader: comp.loader
|
|
1198
|
-
});
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
registeredComponentLists.add(components);
|
|
1202
|
-
}
|
|
1203
|
-
const { page, configs, project, pageAssignment } = data || {};
|
|
1204
|
-
const weaverse = createWeaverseInstance({
|
|
1205
|
-
...configs,
|
|
1206
|
-
dataContext,
|
|
1207
|
-
data: page,
|
|
1208
|
-
pageId: page?.id,
|
|
1209
|
-
internal: { project, pageAssignment }
|
|
1210
|
-
});
|
|
1211
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1212
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.WeaverseRoot, { context: weaverse }),
|
|
1213
|
-
/* @__PURE__ */ jsxRuntime.jsx(StudioBridge, { context: weaverse })
|
|
1214
|
-
] });
|
|
1215
|
-
}
|
|
1216
|
-
function registerComponent(element) {
|
|
1217
|
-
WeaverseHydrogen.registerElement(element);
|
|
1218
|
-
}
|
|
1219
|
-
var WeaverseHydrogenRoot = react$1.memo(
|
|
1220
|
-
({
|
|
1221
|
-
components,
|
|
1222
|
-
data: dataProp,
|
|
1223
|
-
errorComponent: ErrorComponent = ({ error }) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: error instanceof Error ? error.message : "An unexpected error occurred" })
|
|
1224
|
-
}) => {
|
|
1225
|
-
const matches = reactRouter.useMatches();
|
|
1226
|
-
const enhancedDataContext = react$1.useMemo(
|
|
1227
|
-
() => createWeaverseDataContext(matches),
|
|
1228
|
-
[matches]
|
|
1229
|
-
);
|
|
1230
|
-
const ownLoaderData = reactRouter.useLoaderData();
|
|
1231
|
-
const weaverseData = react$1.useMemo(
|
|
1232
|
-
() => pickWeaverseData(dataProp, ownLoaderData, matches),
|
|
1233
|
-
[dataProp, ownLoaderData, matches]
|
|
1234
|
-
);
|
|
1235
|
-
if (dataProp === null) {
|
|
1236
|
-
return null;
|
|
1237
|
-
}
|
|
1238
|
-
if (weaverseData) {
|
|
1239
|
-
if (weaverseData instanceof Promise) {
|
|
1240
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactErrorBoundary.ErrorBoundary, { fallbackRender: ErrorComponent, children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Suspense, { children: /* @__PURE__ */ jsxRuntime.jsx(reactRouter.Await, { resolve: weaverseData, children: (resolvedData) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1241
|
-
RenderRoot,
|
|
1242
|
-
{
|
|
1243
|
-
components,
|
|
1244
|
-
data: resolvedData,
|
|
1245
|
-
dataContext: enhancedDataContext
|
|
1246
|
-
}
|
|
1247
|
-
) }) }) });
|
|
1248
|
-
}
|
|
1249
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1250
|
-
RenderRoot,
|
|
1251
|
-
{
|
|
1252
|
-
components,
|
|
1253
|
-
data: weaverseData,
|
|
1254
|
-
dataContext: enhancedDataContext
|
|
1255
|
-
}
|
|
1256
|
-
);
|
|
1257
|
-
}
|
|
1258
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1259
|
-
ErrorComponent,
|
|
1260
|
-
{
|
|
1261
|
-
error: { message: "No Weaverse data found in route matches!" }
|
|
1262
|
-
}
|
|
1263
|
-
);
|
|
1264
|
-
}
|
|
1265
|
-
);
|
|
1266
|
-
function withWeaverse(Component, options) {
|
|
1267
|
-
return (props) => {
|
|
1268
|
-
const themeSettingsStore = useCreateThemeSettingsStore();
|
|
1269
|
-
const translationData = useTranslationData();
|
|
1270
|
-
const translationStoreRef = react$1.useRef(null);
|
|
1271
|
-
if (!translationStoreRef.current) {
|
|
1272
|
-
translationStoreRef.current = new TranslationStore();
|
|
1273
|
-
}
|
|
1274
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ThemeSettingsStoreContext.Provider, { value: themeSettingsStore, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1275
|
-
TranslationProvider,
|
|
1276
|
-
{
|
|
1277
|
-
merchantOverrides: translationData.merchantOverrides,
|
|
1278
|
-
staticContent: translationData.staticContent,
|
|
1279
|
-
t: options?.t,
|
|
1280
|
-
translationStore: translationStoreRef.current,
|
|
1281
|
-
children: [
|
|
1282
|
-
/* @__PURE__ */ jsxRuntime.jsx(StudioConnect, {}),
|
|
1283
|
-
/* @__PURE__ */ jsxRuntime.jsx(Component, { ...props })
|
|
1284
|
-
]
|
|
1285
|
-
}
|
|
1286
|
-
) });
|
|
1287
|
-
};
|
|
1288
|
-
}
|
|
1289
|
-
function useTranslationData() {
|
|
1290
|
-
const data = reactRouter.useRouteLoaderData("root");
|
|
1291
|
-
return {
|
|
1292
|
-
staticContent: data?.weaverseTheme?.staticContent ?? {},
|
|
1293
|
-
merchantOverrides: data?.weaverseTheme?.merchantOverrides
|
|
1294
|
-
};
|
|
1295
|
-
}
|
|
1296
|
-
function useThemeSettings() {
|
|
1297
|
-
const themeSettingsStore = useThemeSettingsStore();
|
|
1298
|
-
const settings = react.useSafeExternalStore(
|
|
1299
|
-
themeSettingsStore.subscribe,
|
|
1300
|
-
themeSettingsStore.getSnapshot,
|
|
1301
|
-
themeSettingsStore.getServerSnapshot
|
|
1302
|
-
);
|
|
1303
|
-
return settings;
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
|
-
// src/utils/normalize-page-url.ts
|
|
1307
|
-
var KEPT_PARAM_RE = /^(?:__revisionId|isDesignMode|weaverse)/;
|
|
1308
|
-
function normalizePageUrl(url) {
|
|
1309
|
-
let parsed;
|
|
1310
|
-
try {
|
|
1311
|
-
parsed = new URL(url);
|
|
1312
|
-
} catch {
|
|
1313
|
-
return url;
|
|
1314
|
-
}
|
|
1315
|
-
const kept = [...parsed.searchParams].filter(
|
|
1316
|
-
([key]) => KEPT_PARAM_RE.test(key)
|
|
1317
|
-
);
|
|
1318
|
-
kept.sort(([a], [b]) => a.localeCompare(b));
|
|
1319
|
-
const search = new URLSearchParams(kept).toString();
|
|
1320
|
-
let { pathname } = parsed;
|
|
1321
|
-
if (pathname.endsWith(".data")) {
|
|
1322
|
-
pathname = pathname.slice(0, -".data".length);
|
|
1323
|
-
}
|
|
1324
|
-
return `${parsed.origin}${pathname}${search ? `?${search}` : ""}`;
|
|
1325
|
-
}
|
|
1326
|
-
|
|
1327
|
-
// src/weaverse-client.ts
|
|
1328
|
-
var CACHE_DURATIONS = {
|
|
1329
|
-
/** Short browser freshness for content that can change in Builder */
|
|
1330
|
-
SHORT: 60,
|
|
1331
|
-
/** Shared cache freshness for anonymous storefront traffic */
|
|
1332
|
-
SHARED_SHORT: 300,
|
|
1333
|
-
/** Long stale window so slow Builder responses do not block storefront rendering */
|
|
1334
|
-
LONG: 86400,
|
|
1335
|
-
/** Extra freshness for sitemap-like index data */
|
|
1336
|
-
STATIC: 3600
|
|
1337
|
-
};
|
|
1338
|
-
var DEFAULT_FETCH_TIMEOUT_MS = 1e4;
|
|
1339
|
-
var MAX_FETCH_ATTEMPTS = 2;
|
|
1340
|
-
var FETCH_RETRY_BACKOFF_MS = 300;
|
|
1341
|
-
function isRetryableFetchError(error) {
|
|
1342
|
-
if (!(error instanceof WeaverseError)) {
|
|
1343
|
-
return false;
|
|
1344
|
-
}
|
|
1345
|
-
if (error.code === "TIMEOUT_ERROR" || error.code === "NETWORK_ERROR") {
|
|
1346
|
-
return true;
|
|
1347
|
-
}
|
|
1348
|
-
return error.code === "FETCH_ERROR" && (error.statusCode ?? 0) >= 500;
|
|
1349
|
-
}
|
|
1350
|
-
var API_PATH = "v1";
|
|
1351
|
-
var DEFAULT_CACHE_STRATEGY = {
|
|
1352
|
-
maxAge: CACHE_DURATIONS.SHORT,
|
|
1353
|
-
sMaxAge: CACHE_DURATIONS.SHARED_SHORT,
|
|
1354
|
-
staleWhileRevalidate: CACHE_DURATIONS.LONG,
|
|
1355
|
-
staleIfError: CACHE_DURATIONS.LONG
|
|
1356
|
-
};
|
|
1357
|
-
var SMART_CACHE_STRATEGIES = {
|
|
1358
|
-
project: DEFAULT_CACHE_STRATEGY,
|
|
1359
|
-
"theme-settings": DEFAULT_CACHE_STRATEGY,
|
|
1360
|
-
"merchant-overrides": DEFAULT_CACHE_STRATEGY,
|
|
1361
|
-
"custom-pages": {
|
|
1362
|
-
maxAge: CACHE_DURATIONS.SHORT,
|
|
1363
|
-
sMaxAge: CACHE_DURATIONS.STATIC,
|
|
1364
|
-
staleWhileRevalidate: CACHE_DURATIONS.LONG,
|
|
1365
|
-
staleIfError: CACHE_DURATIONS.LONG
|
|
1366
|
-
}
|
|
1367
|
-
};
|
|
1368
|
-
var bodyFreeCacheRequests = /* @__PURE__ */ new WeakSet();
|
|
1369
|
-
var BODY_FREE_CACHE_SENTINEL = "\0weaverse:body-free";
|
|
1370
|
-
var WeaverseClient = class {
|
|
1371
|
-
/** Builder API version used by this client. */
|
|
1372
|
-
API = API_PATH;
|
|
1373
|
-
/** Stable project configuration shared by page requests. */
|
|
1374
|
-
basePageConfigs;
|
|
1375
|
-
/** Stable request body fields shared by page requests. */
|
|
1376
|
-
basePageRequestBody;
|
|
1377
|
-
/** Resolved project and rendering-mode configuration. */
|
|
1378
|
-
configs;
|
|
1379
|
-
/** Hydrogen cache wrapper used for Builder API requests. */
|
|
1380
|
-
withCache;
|
|
1381
|
-
/** Incoming request associated with this client instance. */
|
|
1382
|
-
request;
|
|
1383
|
-
/** Hydrogen customer-account client, when configured. */
|
|
1384
|
-
customerAccount;
|
|
1385
|
-
/** Hydrogen Storefront API client and locale context. */
|
|
1386
|
-
storefront;
|
|
1387
|
-
/** Components registered for page rendering and component loaders. */
|
|
1388
|
-
components;
|
|
1389
|
-
/** Theme schema used for defaults and Studio editing. */
|
|
1390
|
-
themeSchema;
|
|
1391
|
-
/** Hydrogen runtime environment variables. */
|
|
1392
|
-
env;
|
|
1393
|
-
/** Cache storage supplied by the Hydrogen runtime. */
|
|
1394
|
-
cache;
|
|
1395
|
-
/** Background execution hook supplied by the Oxygen runtime. */
|
|
1396
|
-
waitUntil;
|
|
1397
|
-
// Performance optimizations
|
|
1398
|
-
parsedUrl;
|
|
1399
|
-
componentsByType;
|
|
1400
|
-
// Configuration
|
|
1401
|
-
fetchTimeoutMs;
|
|
1402
|
-
/** Creates a request-scoped client from the Hydrogen app context. */
|
|
1403
|
-
constructor(args) {
|
|
1404
|
-
this.request = args.request;
|
|
1405
|
-
this.storefront = args.storefront;
|
|
1406
|
-
this.customerAccount = args.customerAccount;
|
|
1407
|
-
this.components = args.components;
|
|
1408
|
-
this.themeSchema = args.themeSchema;
|
|
1409
|
-
this.env = args.env;
|
|
1410
|
-
this.cache = args.cache;
|
|
1411
|
-
this.waitUntil = args.waitUntil;
|
|
1412
|
-
this.parsedUrl = new URL(args.request.url);
|
|
1413
|
-
this.componentsByType = this.buildComponentLookupMap(args.components);
|
|
1414
|
-
this.fetchTimeoutMs = args.fetchTimeoutMs || DEFAULT_FETCH_TIMEOUT_MS;
|
|
1415
|
-
this.initializeCache(args);
|
|
1416
|
-
this.initializeConfigs(args);
|
|
1417
|
-
}
|
|
1418
|
-
/**
|
|
1419
|
-
* Initialize Hydrogen cache with proper configuration.
|
|
1420
|
-
* Logs warning if waitUntil is missing.
|
|
1421
|
-
*/
|
|
1422
|
-
initializeCache(args) {
|
|
1423
|
-
if (!args.waitUntil) {
|
|
1424
|
-
console.warn(
|
|
1425
|
-
"\u26A0\uFE0F WeaverseClient: waitUntil not provided, background operations may not complete"
|
|
1426
|
-
);
|
|
1427
|
-
}
|
|
1428
|
-
this.withCache = hydrogen.createWithCache({
|
|
1429
|
-
cache: args.cache,
|
|
1430
|
-
waitUntil: args.waitUntil || (() => Promise.resolve()),
|
|
1431
|
-
request: args.request
|
|
1432
|
-
});
|
|
1433
|
-
}
|
|
1434
|
-
/**
|
|
1435
|
-
* Initialize configs with projectId resolution and fail-fast validation.
|
|
1436
|
-
* Throws WeaverseError if projectId cannot be resolved.
|
|
1437
|
-
*/
|
|
1438
|
-
initializeConfigs(args) {
|
|
1439
|
-
const baseConfigs = getWeaverseConfigs(
|
|
1440
|
-
args.request,
|
|
1441
|
-
args.env
|
|
1442
|
-
);
|
|
1443
|
-
const resolvedProjectId = this.resolveProjectIdSync(
|
|
1444
|
-
args.projectId,
|
|
1445
|
-
args.request,
|
|
1446
|
-
args.env,
|
|
1447
|
-
baseConfigs
|
|
1448
|
-
);
|
|
1449
|
-
if (!resolvedProjectId || resolvedProjectId.trim() === "") {
|
|
1450
|
-
throw new WeaverseError(
|
|
1451
|
-
"Failed to initialize WeaverseClient: No valid projectId found. Set WEAVERSE_PROJECT_ID environment variable or provide projectId parameter.",
|
|
1452
|
-
"MISSING_PROJECT_ID"
|
|
1453
|
-
);
|
|
1454
|
-
}
|
|
1455
|
-
this.configs = {
|
|
1456
|
-
...baseConfigs,
|
|
1457
|
-
projectId: resolvedProjectId
|
|
1458
|
-
};
|
|
1459
|
-
this.basePageConfigs = {
|
|
1460
|
-
projectId: this.configs.projectId,
|
|
1461
|
-
weaverseHost: this.configs.weaverseHost,
|
|
1462
|
-
weaverseApiBase: this.configs.weaverseApiBase,
|
|
1463
|
-
weaverseApiKey: this.configs.weaverseApiKey,
|
|
1464
|
-
weaverseVersion: this.configs.weaverseVersion,
|
|
1465
|
-
isDesignMode: this.configs.isDesignMode,
|
|
1466
|
-
isPreviewMode: this.configs.isPreviewMode,
|
|
1467
|
-
isRevisionPreview: this.configs.isRevisionPreview
|
|
1468
|
-
};
|
|
1469
|
-
this.basePageRequestBody = {
|
|
1470
|
-
isDesignMode: this.configs.isDesignMode,
|
|
1471
|
-
i18n: args.storefront.i18n,
|
|
1472
|
-
projectId: this.configs.projectId
|
|
1473
|
-
};
|
|
1474
|
-
Object.freeze(this.configs);
|
|
1475
|
-
Object.freeze(this.basePageConfigs);
|
|
1476
|
-
Object.freeze(this.basePageRequestBody);
|
|
1477
|
-
}
|
|
1478
|
-
/**
|
|
1479
|
-
* Build component lookup map for O(1) access by type.
|
|
1480
|
-
* Significantly improves performance for large component lists.
|
|
1481
|
-
*/
|
|
1482
|
-
buildComponentLookupMap(components) {
|
|
1483
|
-
return new Map(components.map((comp) => [comp.schema?.type, comp]));
|
|
1484
|
-
}
|
|
1485
|
-
/**
|
|
1486
|
-
* Extract comprehensive error information from unknown error type.
|
|
1487
|
-
* Preserves error context, codes, and stack traces for debugging.
|
|
1488
|
-
*
|
|
1489
|
-
* @param error - Unknown error to extract information from
|
|
1490
|
-
* @returns Structured error information with message, code, stack, and context
|
|
1491
|
-
*
|
|
1492
|
-
* @example
|
|
1493
|
-
* ```typescript
|
|
1494
|
-
* try {
|
|
1495
|
-
* // ... operation
|
|
1496
|
-
* } catch (error) {
|
|
1497
|
-
* const errorInfo = this.extractErrorInfo(error)
|
|
1498
|
-
* console.error('Operation failed:', errorInfo.message, errorInfo.context)
|
|
1499
|
-
* }
|
|
1500
|
-
* ```
|
|
1501
|
-
*/
|
|
1502
|
-
extractErrorInfo(error) {
|
|
1503
|
-
if (error instanceof WeaverseError) {
|
|
1504
|
-
return {
|
|
1505
|
-
message: error.message,
|
|
1506
|
-
code: error.code,
|
|
1507
|
-
context: error.context,
|
|
1508
|
-
stack: error.stack
|
|
1509
|
-
};
|
|
1510
|
-
}
|
|
1511
|
-
if (error instanceof Error) {
|
|
1512
|
-
return {
|
|
1513
|
-
message: error.message,
|
|
1514
|
-
stack: error.stack
|
|
1515
|
-
};
|
|
1516
|
-
}
|
|
1517
|
-
return {
|
|
1518
|
-
message: String(error)
|
|
1519
|
-
};
|
|
1520
|
-
}
|
|
1521
|
-
/**
|
|
1522
|
-
* Extract error message only (for backward compatibility).
|
|
1523
|
-
* Use extractErrorInfo() for more detailed error information.
|
|
1524
|
-
*
|
|
1525
|
-
* @deprecated Use extractErrorInfo() instead to preserve error context
|
|
1526
|
-
*/
|
|
1527
|
-
extractErrorMessage(error) {
|
|
1528
|
-
return this.extractErrorInfo(error).message;
|
|
1529
|
-
}
|
|
1530
|
-
/**
|
|
1531
|
-
* Validates projectId format (alphanumeric, hyphens, underscores only).
|
|
1532
|
-
* Returns detailed validation result with error message.
|
|
1533
|
-
*
|
|
1534
|
-
* @param projectId - Project identifier to validate
|
|
1535
|
-
* @returns Validation result with error message if invalid
|
|
1536
|
-
*/
|
|
1537
|
-
validateProjectId(projectId) {
|
|
1538
|
-
if (!projectId || projectId.trim() === "") {
|
|
1539
|
-
return {
|
|
1540
|
-
valid: false,
|
|
1541
|
-
error: "Project ID cannot be empty"
|
|
1542
|
-
};
|
|
1543
|
-
}
|
|
1544
|
-
const validPattern = /^[a-zA-Z0-9_-]+$/;
|
|
1545
|
-
if (!validPattern.test(projectId)) {
|
|
1546
|
-
return {
|
|
1547
|
-
valid: false,
|
|
1548
|
-
error: `Invalid format: "${projectId}". Only alphanumeric characters, hyphens, and underscores are allowed.`
|
|
1549
|
-
};
|
|
1550
|
-
}
|
|
1551
|
-
return { valid: true };
|
|
1552
|
-
}
|
|
1553
|
-
/**
|
|
1554
|
-
* Resolves projectId with multi-project architecture support.
|
|
1555
|
-
* Uses priority chain to determine the correct project ID.
|
|
1556
|
-
*
|
|
1557
|
-
* @param projectId - Project identifier (string, function, or undefined)
|
|
1558
|
-
* @param request - HTTP request for context access
|
|
1559
|
-
* @param env - Hydrogen environment with variables
|
|
1560
|
-
* @param baseConfigs - Pre-fetched base configs to avoid duplicate calls
|
|
1561
|
-
* @returns Resolved project ID string (empty string if none found)
|
|
1562
|
-
*/
|
|
1563
|
-
resolveProjectIdSync(projectId, request, env, baseConfigs) {
|
|
1564
|
-
return this.resolveFromQueryParams(request) || this.resolveFromFunction(projectId) || this.resolveFromString(projectId) || this.resolveFromEnvironment(baseConfigs, request, env) || "";
|
|
1565
|
-
}
|
|
1566
|
-
/**
|
|
1567
|
-
* Priority 1: Resolve projectId from URL query parameters.
|
|
1568
|
-
* Used for design mode and preview mode overrides.
|
|
1569
|
-
*/
|
|
1570
|
-
resolveFromQueryParams(request) {
|
|
1571
|
-
const queries = getRequestQueries(request);
|
|
1572
|
-
return queries.weaverseProjectId || null;
|
|
1573
|
-
}
|
|
1574
|
-
/**
|
|
1575
|
-
* Priority 2: Resolve projectId from function parameter.
|
|
1576
|
-
* Detects and rejects async functions with helpful error.
|
|
1577
|
-
*/
|
|
1578
|
-
resolveFromFunction(projectId) {
|
|
1579
|
-
if (!isProjectIdFunction(projectId)) {
|
|
1580
|
-
return null;
|
|
1581
|
-
}
|
|
1582
|
-
if (projectId.constructor.name === "AsyncFunction") {
|
|
1583
|
-
throw new WeaverseError(
|
|
1584
|
-
"Async projectId functions must be awaited before passing to WeaverseClient. Use: projectId: await getProjectAsync() instead of: projectId: getProjectAsync",
|
|
1585
|
-
"ASYNC_PROJECT_ID"
|
|
1586
|
-
);
|
|
1587
|
-
}
|
|
1588
|
-
try {
|
|
1589
|
-
const result = projectId();
|
|
1590
|
-
if (result instanceof Promise) {
|
|
1591
|
-
throw new WeaverseError(
|
|
1592
|
-
"Async projectId functions must be awaited before passing to WeaverseClient. Use: projectId: await getProjectAsync() instead of: projectId: getProjectAsync",
|
|
1593
|
-
"ASYNC_PROJECT_ID"
|
|
1594
|
-
);
|
|
1595
|
-
}
|
|
1596
|
-
if (result && result.trim() !== "") {
|
|
1597
|
-
const trimmed = result.trim();
|
|
1598
|
-
const validation = this.validateProjectId(trimmed);
|
|
1599
|
-
if (validation.valid) {
|
|
1600
|
-
return trimmed;
|
|
1601
|
-
}
|
|
1602
|
-
throw new WeaverseError(
|
|
1603
|
-
validation.error || "Invalid projectId format",
|
|
1604
|
-
"INVALID_PROJECT_ID"
|
|
1605
|
-
);
|
|
1606
|
-
}
|
|
1607
|
-
} catch (err) {
|
|
1608
|
-
if (err instanceof WeaverseError) {
|
|
1609
|
-
throw err;
|
|
1610
|
-
}
|
|
1611
|
-
throw new WeaverseError(
|
|
1612
|
-
`Failed to evaluate projectId function: ${err instanceof Error ? err.message : String(err)}`,
|
|
1613
|
-
"PROJECT_ID_FUNCTION_ERROR",
|
|
1614
|
-
void 0,
|
|
1615
|
-
{ cause: err instanceof Error ? err.stack : String(err) }
|
|
1616
|
-
);
|
|
1617
|
-
}
|
|
1618
|
-
return null;
|
|
1619
|
-
}
|
|
1620
|
-
/**
|
|
1621
|
-
* Priority 3: Resolve projectId from explicit string parameter.
|
|
1622
|
-
*/
|
|
1623
|
-
resolveFromString(projectId) {
|
|
1624
|
-
if (typeof projectId !== "string") {
|
|
1625
|
-
return null;
|
|
1626
|
-
}
|
|
1627
|
-
const trimmed = projectId.trim();
|
|
1628
|
-
if (trimmed === "") {
|
|
1629
|
-
return null;
|
|
1630
|
-
}
|
|
1631
|
-
const validation = this.validateProjectId(trimmed);
|
|
1632
|
-
if (validation.valid) {
|
|
1633
|
-
return trimmed;
|
|
1634
|
-
}
|
|
1635
|
-
throw new WeaverseError(
|
|
1636
|
-
validation.error || "Invalid projectId format",
|
|
1637
|
-
"INVALID_PROJECT_ID"
|
|
1638
|
-
);
|
|
1639
|
-
}
|
|
1640
|
-
/**
|
|
1641
|
-
* Priority 4: Resolve projectId from environment variables.
|
|
1642
|
-
*/
|
|
1643
|
-
resolveFromEnvironment(baseConfigs, request, env) {
|
|
1644
|
-
const configs = baseConfigs || getWeaverseConfigs(request, env);
|
|
1645
|
-
if (configs.projectId && configs.projectId.trim() !== "") {
|
|
1646
|
-
return configs.projectId.trim();
|
|
1647
|
-
}
|
|
1648
|
-
return null;
|
|
1649
|
-
}
|
|
1650
|
-
/**
|
|
1651
|
-
* Helper method for direct fetching in design mode.
|
|
1652
|
-
* Returns same format as withCache.fetch for consistency.
|
|
1653
|
-
* Includes 10-second timeout to prevent hanging requests.
|
|
1654
|
-
*/
|
|
1655
|
-
fetchOnce = async (url, options, timeoutMs) => {
|
|
1656
|
-
const controller = new AbortController();
|
|
1657
|
-
const timeoutId = setTimeout(
|
|
1658
|
-
() => controller.abort(),
|
|
1659
|
-
timeoutMs
|
|
1660
|
-
);
|
|
1661
|
-
try {
|
|
1662
|
-
const response = await fetch(url, {
|
|
1663
|
-
...options,
|
|
1664
|
-
signal: controller.signal
|
|
1665
|
-
});
|
|
1666
|
-
if (!response.ok) {
|
|
1667
|
-
const errorText = await response.text();
|
|
1668
|
-
throw new WeaverseError(
|
|
1669
|
-
`HTTP ${response.status}: ${response.statusText}`,
|
|
1670
|
-
"FETCH_ERROR",
|
|
1671
|
-
response.status,
|
|
1672
|
-
{ url, errorText }
|
|
1673
|
-
);
|
|
1674
|
-
}
|
|
1675
|
-
const data = await response.json();
|
|
1676
|
-
return { data, response };
|
|
1677
|
-
} catch (err) {
|
|
1678
|
-
if (err instanceof WeaverseError) {
|
|
1679
|
-
throw err;
|
|
1680
|
-
}
|
|
1681
|
-
if (err.name === "AbortError") {
|
|
1682
|
-
throw new WeaverseError(
|
|
1683
|
-
`Request timeout after ${timeoutMs}ms`,
|
|
1684
|
-
"TIMEOUT_ERROR",
|
|
1685
|
-
void 0,
|
|
1686
|
-
{ url, timeoutMs }
|
|
1687
|
-
);
|
|
1688
|
-
}
|
|
1689
|
-
throw new WeaverseError(
|
|
1690
|
-
"Network error during fetch",
|
|
1691
|
-
"NETWORK_ERROR",
|
|
1692
|
-
void 0,
|
|
1693
|
-
{ url, cause: err instanceof Error ? err.message : String(err) }
|
|
1694
|
-
);
|
|
1695
|
-
} finally {
|
|
1696
|
-
if (timeoutId !== void 0) {
|
|
1697
|
-
clearTimeout(timeoutId);
|
|
1698
|
-
}
|
|
1699
|
-
}
|
|
1700
|
-
};
|
|
1701
|
-
directFetch = async (url, options = {}, timeoutMs = this.fetchTimeoutMs) => {
|
|
1702
|
-
let lastError;
|
|
1703
|
-
for (let attempt = 1; attempt <= MAX_FETCH_ATTEMPTS; attempt++) {
|
|
1704
|
-
try {
|
|
1705
|
-
return await this.fetchOnce(url, options, timeoutMs);
|
|
1706
|
-
} catch (err) {
|
|
1707
|
-
lastError = err;
|
|
1708
|
-
if (attempt >= MAX_FETCH_ATTEMPTS || !isRetryableFetchError(err)) {
|
|
1709
|
-
throw err;
|
|
1710
|
-
}
|
|
1711
|
-
await new Promise(
|
|
1712
|
-
(resolve) => setTimeout(resolve, FETCH_RETRY_BACKOFF_MS * attempt)
|
|
1713
|
-
);
|
|
1714
|
-
}
|
|
1715
|
-
}
|
|
1716
|
-
throw lastError;
|
|
1717
|
-
};
|
|
1718
|
-
// Helper method for building API URLs consistently
|
|
1719
|
-
getApiUrl(endpoint) {
|
|
1720
|
-
const { weaverseApiBase } = this.configs;
|
|
1721
|
-
return `${weaverseApiBase}/api/public/${endpoint}`;
|
|
1722
|
-
}
|
|
1723
|
-
isExternalPublicApiUrl(url) {
|
|
1724
|
-
const { weaverseApiBase, weaverseHost } = this.configs;
|
|
1725
|
-
return weaverseApiBase !== weaverseHost && url.startsWith(`${weaverseApiBase}/api/public/`);
|
|
1726
|
-
}
|
|
1727
|
-
/**
|
|
1728
|
-
* Fetch data with caching support for both design mode and production.
|
|
1729
|
-
* Uses direct fetch in design mode, Hydrogen's withCache in production.
|
|
1730
|
-
* Automatically includes projectId in cache key for multi-project isolation.
|
|
1731
|
-
*
|
|
1732
|
-
* @param url - The URL to fetch from
|
|
1733
|
-
* @param options - Fetch options including optional cache strategy
|
|
1734
|
-
* @returns Promise resolving to the fetched data
|
|
1735
|
-
*
|
|
1736
|
-
* @example
|
|
1737
|
-
* ```typescript
|
|
1738
|
-
* const data = await weaverse.fetchWithCache<MyData>(
|
|
1739
|
-
* 'https://api.example.com/data',
|
|
1740
|
-
* { method: 'POST', body: JSON.stringify({ key: 'value' }) }
|
|
1741
|
-
* )
|
|
1742
|
-
* ```
|
|
1743
|
-
*/
|
|
1744
|
-
fetchWithCache = async (url, options = {}) => {
|
|
1745
|
-
const { cacheTarget, strategy: strategyOverride, ...fetchOptions } = options;
|
|
1746
|
-
const strategy = strategyOverride || hydrogen.CacheCustom(
|
|
1747
|
-
cacheTarget ? SMART_CACHE_STRATEGIES[cacheTarget] : DEFAULT_CACHE_STRATEGY
|
|
1748
|
-
);
|
|
1749
|
-
const cacheKey = [
|
|
1750
|
-
"weaverse-fetch",
|
|
1751
|
-
url,
|
|
1752
|
-
options.method || "GET",
|
|
1753
|
-
bodyFreeCacheRequests.has(options) ? BODY_FREE_CACHE_SENTINEL : fetchOptions.body,
|
|
1754
|
-
// WeakSet-derived discriminator: this slot cannot be produced by any
|
|
1755
|
-
// caller-supplied shape, so no external call can reach the marked
|
|
1756
|
-
// identity — even one that happens to send the sentinel string as its
|
|
1757
|
-
// body.
|
|
1758
|
-
bodyFreeCacheRequests.has(options),
|
|
1759
|
-
this.configs.projectId,
|
|
1760
|
-
cacheTarget || "default"
|
|
1761
|
-
];
|
|
1762
|
-
let result;
|
|
1763
|
-
if (this.configs.isDesignMode || this.configs.isRevisionPreview || this.isExternalPublicApiUrl(url)) {
|
|
1764
|
-
result = await this.directFetch(url, fetchOptions);
|
|
1765
|
-
} else {
|
|
1766
|
-
result = await this.withCache.fetch(url, fetchOptions, {
|
|
1767
|
-
cacheKey,
|
|
1768
|
-
cacheStrategy: strategy,
|
|
1769
|
-
shouldCacheResponse: (response) => {
|
|
1770
|
-
if (fetchOptions.signal?.aborted) {
|
|
1771
|
-
return false;
|
|
1772
|
-
}
|
|
1773
|
-
return !hasError(response) && response !== null && response !== void 0;
|
|
1774
|
-
},
|
|
1775
|
-
displayName: "Weaverse API"
|
|
1776
|
-
});
|
|
1777
|
-
}
|
|
1778
|
-
return result.data;
|
|
1779
|
-
};
|
|
1780
|
-
/**
|
|
1781
|
-
* Safe origin of the incoming storefront request: scheme, host and explicit
|
|
1782
|
-
* port. Userinfo, path, query and fragment are dropped, so no customer
|
|
1783
|
-
* route or credential-bearing value leaves the storefront. Returns undefined
|
|
1784
|
-
* for a non-http(s) request so the field is simply omitted.
|
|
1785
|
-
*/
|
|
1786
|
-
safeStorefrontOrigin() {
|
|
1787
|
-
const { protocol, host } = this.parsedUrl;
|
|
1788
|
-
if (protocol !== "http:" && protocol !== "https:") {
|
|
1789
|
-
return;
|
|
1790
|
-
}
|
|
1791
|
-
return host ? `${protocol}//${host}` : void 0;
|
|
1792
|
-
}
|
|
1793
|
-
/**
|
|
1794
|
-
* Load theme settings from Weaverse API with fallback to schema defaults.
|
|
1795
|
-
* Merges remote settings with local theme schema and handles design mode serialization.
|
|
1796
|
-
*
|
|
1797
|
-
* @param strategy - Optional cache strategy override
|
|
1798
|
-
* @returns Promise resolving to theme settings response
|
|
1799
|
-
*
|
|
1800
|
-
* @example
|
|
1801
|
-
* ```typescript
|
|
1802
|
-
* const settings = await weaverse.loadThemeSettings()
|
|
1803
|
-
* const primaryColor = settings.theme.colors?.primary
|
|
1804
|
-
* ```
|
|
1805
|
-
*/
|
|
1806
|
-
loadThemeSettings = async (strategy) => {
|
|
1807
|
-
const defaultThemeSettings = generateDataFromSchema(this.themeSchema);
|
|
1808
|
-
try {
|
|
1809
|
-
const { configs } = this;
|
|
1810
|
-
const { projectId, isDesignMode } = configs;
|
|
1811
|
-
if (!projectId) {
|
|
1812
|
-
throw new Error("Missing Weaverse projectId!");
|
|
1813
|
-
}
|
|
1814
|
-
const url = this.getApiUrl("project_configs");
|
|
1815
|
-
const body = JSON.stringify({
|
|
1816
|
-
isDesignMode,
|
|
1817
|
-
projectId,
|
|
1818
|
-
storefrontUrl: this.safeStorefrontOrigin()
|
|
1819
|
-
});
|
|
1820
|
-
const themeSettingsOptions = {
|
|
1821
|
-
method: "POST",
|
|
1822
|
-
cacheTarget: "theme-settings",
|
|
1823
|
-
strategy,
|
|
1824
|
-
body,
|
|
1825
|
-
headers: {
|
|
1826
|
-
"Content-Type": "application/json",
|
|
1827
|
-
Accept: "application/json",
|
|
1828
|
-
"Accept-Encoding": "gzip, deflate, br"
|
|
1829
|
-
}
|
|
1830
|
-
};
|
|
1831
|
-
bodyFreeCacheRequests.add(themeSettingsOptions);
|
|
1832
|
-
const [data, merchantOverrides] = await Promise.all([
|
|
1833
|
-
this.fetchWithCache(url, themeSettingsOptions),
|
|
1834
|
-
this.fetchMerchantOverrides(strategy)
|
|
1835
|
-
]);
|
|
1836
|
-
let result = data;
|
|
1837
|
-
if (typeof result !== "object" || result === null) {
|
|
1838
|
-
console.warn(
|
|
1839
|
-
"Invalid theme settings response format, using defaults:",
|
|
1840
|
-
{
|
|
1841
|
-
type: typeof result,
|
|
1842
|
-
isString: typeof result === "string",
|
|
1843
|
-
length: typeof result === "string" ? result.length : "N/A",
|
|
1844
|
-
preview: typeof result === "string" ? `${result.slice(0, 50)}...` : String(result)
|
|
1845
|
-
}
|
|
1846
|
-
);
|
|
1847
|
-
result = { theme: defaultThemeSettings };
|
|
1848
|
-
}
|
|
1849
|
-
if (this.themeSchema?.settings || this.themeSchema?.inspector) {
|
|
1850
|
-
if (!result.theme || typeof result.theme !== "object") {
|
|
1851
|
-
result.theme = defaultThemeSettings;
|
|
1852
|
-
} else {
|
|
1853
|
-
result.theme = {
|
|
1854
|
-
...defaultThemeSettings,
|
|
1855
|
-
...result.theme
|
|
1856
|
-
};
|
|
1857
|
-
}
|
|
1858
|
-
}
|
|
1859
|
-
const staticContent = this.themeSchema?.i18n?.staticContent;
|
|
1860
|
-
if (staticContent) {
|
|
1861
|
-
result.staticContent = staticContent;
|
|
1862
|
-
}
|
|
1863
|
-
if (merchantOverrides) {
|
|
1864
|
-
result.merchantOverrides = merchantOverrides;
|
|
1865
|
-
}
|
|
1866
|
-
if (this.configs.isDesignMode) {
|
|
1867
|
-
result = {
|
|
1868
|
-
...result,
|
|
1869
|
-
schema: this.themeSchema && typeof this.themeSchema === "object" ? {
|
|
1870
|
-
...this.themeSchema,
|
|
1871
|
-
settings: this.themeSchema?.settings?.map((group) => ({
|
|
1872
|
-
...group,
|
|
1873
|
-
inputs: group?.inputs?.map((input) => {
|
|
1874
|
-
if (typeof input?.condition === "function") {
|
|
1875
|
-
return {
|
|
1876
|
-
...input,
|
|
1877
|
-
condition: input.condition.toString()
|
|
1878
|
-
};
|
|
1879
|
-
}
|
|
1880
|
-
return input;
|
|
1881
|
-
})
|
|
1882
|
-
}))
|
|
1883
|
-
} : void 0,
|
|
1884
|
-
publicEnv: this.configs.publicEnv
|
|
1885
|
-
};
|
|
1886
|
-
}
|
|
1887
|
-
return result;
|
|
1888
|
-
} catch (error) {
|
|
1889
|
-
const errorMessage = "Unable to load theme settings";
|
|
1890
|
-
const errorDetails = this.extractErrorMessage(error);
|
|
1891
|
-
console.error(errorMessage, errorDetails);
|
|
1892
|
-
return {
|
|
1893
|
-
theme: defaultThemeSettings,
|
|
1894
|
-
staticContent: this.themeSchema?.i18n?.staticContent,
|
|
1895
|
-
_error: errorDetails,
|
|
1896
|
-
_loadFailed: true
|
|
1897
|
-
};
|
|
1898
|
-
}
|
|
1899
|
-
};
|
|
1900
|
-
/**
|
|
1901
|
-
* Fetch locale-specific merchant overrides from the translation API.
|
|
1902
|
-
* Returns a nested JSON object with translated values.
|
|
1903
|
-
* Falls back to empty object on error to avoid blocking theme rendering.
|
|
1904
|
-
*/
|
|
1905
|
-
fetchMerchantOverrides = async (strategy) => {
|
|
1906
|
-
try {
|
|
1907
|
-
const { projectId, weaverseHost } = this.configs;
|
|
1908
|
-
const i18n = this.storefront.i18n;
|
|
1909
|
-
if (!this.themeSchema?.i18n) {
|
|
1910
|
-
return;
|
|
1911
|
-
}
|
|
1912
|
-
if (!(projectId && weaverseHost)) {
|
|
1913
|
-
return;
|
|
1914
|
-
}
|
|
1915
|
-
const language = (i18n?.language || "en").toLowerCase();
|
|
1916
|
-
const country = (i18n?.country || "us").toLowerCase();
|
|
1917
|
-
const locale = `${language}-${country}`;
|
|
1918
|
-
const url = `${weaverseHost}/api/translation/static?projectId=${projectId}&locale=${locale}`;
|
|
1919
|
-
const overrides = await this.fetchWithCache(
|
|
1920
|
-
url,
|
|
1921
|
-
{
|
|
1922
|
-
method: "GET",
|
|
1923
|
-
cacheTarget: "merchant-overrides",
|
|
1924
|
-
strategy,
|
|
1925
|
-
headers: {
|
|
1926
|
-
Accept: "application/json"
|
|
1927
|
-
},
|
|
1928
|
-
signal: AbortSignal.timeout(this.fetchTimeoutMs)
|
|
1929
|
-
}
|
|
1930
|
-
);
|
|
1931
|
-
if (typeof overrides === "object" && overrides !== null) {
|
|
1932
|
-
return overrides;
|
|
1933
|
-
}
|
|
1934
|
-
return;
|
|
1935
|
-
} catch (error) {
|
|
1936
|
-
console.warn(
|
|
1937
|
-
"Unable to load merchant overrides, using theme defaults:",
|
|
1938
|
-
this.extractErrorMessage(error)
|
|
1939
|
-
);
|
|
1940
|
-
return;
|
|
1941
|
-
}
|
|
1942
|
-
};
|
|
1943
|
-
/**
|
|
1944
|
-
* Generate fallback page with default structure when page data is unavailable.
|
|
1945
|
-
* Used internally when API returns no page or when page needs default content.
|
|
1946
|
-
*
|
|
1947
|
-
* @param message - Custom message to display in the fallback page
|
|
1948
|
-
* @returns HydrogenPageData with single main component containing the message
|
|
1949
|
-
*/
|
|
1950
|
-
generateFallbackPage = (message) => {
|
|
1951
|
-
const rootId = crypto.randomUUID();
|
|
1952
|
-
return {
|
|
1953
|
-
id: `fallback_page_${Date.now()}`,
|
|
1954
|
-
rootId,
|
|
1955
|
-
name: "Default Page",
|
|
1956
|
-
items: [
|
|
1957
|
-
{
|
|
1958
|
-
type: "main",
|
|
1959
|
-
id: rootId,
|
|
1960
|
-
data: { dangerouslySetInnerHTML: { __html: message } }
|
|
1961
|
-
}
|
|
1962
|
-
]
|
|
1963
|
-
};
|
|
1964
|
-
};
|
|
1965
|
-
/**
|
|
1966
|
-
* Fetch all published custom pages for sitemap generation.
|
|
1967
|
-
* Paginates automatically, never throws, returns accumulated results on partial failure.
|
|
1968
|
-
*/
|
|
1969
|
-
async fetchCustomPages(opts) {
|
|
1970
|
-
const { weaverseApiBase, projectId } = this.configs;
|
|
1971
|
-
const entries = [];
|
|
1972
|
-
const MAX_PAGES = 100;
|
|
1973
|
-
let cursor = null;
|
|
1974
|
-
for (let i = 0; i < MAX_PAGES; i++) {
|
|
1975
|
-
const params = new URLSearchParams();
|
|
1976
|
-
if (opts?.locale) {
|
|
1977
|
-
params.set("locale", opts.locale);
|
|
1978
|
-
}
|
|
1979
|
-
if (opts?.limit) {
|
|
1980
|
-
params.set("limit", String(opts.limit));
|
|
1981
|
-
}
|
|
1982
|
-
if (cursor) {
|
|
1983
|
-
params.set("cursor", cursor);
|
|
1984
|
-
}
|
|
1985
|
-
const qs = params.toString();
|
|
1986
|
-
const url = `${weaverseApiBase}/api/public/v1/projects/${projectId}/custom-pages${qs ? `?${qs}` : ""}`;
|
|
1987
|
-
try {
|
|
1988
|
-
const result = await this.fetchWithCache(url, { cacheTarget: "custom-pages" });
|
|
1989
|
-
entries.push(...result.data || []);
|
|
1990
|
-
if (!result.nextCursor) {
|
|
1991
|
-
return entries;
|
|
1992
|
-
}
|
|
1993
|
-
cursor = result.nextCursor;
|
|
1994
|
-
} catch (err) {
|
|
1995
|
-
const status = err?.status;
|
|
1996
|
-
const msg = err?.message || String(err);
|
|
1997
|
-
console.warn(
|
|
1998
|
-
entries.length === 0 ? `[Weaverse] Failed to fetch custom pages: ${msg}${status ? ` (HTTP ${status})` : ""}` : `[Weaverse] Custom pages pagination interrupted: ${msg}`
|
|
1999
|
-
);
|
|
2000
|
-
return entries;
|
|
2001
|
-
}
|
|
2002
|
-
}
|
|
2003
|
-
console.warn(
|
|
2004
|
-
"[Weaverse] Custom pages pagination cap reached (100 iterations)"
|
|
2005
|
-
);
|
|
2006
|
-
return entries;
|
|
2007
|
-
}
|
|
2008
|
-
/**
|
|
2009
|
-
* Load page data from Weaverse API with optional route-level project override.
|
|
2010
|
-
* Fetches page content, executes component loaders, and handles empty items fallback.
|
|
2011
|
-
*
|
|
2012
|
-
* @param params - Optional page loading parameters
|
|
2013
|
-
* @param params.type - Page type (INDEX, PAGE, PRODUCT, COLLECTION, etc.)
|
|
2014
|
-
* @param params.handle - Page handle for dynamic routes
|
|
2015
|
-
* @param params.locale - Locale override
|
|
2016
|
-
* @param params.projectId - Route-level project ID override (for multi-project)
|
|
2017
|
-
* @param params.strategy - Custom cache strategy override
|
|
2018
|
-
* @returns Promise resolving to page data or null on error
|
|
2019
|
-
*
|
|
2020
|
-
* @example
|
|
2021
|
-
* ```typescript
|
|
2022
|
-
* // Basic usage
|
|
2023
|
-
* const data = await weaverse.loadPage()
|
|
2024
|
-
*
|
|
2025
|
-
* // With page type
|
|
2026
|
-
* const data = await weaverse.loadPage({ type: 'INDEX' })
|
|
2027
|
-
*
|
|
2028
|
-
* // Route-level project override
|
|
2029
|
-
* const data = await weaverse.loadPage({
|
|
2030
|
-
* type: 'PAGE',
|
|
2031
|
-
* handle: 'about',
|
|
2032
|
-
* projectId: 'campaign-project-123'
|
|
2033
|
-
* })
|
|
2034
|
-
* ```
|
|
2035
|
-
*/
|
|
2036
|
-
loadPage = async (params = {}) => {
|
|
2037
|
-
try {
|
|
2038
|
-
const { request, storefront, basePageRequestBody, basePageConfigs } = this;
|
|
2039
|
-
const {
|
|
2040
|
-
projectId: clientProjectId,
|
|
2041
|
-
weaverseHost,
|
|
2042
|
-
isPreviewMode,
|
|
2043
|
-
sectionType
|
|
2044
|
-
} = this.configs;
|
|
2045
|
-
if (params.projectId !== void 0) {
|
|
2046
|
-
if (typeof params.projectId !== "string") {
|
|
2047
|
-
console.error(
|
|
2048
|
-
`Route-level projectId validation failed: must be a string. Received: ${typeof params.projectId}`
|
|
2049
|
-
);
|
|
2050
|
-
return null;
|
|
2051
|
-
}
|
|
2052
|
-
const validation = this.validateProjectId(params.projectId);
|
|
2053
|
-
if (!validation.valid) {
|
|
2054
|
-
console.error(
|
|
2055
|
-
`Route-level projectId validation failed: ${validation.error}`
|
|
2056
|
-
);
|
|
2057
|
-
return null;
|
|
2058
|
-
}
|
|
2059
|
-
}
|
|
2060
|
-
const effectiveProjectId = params.projectId || clientProjectId;
|
|
2061
|
-
if (isPreviewMode) {
|
|
2062
|
-
return getPreviewData(sectionType || "", this.components, weaverseHost);
|
|
2063
|
-
}
|
|
2064
|
-
if (!effectiveProjectId) {
|
|
2065
|
-
throw new Error("Missing Weaverse projectId!");
|
|
2066
|
-
}
|
|
2067
|
-
const { strategy, ...pageLoadParams } = params;
|
|
2068
|
-
const body = {
|
|
2069
|
-
...basePageRequestBody,
|
|
2070
|
-
projectId: effectiveProjectId,
|
|
2071
|
-
// Use effective (potentially overridden) projectId
|
|
2072
|
-
params: pageLoadParams,
|
|
2073
|
-
// Stripped to pathname + Weaverse params — tracking params would
|
|
2074
|
-
// fragment the subrequest cache key (see normalizePageUrl).
|
|
2075
|
-
url: normalizePageUrl(request.url)
|
|
2076
|
-
};
|
|
2077
|
-
const reqInit = {
|
|
2078
|
-
method: "POST",
|
|
2079
|
-
body: JSON.stringify(body),
|
|
2080
|
-
headers: {
|
|
2081
|
-
"Content-Type": "application/json",
|
|
2082
|
-
Accept: "application/json",
|
|
2083
|
-
"Accept-Encoding": "gzip, deflate, br",
|
|
2084
|
-
"X-Visitor-UA": request.headers.get("user-agent") || ""
|
|
2085
|
-
}
|
|
2086
|
-
};
|
|
2087
|
-
const url = this.getApiUrl("project");
|
|
2088
|
-
const projectData = await this.fetchWithCache(url, {
|
|
2089
|
-
...reqInit,
|
|
2090
|
-
cacheTarget: "project",
|
|
2091
|
-
strategy
|
|
2092
|
-
});
|
|
2093
|
-
if (hasError(projectData)) {
|
|
2094
|
-
throw new Error(projectData.error);
|
|
2095
|
-
}
|
|
2096
|
-
let page;
|
|
2097
|
-
let project;
|
|
2098
|
-
let pageAssignment;
|
|
2099
|
-
if (isFetchProjectPayload(projectData)) {
|
|
2100
|
-
page = projectData.page;
|
|
2101
|
-
project = projectData.project;
|
|
2102
|
-
pageAssignment = projectData.pageAssignment;
|
|
2103
|
-
} else {
|
|
2104
|
-
console.warn(
|
|
2105
|
-
"Invalid project data structure received from API, using fallback data",
|
|
2106
|
-
{ projectId: effectiveProjectId }
|
|
2107
|
-
);
|
|
2108
|
-
const responseData = projectData;
|
|
2109
|
-
page = responseData?.page;
|
|
2110
|
-
project = responseData?.project;
|
|
2111
|
-
pageAssignment = responseData?.pageAssignment;
|
|
2112
|
-
}
|
|
2113
|
-
if (!project) {
|
|
2114
|
-
console.warn("Weaverse project not found. Id:", effectiveProjectId);
|
|
2115
|
-
project = {
|
|
2116
|
-
id: effectiveProjectId,
|
|
2117
|
-
name: "Weaverse project not found.",
|
|
2118
|
-
weaverseShopId: ""
|
|
2119
|
-
};
|
|
2120
|
-
}
|
|
2121
|
-
if (!page) {
|
|
2122
|
-
page = this.generateFallbackPage(
|
|
2123
|
-
'<div style="text-align: center;">Please add new section to start.</div>'
|
|
2124
|
-
);
|
|
2125
|
-
}
|
|
2126
|
-
if (page?.items?.length === 0) {
|
|
2127
|
-
page.items.push({
|
|
2128
|
-
type: "main",
|
|
2129
|
-
id: page.rootId || crypto.randomUUID(),
|
|
2130
|
-
data: {}
|
|
2131
|
-
});
|
|
2132
|
-
}
|
|
2133
|
-
if (page?.items) {
|
|
2134
|
-
const items = page.items;
|
|
2135
|
-
page.items = await Promise.all(items.map(this.execComponentLoader));
|
|
2136
|
-
}
|
|
2137
|
-
return {
|
|
2138
|
-
page,
|
|
2139
|
-
project,
|
|
2140
|
-
pageAssignment,
|
|
2141
|
-
configs: {
|
|
2142
|
-
...basePageConfigs,
|
|
2143
|
-
requestInfo: {
|
|
2144
|
-
i18n: storefront.i18n,
|
|
2145
|
-
queries: getRequestQueries(request),
|
|
2146
|
-
pathname: this.parsedUrl.pathname,
|
|
2147
|
-
search: this.parsedUrl.search
|
|
2148
|
-
}
|
|
2149
|
-
}
|
|
2150
|
-
};
|
|
2151
|
-
} catch (error) {
|
|
2152
|
-
const errorMessage = "\u274C Page load failed";
|
|
2153
|
-
const errorContext = {
|
|
2154
|
-
projectId: params.projectId || this.configs.projectId
|
|
2155
|
-
};
|
|
2156
|
-
if (error instanceof WeaverseError) {
|
|
2157
|
-
console.error(errorMessage, {
|
|
2158
|
-
code: error.code,
|
|
2159
|
-
message: error.message,
|
|
2160
|
-
...errorContext,
|
|
2161
|
-
...error.context
|
|
2162
|
-
});
|
|
2163
|
-
} else if (error instanceof Error) {
|
|
2164
|
-
console.error(errorMessage, {
|
|
2165
|
-
message: error.message,
|
|
2166
|
-
stack: error.stack,
|
|
2167
|
-
...errorContext
|
|
2168
|
-
});
|
|
2169
|
-
} else {
|
|
2170
|
-
console.error(errorMessage, {
|
|
2171
|
-
error: String(error),
|
|
2172
|
-
...errorContext
|
|
2173
|
-
});
|
|
2174
|
-
}
|
|
2175
|
-
return null;
|
|
2176
|
-
}
|
|
2177
|
-
};
|
|
2178
|
-
/** Executes the registered loader for one component and attaches its result. */
|
|
2179
|
-
execComponentLoader = async (item) => {
|
|
2180
|
-
const { data = {}, type, id } = item;
|
|
2181
|
-
const component = this.componentsByType.get(type);
|
|
2182
|
-
const loader = component?.loader;
|
|
2183
|
-
if (typeof loader === "function" && component) {
|
|
2184
|
-
try {
|
|
2185
|
-
return {
|
|
2186
|
-
...item,
|
|
2187
|
-
loaderData: await Promise.resolve(
|
|
2188
|
-
loader({
|
|
2189
|
-
data: { ...generateDataFromSchema(component.schema), ...data },
|
|
2190
|
-
weaverse: this
|
|
2191
|
-
})
|
|
2192
|
-
)
|
|
2193
|
-
};
|
|
2194
|
-
} catch (error) {
|
|
2195
|
-
console.warn("\u274C Item loader run failed.", type, id, error);
|
|
2196
|
-
return item;
|
|
2197
|
-
}
|
|
2198
|
-
}
|
|
2199
|
-
return item;
|
|
2200
|
-
};
|
|
2201
|
-
};
|
|
2202
|
-
|
|
2203
|
-
// src/index.ts
|
|
2204
|
-
function getSelectedProductOptions(request) {
|
|
2205
|
-
let options = hydrogen.getSelectedProductOptions(request);
|
|
2206
|
-
return options.filter(
|
|
2207
|
-
({ name }) => name !== "isDesignMode" && !name.startsWith("weaverse")
|
|
2208
|
-
);
|
|
2209
|
-
}
|
|
2210
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_translation_store = require("./translation-store-BpPWqZ0B.js");
|
|
3
|
+
let _weaverse_react = require("@weaverse/react");
|
|
4
|
+
let _weaverse_schema = require("@weaverse/schema");
|
|
5
|
+
Object.defineProperty(exports, "IMAGES_PLACEHOLDERS", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return _weaverse_schema.IMAGES_PLACEHOLDERS;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
exports.TranslationStore = require_translation_store.TranslationStore;
|
|
12
|
+
exports.WeaverseError = require_translation_store.WeaverseError;
|
|
13
|
+
exports.WeaverseLoadError = require_translation_store.WeaverseLoadError;
|
|
14
|
+
Object.defineProperty(exports, "createSchema", {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function() {
|
|
17
|
+
return _weaverse_schema.createSchema;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
exports.generateDataFromSchema = require_translation_store.generateDataFromSchema;
|
|
21
|
+
exports.getNestedKey = require_translation_store.getNestedKey;
|
|
2211
22
|
Object.defineProperty(exports, "isBrowser", {
|
|
2212
|
-
|
|
2213
|
-
|
|
23
|
+
enumerable: true,
|
|
24
|
+
get: function() {
|
|
25
|
+
return _weaverse_react.isBrowser;
|
|
26
|
+
}
|
|
2214
27
|
});
|
|
2215
28
|
Object.defineProperty(exports, "isIframe", {
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
enumerable: true,
|
|
2221
|
-
get: function () { return react.useChildInstances; }
|
|
2222
|
-
});
|
|
2223
|
-
Object.defineProperty(exports, "useItemInstance", {
|
|
2224
|
-
enumerable: true,
|
|
2225
|
-
get: function () { return react.useItemInstance; }
|
|
2226
|
-
});
|
|
2227
|
-
Object.defineProperty(exports, "useParentInstance", {
|
|
2228
|
-
enumerable: true,
|
|
2229
|
-
get: function () { return react.useParentInstance; }
|
|
2230
|
-
});
|
|
2231
|
-
Object.defineProperty(exports, "useWeaverse", {
|
|
2232
|
-
enumerable: true,
|
|
2233
|
-
get: function () { return react.useWeaverse; }
|
|
2234
|
-
});
|
|
2235
|
-
exports.ThemeTextProvider = ThemeTextProvider;
|
|
2236
|
-
exports.ThemeTextStore = ThemeTextStore;
|
|
2237
|
-
exports.TranslationProvider = TranslationProvider;
|
|
2238
|
-
exports.TranslationStore = TranslationStore;
|
|
2239
|
-
exports.WeaverseClient = WeaverseClient;
|
|
2240
|
-
exports.WeaverseError = WeaverseError;
|
|
2241
|
-
exports.WeaverseHydrogen = WeaverseHydrogen;
|
|
2242
|
-
exports.WeaverseHydrogenItem = WeaverseHydrogenItem;
|
|
2243
|
-
exports.WeaverseHydrogenRoot = WeaverseHydrogenRoot;
|
|
2244
|
-
exports.createWeaverseDataContext = createWeaverseDataContext;
|
|
2245
|
-
exports.defaultComponents = defaultComponents;
|
|
2246
|
-
exports.formatMetaDescriptors = formatMetaDescriptors;
|
|
2247
|
-
exports.generateDataFromSchema = generateDataFromSchema;
|
|
2248
|
-
exports.getNestedKey = getNestedKey;
|
|
2249
|
-
exports.getPreviewData = getPreviewData;
|
|
2250
|
-
exports.getRequestQueries = getRequestQueries;
|
|
2251
|
-
exports.getSelectedProductOptions = getSelectedProductOptions;
|
|
2252
|
-
exports.getWeaverseConfigs = getWeaverseConfigs;
|
|
2253
|
-
exports.getWeaverseSeoMeta = getWeaverseSeoMeta;
|
|
2254
|
-
exports.hasError = hasError;
|
|
2255
|
-
exports.hasWeaverseStudio = hasWeaverseStudio;
|
|
2256
|
-
exports.interpolate = interpolate;
|
|
2257
|
-
exports.isFetchProjectPayload = isFetchProjectPayload;
|
|
2258
|
-
exports.isProjectIdFunction = isProjectIdFunction;
|
|
2259
|
-
exports.isThemeSettingsResponse = isThemeSettingsResponse;
|
|
2260
|
-
exports.isValidHydrogenSchema = isValidHydrogenSchema;
|
|
2261
|
-
exports.isWithCacheFetchResponse = isWithCacheFetchResponse;
|
|
2262
|
-
exports.registerComponent = registerComponent;
|
|
2263
|
-
exports.useThemeSettings = useThemeSettings;
|
|
2264
|
-
exports.useThemeText = useThemeText;
|
|
2265
|
-
exports.useTranslation = useTranslation;
|
|
2266
|
-
exports.useWeaverseDataContext = useWeaverseDataContext;
|
|
2267
|
-
exports.withWeaverse = withWeaverse;
|
|
2268
|
-
Object.keys(schema$1).forEach(function (k) {
|
|
2269
|
-
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
2270
|
-
enumerable: true,
|
|
2271
|
-
get: function () { return schema$1[k]; }
|
|
2272
|
-
});
|
|
29
|
+
enumerable: true,
|
|
30
|
+
get: function() {
|
|
31
|
+
return _weaverse_react.isIframe;
|
|
32
|
+
}
|
|
2273
33
|
});
|
|
2274
|
-
//# sourceMappingURL=index.js.map
|
|
2275
|
-
//# sourceMappingURL=index.js.map
|