@weaverse/next 0.1.0-alpha.0 → 0.1.0-alpha.2
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 +165 -0
- package/dist/chunk-SS6QUKYY.mjs +149 -0
- package/dist/chunk-SS6QUKYY.mjs.map +1 -0
- package/dist/index.d.mts +145 -160
- package/dist/index.d.ts +145 -160
- package/dist/index.js +477 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +407 -108
- package/dist/index.mjs.map +1 -1
- package/dist/server.d.mts +60 -0
- package/dist/server.d.ts +60 -0
- package/dist/server.js +662 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +513 -0
- package/dist/server.mjs.map +1 -0
- package/dist/types-DvEeLX6L.d.mts +321 -0
- package/dist/types-DvEeLX6L.d.ts +321 -0
- package/package.json +22 -3
package/README.md
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# @weaverse/next
|
|
2
|
+
|
|
3
|
+
Next.js App Router integration for building Weaverse-powered storefronts.
|
|
4
|
+
|
|
5
|
+
This package adapts the Weaverse runtime (component registry, page-tree
|
|
6
|
+
rendering, Studio bridge) to Next.js without depending on React Router or
|
|
7
|
+
Hydrogen. It mirrors the `@weaverse/hydrogen` contract where it makes sense, but
|
|
8
|
+
takes plain, framework-neutral inputs (URL, headers, search params) instead of a
|
|
9
|
+
React Router `Request`/`LoaderFunctionArgs`.
|
|
10
|
+
|
|
11
|
+
## Entrypoints
|
|
12
|
+
|
|
13
|
+
| Import | Use in | Purpose |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `@weaverse/next` | Client & server | Registry, renderer, provider, hooks, Studio runtime/bridge. |
|
|
16
|
+
| `@weaverse/next/server` | Server only | Server-side Weaverse client that fetches page/theme data from the Weaverse API. |
|
|
17
|
+
|
|
18
|
+
> The server-side data-loading API lives under **`@weaverse/next/server`** so the
|
|
19
|
+
> root entry stays free of server-only fetch assumptions and safe to import from
|
|
20
|
+
> client components.
|
|
21
|
+
|
|
22
|
+
## Package structure
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
packages/next/src/
|
|
26
|
+
index.ts # root (@weaverse/next) public exports
|
|
27
|
+
server.ts # server (@weaverse/next/server) public exports
|
|
28
|
+
client.ts # createWeaverseNextClient (injected-fetcher client)
|
|
29
|
+
loader.ts # runWeaverseComponentLoaders (server-side section loaders)
|
|
30
|
+
registry.ts # register components with the Weaverse element registry
|
|
31
|
+
renderer.tsx # WeaverseNextRenderer (page-tree → React)
|
|
32
|
+
provider.tsx # WeaverseNextProvider (client context for hooks)
|
|
33
|
+
hooks.ts # useThemeSettings / useWeaversePageData / ...
|
|
34
|
+
runtime.ts # WeaverseNextRuntime + Studio binding
|
|
35
|
+
studio-bridge.tsx # Studio script injection / connect
|
|
36
|
+
request-info.ts # buildWeaverseNextRequestInfo (Studio-compatible)
|
|
37
|
+
theme-settings-store.ts
|
|
38
|
+
types.ts # shared types (root + server)
|
|
39
|
+
server/
|
|
40
|
+
server-client.ts # createWeaverseNextServerClient
|
|
41
|
+
configs.ts # getWeaverseNextConfigs (host/api-base/flags/env)
|
|
42
|
+
normalize-page-url.ts
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Root API (`@weaverse/next`)
|
|
46
|
+
|
|
47
|
+
- `createWeaverseNextClient(config)` — request-safe client that delegates network
|
|
48
|
+
I/O to injected `fetchPage` / `fetchThemeSettings`.
|
|
49
|
+
- `WeaverseNextProvider` / `WeaverseNextRenderer` — client provider + page-tree
|
|
50
|
+
renderer.
|
|
51
|
+
- `runWeaverseComponentLoaders(args)` — walk a page tree and run each registered
|
|
52
|
+
component's `loader` server-side.
|
|
53
|
+
- Hooks: `useThemeSettings`, `useWeaversePageData`, `useWeaverseRootData`,
|
|
54
|
+
`useWeaverseCommerce` (plus re-exported `@weaverse/react` hooks).
|
|
55
|
+
- Studio helpers: `WeaverseNextRuntime`, `createWeaverseNextRuntime`,
|
|
56
|
+
`bindWeaverseNextStudioRuntime`, `WeaverseNextStudioBridge`,
|
|
57
|
+
`WeaverseNextStudioConnect`, `resolveWeaverseNextStudioScriptSrc`,
|
|
58
|
+
`buildWeaverseNextRequestInfo`, `createWeaverseNextThemeSettingsStore`.
|
|
59
|
+
- `createSchema` (re-exported from `@weaverse/schema`).
|
|
60
|
+
|
|
61
|
+
## Server API (`@weaverse/next/server`)
|
|
62
|
+
|
|
63
|
+
`createWeaverseNextServerClient(config)` returns a client that performs the real
|
|
64
|
+
Weaverse public API fetch — the equivalent of Hydrogen/Pilot's
|
|
65
|
+
`context.weaverse.loadPage(...)`.
|
|
66
|
+
|
|
67
|
+
### Next App Router server context model
|
|
68
|
+
|
|
69
|
+
Hydrogen's classic storefront runtime is built on React Router. Its request
|
|
70
|
+
handler accepts `getLoadContext(request)`, creates a Hydrogen context, and React
|
|
71
|
+
Router injects that object into every route loader. That is why a Pilot route can
|
|
72
|
+
call `context.weaverse.loadPage(...)` directly.
|
|
73
|
+
|
|
74
|
+
Next App Router does not inject an app-defined global loader context into
|
|
75
|
+
`app/page.tsx`. A page is a Server Component whose framework-provided inputs are
|
|
76
|
+
`params` and `searchParams`; request-scoped data is read with Next functions such
|
|
77
|
+
as `headers()` / `cookies()`. Hydrogen preview follows that framework model for
|
|
78
|
+
Next examples: fetch in `app/page.tsx` or a server helper, then pass the snapshot
|
|
79
|
+
to client components.
|
|
80
|
+
|
|
81
|
+
So the Next equivalent is explicit server-client creation at the route boundary:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { createWeaverseNextServerClient } from '@weaverse/next/server'
|
|
85
|
+
import { components } from '@/weaverse/components'
|
|
86
|
+
|
|
87
|
+
export async function loadWeaverse(request: Request, storefront: Storefront) {
|
|
88
|
+
let url = new URL(request.url)
|
|
89
|
+
let weaverse = createWeaverseNextServerClient({
|
|
90
|
+
projectId: process.env.WEAVERSE_PROJECT_ID, // string | (ctx) => string | Promise<string>
|
|
91
|
+
components,
|
|
92
|
+
themeSchema,
|
|
93
|
+
commerce: { storefront },
|
|
94
|
+
env: process.env,
|
|
95
|
+
requestContext: {
|
|
96
|
+
url,
|
|
97
|
+
headers: request.headers,
|
|
98
|
+
searchParams: url.searchParams,
|
|
99
|
+
i18n: storefront.i18n,
|
|
100
|
+
},
|
|
101
|
+
cache: { revalidate: 60, tags: ['weaverse'] },
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
let [page, theme] = await Promise.all([
|
|
105
|
+
weaverse.loadPage({ type: 'INDEX' }),
|
|
106
|
+
weaverse.loadThemeSettings(),
|
|
107
|
+
])
|
|
108
|
+
return { page, theme, weaverse }
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Returned client
|
|
113
|
+
|
|
114
|
+
| Member | Description |
|
|
115
|
+
| --- | --- |
|
|
116
|
+
| `loadPage(input?)` | POSTs `{ projectId, url, i18n, params, isDesignMode }` to `/api/public/project`, runs component loaders, returns `WeaverseNextLoaderData` (`page`, `project`, `pageAssignment`, `configs.requestInfo`). In Studio preview mode (`?isPreviewMode=true`) it short-circuits to a synthetic single-section page built from the `sectionType` presets — no fetch, no `projectId` required. A route-level `projectId` override is propagated to `client.projectId`, loaders, and the returned `configs`. |
|
|
117
|
+
| `loadThemeSettings(options?)` | POSTs to `/api/public/project_configs`, merges `themeSchema` defaults under `theme`, includes `staticContent`; falls back to defaults on failure. |
|
|
118
|
+
| `fetchWithCache<T>(url, options?)` | Mode-aware fetch: `cache: 'no-store'` in design/revision, `next: { revalidate, tags }` in published mode. |
|
|
119
|
+
| `projectId` / `resolveProjectId()` | Resolved project id (query → function → string → env). |
|
|
120
|
+
| `components`, `commerce`, `storefront`, `requestContext`, `themeSchema`, `themeSettings`, `data`, `dataContext`, `configs` | Readonly request state. `storefront` aliases `commerce.storefront`. |
|
|
121
|
+
|
|
122
|
+
### Config resolution
|
|
123
|
+
|
|
124
|
+
Close to Hydrogen's `getWeaverseConfigs`:
|
|
125
|
+
|
|
126
|
+
- **projectId** — `?weaverseProjectId=` query → config function → config string →
|
|
127
|
+
`WEAVERSE_PROJECT_ID` env.
|
|
128
|
+
- **weaverseHost** — trusted request `?weaverseHost=` (only `weaverse.io` /
|
|
129
|
+
`weaverse.dev` over https) → `WEAVERSE_HOST` env → `https://studio.weaverse.io`.
|
|
130
|
+
- **API base** — trusted request host → `WEAVERSE_PUBLIC_API_BASE` env → custom
|
|
131
|
+
non-production `WEAVERSE_HOST` → `https://api.weaverse.io`.
|
|
132
|
+
- **publicEnv** — `PUBLIC_STORE_DOMAIN`, `PUBLIC_STOREFRONT_API_TOKEN`.
|
|
133
|
+
|
|
134
|
+
`WEAVERSE_API_KEY` is read from the request query / env and kept on the internal
|
|
135
|
+
base configs, but the current server client does **not** attach it to the
|
|
136
|
+
page/theme API requests. It is also **never** serialized into client-facing
|
|
137
|
+
`configs` / loader data, so it cannot leak to the browser.
|
|
138
|
+
|
|
139
|
+
## Studio helpers
|
|
140
|
+
|
|
141
|
+
Design/preview detection, the Studio bridge script, and the in-page runtime are
|
|
142
|
+
shared with the root entry: `createWeaverseNextRuntime` + `WeaverseNextProvider`
|
|
143
|
+
hydrate Studio, and `bindWeaverseNextStudioRuntime` wires live updates. The
|
|
144
|
+
server client emits `configs.requestInfo` and design-mode flags the bridge
|
|
145
|
+
expects.
|
|
146
|
+
|
|
147
|
+
> **Mount `WeaverseNextStudioConnect` at your root/client shell.**
|
|
148
|
+
> `WeaverseNextRenderer` mounts the in-page runtime bridge but does **not**
|
|
149
|
+
> inject the Studio bridge script by itself. The script (which lets Studio's
|
|
150
|
+
> `checkWeaversePage()` handshake answer on every route, including content-less
|
|
151
|
+
> ones) is loaded by `WeaverseNextStudioConnect`, so it must be rendered once at
|
|
152
|
+
> the app root/client shell for the Studio editor to connect.
|
|
153
|
+
|
|
154
|
+
## Current limitations
|
|
155
|
+
|
|
156
|
+
- Server fetch has a timeout + single attempt; it does not yet replicate
|
|
157
|
+
Hydrogen's subrequest cache, retry/backoff, or merchant-overrides translation
|
|
158
|
+
fetch.
|
|
159
|
+
- Next caching is expressed only via `cache: 'no-store'` and
|
|
160
|
+
`next: { revalidate, tags }`; on-demand `revalidatePath`/`revalidateTag` is left
|
|
161
|
+
to the host app.
|
|
162
|
+
- `loadCustomPages` (sitemap) and SEO helpers are not ported yet.
|
|
163
|
+
- The Studio bridge currently reuses the Hydrogen bundle until a Next-specific
|
|
164
|
+
bundle is required.
|
|
165
|
+
- Package is pre-release (`alpha`); the API may still change.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// src/utils.ts
|
|
2
|
+
function generateDataFromSchema(schema) {
|
|
3
|
+
let data = {};
|
|
4
|
+
if (!schema) {
|
|
5
|
+
return data;
|
|
6
|
+
}
|
|
7
|
+
let groups = schema.settings ?? schema.inspector ?? [];
|
|
8
|
+
for (let group of groups) {
|
|
9
|
+
for (let input of group?.inputs ?? []) {
|
|
10
|
+
let { name, defaultValue } = input;
|
|
11
|
+
if (name && defaultValue !== null && defaultValue !== void 0) {
|
|
12
|
+
data[name] = defaultValue;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return data;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/loader.ts
|
|
20
|
+
function isItemNode(node) {
|
|
21
|
+
return typeof node === "object" && node !== null && typeof node.type === "string";
|
|
22
|
+
}
|
|
23
|
+
function cloneItem(item) {
|
|
24
|
+
return {
|
|
25
|
+
...item,
|
|
26
|
+
children: Array.isArray(item.children) ? item.children.map(
|
|
27
|
+
(child) => isItemNode(child) ? cloneItem(child) : { ...child }
|
|
28
|
+
) : item.children
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async function runWeaverseComponentLoaders(args) {
|
|
32
|
+
let { client, context, commerce } = args;
|
|
33
|
+
let sourceData = args.data ?? client.data;
|
|
34
|
+
if (!sourceData) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
if (!sourceData.page.items.length) {
|
|
38
|
+
return sourceData;
|
|
39
|
+
}
|
|
40
|
+
let data = {
|
|
41
|
+
...sourceData,
|
|
42
|
+
page: {
|
|
43
|
+
...sourceData.page,
|
|
44
|
+
items: sourceData.page.items.map(cloneItem)
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
let items = data.page.items;
|
|
48
|
+
let componentMap = /* @__PURE__ */ new Map();
|
|
49
|
+
for (let component of client.components) {
|
|
50
|
+
if (component?.schema?.type) {
|
|
51
|
+
componentMap.set(component.schema.type, component);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
let visited = /* @__PURE__ */ new Set();
|
|
55
|
+
let resolvedContext = context ?? client.requestContext;
|
|
56
|
+
let resolvedCommerce = commerce ?? client.commerce;
|
|
57
|
+
let resolvedWeaverse = resolvedCommerce === client.commerce ? client : {
|
|
58
|
+
...client,
|
|
59
|
+
commerce: resolvedCommerce,
|
|
60
|
+
storefront: resolvedCommerce?.storefront
|
|
61
|
+
};
|
|
62
|
+
async function walk(nodes) {
|
|
63
|
+
for (let item of nodes) {
|
|
64
|
+
if (!item || visited.has(item.id)) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
visited.add(item.id);
|
|
68
|
+
let component = componentMap.get(item.type);
|
|
69
|
+
if (component?.loader) {
|
|
70
|
+
try {
|
|
71
|
+
item.loaderData = await component.loader({
|
|
72
|
+
data: { ...generateDataFromSchema(component.schema), ...item.data },
|
|
73
|
+
weaverse: resolvedWeaverse,
|
|
74
|
+
context: resolvedContext,
|
|
75
|
+
commerce: resolvedCommerce
|
|
76
|
+
});
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.warn("\u274C Item loader run failed.", item.type, item.id, error);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
let children = item.children;
|
|
82
|
+
if (Array.isArray(children)) {
|
|
83
|
+
let inlineChildren = children.filter(
|
|
84
|
+
isItemNode
|
|
85
|
+
);
|
|
86
|
+
if (inlineChildren.length) {
|
|
87
|
+
await walk(inlineChildren);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
await walk(items);
|
|
93
|
+
return data;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// src/request-info.ts
|
|
97
|
+
function toUrl(value) {
|
|
98
|
+
return typeof value === "string" ? new URL(value, "http://localhost") : value;
|
|
99
|
+
}
|
|
100
|
+
function getSearchParamsFromContext(context) {
|
|
101
|
+
if (context?.searchParams) {
|
|
102
|
+
return new URLSearchParams(context.searchParams);
|
|
103
|
+
}
|
|
104
|
+
if (context?.url) {
|
|
105
|
+
let url = toUrl(context.url);
|
|
106
|
+
return new URLSearchParams(url.searchParams);
|
|
107
|
+
}
|
|
108
|
+
return new URLSearchParams();
|
|
109
|
+
}
|
|
110
|
+
function getPathnameFromContext(context) {
|
|
111
|
+
if (context?.pathname) {
|
|
112
|
+
return context.pathname;
|
|
113
|
+
}
|
|
114
|
+
if (context?.url) {
|
|
115
|
+
let url = toUrl(context.url);
|
|
116
|
+
return url.pathname || "/";
|
|
117
|
+
}
|
|
118
|
+
return "/";
|
|
119
|
+
}
|
|
120
|
+
function coerceQueryValue(value) {
|
|
121
|
+
if (value === "true") {
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
if (value === "false") {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
return value;
|
|
128
|
+
}
|
|
129
|
+
function toQueryRecord(searchParams) {
|
|
130
|
+
let queries = {};
|
|
131
|
+
for (let [key, value] of searchParams.entries()) {
|
|
132
|
+
queries[key] = coerceQueryValue(value);
|
|
133
|
+
}
|
|
134
|
+
return queries;
|
|
135
|
+
}
|
|
136
|
+
function buildWeaverseNextRequestInfo(context) {
|
|
137
|
+
let searchParams = getSearchParamsFromContext(context);
|
|
138
|
+
let search = searchParams.toString();
|
|
139
|
+
return {
|
|
140
|
+
pathname: getPathnameFromContext(context),
|
|
141
|
+
search: search ? `?${search}` : "",
|
|
142
|
+
queries: toQueryRecord(searchParams),
|
|
143
|
+
...context?.i18n ? { i18n: context.i18n } : {}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export { buildWeaverseNextRequestInfo, generateDataFromSchema, runWeaverseComponentLoaders };
|
|
148
|
+
//# sourceMappingURL=chunk-SS6QUKYY.mjs.map
|
|
149
|
+
//# sourceMappingURL=chunk-SS6QUKYY.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/loader.ts","../src/request-info.ts"],"names":[],"mappings":";AAUO,SAAS,uBACd,MAAA,EACyB;AACzB,EAAA,IAAI,OAAgC,EAAC;AACrC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,GACD,MAAA,CAAO,QAAA,IAGP,MAAA,CAAyC,aAC1C,EAAC;AAEH,EAAA,KAAA,IAAS,SAAS,MAAA,EAAQ;AACxB,IAAA,KAAA,IAAS,KAAA,IAAS,KAAA,EAAO,MAAA,IAAU,EAAC,EAAG;AACrC,MAAA,IAAI,EAAE,IAAA,EAAM,YAAA,EAAa,GAAI,KAAA;AAC7B,MAAA,IAAI,IAAA,IAAQ,YAAA,KAAiB,IAAA,IAAQ,YAAA,KAAiB,MAAA,EAAW;AAC/D,QAAA,IAAA,CAAK,IAAI,CAAA,GAAI,YAAA;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;;;ACjBA,SAAS,WAAW,IAAA,EAAkD;AACpE,EAAA,OACE,OAAO,IAAA,KAAS,QAAA,IAChB,SAAS,IAAA,IACT,OAAQ,KAAmC,IAAA,KAAS,QAAA;AAExD;AAEA,SAAS,UAAU,IAAA,EAA4D;AAC7E,EAAA,OAAO;AAAA,IACL,GAAG,IAAA;AAAA,IACH,UAAU,KAAA,CAAM,OAAA,CAAQ,KAAK,QAAQ,CAAA,GACjC,KAAK,QAAA,CAAS,GAAA;AAAA,MAAI,CAAC,KAAA,KACjB,UAAA,CAAW,KAAK,CAAA,GAAI,UAAU,KAAK,CAAA,GAAI,EAAE,GAAG,KAAA;AAAM,QAEpD,IAAA,CAAK;AAAA,GACX;AACF;AAaA,eAAsB,4BACpB,IAAA,EACwC;AACxC,EAAA,IAAI,EAAE,MAAA,EAAQ,OAAA,EAAS,QAAA,EAAS,GAAI,IAAA;AACpC,EAAA,IAAI,UAAA,GAAa,IAAA,CAAK,IAAA,IAAQ,MAAA,CAAO,IAAA;AACrC,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,CAAC,UAAA,CAAW,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ;AACjC,IAAA,OAAO,UAAA;AAAA,EACT;AAEA,EAAA,IAAI,IAAA,GAA+B;AAAA,IACjC,GAAG,UAAA;AAAA,IACH,IAAA,EAAM;AAAA,MACJ,GAAG,UAAA,CAAW,IAAA;AAAA,MACd,KAAA,EAAO,UAAA,CAAW,IAAA,CAAK,KAAA,CAAM,IAAI,SAAS;AAAA;AAC5C,GACF;AACA,EAAA,IAAI,KAAA,GAAQ,KAAK,IAAA,CAAK,KAAA;AAEtB,EAAA,IAAI,YAAA,uBAAmB,GAAA,EAAmC;AAC1D,EAAA,KAAA,IAAS,SAAA,IAAa,OAAO,UAAA,EAAY;AACvC,IAAA,IAAI,SAAA,EAAW,QAAQ,IAAA,EAAM;AAC3B,MAAA,YAAA,CAAa,GAAA,CAAI,SAAA,CAAU,MAAA,CAAO,IAAA,EAAM,SAAS,CAAA;AAAA,IACnD;AAAA,EACF;AAEA,EAAA,IAAI,OAAA,uBAAc,GAAA,EAAY;AAC9B,EAAA,IAAI,eAAA,GAAkB,WAAW,MAAA,CAAO,cAAA;AACxC,EAAA,IAAI,gBAAA,GAAmB,YAAY,MAAA,CAAO,QAAA;AAQ1C,EAAA,IAAI,gBAAA,GACF,gBAAA,KAAqB,MAAA,CAAO,QAAA,GACxB,MAAA,GACA;AAAA,IACE,GAAG,MAAA;AAAA,IACH,QAAA,EAAU,gBAAA;AAAA,IACV,YAAY,gBAAA,EAAkB;AAAA,GAChC;AAEN,EAAA,eAAe,KAAK,KAAA,EAAoC;AACtD,IAAA,KAAA,IAAS,QAAQ,KAAA,EAAO;AACtB,MAAA,IAAI,CAAC,IAAA,IAAQ,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,EAAE,CAAA,EAAG;AACjC,QAAA;AAAA,MACF;AACA,MAAA,OAAA,CAAQ,GAAA,CAAI,KAAK,EAAE,CAAA;AAEnB,MAAA,IAAI,SAAA,GAAY,YAAA,CAAa,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA;AAC1C,MAAA,IAAI,WAAW,MAAA,EAAQ;AACrB,QAAA,IAAI;AACF,UAAA,IAAA,CAAK,UAAA,GAAa,MAAM,SAAA,CAAU,MAAA,CAAO;AAAA,YACvC,IAAA,EAAM,EAAE,GAAG,sBAAA,CAAuB,UAAU,MAAM,CAAA,EAAG,GAAG,IAAA,CAAK,IAAA,EAAK;AAAA,YAClE,QAAA,EAAU,gBAAA;AAAA,YACV,OAAA,EAAS,eAAA;AAAA,YACT,QAAA,EAAU;AAAA,WACX,CAAA;AAAA,QACH,SAAS,KAAA,EAAO;AACd,UAAA,OAAA,CAAQ,KAAK,gCAAA,EAA6B,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,IAAI,KAAK,CAAA;AAAA,QACrE;AAAA,MACF;AAEA,MAAA,IAAI,WAAW,IAAA,CAAK,QAAA;AACpB,MAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAC3B,QAAA,IAAI,iBAAiB,QAAA,CAAS,MAAA;AAAA,UAC5B;AAAA,SACF;AACA,QAAA,IAAI,eAAe,MAAA,EAAQ;AACzB,UAAA,MAAM,KAAK,cAAc,CAAA;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,KAAK,KAAK,CAAA;AAChB,EAAA,OAAO,IAAA;AACT;;;AC7HA,SAAS,MAAM,KAAA,EAA0B;AACvC,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,GAAW,IAAI,GAAA,CAAI,KAAA,EAAO,kBAAkB,CAAA,GAAI,KAAA;AAC1E;AAEA,SAAS,2BACP,OAAA,EACiB;AACjB,EAAA,IAAI,SAAS,YAAA,EAAc;AACzB,IAAA,OAAO,IAAI,eAAA,CAAgB,OAAA,CAAQ,YAAY,CAAA;AAAA,EACjD;AAEA,EAAA,IAAI,SAAS,GAAA,EAAK;AAChB,IAAA,IAAI,GAAA,GAAM,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAC3B,IAAA,OAAO,IAAI,eAAA,CAAgB,GAAA,CAAI,YAAY,CAAA;AAAA,EAC7C;AAEA,EAAA,OAAO,IAAI,eAAA,EAAgB;AAC7B;AAEA,SAAS,uBAAuB,OAAA,EAA8C;AAC5E,EAAA,IAAI,SAAS,QAAA,EAAU;AACrB,IAAA,OAAO,OAAA,CAAQ,QAAA;AAAA,EACjB;AAEA,EAAA,IAAI,SAAS,GAAA,EAAK;AAChB,IAAA,IAAI,GAAA,GAAM,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAC3B,IAAA,OAAO,IAAI,QAAA,IAAY,GAAA;AAAA,EACzB;AAEA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,iBAAiB,KAAA,EAAiC;AACzD,EAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,UAAU,OAAA,EAAS;AACrB,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,cACP,YAAA,EACkC;AAClC,EAAA,IAAI,UAA4C,EAAC;AACjD,EAAA,KAAA,IAAS,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,YAAA,CAAa,SAAQ,EAAG;AAC/C,IAAA,OAAA,CAAQ,GAAG,CAAA,GAAI,gBAAA,CAAiB,KAAK,CAAA;AAAA,EACvC;AACA,EAAA,OAAO,OAAA;AACT;AAOO,SAAS,6BACd,OAAA,EACyB;AACzB,EAAA,IAAI,YAAA,GAAe,2BAA2B,OAAO,CAAA;AACrD,EAAA,IAAI,MAAA,GAAS,aAAa,QAAA,EAAS;AAEnC,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,uBAAuB,OAAO,CAAA;AAAA,IACxC,MAAA,EAAQ,MAAA,GAAS,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA,GAAK,EAAA;AAAA,IAChC,OAAA,EAAS,cAAc,YAAY,CAAA;AAAA,IACnC,GAAI,SAAS,IAAA,GAAO,EAAE,MAAM,OAAA,CAAQ,IAAA,KAAS;AAAC,GAChD;AACF","file":"chunk-SS6QUKYY.mjs","sourcesContent":["import type { SchemaType } from '@weaverse/schema'\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 | 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\nexport interface RunComponentLoadersArgs {\n client: WeaverseNextClient\n commerce?: WeaverseNextCommerceContext\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\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 = getSearchParamsFromContext(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 }\n}\n"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,163 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Weaverse } from '@weaverse/react';
|
|
2
2
|
export { isBrowser, isIframe, useChildInstances, useItemInstance, useParentInstance, useWeaverse } from '@weaverse/react';
|
|
3
|
-
import { PageType, SchemaType } from '@weaverse/schema';
|
|
4
3
|
export { InspectorGroup, PageType, SchemaType, createSchema } from '@weaverse/schema';
|
|
5
|
-
import
|
|
6
|
-
|
|
4
|
+
import { d as WeaverseNextClientConfig, c as WeaverseNextClient, e as WeaverseNextCommerceContext, q as WeaverseNextRequestContext, n as WeaverseNextLoaderData, r as WeaverseNextRequestInfo, t as WeaverseNextRuntimeInternal, s as WeaverseNextRuntimeConfig, A as WeaverseNextThemeSettingsStore } from './types-DvEeLX6L.mjs';
|
|
5
|
+
export { W as WeaverseCollection, f as WeaverseNextComponent, g as WeaverseNextComponentData, h as WeaverseNextComponentLoaderArgs, i as WeaverseNextComponentProps, l as WeaverseNextI18n, m as WeaverseNextLoadPageInput, o as WeaverseNextPageData, x as WeaverseNextStorefront, B as WeaverseProduct } from './types-DvEeLX6L.mjs';
|
|
7
6
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* Locale/market info passed through to component loaders and the Storefront
|
|
11
|
-
* client. Kept structurally close to Hydrogen's `WeaverseI18n` but without the
|
|
12
|
-
* `@shopify/hydrogen` `I18nBase` dependency so the adapter stays framework
|
|
13
|
-
* neutral.
|
|
14
|
-
*/
|
|
15
|
-
interface WeaverseNextI18n {
|
|
16
|
-
country?: string;
|
|
17
|
-
label?: string;
|
|
18
|
-
language?: string;
|
|
19
|
-
locale?: string;
|
|
20
|
-
pathPrefix?: string;
|
|
21
|
-
[key: string]: unknown;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Minimal Storefront client shape required by component loaders. The host app
|
|
25
|
-
* provides this (public or private token mode); Weaverse never owns it.
|
|
26
|
-
*/
|
|
27
|
-
interface WeaverseNextStorefront {
|
|
28
|
-
i18n?: WeaverseNextI18n;
|
|
29
|
-
query: (query: string, options?: unknown) => Promise<unknown>;
|
|
30
|
-
[key: string]: unknown;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* App-provided commerce context. `storefront` is the only v0 must-have; cart
|
|
34
|
-
* and customer-account stay app-owned and are passed through untouched.
|
|
35
|
-
*/
|
|
36
|
-
interface WeaverseNextCommerceContext {
|
|
37
|
-
cart?: unknown;
|
|
38
|
-
customerAccount?: unknown;
|
|
39
|
-
storefront?: WeaverseNextStorefront;
|
|
40
|
-
[key: string]: unknown;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Explicit, framework-neutral replacement for React Router's
|
|
44
|
-
* `LoaderFunctionArgs`. Built by the Next route/page from params + headers +
|
|
45
|
-
* searchParams instead of an implicit loader context.
|
|
46
|
-
*/
|
|
47
|
-
interface WeaverseNextRequestContext {
|
|
48
|
-
handle?: string;
|
|
49
|
-
headers?: Headers;
|
|
50
|
-
i18n?: WeaverseNextI18n;
|
|
51
|
-
isDesignMode?: boolean;
|
|
52
|
-
isPreviewMode?: boolean;
|
|
53
|
-
isRevisionPreview?: boolean;
|
|
54
|
-
pageType?: PageType;
|
|
55
|
-
pathname?: string;
|
|
56
|
-
searchParams?: URLSearchParams;
|
|
57
|
-
sectionType?: string;
|
|
58
|
-
url?: URL | string;
|
|
59
|
-
[key: string]: unknown;
|
|
60
|
-
}
|
|
61
|
-
/** A single serialized item in a Weaverse page tree. */
|
|
62
|
-
interface WeaverseNextComponentData {
|
|
63
|
-
children?: WeaverseNextComponentData[] | {
|
|
64
|
-
id: string;
|
|
65
|
-
}[];
|
|
66
|
-
data?: Record<string, unknown>;
|
|
67
|
-
id: string;
|
|
68
|
-
/** Attached by {@link runWeaverseComponentLoaders} after a loader runs. */
|
|
69
|
-
loaderData?: unknown;
|
|
70
|
-
type: string;
|
|
71
|
-
[key: string]: unknown;
|
|
72
|
-
}
|
|
73
|
-
/** Serialized page tree fetched from Weaverse. */
|
|
74
|
-
interface WeaverseNextPageData {
|
|
75
|
-
id: string;
|
|
76
|
-
items: WeaverseNextComponentData[];
|
|
77
|
-
name?: string;
|
|
78
|
-
rootId?: string;
|
|
79
|
-
[key: string]: unknown;
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Top-level payload returned by `client.loadPage`. Kept close to Hydrogen's
|
|
83
|
-
* `WeaverseLoaderData` so registered components stay portable.
|
|
84
|
-
*/
|
|
85
|
-
interface WeaverseNextLoaderData {
|
|
86
|
-
configs?: Record<string, unknown>;
|
|
87
|
-
page: WeaverseNextPageData;
|
|
88
|
-
pageAssignment?: Record<string, unknown>;
|
|
89
|
-
project?: Record<string, unknown>;
|
|
90
|
-
[key: string]: unknown;
|
|
91
|
-
}
|
|
92
|
-
/** Props injected into every registered Weaverse component. */
|
|
93
|
-
interface WeaverseNextComponentProps<L = unknown> extends Partial<WeaverseElement> {
|
|
94
|
-
children?: ReactNode;
|
|
95
|
-
className?: string;
|
|
96
|
-
loaderData?: L;
|
|
97
|
-
[key: string]: unknown;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Arguments passed to a component `loader`. `commerce.storefront` is the
|
|
101
|
-
* explicit contract; `weaverse.storefront` exists as a compatibility alias for
|
|
102
|
-
* Pilot-style loaders that call `weaverse.storefront.query(...)`.
|
|
103
|
-
*/
|
|
104
|
-
interface WeaverseNextComponentLoaderArgs<TData = unknown> {
|
|
105
|
-
commerce?: WeaverseNextCommerceContext;
|
|
106
|
-
context?: WeaverseNextRequestContext;
|
|
107
|
-
data: TData;
|
|
108
|
-
weaverse: WeaverseNextClient;
|
|
109
|
-
}
|
|
110
|
-
/** Registered component module shape: `default` + `schema` + optional `loader`. */
|
|
111
|
-
interface WeaverseNextComponent<TProps extends WeaverseNextComponentProps = WeaverseNextComponentProps> {
|
|
112
|
-
default: ComponentType<TProps> | ForwardRefExoticComponent<TProps>;
|
|
113
|
-
loader?: (args: WeaverseNextComponentLoaderArgs) => Promise<unknown>;
|
|
114
|
-
schema: SchemaType;
|
|
115
|
-
}
|
|
116
|
-
/** Input for `client.loadPage`. The Next route maps `params` → `type/handle`. */
|
|
117
|
-
interface WeaverseNextLoadPageInput {
|
|
118
|
-
handle?: string;
|
|
119
|
-
locale?: string;
|
|
120
|
-
type?: PageType;
|
|
121
|
-
[key: string]: unknown;
|
|
122
|
-
}
|
|
123
|
-
interface WeaverseNextClientConfig {
|
|
124
|
-
commerce?: WeaverseNextCommerceContext;
|
|
125
|
-
components: WeaverseNextComponent[];
|
|
126
|
-
/**
|
|
127
|
-
* Injected page fetcher. v0 delegates network I/O to the host app so the
|
|
128
|
-
* adapter can be tested without real Weaverse API calls.
|
|
129
|
-
*/
|
|
130
|
-
fetchPage?: (input: WeaverseNextLoadPageInput) => Promise<WeaverseNextLoaderData | null>;
|
|
131
|
-
/** Injected theme-settings fetcher. */
|
|
132
|
-
fetchThemeSettings?: (context?: WeaverseNextRequestContext) => Promise<unknown>;
|
|
133
|
-
projectId: string;
|
|
134
|
-
requestContext?: WeaverseNextRequestContext;
|
|
135
|
-
themeSchema?: unknown;
|
|
136
|
-
themeSettings?: Record<string, unknown>;
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Request-safe client returned by {@link createWeaverseNextClient}. Holds the
|
|
140
|
-
* registry/config plus the currently loaded page data, and is the object passed
|
|
141
|
-
* to component loaders as `weaverse`.
|
|
142
|
-
*/
|
|
143
|
-
interface WeaverseNextClient {
|
|
144
|
-
commerce?: WeaverseNextCommerceContext;
|
|
145
|
-
components: WeaverseNextComponent[];
|
|
146
|
-
/** Currently loaded page payload (set by `loadPage`). */
|
|
147
|
-
data: WeaverseNextLoaderData | null;
|
|
148
|
-
/** Data-connector context handed to the React renderer. */
|
|
149
|
-
dataContext: Record<string, unknown>;
|
|
150
|
-
loadPage: (input?: WeaverseNextLoadPageInput) => Promise<WeaverseNextLoaderData | null>;
|
|
151
|
-
loadThemeSettings: (context?: WeaverseNextRequestContext) => Promise<unknown>;
|
|
152
|
-
projectId: string;
|
|
153
|
-
requestContext?: WeaverseNextRequestContext;
|
|
154
|
-
/** Compatibility alias for `commerce.storefront`. */
|
|
155
|
-
storefront?: WeaverseNextStorefront;
|
|
156
|
-
themeSchema?: unknown;
|
|
157
|
-
themeSettings: Record<string, unknown>;
|
|
158
|
-
}
|
|
159
|
-
type WeaverseProduct = WeaverseResourcePickerData;
|
|
160
|
-
type WeaverseCollection = WeaverseResourcePickerData;
|
|
7
|
+
import * as react from 'react';
|
|
8
|
+
import { ReactNode } from 'react';
|
|
161
9
|
|
|
162
10
|
/**
|
|
163
11
|
* Create a {@link WeaverseNextClient} from explicit config.
|
|
@@ -187,8 +35,9 @@ declare function useWeaversePageData<T = unknown>(): T;
|
|
|
187
35
|
/** Read the app-provided commerce context (storefront/cart/customer). */
|
|
188
36
|
declare function useWeaverseCommerce<T = WeaverseNextCommerceContext>(): T;
|
|
189
37
|
/**
|
|
190
|
-
* Read Weaverse theme settings.
|
|
191
|
-
*
|
|
38
|
+
* Read live Weaverse theme settings. The Studio bridge updates the provider's
|
|
39
|
+
* external store via `updateThemeSettings`, so components re-render during live
|
|
40
|
+
* design-mode edits.
|
|
192
41
|
*/
|
|
193
42
|
declare function useThemeSettings<T = Record<string, unknown>>(): T;
|
|
194
43
|
|
|
@@ -262,4 +111,140 @@ interface WeaverseNextRendererProps {
|
|
|
262
111
|
*/
|
|
263
112
|
declare const WeaverseNextRenderer: react.MemoExoticComponent<(props: WeaverseNextRendererProps) => react_jsx_runtime.JSX.Element | null>;
|
|
264
113
|
|
|
265
|
-
|
|
114
|
+
/**
|
|
115
|
+
* Build the Hydrogen-like request info shape consumed by the Studio bridge.
|
|
116
|
+
* Duplicate query keys keep the last value, matching `URLSearchParams` iteration
|
|
117
|
+
* assignment and Hydrogen's practical query-object behavior.
|
|
118
|
+
*/
|
|
119
|
+
declare function buildWeaverseNextRequestInfo(context?: WeaverseNextRequestContext): WeaverseNextRequestInfo;
|
|
120
|
+
|
|
121
|
+
declare global {
|
|
122
|
+
interface Window {
|
|
123
|
+
__weaverse?: WeaverseNextRuntime;
|
|
124
|
+
__weaverses?: Record<string, WeaverseNextRuntime>;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
declare class WeaverseNextRuntime extends Weaverse {
|
|
128
|
+
pageId: string;
|
|
129
|
+
internal: WeaverseNextRuntimeInternal;
|
|
130
|
+
requestInfo: WeaverseNextRequestInfo;
|
|
131
|
+
isPreviewMode: boolean;
|
|
132
|
+
isRevisionPreview: boolean;
|
|
133
|
+
sectionType?: string;
|
|
134
|
+
translationMap: Record<string, unknown>;
|
|
135
|
+
translationLocale: string;
|
|
136
|
+
translationLanguageId: string;
|
|
137
|
+
constructor(config: WeaverseNextRuntimeConfig);
|
|
138
|
+
extractTranslationSidecar: () => undefined;
|
|
139
|
+
setTranslationSidecar: (map?: Record<string, unknown>, locale?: string, languageId?: string) => void;
|
|
140
|
+
updateTranslation: () => undefined;
|
|
141
|
+
getTranslationChanges: () => undefined;
|
|
142
|
+
}
|
|
143
|
+
declare function createWeaverseNextRuntime(config: WeaverseNextRuntimeConfig): WeaverseNextRuntime;
|
|
144
|
+
declare function bindWeaverseNextStudioRuntime(runtime: WeaverseNextRuntime): boolean;
|
|
145
|
+
|
|
146
|
+
interface WeaverseNextStudioBridgeProps {
|
|
147
|
+
navigate?: WeaverseNextRuntimeInternal['navigate'];
|
|
148
|
+
revalidate?: WeaverseNextRuntimeInternal['revalidate'];
|
|
149
|
+
runtime: WeaverseNextRuntime;
|
|
150
|
+
}
|
|
151
|
+
/** Page-level Studio runtime binder. */
|
|
152
|
+
declare function WeaverseNextStudioBridge(props: WeaverseNextStudioBridgeProps): null;
|
|
153
|
+
|
|
154
|
+
interface WeaverseNextStudioConnectProps {
|
|
155
|
+
context?: WeaverseNextRequestContext;
|
|
156
|
+
storefrontHostname?: string;
|
|
157
|
+
}
|
|
158
|
+
/** Root-level Studio script connector for Next client boundaries. */
|
|
159
|
+
declare function WeaverseNextStudioConnect(props: WeaverseNextStudioConnectProps): null;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Minimal structural shape of the Next App Router returned by `useRouter()`
|
|
163
|
+
* (`next/navigation`) that the Studio bridge needs. Declared locally — rather
|
|
164
|
+
* than importing `AppRouterInstance` from `next` — so the adapter stays a pure
|
|
165
|
+
* function that unit tests can drive with a plain mock and never pulls
|
|
166
|
+
* `next/navigation` into the test graph.
|
|
167
|
+
*/
|
|
168
|
+
interface WeaverseNextRouterLike {
|
|
169
|
+
push: (href: string, options?: {
|
|
170
|
+
scroll?: boolean;
|
|
171
|
+
}) => void;
|
|
172
|
+
refresh: () => void;
|
|
173
|
+
replace: (href: string, options?: {
|
|
174
|
+
scroll?: boolean;
|
|
175
|
+
}) => void;
|
|
176
|
+
}
|
|
177
|
+
/** Resolved Studio navigation/revalidation callbacks for a Next runtime. */
|
|
178
|
+
interface WeaverseNextStudioInternals {
|
|
179
|
+
navigate: NonNullable<WeaverseNextRuntimeInternal['navigate']>;
|
|
180
|
+
revalidate: NonNullable<WeaverseNextRuntimeInternal['revalidate']>;
|
|
181
|
+
}
|
|
182
|
+
interface CreateWeaverseNextStudioInternalsOptions {
|
|
183
|
+
/** Use `router.replace` instead of `router.push` for navigation. */
|
|
184
|
+
replace?: boolean;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Build Studio `navigate` / `revalidate` callbacks from a Next App Router.
|
|
188
|
+
*
|
|
189
|
+
* Maps Hydrogen's React Router semantics onto Next App Router:
|
|
190
|
+
* - `navigate(to, { preventScrollReset })` → `router.push(to, { scroll })`,
|
|
191
|
+
* where `scroll` is the inverse of `preventScrollReset`. Studio passes
|
|
192
|
+
* `preventScrollReset` for in-place edits so the preview viewport is kept,
|
|
193
|
+
* matching React Router's `navigate({ preventScrollReset })`.
|
|
194
|
+
* - `revalidate()` → `router.refresh()`, the App Router's loader-backed refresh
|
|
195
|
+
* and the closest equivalent to React Router's `useRevalidator`.
|
|
196
|
+
*
|
|
197
|
+
* Pure (no React, no `next/navigation`) so it is unit-testable with a mock
|
|
198
|
+
* router; the {@link WeaverseNextRouterLike} contract is the only coupling.
|
|
199
|
+
*/
|
|
200
|
+
declare function createWeaverseNextStudioInternals(router: WeaverseNextRouterLike, options?: CreateWeaverseNextStudioInternalsOptions): WeaverseNextStudioInternals;
|
|
201
|
+
|
|
202
|
+
interface ResolveWeaverseNextStudioScriptSrcOptions {
|
|
203
|
+
framework?: 'hydrogen' | 'next';
|
|
204
|
+
storefrontHostname?: string;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Resolve the Studio script URL from request/search context. v0 intentionally
|
|
208
|
+
* reuses the existing structural Hydrogen bridge script until a concrete Builder
|
|
209
|
+
* incompatibility requires a dedicated Next bundle.
|
|
210
|
+
*/
|
|
211
|
+
declare function resolveWeaverseNextStudioScriptSrc(context?: WeaverseNextRequestContext, options?: ResolveWeaverseNextStudioScriptSrcOptions): string | null;
|
|
212
|
+
|
|
213
|
+
interface CreateWeaverseNextThemeSettingsStoreOptions {
|
|
214
|
+
publicEnv?: Record<string, string | undefined>;
|
|
215
|
+
schema?: unknown;
|
|
216
|
+
settings?: Record<string, unknown>;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Small external store shape compatible with the Studio bridge and React's
|
|
220
|
+
* `useSyncExternalStore` contract. The bridge calls `updateThemeSettings` during
|
|
221
|
+
* live theme edits, so keep that method name stable.
|
|
222
|
+
*/
|
|
223
|
+
declare function createWeaverseNextThemeSettingsStore(options?: CreateWeaverseNextThemeSettingsStoreOptions): WeaverseNextThemeSettingsStore;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Resolve stable Studio `navigate` / `revalidate` callbacks from the Next App
|
|
227
|
+
* Router. `useRouter()` is stable across renders, but the derived callbacks are
|
|
228
|
+
* cached in a ref keyed on the router instance so the bridge's bind effect
|
|
229
|
+
* (which depends on `navigate` / `revalidate` identity) doesn't re-run — and
|
|
230
|
+
* re-`refreshStudio` — on every render.
|
|
231
|
+
*/
|
|
232
|
+
declare function useWeaverseNextStudioInternals(options?: CreateWeaverseNextStudioInternalsOptions): WeaverseNextStudioInternals;
|
|
233
|
+
interface WeaverseNextStudioProps extends CreateWeaverseNextStudioInternalsOptions {
|
|
234
|
+
runtime: WeaverseNextRuntime;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Page-level Studio binder wired to the Next App Router. Mirrors Hydrogen's
|
|
238
|
+
* `useStudio` (which binds the runtime and feeds it React Router's `navigate` /
|
|
239
|
+
* `revalidate`): it resolves the App Router callbacks via
|
|
240
|
+
* {@link useWeaverseNextStudioInternals} and hands them to
|
|
241
|
+
* {@link WeaverseNextStudioBridge}, so consuming apps get Studio navigation and
|
|
242
|
+
* revalidation without manually wiring `next/navigation`.
|
|
243
|
+
*
|
|
244
|
+
* Client-only — it is the single place `@weaverse/next` touches
|
|
245
|
+
* `next/navigation`, keeping the runtime/renderer and `@weaverse/next/server`
|
|
246
|
+
* free of router imports.
|
|
247
|
+
*/
|
|
248
|
+
declare function WeaverseNextStudio(props: WeaverseNextStudioProps): react_jsx_runtime.JSX.Element;
|
|
249
|
+
|
|
250
|
+
export { type CreateWeaverseNextStudioInternalsOptions, type CreateWeaverseNextThemeSettingsStoreOptions, type ResolveWeaverseNextStudioScriptSrcOptions, type RunComponentLoadersArgs, WeaverseNextClient, WeaverseNextClientConfig, WeaverseNextCommerceContext, WeaverseNextLoaderData, WeaverseNextProvider, type WeaverseNextProviderProps, WeaverseNextRenderer, type WeaverseNextRendererProps, WeaverseNextRequestContext, WeaverseNextRequestInfo, type WeaverseNextRouterLike, WeaverseNextRuntime, WeaverseNextRuntimeConfig, WeaverseNextRuntimeInternal, WeaverseNextStudio, WeaverseNextStudioBridge, type WeaverseNextStudioBridgeProps, WeaverseNextStudioConnect, type WeaverseNextStudioConnectProps, type WeaverseNextStudioInternals, type WeaverseNextStudioProps, WeaverseNextThemeSettingsStore, bindWeaverseNextStudioRuntime, buildWeaverseNextRequestInfo, createWeaverseNextClient, createWeaverseNextRuntime, createWeaverseNextStudioInternals, createWeaverseNextThemeSettingsStore, resolveWeaverseNextStudioScriptSrc, runWeaverseComponentLoaders, useThemeSettings, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData };
|