@weaverse/hydrogen 5.25.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +23 -2444
- package/dist/index.mjs +4 -2407
- 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 +7 -7
- 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 +88 -68
- 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/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 +14 -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 -6
- package/readme.md +44 -24
- 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 +104 -74
- 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 +88 -96
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
let _weaverse_schema = require("@weaverse/schema");
|
|
2
|
+
//#region src/types.ts
|
|
3
|
+
/**
|
|
4
|
+
* Type guard for detecting function-based projectId.
|
|
5
|
+
*
|
|
6
|
+
* Used internally by WeaverseClient constructor to determine
|
|
7
|
+
* if projectId needs evaluation or can be used directly.
|
|
8
|
+
*/
|
|
9
|
+
function isProjectIdFunction(projectId) {
|
|
10
|
+
return typeof projectId === "function";
|
|
11
|
+
}
|
|
12
|
+
/** Error raised by Weaverse requests with a stable code and optional context. */
|
|
13
|
+
var WeaverseError = class WeaverseError extends Error {
|
|
14
|
+
/** Machine-readable error code. */
|
|
15
|
+
code;
|
|
16
|
+
/** HTTP status associated with the failure, when available. */
|
|
17
|
+
statusCode;
|
|
18
|
+
/** Structured diagnostic details for logging and error handling. */
|
|
19
|
+
context;
|
|
20
|
+
/** Creates a Weaverse request error with a stable code and diagnostics. */
|
|
21
|
+
constructor(message, code = "WEAVERSE_ERROR", statusCode, context) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.name = "WeaverseError";
|
|
24
|
+
this.code = code;
|
|
25
|
+
this.statusCode = statusCode;
|
|
26
|
+
this.context = context;
|
|
27
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, WeaverseError);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Error thrown by `WeaverseClient.loadPage()` when the client is created
|
|
32
|
+
* with `throwPageLoadFailures: true` and the page cannot be loaded.
|
|
33
|
+
*
|
|
34
|
+
* Genuine absence is not an error: a missing project still resolves to `null`
|
|
35
|
+
* and an unassigned page still resolves to a fallback page.
|
|
36
|
+
*/
|
|
37
|
+
var WeaverseLoadError = class extends WeaverseError {
|
|
38
|
+
/** Failure class used to choose a response status or recovery action. */
|
|
39
|
+
kind;
|
|
40
|
+
/** Creates a classified page-load failure. */
|
|
41
|
+
constructor(message, kind, statusCode, context) {
|
|
42
|
+
super(message, "LOAD_FAILURE", statusCode, context);
|
|
43
|
+
this.name = "WeaverseLoadError";
|
|
44
|
+
this.kind = kind;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Type guards for response validation
|
|
49
|
+
*/
|
|
50
|
+
function isWithCacheFetchResponse(response) {
|
|
51
|
+
return typeof response === "object" && response !== null && "data" in response && "response" in response;
|
|
52
|
+
}
|
|
53
|
+
/** Checks whether a value contains the required project response fields. */
|
|
54
|
+
function isFetchProjectPayload(payload) {
|
|
55
|
+
return typeof payload === "object" && payload !== null && "page" in payload && "project" in payload && "pageAssignment" in payload;
|
|
56
|
+
}
|
|
57
|
+
/** Checks whether a response contains a string error message. */
|
|
58
|
+
function hasError(response) {
|
|
59
|
+
return typeof response === "object" && response !== null && "error" in response && typeof response.error === "string";
|
|
60
|
+
}
|
|
61
|
+
/** Checks whether a value contains a theme settings object. */
|
|
62
|
+
function isThemeSettingsResponse(data) {
|
|
63
|
+
if (typeof data !== "object" || data === null) return false;
|
|
64
|
+
const record = data;
|
|
65
|
+
return "theme" in record && typeof record.theme === "object" && record.theme !== null;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Type guard to check if a schema is valid.
|
|
69
|
+
* Leverages validation from @weaverse/schema package which provides
|
|
70
|
+
* comprehensive Zod-based validation with the ElementSchema.
|
|
71
|
+
*
|
|
72
|
+
* @param schema - Unknown value to validate
|
|
73
|
+
* @returns True if schema is a valid WeaverseComponentSchema
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* if (isValidHydrogenSchema(userInput)) {
|
|
78
|
+
* // userInput is now typed as WeaverseComponentSchema
|
|
79
|
+
* console.log(userInput.type)
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
function isValidHydrogenSchema(schema) {
|
|
84
|
+
return (0, _weaverse_schema.isValidSchema)(schema);
|
|
85
|
+
}
|
|
86
|
+
/** Checks whether the browser window exposes the Weaverse Studio bridge. */
|
|
87
|
+
function hasWeaverseStudio(window) {
|
|
88
|
+
return "weaverseStudio" in window && typeof window.weaverseStudio === "object";
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/utils/studio-script-src.ts
|
|
92
|
+
const DEFAULT_WEAVERSE_HOST = "https://studio.weaverse.io";
|
|
93
|
+
/**
|
|
94
|
+
* Weaverse-controlled apex domains the Studio bridge may be served from
|
|
95
|
+
* (matched on the host itself and any subdomain).
|
|
96
|
+
*/
|
|
97
|
+
const TRUSTED_STUDIO_DOMAINS = ["weaverse.io", "weaverse.dev"];
|
|
98
|
+
function isLoopbackHostname(hostname) {
|
|
99
|
+
return hostname === "localhost" || hostname === "127.0.0.1" || hostname.endsWith(".localhost");
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Whether `host` is an origin we trust to serve the Studio bridge script (or,
|
|
103
|
+
* server-side, to resolve page/theme data).
|
|
104
|
+
*
|
|
105
|
+
* The bridge executes inside the storefront document and the host can drive
|
|
106
|
+
* server-side fetches, so a host taken from an attacker-controllable source —
|
|
107
|
+
* e.g. a crafted `?weaverseHost=` query — is both an XSS and an SSRF vector.
|
|
108
|
+
* Callers MUST reject untrusted hosts before acting on them. Trusts
|
|
109
|
+
* `weaverse.io`/`weaverse.dev` and their subdomains over https; loopback is
|
|
110
|
+
* opt-in (see {@link TrustedStudioHostOptions.allowLoopback}).
|
|
111
|
+
*/
|
|
112
|
+
function isTrustedStudioHost(host, options) {
|
|
113
|
+
let parsed;
|
|
114
|
+
try {
|
|
115
|
+
parsed = new URL(host);
|
|
116
|
+
} catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
let { hostname, protocol } = parsed;
|
|
120
|
+
if (options?.allowLoopback && isLoopbackHostname(hostname)) return protocol === "http:" || protocol === "https:";
|
|
121
|
+
if (protocol !== "https:") return false;
|
|
122
|
+
return TRUSTED_STUDIO_DOMAINS.some((domain) => hostname === domain || hostname.endsWith(`.${domain}`));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Build the Studio bridge script URL for the current mode, or `null` when the
|
|
126
|
+
* storefront is not being previewed inside Weaverse Studio.
|
|
127
|
+
*
|
|
128
|
+
* This is the single gate that keeps the bridge off production storefronts:
|
|
129
|
+
* a normal visitor's URL carries none of the design/preview markers, so the
|
|
130
|
+
* result is `null` and no script is ever requested.
|
|
131
|
+
*
|
|
132
|
+
* Shared by the page-scoped `useStudio` (which also binds the page for
|
|
133
|
+
* editing) and the root-level `useStudioConnect` (which only needs the script
|
|
134
|
+
* to load so Studio's `checkWeaversePage()` handshake can answer on routes
|
|
135
|
+
* with no Weaverse content).
|
|
136
|
+
*/
|
|
137
|
+
function getStudioScriptSrc(mode) {
|
|
138
|
+
let { isDesignMode, isPreviewMode, isRevisionPreview, weaverseHost, weaverseVersion } = mode;
|
|
139
|
+
let base = `${weaverseHost}/static/studio/hydrogen`;
|
|
140
|
+
let version = `?v=${weaverseVersion}`;
|
|
141
|
+
if (isRevisionPreview || isPreviewMode) return `${base}/preview.js${version}`;
|
|
142
|
+
if (isDesignMode) return `${base}/index.js${version}`;
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Resolve the Studio bridge script URL from a URL query string — the markers
|
|
147
|
+
* Studio attaches when it drives the preview iframe (`isDesignMode`,
|
|
148
|
+
* `isPreviewMode`, `__revisionId`, `weaverseHost`, `weaverseVersion`) — or
|
|
149
|
+
* `null` outside Studio.
|
|
150
|
+
*
|
|
151
|
+
* `storefrontHostname` is the document's own hostname: a loopback Studio host
|
|
152
|
+
* is only honored when the storefront itself is loopback (genuine local-builder
|
|
153
|
+
* dev), so a crafted public link can't load a script from a visitor's loopback
|
|
154
|
+
* service into the storefront origin.
|
|
155
|
+
*
|
|
156
|
+
* The `weaverseHost` query is attacker-controllable, so a host that is not a
|
|
157
|
+
* {@link isTrustedStudioHost trusted origin} resolves to `null` (no bridge) —
|
|
158
|
+
* it is never silently replaced with production Studio, which would otherwise
|
|
159
|
+
* inject the wrong bridge for self-hosted/staging deployments. Such deployments
|
|
160
|
+
* (a non-`weaverse.io` `WEAVERSE_HOST`) therefore don't load the root bridge on
|
|
161
|
+
* content-less routes; the page-scoped {@link getStudioScriptSrc} via
|
|
162
|
+
* `useStudio` still uses the configured host on content routes.
|
|
163
|
+
*
|
|
164
|
+
* Pure (no DOM) so the root-level connect's production gate stays unit-testable
|
|
165
|
+
* and needs no loader data.
|
|
166
|
+
*/
|
|
167
|
+
function resolveStudioScriptSrc(search, storefrontHostname = "") {
|
|
168
|
+
let params = new URLSearchParams(search);
|
|
169
|
+
let last = (key) => params.getAll(key).at(-1);
|
|
170
|
+
let host = last("weaverseHost");
|
|
171
|
+
if (host) {
|
|
172
|
+
if (!isTrustedStudioHost(host, { allowLoopback: isLoopbackHostname(storefrontHostname) })) return null;
|
|
173
|
+
}
|
|
174
|
+
return getStudioScriptSrc({
|
|
175
|
+
isDesignMode: last("isDesignMode") === "true",
|
|
176
|
+
isPreviewMode: last("isPreviewMode") === "true",
|
|
177
|
+
isRevisionPreview: params.has("__revisionId"),
|
|
178
|
+
weaverseHost: host || DEFAULT_WEAVERSE_HOST,
|
|
179
|
+
weaverseVersion: last("weaverseVersion") || ""
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region src/utils/index.ts
|
|
184
|
+
let warnedTypes = /* @__PURE__ */ new Set();
|
|
185
|
+
function logOnce(type, message) {
|
|
186
|
+
if (!warnedTypes.has(type)) {
|
|
187
|
+
console.warn(message);
|
|
188
|
+
warnedTypes.add(type);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function deepMergeArrays(target, source) {
|
|
192
|
+
return [...target, ...source];
|
|
193
|
+
}
|
|
194
|
+
function mergeInspectorSettings(settings, inspector, type) {
|
|
195
|
+
if (!inspector?.length) return settings;
|
|
196
|
+
if (!settings?.length) return inspector;
|
|
197
|
+
console.info(`Schema "${type}": Both 'settings' and 'inspector' found. Using 'settings' with 'inspector' as fallback.`);
|
|
198
|
+
return deepMergeArrays(settings, inspector);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Extract and parse query parameters from a request URL.
|
|
202
|
+
* Supports optional allowlist for security-sensitive applications.
|
|
203
|
+
*
|
|
204
|
+
* @param request - The incoming request
|
|
205
|
+
* @param options - Optional configuration
|
|
206
|
+
* @param options.allowedKeys - If provided, only these keys will be extracted
|
|
207
|
+
* @returns Parsed query parameters with type coercion for booleans
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```typescript
|
|
211
|
+
* // Extract all params
|
|
212
|
+
* const queries = getRequestQueries(request)
|
|
213
|
+
*
|
|
214
|
+
* // Extract only allowed params (security-sensitive)
|
|
215
|
+
* const queries = getRequestQueries(request, {
|
|
216
|
+
* allowedKeys: ['weaverseProjectId', 'weaverseHost']
|
|
217
|
+
* })
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
function getRequestQueries(request, options) {
|
|
221
|
+
let url = new URL(request.url);
|
|
222
|
+
let queries = {};
|
|
223
|
+
for (let [key, value] of url.searchParams.entries()) {
|
|
224
|
+
if (options?.allowedKeys && !options.allowedKeys.includes(key)) continue;
|
|
225
|
+
if (value === "true") queries[key] = true;
|
|
226
|
+
else if (value === "false") queries[key] = false;
|
|
227
|
+
else queries[key] = value;
|
|
228
|
+
}
|
|
229
|
+
return queries;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Resolves project, endpoint, and Studio mode configuration for a request.
|
|
233
|
+
* URL-provided Studio values take precedence over environment defaults.
|
|
234
|
+
*/
|
|
235
|
+
function getWeaverseConfigs(request, env) {
|
|
236
|
+
let queries = getRequestQueries(request);
|
|
237
|
+
let { WEAVERSE_PROJECT_ID, WEAVERSE_API_KEY, WEAVERSE_HOST, WEAVERSE_PUBLIC_API_BASE, PUBLIC_STORE_DOMAIN, PUBLIC_STOREFRONT_API_TOKEN } = env || {};
|
|
238
|
+
let envFromProcess = typeof process !== "undefined" && process.env || {};
|
|
239
|
+
let { weaverseProjectId, weaverseHost, isDesignMode, isPreviewMode, sectionType, weaverseVersion, weaverseApiKey } = queries;
|
|
240
|
+
let isRevisionPreview = new URL(request.url).searchParams.has("__revisionId");
|
|
241
|
+
let configuredWeaverseHost = WEAVERSE_HOST || envFromProcess.WEAVERSE_HOST;
|
|
242
|
+
let trustedUrlHost = typeof weaverseHost === "string" && isTrustedStudioHost(weaverseHost) ? weaverseHost : "";
|
|
243
|
+
let resolvedWeaverseHost = trustedUrlHost || configuredWeaverseHost || "https://studio.weaverse.io";
|
|
244
|
+
let resolvedWeaverseApiBase = trustedUrlHost ? trustedUrlHost : WEAVERSE_PUBLIC_API_BASE || envFromProcess.WEAVERSE_PUBLIC_API_BASE || (configuredWeaverseHost && configuredWeaverseHost !== "https://studio.weaverse.io" ? configuredWeaverseHost : "https://api.weaverse.io");
|
|
245
|
+
return {
|
|
246
|
+
projectId: weaverseProjectId || WEAVERSE_PROJECT_ID || envFromProcess.WEAVERSE_PROJECT_ID || "",
|
|
247
|
+
weaverseHost: resolvedWeaverseHost,
|
|
248
|
+
weaverseApiBase: resolvedWeaverseApiBase,
|
|
249
|
+
weaversePublicApiBase: resolvedWeaverseApiBase,
|
|
250
|
+
weaverseApiKey: weaverseApiKey || WEAVERSE_API_KEY || envFromProcess.WEAVERSE_API_KEY || "",
|
|
251
|
+
weaverseVersion: weaverseVersion || "",
|
|
252
|
+
isDesignMode,
|
|
253
|
+
isPreviewMode,
|
|
254
|
+
isRevisionPreview,
|
|
255
|
+
sectionType: sectionType || "",
|
|
256
|
+
publicEnv: {
|
|
257
|
+
PUBLIC_STORE_DOMAIN: PUBLIC_STORE_DOMAIN || "",
|
|
258
|
+
PUBLIC_STOREFRONT_API_TOKEN: PUBLIC_STOREFRONT_API_TOKEN || ""
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Cache for generateDataFromSchema results using WeakMap.
|
|
264
|
+
* WeakMap allows garbage collection when schema objects are no longer referenced.
|
|
265
|
+
*/
|
|
266
|
+
const schemaDefaultsCache = /* @__PURE__ */ new WeakMap();
|
|
267
|
+
/**
|
|
268
|
+
* Generate default data from component or theme schema.
|
|
269
|
+
* Results are memoized using WeakMap for performance.
|
|
270
|
+
*
|
|
271
|
+
* @param schema - Component or theme schema
|
|
272
|
+
* @returns Default data object extracted from schema inputs
|
|
273
|
+
*/
|
|
274
|
+
function generateDataFromSchema(schema) {
|
|
275
|
+
const cached = schemaDefaultsCache.get(schema);
|
|
276
|
+
if (cached) return cached;
|
|
277
|
+
let data = {};
|
|
278
|
+
let inspectorGroups = [];
|
|
279
|
+
const isComponentSchema = (s) => "type" in s && typeof s.type === "string";
|
|
280
|
+
if (isComponentSchema(schema)) {
|
|
281
|
+
if (schema.settings) inspectorGroups = schema.settings;
|
|
282
|
+
if (schema.inspector) if (schema.settings?.length) inspectorGroups = mergeInspectorSettings(schema.settings, schema.inspector, schema.type || "unknown");
|
|
283
|
+
else {
|
|
284
|
+
inspectorGroups = schema.inspector;
|
|
285
|
+
if (schema.type) logOnce(schema.type, `⚠️ Schema "${schema.type}": The 'inspector' property is deprecated. Please use 'settings' instead.`);
|
|
286
|
+
}
|
|
287
|
+
} else {
|
|
288
|
+
if (schema.settings) inspectorGroups = schema.settings;
|
|
289
|
+
if (schema.inspector) if (schema.settings?.length) inspectorGroups = mergeInspectorSettings(schema.settings, schema.inspector, "Theme Schema");
|
|
290
|
+
else {
|
|
291
|
+
inspectorGroups = schema.inspector;
|
|
292
|
+
logOnce("ThemeSchema", `⚠️ Theme Schema: The 'inspector' property is deprecated. Please use 'settings' instead.`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (inspectorGroups?.length) for (let group of inspectorGroups) for (let input of group.inputs) {
|
|
296
|
+
let { name, defaultValue } = input;
|
|
297
|
+
if (name && defaultValue !== null && defaultValue !== void 0) data[name] = defaultValue;
|
|
298
|
+
}
|
|
299
|
+
schemaDefaultsCache.set(schema, data);
|
|
300
|
+
return data;
|
|
301
|
+
}
|
|
302
|
+
function recursivelyAddDataItem(type, components, items, initData) {
|
|
303
|
+
let component = components.find((c) => c.schema.type === type);
|
|
304
|
+
if (!component) return;
|
|
305
|
+
let childIds = [];
|
|
306
|
+
let id = crypto.randomUUID();
|
|
307
|
+
let { children, ...data } = component.schema?.presets || {};
|
|
308
|
+
if (children) for (let c of children) {
|
|
309
|
+
let { type, children, ...data } = c;
|
|
310
|
+
let childId = recursivelyAddDataItem(type, components, items, data);
|
|
311
|
+
childIds.push({ id: childId });
|
|
312
|
+
}
|
|
313
|
+
items.push({
|
|
314
|
+
data: {
|
|
315
|
+
...data,
|
|
316
|
+
...initData
|
|
317
|
+
},
|
|
318
|
+
id,
|
|
319
|
+
type,
|
|
320
|
+
children: childIds
|
|
321
|
+
});
|
|
322
|
+
return id;
|
|
323
|
+
}
|
|
324
|
+
/** Creates synthetic loader data for previewing one registered component type. */
|
|
325
|
+
function getPreviewData(type, components, weaverseHost) {
|
|
326
|
+
let items = [];
|
|
327
|
+
return {
|
|
328
|
+
project: {
|
|
329
|
+
id: "x",
|
|
330
|
+
weaverseShopId: "shop-id",
|
|
331
|
+
name: "Section Preview"
|
|
332
|
+
},
|
|
333
|
+
configs: {
|
|
334
|
+
projectId: "x",
|
|
335
|
+
weaverseHost,
|
|
336
|
+
isDesignMode: false,
|
|
337
|
+
isPreviewMode: true,
|
|
338
|
+
requestInfo: {
|
|
339
|
+
i18n: {
|
|
340
|
+
label: "United States (USD $)",
|
|
341
|
+
language: "EN",
|
|
342
|
+
country: "US",
|
|
343
|
+
currency: "USD",
|
|
344
|
+
pathPrefix: ""
|
|
345
|
+
},
|
|
346
|
+
queries: {},
|
|
347
|
+
pathname: "/",
|
|
348
|
+
search: ""
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
page: {
|
|
352
|
+
id: "weaverse-preview-page",
|
|
353
|
+
name: "Preview section",
|
|
354
|
+
rootId: "1",
|
|
355
|
+
items: [{
|
|
356
|
+
data: {},
|
|
357
|
+
id: "1",
|
|
358
|
+
type: "main",
|
|
359
|
+
children: [{ id: recursivelyAddDataItem(type, components, items) }]
|
|
360
|
+
}, ...items]
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
//#endregion
|
|
365
|
+
//#region src/utils/nested-key.ts
|
|
366
|
+
/**
|
|
367
|
+
* Traverse a nested object by dot-path.
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
* getNestedKey({ cart: { title: 'Cart' } }, 'cart.title') // => 'Cart'
|
|
371
|
+
* getNestedKey({}, 'cart.title', 'fallback') // => 'fallback'
|
|
372
|
+
*/
|
|
373
|
+
function getNestedKey(obj, path, fallback) {
|
|
374
|
+
const keys = path.split(".");
|
|
375
|
+
let current = obj;
|
|
376
|
+
for (const key of keys) {
|
|
377
|
+
if (current == null || typeof current !== "object") return fallback;
|
|
378
|
+
current = current[key];
|
|
379
|
+
}
|
|
380
|
+
if (typeof current === "string") return current;
|
|
381
|
+
return fallback;
|
|
382
|
+
}
|
|
383
|
+
//#endregion
|
|
384
|
+
//#region src/utils/translation-store.ts
|
|
385
|
+
/**
|
|
386
|
+
* Minimal mutable store for design-mode static text overrides.
|
|
387
|
+
*
|
|
388
|
+
* useSyncExternalStore-compatible. Passed into TranslationProvider which
|
|
389
|
+
* subscribes internally and merges overrides into merchantOverrides.
|
|
390
|
+
* The studio bridge calls updateOverrides() via weaverse.internal.translationStore
|
|
391
|
+
* (also exposed as the deprecated weaverse.internal.themeTextStore alias).
|
|
392
|
+
*
|
|
393
|
+
* Shape: flat Record<string, string> — dot-notation keys map to values
|
|
394
|
+
* (e.g. "cart.title" → "Shopping Cart").
|
|
395
|
+
*/
|
|
396
|
+
var TranslationStore = class {
|
|
397
|
+
/** Current flat translation overrides keyed by dot-path. */
|
|
398
|
+
overrides = {};
|
|
399
|
+
listeners = /* @__PURE__ */ new Set();
|
|
400
|
+
/** Replaces all overrides and notifies subscribers. */
|
|
401
|
+
setOverrides = (overrides) => {
|
|
402
|
+
this.overrides = { ...overrides };
|
|
403
|
+
this.emit();
|
|
404
|
+
};
|
|
405
|
+
/** Merges changed overrides and notifies subscribers. */
|
|
406
|
+
updateOverrides = (newOverrides) => {
|
|
407
|
+
this.overrides = {
|
|
408
|
+
...this.overrides,
|
|
409
|
+
...newOverrides
|
|
410
|
+
};
|
|
411
|
+
this.emit();
|
|
412
|
+
};
|
|
413
|
+
/** Returns the current client snapshot for `useSyncExternalStore`. */
|
|
414
|
+
getSnapshot = () => this.overrides;
|
|
415
|
+
/** Returns the current server snapshot for `useSyncExternalStore`. */
|
|
416
|
+
getServerSnapshot = () => this.overrides;
|
|
417
|
+
/** Subscribes to override changes and returns an unsubscribe callback. */
|
|
418
|
+
subscribe = (callback) => {
|
|
419
|
+
this.listeners.add(callback);
|
|
420
|
+
return () => {
|
|
421
|
+
this.listeners.delete(callback);
|
|
422
|
+
};
|
|
423
|
+
};
|
|
424
|
+
emit = () => {
|
|
425
|
+
for (const listener of Array.from(this.listeners)) try {
|
|
426
|
+
listener();
|
|
427
|
+
} catch (error) {
|
|
428
|
+
console.error("TranslationStore: Listener error", error);
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
};
|
|
432
|
+
/**
|
|
433
|
+
* Legacy constructor alias retained for existing theme text integrations.
|
|
434
|
+
* @deprecated Use {@link TranslationStore} instead. This alias remains available
|
|
435
|
+
* for backward compatibility.
|
|
436
|
+
*/
|
|
437
|
+
const ThemeTextStore = TranslationStore;
|
|
438
|
+
//#endregion
|
|
439
|
+
Object.defineProperty(exports, "ThemeTextStore", {
|
|
440
|
+
enumerable: true,
|
|
441
|
+
get: function() {
|
|
442
|
+
return ThemeTextStore;
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
Object.defineProperty(exports, "TranslationStore", {
|
|
446
|
+
enumerable: true,
|
|
447
|
+
get: function() {
|
|
448
|
+
return TranslationStore;
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
Object.defineProperty(exports, "WeaverseError", {
|
|
452
|
+
enumerable: true,
|
|
453
|
+
get: function() {
|
|
454
|
+
return WeaverseError;
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
Object.defineProperty(exports, "WeaverseLoadError", {
|
|
458
|
+
enumerable: true,
|
|
459
|
+
get: function() {
|
|
460
|
+
return WeaverseLoadError;
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
Object.defineProperty(exports, "generateDataFromSchema", {
|
|
464
|
+
enumerable: true,
|
|
465
|
+
get: function() {
|
|
466
|
+
return generateDataFromSchema;
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
Object.defineProperty(exports, "getNestedKey", {
|
|
470
|
+
enumerable: true,
|
|
471
|
+
get: function() {
|
|
472
|
+
return getNestedKey;
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
Object.defineProperty(exports, "getPreviewData", {
|
|
476
|
+
enumerable: true,
|
|
477
|
+
get: function() {
|
|
478
|
+
return getPreviewData;
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
Object.defineProperty(exports, "getRequestQueries", {
|
|
482
|
+
enumerable: true,
|
|
483
|
+
get: function() {
|
|
484
|
+
return getRequestQueries;
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
Object.defineProperty(exports, "getStudioScriptSrc", {
|
|
488
|
+
enumerable: true,
|
|
489
|
+
get: function() {
|
|
490
|
+
return getStudioScriptSrc;
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
Object.defineProperty(exports, "getWeaverseConfigs", {
|
|
494
|
+
enumerable: true,
|
|
495
|
+
get: function() {
|
|
496
|
+
return getWeaverseConfigs;
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
Object.defineProperty(exports, "hasError", {
|
|
500
|
+
enumerable: true,
|
|
501
|
+
get: function() {
|
|
502
|
+
return hasError;
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
Object.defineProperty(exports, "hasWeaverseStudio", {
|
|
506
|
+
enumerable: true,
|
|
507
|
+
get: function() {
|
|
508
|
+
return hasWeaverseStudio;
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
Object.defineProperty(exports, "isFetchProjectPayload", {
|
|
512
|
+
enumerable: true,
|
|
513
|
+
get: function() {
|
|
514
|
+
return isFetchProjectPayload;
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
Object.defineProperty(exports, "isProjectIdFunction", {
|
|
518
|
+
enumerable: true,
|
|
519
|
+
get: function() {
|
|
520
|
+
return isProjectIdFunction;
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
Object.defineProperty(exports, "isThemeSettingsResponse", {
|
|
524
|
+
enumerable: true,
|
|
525
|
+
get: function() {
|
|
526
|
+
return isThemeSettingsResponse;
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
Object.defineProperty(exports, "isValidHydrogenSchema", {
|
|
530
|
+
enumerable: true,
|
|
531
|
+
get: function() {
|
|
532
|
+
return isValidHydrogenSchema;
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
Object.defineProperty(exports, "isWithCacheFetchResponse", {
|
|
536
|
+
enumerable: true,
|
|
537
|
+
get: function() {
|
|
538
|
+
return isWithCacheFetchResponse;
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
Object.defineProperty(exports, "resolveStudioScriptSrc", {
|
|
542
|
+
enumerable: true,
|
|
543
|
+
get: function() {
|
|
544
|
+
return resolveStudioScriptSrc;
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
//# sourceMappingURL=translation-store-BpPWqZ0B.js.map
|