@weaverse/next 0.1.0-alpha.13 → 0.1.0-alpha.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -23
- package/dist/{chunk-MQ6N5ODA.mjs → chunk-NL22OVD7.mjs} +93 -4
- package/dist/chunk-NL22OVD7.mjs.map +1 -0
- package/dist/index.js +86 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +20 -27
- package/dist/index.mjs.map +1 -1
- package/dist/server.js +158 -2
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +126 -5
- package/dist/server.mjs.map +1 -1
- package/dist/types/client.d.ts +16 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/hooks.d.ts +20 -0
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/index.d.ts +34 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/item.d.ts +54 -0
- package/dist/types/item.d.ts.map +1 -0
- package/dist/types/loader.d.ts +25 -0
- package/dist/types/loader.d.ts.map +1 -0
- package/dist/types/main.d.ts +11 -0
- package/dist/types/main.d.ts.map +1 -0
- package/dist/types/provider.d.ts +82 -0
- package/dist/types/provider.d.ts.map +1 -0
- package/dist/types/registry.d.ts +15 -0
- package/dist/types/registry.d.ts.map +1 -0
- package/dist/types/renderer.d.ts +20 -0
- package/dist/types/renderer.d.ts.map +1 -0
- package/dist/types/request-info.d.ts +8 -0
- package/dist/types/request-info.d.ts.map +1 -0
- package/dist/types/revalidate-item.d.ts +81 -0
- package/dist/types/revalidate-item.d.ts.map +1 -0
- package/dist/types/root-provider.d.ts +61 -0
- package/dist/types/root-provider.d.ts.map +1 -0
- package/dist/types/runtime.d.ts +113 -0
- package/dist/types/runtime.d.ts.map +1 -0
- package/dist/types/seo.d.ts +55 -0
- package/dist/types/seo.d.ts.map +1 -0
- package/dist/types/server/configs.d.ts +27 -0
- package/dist/types/server/configs.d.ts.map +1 -0
- package/dist/types/server/normalize-page-url.d.ts +19 -0
- package/dist/types/server/normalize-page-url.d.ts.map +1 -0
- package/dist/types/server/revalidate-handler.d.ts +55 -0
- package/dist/types/server/revalidate-handler.d.ts.map +1 -0
- package/dist/types/server/server-client.d.ts +21 -0
- package/dist/types/server/server-client.d.ts.map +1 -0
- package/dist/types/server.d.ts +19 -0
- package/dist/types/server.d.ts.map +1 -0
- package/dist/types/studio-bridge.d.ts +16 -0
- package/dist/types/studio-bridge.d.ts.map +1 -0
- package/dist/types/studio-connect.d.ts +27 -0
- package/dist/types/studio-connect.d.ts.map +1 -0
- package/dist/types/studio-router.d.ts +50 -0
- package/dist/types/studio-router.d.ts.map +1 -0
- package/dist/types/studio-script-src.d.ts +12 -0
- package/dist/types/studio-script-src.d.ts.map +1 -0
- package/dist/types/theme-settings-store.d.ts +17 -0
- package/dist/types/theme-settings-store.d.ts.map +1 -0
- package/dist/types/translation-context.d.ts +156 -0
- package/dist/types/translation-context.d.ts.map +1 -0
- package/dist/types/translation-store.d.ts +44 -0
- package/dist/types/translation-store.d.ts.map +1 -0
- package/dist/types/types.d.ts +661 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/use-weaverse-next-studio.d.ts +34 -0
- package/dist/types/use-weaverse-next-studio.d.ts.map +1 -0
- package/dist/types/utils.d.ts +12 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/package.json +7 -6
- package/src/client.ts +101 -0
- package/src/hooks.ts +50 -0
- package/src/index.ts +153 -0
- package/src/item.ts +151 -0
- package/src/loader.ts +135 -0
- package/src/main.tsx +45 -0
- package/src/provider.tsx +225 -0
- package/src/registry.ts +63 -0
- package/src/renderer.tsx +99 -0
- package/src/request-info.ts +95 -0
- package/src/revalidate-item.ts +210 -0
- package/src/root-provider.tsx +181 -0
- package/src/runtime.ts +521 -0
- package/src/seo.ts +157 -0
- package/src/server/configs.ts +182 -0
- package/src/server/normalize-page-url.ts +65 -0
- package/src/server/revalidate-handler.ts +357 -0
- package/src/server/server-client.ts +727 -0
- package/src/server.ts +67 -0
- package/src/studio-bridge.tsx +82 -0
- package/src/studio-connect.tsx +88 -0
- package/src/studio-router.ts +85 -0
- package/src/studio-script-src.ts +128 -0
- package/src/theme-settings-store.ts +46 -0
- package/src/translation-context.tsx +299 -0
- package/src/translation-store.ts +69 -0
- package/src/types.ts +748 -0
- package/src/use-weaverse-next-studio.tsx +106 -0
- package/src/utils.ts +37 -0
- package/dist/chunk-MQ6N5ODA.mjs.map +0 -1
- package/dist/index.d.mts +0 -592
- package/dist/index.d.ts +0 -592
- package/dist/seo-CrEFl_Up.d.mts +0 -516
- package/dist/seo-CrEFl_Up.d.ts +0 -516
- package/dist/server.d.mts +0 -100
- package/dist/server.d.ts +0 -100
package/README.md
CHANGED
|
@@ -170,15 +170,26 @@ Main exports:
|
|
|
170
170
|
|
|
171
171
|
Example helper for a Next route/server component boundary:
|
|
172
172
|
|
|
173
|
+
This helper is app-level (not exported by `@weaverse/next`); it plays the role
|
|
174
|
+
of Hydrogen's global load context, but the app owns route identity explicitly.
|
|
175
|
+
The App Router boundary supplies `pathname`, `pageType`, and `handle`, so the
|
|
176
|
+
same identity reaches page loads and per-item revalidation loaders. It uses the
|
|
177
|
+
exported `PageType` and `WeaverseNextRequestContext` types. The module defines
|
|
178
|
+
both helpers used by the route-handler example below:
|
|
179
|
+
|
|
173
180
|
```ts
|
|
174
181
|
import { createWeaverseNextServerClient } from '@weaverse/next/server'
|
|
182
|
+
import type { PageType, WeaverseNextRequestContext } from '@weaverse/next'
|
|
175
183
|
import { headers } from 'next/headers'
|
|
176
184
|
import { serverComponents } from './server-components'
|
|
177
185
|
import { getStaticStorefrontClient } from './storefront'
|
|
178
186
|
|
|
179
187
|
export async function getWeaverseServerClient(
|
|
180
188
|
searchParamsPromise: Promise<Record<string, string | string[] | undefined>>,
|
|
181
|
-
pathname = '/'
|
|
189
|
+
pathname = '/',
|
|
190
|
+
// Route identity the App Router segment owns. Seeding it here means loaders
|
|
191
|
+
// resolve the same page type / handle during SSR and per-item revalidation.
|
|
192
|
+
identity: { pageType?: PageType; handle?: string } = {}
|
|
182
193
|
) {
|
|
183
194
|
let [headersList, rawSearchParams] = await Promise.all([
|
|
184
195
|
headers(),
|
|
@@ -202,6 +213,27 @@ export async function getWeaverseServerClient(
|
|
|
202
213
|
}`
|
|
203
214
|
)
|
|
204
215
|
|
|
216
|
+
let requestContext: WeaverseNextRequestContext = {
|
|
217
|
+
url,
|
|
218
|
+
headers: requestHeaders,
|
|
219
|
+
searchParams,
|
|
220
|
+
pathname,
|
|
221
|
+
pageType: identity.pageType,
|
|
222
|
+
handle: identity.handle,
|
|
223
|
+
i18n: { country: 'US', language: 'EN', locale: 'en-US' },
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return createWeaverseServerClientFromContext(requestContext)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Explicit-context path used by the revalidation callback. The context has
|
|
230
|
+
// already been validated by the SDK handler; project/host/env remain app-owned.
|
|
231
|
+
export function createWeaverseServerClientFromContext(
|
|
232
|
+
requestContext: WeaverseNextRequestContext
|
|
233
|
+
) {
|
|
234
|
+
// A localized app should select/cache this client from its own supported
|
|
235
|
+
// market allowlist using requestContext.i18n. This compact example uses the
|
|
236
|
+
// default market configured by the app helper.
|
|
205
237
|
let storefront = getStaticStorefrontClient()
|
|
206
238
|
|
|
207
239
|
return createWeaverseNextServerClient({
|
|
@@ -220,26 +252,36 @@ export async function getWeaverseServerClient(
|
|
|
220
252
|
},
|
|
221
253
|
}
|
|
222
254
|
: undefined,
|
|
223
|
-
requestContext
|
|
224
|
-
url,
|
|
225
|
-
headers: requestHeaders,
|
|
226
|
-
searchParams,
|
|
227
|
-
pathname,
|
|
228
|
-
i18n: { country: 'US', language: 'EN', locale: 'en-US' },
|
|
229
|
-
},
|
|
255
|
+
requestContext,
|
|
230
256
|
cache: { revalidate: 60, tags: ['weaverse'] },
|
|
231
257
|
})
|
|
232
258
|
}
|
|
233
259
|
```
|
|
234
260
|
|
|
235
|
-
Then each route
|
|
261
|
+
Then each route stays close to the Hydrogen mental model while supplying the
|
|
262
|
+
route identity the segment owns — an `INDEX` home route and a handle-bearing
|
|
263
|
+
`PRODUCT` route:
|
|
236
264
|
|
|
237
265
|
```ts
|
|
238
|
-
|
|
266
|
+
// app/page.tsx — the INDEX segment owns the page type.
|
|
267
|
+
let weaverse = await getWeaverseServerClient(props.searchParams, '/', {
|
|
268
|
+
pageType: 'INDEX',
|
|
269
|
+
})
|
|
239
270
|
let data = await weaverse.loadPage({ type: 'INDEX' })
|
|
240
271
|
let theme = await weaverse.loadThemeSettings()
|
|
241
272
|
```
|
|
242
273
|
|
|
274
|
+
```ts
|
|
275
|
+
// app/products/[handle]/page.tsx — the PRODUCT segment supplies the handle.
|
|
276
|
+
let { handle } = await props.params
|
|
277
|
+
let weaverse = await getWeaverseServerClient(
|
|
278
|
+
props.searchParams,
|
|
279
|
+
`/products/${handle}`,
|
|
280
|
+
{ pageType: 'PRODUCT', handle }
|
|
281
|
+
)
|
|
282
|
+
let data = await weaverse.loadPage({ type: 'PRODUCT', handle })
|
|
283
|
+
```
|
|
284
|
+
|
|
243
285
|
### Server client members
|
|
244
286
|
|
|
245
287
|
| Member | Description |
|
|
@@ -349,16 +391,18 @@ import {
|
|
|
349
391
|
WeaverseNextProvider,
|
|
350
392
|
WeaverseNextRenderer,
|
|
351
393
|
} from '@weaverse/next'
|
|
352
|
-
import type {
|
|
394
|
+
import type {
|
|
395
|
+
WeaverseNextLoaderData,
|
|
396
|
+
WeaverseNextRequestInfo,
|
|
397
|
+
} from '@weaverse/next'
|
|
353
398
|
import { components } from './components'
|
|
354
399
|
|
|
355
400
|
export function WeaversePage({ data }: { data: WeaverseNextLoaderData }) {
|
|
401
|
+
// The server client returns `requestInfo` in the exported shape, so restore
|
|
402
|
+
// the full route identity — including `pageType` and `handle` — into the
|
|
403
|
+
// client request context instead of a narrow inline subset.
|
|
356
404
|
let requestInfo = data.configs?.requestInfo as
|
|
357
|
-
|
|
|
358
|
-
i18n?: { country?: string; language?: string; locale?: string }
|
|
359
|
-
pathname?: string
|
|
360
|
-
search?: string
|
|
361
|
-
}
|
|
405
|
+
| WeaverseNextRequestInfo
|
|
362
406
|
| undefined
|
|
363
407
|
let projectId =
|
|
364
408
|
(data.configs?.projectId as string | undefined) ?? data.project?.id
|
|
@@ -374,6 +418,8 @@ export function WeaversePage({ data }: { data: WeaverseNextLoaderData }) {
|
|
|
374
418
|
isPreviewMode: Boolean(data.configs?.isPreviewMode),
|
|
375
419
|
isRevisionPreview: Boolean(data.configs?.isRevisionPreview),
|
|
376
420
|
i18n: requestInfo?.i18n,
|
|
421
|
+
pageType: requestInfo?.pageType,
|
|
422
|
+
handle: requestInfo?.handle,
|
|
377
423
|
},
|
|
378
424
|
})
|
|
379
425
|
|
|
@@ -492,13 +538,38 @@ The root script connector and page-level renderer are both required for full Stu
|
|
|
492
538
|
|
|
493
539
|
Resource-picker edits should refresh only the affected item's server loader data. The happy path should not call `router.refresh()` because refreshing the whole RSC tree can remount the page and reset scroll.
|
|
494
540
|
|
|
495
|
-
Mount the route handler in the consuming app
|
|
541
|
+
Mount the route handler in the consuming app. `getClient` receives a second
|
|
542
|
+
argument — the validated, same-origin route context reconstructed from the
|
|
543
|
+
request body — so the revalidated loader runs with the same pathname, locale,
|
|
544
|
+
page type, handle, and ordinary search params as the active storefront route.
|
|
545
|
+
The two server-client helpers below are app-level consumer helpers, not exports
|
|
546
|
+
from `@weaverse/next`:
|
|
496
547
|
|
|
497
548
|
```ts
|
|
498
549
|
// app/api/weaverse/revalidate/route.ts
|
|
499
550
|
import { createWeaverseNextRevalidateHandler } from '@weaverse/next/server'
|
|
500
|
-
import {
|
|
551
|
+
import {
|
|
552
|
+
createWeaverseServerClientFromContext,
|
|
553
|
+
getWeaverseServerClient,
|
|
554
|
+
} from '../../../weaverse-next/server'
|
|
555
|
+
|
|
556
|
+
export const { POST } = createWeaverseNextRevalidateHandler({
|
|
557
|
+
// `requestContext` is validated browser input for route identity only.
|
|
558
|
+
// Project ID, Studio host, API base/key, and env must still come from
|
|
559
|
+
// server config — never from this context — and it is `undefined` for
|
|
560
|
+
// legacy request bodies that carry no route context.
|
|
561
|
+
getClient: (_request, requestContext) =>
|
|
562
|
+
requestContext
|
|
563
|
+
? createWeaverseServerClientFromContext(requestContext)
|
|
564
|
+
: getWeaverseServerClient(Promise.resolve({})),
|
|
565
|
+
})
|
|
566
|
+
```
|
|
501
567
|
|
|
568
|
+
The existing one-argument callback still works. A handler mounted with a
|
|
569
|
+
`(request) => client` callback ignores the optional second argument and keeps
|
|
570
|
+
compiling and running, so old wiring needs no change:
|
|
571
|
+
|
|
572
|
+
```ts
|
|
502
573
|
export const { POST } = createWeaverseNextRevalidateHandler({
|
|
503
574
|
getClient: () => getWeaverseServerClient(Promise.resolve({})),
|
|
504
575
|
})
|
|
@@ -508,15 +579,46 @@ Flow:
|
|
|
508
579
|
|
|
509
580
|
```text
|
|
510
581
|
Studio resource picker edit
|
|
511
|
-
-> Builder calls runtime.internal.revalidateItem(draftItem)
|
|
512
|
-
-> SDK
|
|
582
|
+
-> Builder calls runtime.internal.revalidateItem(draftItem) (unchanged)
|
|
583
|
+
-> SDK snapshots runtime.requestInfo, strips server-owned/transient controls
|
|
584
|
+
-> SDK POSTs { draftItem, routeContext? } to /api/weaverse/revalidate
|
|
585
|
+
-> handler validates + sanitizes routeContext at the trust boundary
|
|
586
|
+
-> handler reconstructs a same-origin WeaverseNextRequestContext
|
|
587
|
+
-> getClient(request, requestContext) builds the route-aware server client
|
|
513
588
|
-> route handler finds the registered component by draftItem.type
|
|
514
|
-
-> handler runs that component's loader with draft
|
|
515
|
-
-> response returns { loaderData }
|
|
589
|
+
-> handler runs that component's loader with draft data + client.requestContext
|
|
590
|
+
-> response returns { loaderData } with Cache-Control: no-store
|
|
516
591
|
-> SDK applies loaderData to the live item instance in place
|
|
517
592
|
```
|
|
518
593
|
|
|
519
|
-
If the route is missing or returns an error, Builder falls back to the older
|
|
594
|
+
If the route is missing or returns an error, Builder falls back to the older
|
|
595
|
+
route-refresh path.
|
|
596
|
+
|
|
597
|
+
### Trust boundary
|
|
598
|
+
|
|
599
|
+
The revalidation endpoint is public and every JSON field is attacker-controlled.
|
|
600
|
+
The SDK sanitizes `routeContext` on the client for clean traffic, but the route
|
|
601
|
+
handler is the security boundary and re-validates independently:
|
|
602
|
+
|
|
603
|
+
- Only `pathname`, sanitized `search`, a narrow i18n subset, a
|
|
604
|
+
`PageTypeSchema`-valid `pageType`, and a bounded `handle` cross the boundary.
|
|
605
|
+
Headers, cookies, auth, env, project ID, Studio host, API base/key, commerce
|
|
606
|
+
clients, the runtime, and the client are never serialized.
|
|
607
|
+
- Server-owned controls (`weaverseProjectId`, `weaverseHost`, `weaverseApiKey`,
|
|
608
|
+
`weaverseApiBase`, `weaversePublicApiBase`, `weaverseVersion`, `projectId`) and
|
|
609
|
+
transient transport controls (`weaverseDraftItem`, `__weaverseDraftItem`,
|
|
610
|
+
`_rsc`) are stripped case-insensitively on both sides, so a crafted body cannot
|
|
611
|
+
influence server config resolution.
|
|
612
|
+
- The origin is fixed from the endpoint request before assigning any
|
|
613
|
+
browser-provided pathname/search, so input cannot change protocol, host, port,
|
|
614
|
+
or credentials. `pathname` and `url.pathname` share one URL-canonicalized value.
|
|
615
|
+
- A malformed present `routeContext` returns `400 { error: 'invalid-route-context' }`
|
|
616
|
+
before `getClient` runs; a missing `routeContext` is valid legacy input and
|
|
617
|
+
passes `undefined` to the callback.
|
|
618
|
+
- Route context is routing input, never an authorization decision. A registered
|
|
619
|
+
loader must not treat pathname, handle, page type, locale, or search as proof
|
|
620
|
+
of access; customer/private data still requires independent server-side session
|
|
621
|
+
and authorization checks derived from the actual request.
|
|
520
622
|
|
|
521
623
|
## Config resolution
|
|
522
624
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { PageTypeSchema } from '@weaverse/schema';
|
|
2
|
+
|
|
1
3
|
// src/utils.ts
|
|
2
4
|
function generateDataFromSchema(schema) {
|
|
3
5
|
let data = {};
|
|
@@ -154,8 +156,95 @@ function buildWeaverseNextRequestInfo(context) {
|
|
|
154
156
|
pathname: getPathnameFromContext(context),
|
|
155
157
|
search: search ? `?${search}` : "",
|
|
156
158
|
queries: toQueryRecord(searchParams),
|
|
157
|
-
...context?.i18n ? { i18n: context.i18n } : {}
|
|
159
|
+
...context?.i18n ? { i18n: context.i18n } : {},
|
|
160
|
+
...context?.pageType ? { pageType: context.pageType } : {},
|
|
161
|
+
...context?.handle ? { handle: context.handle } : {}
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
var DEFAULT_REVALIDATE_ENDPOINT = "/api/weaverse/revalidate";
|
|
165
|
+
var MAX_ROUTE_CONTEXT_HANDLE_LENGTH = 512;
|
|
166
|
+
var DENIED_ROUTE_CONTEXT_PARAMS = [
|
|
167
|
+
"weaverseprojectid",
|
|
168
|
+
"weaversehost",
|
|
169
|
+
"weaverseapikey",
|
|
170
|
+
"weaverseapibase",
|
|
171
|
+
"weaversepublicapibase",
|
|
172
|
+
"weaverseversion",
|
|
173
|
+
"projectid",
|
|
174
|
+
"weaversedraftitem",
|
|
175
|
+
"__weaversedraftitem",
|
|
176
|
+
"_rsc"
|
|
177
|
+
];
|
|
178
|
+
var ROUTE_CONTEXT_I18N_KEYS = [
|
|
179
|
+
"country",
|
|
180
|
+
"label",
|
|
181
|
+
"language",
|
|
182
|
+
"locale",
|
|
183
|
+
"pathPrefix"
|
|
184
|
+
];
|
|
185
|
+
function sanitizeRouteContextSearch(search) {
|
|
186
|
+
let params = new URLSearchParams(search);
|
|
187
|
+
let denied = new Set(DENIED_ROUTE_CONTEXT_PARAMS);
|
|
188
|
+
for (let key of [...new Set(params.keys())]) {
|
|
189
|
+
if (denied.has(key.toLowerCase())) {
|
|
190
|
+
params.delete(key);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
let serialized = params.toString();
|
|
194
|
+
return serialized ? `?${serialized}` : "";
|
|
195
|
+
}
|
|
196
|
+
function buildWeaverseNextRevalidateRouteContext(requestInfo) {
|
|
197
|
+
if (!requestInfo || typeof requestInfo.pathname !== "string" || !requestInfo.pathname) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
let routeContext = {
|
|
201
|
+
pathname: requestInfo.pathname,
|
|
202
|
+
search: sanitizeRouteContextSearch(requestInfo.search ?? "")
|
|
158
203
|
};
|
|
204
|
+
let { i18n } = requestInfo;
|
|
205
|
+
if (i18n && typeof i18n === "object") {
|
|
206
|
+
let picked = {};
|
|
207
|
+
for (let key of ROUTE_CONTEXT_I18N_KEYS) {
|
|
208
|
+
let value = i18n[key];
|
|
209
|
+
if (typeof value === "string") {
|
|
210
|
+
picked[key] = value;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (Object.keys(picked).length) {
|
|
214
|
+
routeContext.i18n = picked;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (requestInfo.pageType && PageTypeSchema.safeParse(requestInfo.pageType).success) {
|
|
218
|
+
routeContext.pageType = requestInfo.pageType;
|
|
219
|
+
}
|
|
220
|
+
if (typeof requestInfo.handle === "string" && requestInfo.handle && requestInfo.handle.length <= MAX_ROUTE_CONTEXT_HANDLE_LENGTH) {
|
|
221
|
+
routeContext.handle = requestInfo.handle;
|
|
222
|
+
}
|
|
223
|
+
return routeContext;
|
|
224
|
+
}
|
|
225
|
+
async function revalidateWeaverseNextItem(runtime, draftItem, endpoint = DEFAULT_REVALIDATE_ENDPOINT) {
|
|
226
|
+
let instance = runtime.itemInstances.get(draftItem.id);
|
|
227
|
+
if (!instance) {
|
|
228
|
+
throw new Error(
|
|
229
|
+
`[weaverse-next] No live item instance for "${draftItem.id}".`
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
let routeContext = buildWeaverseNextRevalidateRouteContext(
|
|
233
|
+
runtime.requestInfo
|
|
234
|
+
);
|
|
235
|
+
let body = routeContext ? { draftItem, routeContext } : { draftItem };
|
|
236
|
+
let response = await fetch(endpoint, {
|
|
237
|
+
method: "POST",
|
|
238
|
+
headers: { "Content-Type": "application/json" },
|
|
239
|
+
body: JSON.stringify(body)
|
|
240
|
+
});
|
|
241
|
+
if (!response.ok) {
|
|
242
|
+
throw new Error(
|
|
243
|
+
`[weaverse-next] Revalidate endpoint responded ${response.status}.`
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
let { loaderData } = await response.json();
|
|
247
|
+
instance.setData({ loaderData: loaderData ?? null });
|
|
159
248
|
}
|
|
160
249
|
|
|
161
250
|
// src/seo.ts
|
|
@@ -223,6 +312,6 @@ function getWeaverseNextSeoMetadata(data) {
|
|
|
223
312
|
return formatWeaverseNextSeoMetadata(page?.seo ?? null);
|
|
224
313
|
}
|
|
225
314
|
|
|
226
|
-
export { buildWeaverseNextRequestInfo, formatWeaverseNextSeoMetadata, generateDataFromSchema, getWeaverseNextSeoMetadata, runWeaverseComponentLoaders };
|
|
227
|
-
//# sourceMappingURL=chunk-
|
|
228
|
-
//# sourceMappingURL=chunk-
|
|
315
|
+
export { DEFAULT_REVALIDATE_ENDPOINT, ROUTE_CONTEXT_I18N_KEYS, buildWeaverseNextRequestInfo, buildWeaverseNextRevalidateRouteContext, formatWeaverseNextSeoMetadata, generateDataFromSchema, getWeaverseNextSeoMetadata, revalidateWeaverseNextItem, runWeaverseComponentLoaders, sanitizeRouteContextSearch };
|
|
316
|
+
//# sourceMappingURL=chunk-NL22OVD7.mjs.map
|
|
317
|
+
//# sourceMappingURL=chunk-NL22OVD7.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/loader.ts","../src/request-info.ts","../src/revalidate-item.ts","../src/seo.ts"],"names":[],"mappings":"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","file":"chunk-NL22OVD7.mjs","sourcesContent":["import type { SchemaType } from '@weaverse/schema'\nimport type { WeaverseNextThemeSchema } from './types'\n\n/**\n * Generate default component data from a schema's `settings` inputs.\n *\n * Mirrors Hydrogen's `generateDataFromSchema` (settings → `{ [name]:\n * defaultValue }`) but is kept local so `@weaverse/next` doesn't depend on\n * `@weaverse/hydrogen`. Falls back to the deprecated `inspector` array when a\n * schema predates `settings`.\n */\nexport function generateDataFromSchema(\n schema: SchemaType | WeaverseNextThemeSchema | undefined\n): Record<string, unknown> {\n let data: Record<string, unknown> = {}\n if (!schema) {\n return data\n }\n\n let groups =\n (schema.settings as {\n inputs?: { name?: string; defaultValue?: unknown }[]\n }[]) ??\n (schema as { inspector?: typeof groups }).inspector ??\n []\n\n for (let group of groups) {\n for (let input of group?.inputs ?? []) {\n let { name, defaultValue } = input\n if (name && defaultValue !== null && defaultValue !== undefined) {\n data[name] = defaultValue\n }\n }\n }\n\n return data\n}\n","import type {\n WeaverseNextClient,\n WeaverseNextCommerceContext,\n WeaverseNextComponent,\n WeaverseNextComponentData,\n WeaverseNextLoaderData,\n WeaverseNextRequestContext,\n} from './types'\nimport { generateDataFromSchema } from './utils'\n\n/** Inputs for running registered component loaders over a page tree. */\nexport interface RunComponentLoadersArgs {\n /** Weaverse client containing the component registry. */\n client: WeaverseNextClient\n /** Request-scoped commerce override; defaults to `client.commerce`. */\n commerce?: WeaverseNextCommerceContext\n /** Request-context override; defaults to `client.requestContext`. */\n context?: WeaverseNextRequestContext\n /** Page payload to walk; defaults to `client.data`. */\n data?: WeaverseNextLoaderData | null\n}\n\nfunction isItemNode(node: unknown): node is WeaverseNextComponentData {\n return (\n typeof node === 'object' &&\n node !== null &&\n typeof (node as WeaverseNextComponentData).type === 'string'\n )\n}\n\nfunction cloneItem(item: WeaverseNextComponentData): WeaverseNextComponentData {\n return {\n ...item,\n children: Array.isArray(item.children)\n ? item.children.map((child) =>\n isItemNode(child) ? cloneItem(child) : { ...child }\n )\n : item.children,\n }\n}\n\n/**\n * Walk a serialized page tree and run each registered component's `loader`,\n * attaching the result to the item as `loaderData`.\n *\n * Loaders receive explicit `commerce.storefront` (and `weaverse.storefront` as\n * a compatibility alias via the client). Children are walked recursively when\n * they are inline item objects; flat `items` arrays are covered by the\n * top-level walk.\n *\n * @returns a cloned `data` object with `loaderData` attached to cloned items.\n */\nexport async function runWeaverseComponentLoaders(\n args: RunComponentLoadersArgs\n): Promise<WeaverseNextLoaderData | null> {\n let { client, context, commerce } = args\n let sourceData = args.data ?? client.data\n if (!sourceData) {\n return null\n }\n if (!sourceData.page.items.length) {\n return sourceData\n }\n\n let data: WeaverseNextLoaderData = {\n ...sourceData,\n page: {\n ...sourceData.page,\n items: sourceData.page.items.map(cloneItem),\n },\n }\n let items = data.page.items\n\n let componentMap = new Map<string, WeaverseNextComponent>()\n for (let component of client.components) {\n if (component?.schema?.type) {\n componentMap.set(component.schema.type, component)\n }\n }\n\n let visited = new Set<string>()\n let resolvedContext = context ?? client.requestContext\n let resolvedCommerce = commerce ?? client.commerce\n\n // Per-call `weaverse` alias. When a request-scoped `commerce` is passed, the\n // `weaverse.storefront` compatibility alias must resolve to *that* storefront,\n // not the client's construction-time commerce. Pilot-style loaders call\n // `weaverse.storefront.query(...)`, so a stale alias would query the wrong\n // (or an undefined) storefront. When no override is given we reuse the client\n // as-is to preserve its prototype getters.\n let resolvedWeaverse: WeaverseNextClient =\n resolvedCommerce === client.commerce\n ? client\n : {\n ...client,\n commerce: resolvedCommerce,\n storefront: resolvedCommerce?.storefront,\n }\n\n async function walk(nodes: WeaverseNextComponentData[]) {\n for (let item of nodes) {\n if (!item || visited.has(item.id)) {\n continue\n }\n visited.add(item.id)\n\n let component = componentMap.get(item.type)\n if (component?.loader) {\n try {\n item.loaderData = await component.loader({\n data: { ...generateDataFromSchema(component.schema), ...item.data },\n weaverse: resolvedWeaverse,\n context: resolvedContext,\n commerce: resolvedCommerce,\n })\n } catch (error) {\n console.warn('❌ Item loader run failed.', item.type, item.id, error)\n }\n }\n\n let children = item.children\n if (Array.isArray(children)) {\n let inlineChildren = children.filter(\n isItemNode\n ) as WeaverseNextComponentData[]\n if (inlineChildren.length) {\n await walk(inlineChildren)\n }\n }\n }\n }\n\n await walk(items)\n return data\n}\n","import type {\n WeaverseNextRequestContext,\n WeaverseNextRequestInfo,\n} from './types'\n\nfunction toUrl(value: string | URL): URL {\n return typeof value === 'string' ? new URL(value, 'http://localhost') : value\n}\n\nfunction getSearchParamsFromContext(\n context?: WeaverseNextRequestContext\n): URLSearchParams {\n if (context?.searchParams) {\n return new URLSearchParams(context.searchParams)\n }\n\n if (context?.url) {\n let url = toUrl(context.url)\n return new URLSearchParams(url.searchParams)\n }\n\n return new URLSearchParams()\n}\n\nfunction getPathnameFromContext(context?: WeaverseNextRequestContext): string {\n if (context?.pathname) {\n return context.pathname\n }\n\n if (context?.url) {\n let url = toUrl(context.url)\n return url.pathname || '/'\n }\n\n return '/'\n}\n\nfunction coerceQueryValue(value: string): string | boolean {\n if (value === 'true') {\n return true\n }\n if (value === 'false') {\n return false\n }\n return value\n}\n\nfunction toQueryRecord(\n searchParams: URLSearchParams\n): Record<string, string | boolean> {\n let queries: Record<string, string | boolean> = {}\n for (let [key, value] of searchParams.entries()) {\n queries[key] = coerceQueryValue(value)\n }\n return queries\n}\n\nconst TRANSIENT_STUDIO_PARAMS = new Set([\n 'weaverseDraftItem',\n // Legacy name from the original design-mode draft-item spike. Keep it out of\n // runtime requestInfo too, in case an older Builder bundle is in front of a\n // newer Next storefront.\n '__weaverseDraftItem',\n])\n\nfunction getRequestInfoSearchParams(\n context?: WeaverseNextRequestContext\n): URLSearchParams {\n let searchParams = new URLSearchParams(getSearchParamsFromContext(context))\n for (let key of TRANSIENT_STUDIO_PARAMS) {\n searchParams.delete(key)\n }\n return searchParams\n}\n\n/**\n * Build the Hydrogen-like request info shape consumed by the Studio bridge.\n * Duplicate query keys keep the last value, matching `URLSearchParams` iteration\n * assignment and Hydrogen's practical query-object behavior.\n */\nexport function buildWeaverseNextRequestInfo(\n context?: WeaverseNextRequestContext\n): WeaverseNextRequestInfo {\n let searchParams = getRequestInfoSearchParams(context)\n let search = searchParams.toString()\n\n return {\n pathname: getPathnameFromContext(context),\n search: search ? `?${search}` : '',\n queries: toQueryRecord(searchParams),\n ...(context?.i18n ? { i18n: context.i18n } : {}),\n ...(context?.pageType ? { pageType: context.pageType } : {}),\n ...(context?.handle ? { handle: context.handle } : {}),\n }\n}\n","import type { PageType } from '@weaverse/schema'\nimport { PageTypeSchema } from '@weaverse/schema'\nimport type {\n WeaverseNextComponentData,\n WeaverseNextI18n,\n WeaverseNextRequestInfo,\n} from './types'\n\n/** Default App Router endpoint used for Studio item-loader revalidation. */\nexport const DEFAULT_REVALIDATE_ENDPOINT = '/api/weaverse/revalidate'\n\nconst MAX_ROUTE_CONTEXT_HANDLE_LENGTH = 512\n\n/**\n * Server-owned and transient controls stripped from the revalidation route\n * context on both sides of the trust boundary. Compared case-insensitively, so\n * every entry is stored lowercased. Client sanitization keeps normal traffic\n * clean; the route handler repeats this deny-list as the security boundary.\n *\n * - Server-owned: a crafted `?weaverseProjectId=`/`?weaverseHost=`/`?weaverseApiKey=`\n * must never influence server config resolution (see `getWeaverseNextConfigs`).\n * - Transient: draft-item and RSC transport params never describe route identity.\n */\nexport const DENIED_ROUTE_CONTEXT_PARAMS = [\n 'weaverseprojectid',\n 'weaversehost',\n 'weaverseapikey',\n 'weaverseapibase',\n 'weaversepublicapibase',\n 'weaverseversion',\n 'projectid',\n 'weaversedraftitem',\n '__weaversedraftitem',\n '_rsc',\n]\n\n/** i18n fields allowed to cross the browser boundary. */\nexport const ROUTE_CONTEXT_I18N_KEYS = [\n 'country',\n 'label',\n 'language',\n 'locale',\n 'pathPrefix',\n] as const\n\n/**\n * JSON-safe route subset that may cross the browser boundary alongside the\n * draft item. Never carries headers, cookies, auth, env, project ID, Studio\n * host, API keys/bases, commerce clients, the request context, runtime, or\n * client. `search` is canonical (preserves duplicate keys); the derived\n * `queries` record is intentionally omitted.\n */\nexport interface WeaverseNextRevalidateRouteContext {\n /** Route handle used for page assignment. */\n handle?: string\n /** Public locale and market identity allowed across the browser boundary. */\n i18n?: Pick<\n WeaverseNextI18n,\n 'country' | 'label' | 'language' | 'locale' | 'pathPrefix'\n >\n /** Weaverse page type resolved by the active route. */\n pageType?: PageType\n /** Canonical same-origin route pathname. */\n pathname: string\n /** Sanitized serialized query string, including the leading `?` when set. */\n search: string\n}\n\n/**\n * Minimal runtime surface the in-place apply needs. Structural (not the\n * concrete `WeaverseNextRuntime` class) so unit tests can drive it with a\n * plain mock. `requestInfo` stays optional: a real `WeaverseNextRuntime`\n * always supplies it, but when absent the client omits `routeContext` and the\n * legacy `{ draftItem }` request is preserved.\n */\nexport interface RevalidateItemRuntimeLike {\n /** Live item stores keyed by Weaverse item ID. */\n itemInstances: Map<\n string,\n {\n /** Merge refreshed loader data into the live item store. */\n setData: (update: Record<string, unknown>) => unknown\n }\n >\n /** Active route identity used to construct the optional revalidation payload. */\n requestInfo?: WeaverseNextRequestInfo\n}\n\n/**\n * Strip denied (server-owned/transient) controls from a `search` string and\n * re-serialize it. Preserves ordinary application queries, duplicate keys,\n * encoded Unicode, and mode controls (`isDesignMode`, `isPreviewMode`,\n * `__revisionId`, `sectionType`). Returns `''` or a `?`-prefixed string.\n */\nexport function sanitizeRouteContextSearch(search: string): string {\n let params = new URLSearchParams(search)\n let denied = new Set(DENIED_ROUTE_CONTEXT_PARAMS)\n for (let key of [...new Set(params.keys())]) {\n if (denied.has(key.toLowerCase())) {\n params.delete(key)\n }\n }\n let serialized = params.toString()\n return serialized ? `?${serialized}` : ''\n}\n\n/**\n * Build the sanitized {@link WeaverseNextRevalidateRouteContext} from the\n * active runtime's request info. Returns `undefined` without a usable pathname\n * so the caller omits `routeContext` and keeps the legacy request. This is not\n * the security boundary — the route handler re-validates and re-sanitizes.\n */\nexport function buildWeaverseNextRevalidateRouteContext(\n requestInfo?: WeaverseNextRequestInfo\n): WeaverseNextRevalidateRouteContext | undefined {\n if (\n !requestInfo ||\n typeof requestInfo.pathname !== 'string' ||\n !requestInfo.pathname\n ) {\n return\n }\n\n let routeContext: WeaverseNextRevalidateRouteContext = {\n pathname: requestInfo.pathname,\n search: sanitizeRouteContextSearch(requestInfo.search ?? ''),\n }\n\n let { i18n } = requestInfo\n if (i18n && typeof i18n === 'object') {\n let picked: Record<string, string> = {}\n for (let key of ROUTE_CONTEXT_I18N_KEYS) {\n let value = i18n[key]\n if (typeof value === 'string') {\n picked[key] = value\n }\n }\n if (Object.keys(picked).length) {\n routeContext.i18n = picked\n }\n }\n\n if (\n requestInfo.pageType &&\n PageTypeSchema.safeParse(requestInfo.pageType).success\n ) {\n routeContext.pageType = requestInfo.pageType\n }\n\n if (\n typeof requestInfo.handle === 'string' &&\n requestInfo.handle &&\n requestInfo.handle.length <= MAX_ROUTE_CONTEXT_HANDLE_LENGTH\n ) {\n routeContext.handle = requestInfo.handle\n }\n\n return routeContext\n}\n\n/**\n * Studio per-item loader revalidation: POST the unsaved draft item (and, when\n * the runtime exposes route context, a sanitized `routeContext`) to the app's\n * revalidate route (see `createWeaverseNextRevalidateHandler`) and apply the\n * returned `loaderData` to the live item instance in place.\n *\n * No `router.refresh()` is involved, so the RSC tree is never re-applied — no\n * page remount, no scroll reset, and the draft payload never touches the URL.\n *\n * Throws on any failure (missing route, non-OK response, unknown item) so the\n * Builder Studio bridge can detect the miss and fall back to its legacy\n * refresh-based revalidation for this window.\n */\nexport async function revalidateWeaverseNextItem(\n runtime: RevalidateItemRuntimeLike,\n draftItem: WeaverseNextComponentData,\n endpoint: string = DEFAULT_REVALIDATE_ENDPOINT\n): Promise<void> {\n let instance = runtime.itemInstances.get(draftItem.id)\n if (!instance) {\n throw new Error(\n `[weaverse-next] No live item instance for \"${draftItem.id}\".`\n )\n }\n\n // Snapshot route identity at revalidation start so a later navigation cannot\n // retarget this in-flight request. Omit `routeContext` for legacy runtimes.\n let routeContext = buildWeaverseNextRevalidateRouteContext(\n runtime.requestInfo\n )\n let body = routeContext ? { draftItem, routeContext } : { draftItem }\n\n let response = await fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n if (!response.ok) {\n throw new Error(\n `[weaverse-next] Revalidate endpoint responded ${response.status}.`\n )\n }\n\n let { loaderData } = (await response.json()) as { loaderData?: unknown }\n // The item's settings were already mutated by the Studio edit; only the\n // loader payload needs applying. `setData` merges and notifies subscribers,\n // and the new `loaderData` identity is what Builder's revalidation poll\n // observes for completion.\n instance.setData({ loaderData: loaderData ?? null })\n}\n","import type { PageSEOData } from '@weaverse/schema'\nimport type { Metadata } from 'next'\nimport type { WeaverseNextLoaderData, WeaverseNextPageData } from './types'\n\n/** Object containing an optional Weaverse page for SEO extraction. */\nexport interface WeaverseNextSeoPageContainer {\n /** Page whose published SEO fields should be formatted. */\n page?: WeaverseNextPageData | null\n}\n\n/** Input accepted by {@link getWeaverseNextSeoMetadata}. */\nexport type WeaverseNextSeoInput =\n | WeaverseNextLoaderData\n | WeaverseNextPageData\n | WeaverseNextSeoPageContainer\n | null\n | undefined\n\n/** Open Graph metadata accepted by Next.js's `Metadata` API. */\nexport type NextOpenGraph = NonNullable<Metadata['openGraph']>\n\n/** Twitter card metadata accepted by Next.js's `Metadata` API. */\nexport type NextTwitter = NonNullable<Metadata['twitter']>\n\n/**\n * Weaverse page SEO expressed as a subset of Next's `Metadata`. Assignable to\n * `Metadata` as-is: `const metadata: Metadata = getWeaverseNextSeoMetadata(data)`.\n */\nexport interface WeaverseNextSeoMetadata {\n /** Canonical URL settings for Next's metadata API. */\n alternates?: {\n /** Preferred URL for search indexing. */\n canonical?: string\n }\n /** Page meta description. */\n description?: string\n /** Page meta keywords. */\n keywords?: string\n /** Open Graph metadata normalized to Next's supported union. */\n openGraph?: NextOpenGraph\n /** Search crawler indexing and link-following directives. */\n robots: {\n /** Whether crawlers may follow links on the page. */\n follow: boolean\n /** Whether crawlers may index the page. */\n index: boolean\n }\n /** Page title. */\n title?: string\n /** Twitter card metadata normalized for Next's metadata API. */\n twitter?: NextTwitter\n}\n\nfunction hasOpenGraphContent(seo: PageSEOData['openGraph']): boolean {\n return Boolean(seo?.title || seo?.description || seo?.image || seo?.type)\n}\n\nfunction hasTwitterContent(seo: PageSEOData['twitter']): boolean {\n return Boolean(seo?.title || seo?.description || seo?.image || seo?.cardType)\n}\n\nfunction normalizeTwitterCard(\n cardType: NonNullable<PageSEOData['twitter']>['cardType']\n): 'summary' | 'summary_large_image' {\n return cardType === 'summary_large_image' ? 'summary_large_image' : 'summary'\n}\n\n/**\n * Map a Builder Open Graph type onto Next's `OpenGraphType` union. Every\n * Builder value except `product` exists in Next's union and is preserved\n * verbatim; `product` is not modeled by Next and makes `generateMetadata()`\n * throw, so it degrades to `website` — the closest renderable equivalent.\n */\nfunction normalizeOpenGraphType(\n type: NonNullable<PageSEOData['openGraph']>['type']\n): 'article' | 'profile' | 'video.other' | 'website' {\n if (type === 'article' || type === 'profile' || type === 'video.other') {\n return type\n }\n return 'website'\n}\n\n/**\n * Convert Builder SEO fields into metadata accepted by Next.js.\n *\n * Unsupported Open Graph product types and incomplete Twitter app/player\n * cards are safely downgraded to renderable Next.js variants.\n */\nexport function formatWeaverseNextSeoMetadata(\n seo: PageSEOData | null | undefined\n): WeaverseNextSeoMetadata {\n let index = seo?.robots?.index !== false\n let follow = seo?.robots?.follow !== false\n let metadata: WeaverseNextSeoMetadata = {\n robots: { index, follow },\n }\n\n if (!seo) {\n return metadata\n }\n\n if (seo.title) {\n metadata.title = seo.title\n }\n if (seo.description) {\n metadata.description = seo.description\n }\n if (seo.keywords) {\n metadata.keywords = seo.keywords\n }\n if (seo.canonicalUrl) {\n metadata.alternates = { canonical: seo.canonicalUrl }\n }\n\n let openGraph = seo.openGraph\n if (hasOpenGraphContent(openGraph)) {\n metadata.openGraph = {\n title: openGraph?.title,\n description: openGraph?.description,\n images: openGraph?.image ? [openGraph.image] : undefined,\n type: normalizeOpenGraphType(openGraph?.type),\n }\n }\n\n let twitter = seo.twitter\n if (hasTwitterContent(twitter)) {\n // Builder does not collect the descriptors Next requires for `app` cards\n // (Next throws when they are missing) or `player` cards (which render an\n // empty, useless card without a player URL and dimensions). Downgrade both\n // to `summary` rather than emitting metadata Next cannot render.\n metadata.twitter = {\n card: normalizeTwitterCard(twitter?.cardType),\n title: twitter?.title,\n description: twitter?.description,\n images: twitter?.image ? [twitter.image] : undefined,\n }\n }\n\n return metadata\n}\n\n/**\n * Read page SEO from loader data or a page payload and format it for Next.js\n * `generateMetadata`. Missing data returns indexable/followable robot defaults.\n */\nexport function getWeaverseNextSeoMetadata(\n data: WeaverseNextSeoInput\n): WeaverseNextSeoMetadata {\n if (!data) {\n return formatWeaverseNextSeoMetadata(null)\n }\n let page =\n 'items' in data && 'id' in data\n ? (data as WeaverseNextPageData)\n : ((data as WeaverseNextSeoPageContainer).page ?? null)\n return formatWeaverseNextSeoMetadata(page?.seo ?? null)\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -54,6 +54,7 @@ var WeaverseNextItem = class extends react.WeaverseItemStore {
|
|
|
54
54
|
_cachedSnapshot = null;
|
|
55
55
|
_snapshotStoreRef = null;
|
|
56
56
|
_snapshotTranslationRef = null;
|
|
57
|
+
/** Create an item store from serialized component data and its runtime. */
|
|
57
58
|
constructor(initialData, weaverse) {
|
|
58
59
|
super(initialData, weaverse);
|
|
59
60
|
let schemaData = generateDataFromSchema(this.Element?.schema);
|
|
@@ -319,18 +320,24 @@ var useThemeText = useTranslation;
|
|
|
319
320
|
|
|
320
321
|
// src/translation-store.ts
|
|
321
322
|
var TranslationStore = class {
|
|
323
|
+
/** Current flat translation overrides keyed by dot path. */
|
|
322
324
|
overrides = {};
|
|
323
325
|
listeners = /* @__PURE__ */ new Set();
|
|
326
|
+
/** Replace every override and notify subscribers. */
|
|
324
327
|
setOverrides = (overrides) => {
|
|
325
328
|
this.overrides = { ...overrides };
|
|
326
329
|
this.emit();
|
|
327
330
|
};
|
|
331
|
+
/** Merge changed overrides into the current values and notify subscribers. */
|
|
328
332
|
updateOverrides = (newOverrides) => {
|
|
329
333
|
this.overrides = { ...this.overrides, ...newOverrides };
|
|
330
334
|
this.emit();
|
|
331
335
|
};
|
|
336
|
+
/** Return the current client-side override snapshot. */
|
|
332
337
|
getSnapshot = () => this.overrides;
|
|
338
|
+
/** Return the override snapshot used during server rendering. */
|
|
333
339
|
getServerSnapshot = () => this.overrides;
|
|
340
|
+
/** Subscribe to override changes and return an unsubscribe function. */
|
|
334
341
|
subscribe = (callback) => {
|
|
335
342
|
this.listeners.add(callback);
|
|
336
343
|
return () => {
|
|
@@ -648,7 +655,9 @@ function buildWeaverseNextRequestInfo(context) {
|
|
|
648
655
|
pathname: getPathnameFromContext(context),
|
|
649
656
|
search: search ? `?${search}` : "",
|
|
650
657
|
queries: toQueryRecord(searchParams),
|
|
651
|
-
...context?.i18n ? { i18n: context.i18n } : {}
|
|
658
|
+
...context?.i18n ? { i18n: context.i18n } : {},
|
|
659
|
+
...context?.pageType ? { pageType: context.pageType } : {},
|
|
660
|
+
...context?.handle ? { handle: context.handle } : {}
|
|
652
661
|
};
|
|
653
662
|
}
|
|
654
663
|
|
|
@@ -714,11 +723,17 @@ function rebindPageItemsToRuntime(runtime) {
|
|
|
714
723
|
}
|
|
715
724
|
}
|
|
716
725
|
var WeaverseNextRuntime = class extends react.Weaverse {
|
|
726
|
+
/** Stable ID of the page owned by this runtime. */
|
|
717
727
|
pageId;
|
|
728
|
+
/** Mutable callbacks and stores consumed by the Studio bridge. */
|
|
718
729
|
internal;
|
|
730
|
+
/** Path, query, and locale metadata for Studio navigation. */
|
|
719
731
|
requestInfo;
|
|
732
|
+
/** Whether this runtime renders a component preview. */
|
|
720
733
|
isPreviewMode;
|
|
734
|
+
/** Whether this runtime renders a saved revision. */
|
|
721
735
|
isRevisionPreview;
|
|
736
|
+
/** Component type rendered in section preview mode. */
|
|
722
737
|
sectionType;
|
|
723
738
|
// ─── Item-level translation sidecar (design mode only) ─────────────
|
|
724
739
|
/**
|
|
@@ -727,7 +742,9 @@ var WeaverseNextRuntime = class extends react.Weaverse {
|
|
|
727
742
|
* components, so translations render without mutating the base `_store`.
|
|
728
743
|
*/
|
|
729
744
|
translationMap = {};
|
|
745
|
+
/** Locale associated with the item-level translation sidecar. */
|
|
730
746
|
translationLocale = String();
|
|
747
|
+
/** Weaverse language ID used when saving translation changes. */
|
|
731
748
|
translationLanguageId = String();
|
|
732
749
|
/**
|
|
733
750
|
* Fresh page data captured while React was rendering. Runtime reuse happens
|
|
@@ -745,6 +762,7 @@ var WeaverseNextRuntime = class extends react.Weaverse {
|
|
|
745
762
|
* deferred to `flushRenderPhaseUpdates()`.
|
|
746
763
|
*/
|
|
747
764
|
pendingItemUpdates = [];
|
|
765
|
+
/** Create a browser runtime from a loaded page and its request context. */
|
|
748
766
|
constructor(config) {
|
|
749
767
|
let { client, data } = config;
|
|
750
768
|
let page = getRenderablePage(data);
|
|
@@ -966,9 +984,67 @@ function bindWeaverseNextStudioRuntime(runtime) {
|
|
|
966
984
|
});
|
|
967
985
|
return true;
|
|
968
986
|
}
|
|
969
|
-
|
|
970
|
-
// src/revalidate-item.ts
|
|
971
987
|
var DEFAULT_REVALIDATE_ENDPOINT = "/api/weaverse/revalidate";
|
|
988
|
+
var MAX_ROUTE_CONTEXT_HANDLE_LENGTH = 512;
|
|
989
|
+
var DENIED_ROUTE_CONTEXT_PARAMS = [
|
|
990
|
+
"weaverseprojectid",
|
|
991
|
+
"weaversehost",
|
|
992
|
+
"weaverseapikey",
|
|
993
|
+
"weaverseapibase",
|
|
994
|
+
"weaversepublicapibase",
|
|
995
|
+
"weaverseversion",
|
|
996
|
+
"projectid",
|
|
997
|
+
"weaversedraftitem",
|
|
998
|
+
"__weaversedraftitem",
|
|
999
|
+
"_rsc"
|
|
1000
|
+
];
|
|
1001
|
+
var ROUTE_CONTEXT_I18N_KEYS = [
|
|
1002
|
+
"country",
|
|
1003
|
+
"label",
|
|
1004
|
+
"language",
|
|
1005
|
+
"locale",
|
|
1006
|
+
"pathPrefix"
|
|
1007
|
+
];
|
|
1008
|
+
function sanitizeRouteContextSearch(search) {
|
|
1009
|
+
let params = new URLSearchParams(search);
|
|
1010
|
+
let denied = new Set(DENIED_ROUTE_CONTEXT_PARAMS);
|
|
1011
|
+
for (let key of [...new Set(params.keys())]) {
|
|
1012
|
+
if (denied.has(key.toLowerCase())) {
|
|
1013
|
+
params.delete(key);
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
let serialized = params.toString();
|
|
1017
|
+
return serialized ? `?${serialized}` : "";
|
|
1018
|
+
}
|
|
1019
|
+
function buildWeaverseNextRevalidateRouteContext(requestInfo) {
|
|
1020
|
+
if (!requestInfo || typeof requestInfo.pathname !== "string" || !requestInfo.pathname) {
|
|
1021
|
+
return;
|
|
1022
|
+
}
|
|
1023
|
+
let routeContext = {
|
|
1024
|
+
pathname: requestInfo.pathname,
|
|
1025
|
+
search: sanitizeRouteContextSearch(requestInfo.search ?? "")
|
|
1026
|
+
};
|
|
1027
|
+
let { i18n } = requestInfo;
|
|
1028
|
+
if (i18n && typeof i18n === "object") {
|
|
1029
|
+
let picked = {};
|
|
1030
|
+
for (let key of ROUTE_CONTEXT_I18N_KEYS) {
|
|
1031
|
+
let value = i18n[key];
|
|
1032
|
+
if (typeof value === "string") {
|
|
1033
|
+
picked[key] = value;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
if (Object.keys(picked).length) {
|
|
1037
|
+
routeContext.i18n = picked;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
if (requestInfo.pageType && schema.PageTypeSchema.safeParse(requestInfo.pageType).success) {
|
|
1041
|
+
routeContext.pageType = requestInfo.pageType;
|
|
1042
|
+
}
|
|
1043
|
+
if (typeof requestInfo.handle === "string" && requestInfo.handle && requestInfo.handle.length <= MAX_ROUTE_CONTEXT_HANDLE_LENGTH) {
|
|
1044
|
+
routeContext.handle = requestInfo.handle;
|
|
1045
|
+
}
|
|
1046
|
+
return routeContext;
|
|
1047
|
+
}
|
|
972
1048
|
async function revalidateWeaverseNextItem(runtime, draftItem, endpoint = DEFAULT_REVALIDATE_ENDPOINT) {
|
|
973
1049
|
let instance = runtime.itemInstances.get(draftItem.id);
|
|
974
1050
|
if (!instance) {
|
|
@@ -976,10 +1052,14 @@ async function revalidateWeaverseNextItem(runtime, draftItem, endpoint = DEFAULT
|
|
|
976
1052
|
`[weaverse-next] No live item instance for "${draftItem.id}".`
|
|
977
1053
|
);
|
|
978
1054
|
}
|
|
1055
|
+
let routeContext = buildWeaverseNextRevalidateRouteContext(
|
|
1056
|
+
runtime.requestInfo
|
|
1057
|
+
);
|
|
1058
|
+
let body = routeContext ? { draftItem, routeContext } : { draftItem };
|
|
979
1059
|
let response = await fetch(endpoint, {
|
|
980
1060
|
method: "POST",
|
|
981
1061
|
headers: { "Content-Type": "application/json" },
|
|
982
|
-
body: JSON.stringify(
|
|
1062
|
+
body: JSON.stringify(body)
|
|
983
1063
|
});
|
|
984
1064
|
if (!response.ok) {
|
|
985
1065
|
throw new Error(
|
|
@@ -1268,7 +1348,7 @@ function resolveWeaverseNextStudioScriptSrc(context, options = {}) {
|
|
|
1268
1348
|
if (!isTrustedStudioOrigin(origin, storefrontHostname)) {
|
|
1269
1349
|
return null;
|
|
1270
1350
|
}
|
|
1271
|
-
let bundle =
|
|
1351
|
+
let bundle = isPreviewMode || isRevisionPreview ? "preview.js" : "index.js";
|
|
1272
1352
|
let version = last(searchParams, "weaverseVersion");
|
|
1273
1353
|
let url = `${origin}/static/studio/next/${bundle}`;
|
|
1274
1354
|
return version ? `${url}?v=${encodeURIComponent(version)}` : url;
|
|
@@ -1356,6 +1436,7 @@ exports.WeaverseNextStudioBridge = WeaverseNextStudioBridge;
|
|
|
1356
1436
|
exports.WeaverseNextStudioConnect = WeaverseNextStudioConnect;
|
|
1357
1437
|
exports.bindWeaverseNextStudioRuntime = bindWeaverseNextStudioRuntime;
|
|
1358
1438
|
exports.buildWeaverseNextRequestInfo = buildWeaverseNextRequestInfo;
|
|
1439
|
+
exports.buildWeaverseNextRevalidateRouteContext = buildWeaverseNextRevalidateRouteContext;
|
|
1359
1440
|
exports.createTranslate = createTranslate;
|
|
1360
1441
|
exports.createWeaverseNextClient = createWeaverseNextClient;
|
|
1361
1442
|
exports.createWeaverseNextRuntime = createWeaverseNextRuntime;
|