@weaverse/next 0.1.0-alpha.4 → 0.1.0-alpha.6

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.
@@ -158,6 +158,62 @@ function buildWeaverseNextRequestInfo(context) {
158
158
  };
159
159
  }
160
160
 
161
- export { buildWeaverseNextRequestInfo, generateDataFromSchema, runWeaverseComponentLoaders };
162
- //# sourceMappingURL=chunk-O2TG2NYL.mjs.map
163
- //# sourceMappingURL=chunk-O2TG2NYL.mjs.map
161
+ // src/seo.ts
162
+ function hasOpenGraphContent(seo) {
163
+ return Boolean(seo?.title || seo?.description || seo?.image || seo?.type);
164
+ }
165
+ function hasTwitterContent(seo) {
166
+ return Boolean(seo?.title || seo?.description || seo?.image || seo?.cardType);
167
+ }
168
+ function formatWeaverseNextSeoMetadata(seo) {
169
+ let index = seo?.robots?.index !== false;
170
+ let follow = seo?.robots?.follow !== false;
171
+ let metadata = {
172
+ robots: { index, follow }
173
+ };
174
+ if (!seo) {
175
+ return metadata;
176
+ }
177
+ if (seo.title) {
178
+ metadata.title = seo.title;
179
+ }
180
+ if (seo.description) {
181
+ metadata.description = seo.description;
182
+ }
183
+ if (seo.keywords) {
184
+ metadata.keywords = seo.keywords;
185
+ }
186
+ if (seo.canonicalUrl) {
187
+ metadata.alternates = { canonical: seo.canonicalUrl };
188
+ }
189
+ let openGraph = seo.openGraph;
190
+ if (hasOpenGraphContent(openGraph)) {
191
+ metadata.openGraph = {
192
+ title: openGraph?.title,
193
+ description: openGraph?.description,
194
+ images: openGraph?.image ? [openGraph.image] : void 0,
195
+ type: openGraph?.type || "website"
196
+ };
197
+ }
198
+ let twitter = seo.twitter;
199
+ if (hasTwitterContent(twitter)) {
200
+ metadata.twitter = {
201
+ card: twitter?.cardType || "summary",
202
+ title: twitter?.title,
203
+ description: twitter?.description,
204
+ images: twitter?.image ? [twitter.image] : void 0
205
+ };
206
+ }
207
+ return metadata;
208
+ }
209
+ function getWeaverseNextSeoMetadata(data) {
210
+ if (!data) {
211
+ return formatWeaverseNextSeoMetadata(null);
212
+ }
213
+ let page = "items" in data && "id" in data ? data : data.page ?? null;
214
+ return formatWeaverseNextSeoMetadata(page?.seo ?? null);
215
+ }
216
+
217
+ export { buildWeaverseNextRequestInfo, formatWeaverseNextSeoMetadata, generateDataFromSchema, getWeaverseNextSeoMetadata, runWeaverseComponentLoaders };
218
+ //# sourceMappingURL=chunk-6PMZ77RA.mjs.map
219
+ //# sourceMappingURL=chunk-6PMZ77RA.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.ts","../src/loader.ts","../src/request-info.ts","../src/seo.ts"],"names":[],"mappings":"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","file":"chunk-6PMZ77RA.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\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 }\n}\n","import type { PageSEOData } from '@weaverse/schema'\nimport type { WeaverseNextLoaderData, WeaverseNextPageData } from './types'\n\nexport interface WeaverseNextSeoMetadata {\n alternates?: { canonical?: string }\n description?: string\n keywords?: string\n openGraph?: {\n description?: string\n images?: string[]\n title?: string\n type?: string\n }\n robots: {\n follow: boolean\n index: boolean\n }\n title?: string\n twitter?: {\n card?: string\n description?: string\n images?: string[]\n title?: string\n }\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\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: openGraph?.type || 'website',\n }\n }\n\n let twitter = seo.twitter\n if (hasTwitterContent(twitter)) {\n metadata.twitter = {\n card: twitter?.cardType || 'summary',\n title: twitter?.title,\n description: twitter?.description,\n images: twitter?.image ? [twitter.image] : undefined,\n }\n }\n\n return metadata\n}\n\nexport function getWeaverseNextSeoMetadata(\n data:\n | WeaverseNextLoaderData\n | WeaverseNextPageData\n | { page?: WeaverseNextPageData | null }\n | null\n | undefined\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 { page?: WeaverseNextPageData | null }).page ?? null)\n return formatWeaverseNextSeoMetadata(page?.seo ?? null)\n}\n"]}
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Weaverse } from '@weaverse/react';
2
2
  export { isBrowser, isIframe, useChildInstances, useItemInstance, useParentInstance, useWeaverse } from '@weaverse/react';
3
3
  export { InspectorGroup, PageType, SchemaType, createSchema } from '@weaverse/schema';
4
- import { d as WeaverseNextClientConfig, c as WeaverseNextClient, e as WeaverseNextCommerceContext, q as WeaverseNextRequestContext, n as WeaverseNextLoaderData, r as WeaverseNextRequestInfo, g as WeaverseNextComponentData, t as WeaverseNextRuntimeInternal, s as WeaverseNextRuntimeConfig, A as WeaverseNextThemeSettingsStore } from './types-DvwaU20C.mjs';
5
- export { W as WeaverseCollection, f as WeaverseNextComponent, h as WeaverseNextComponentLoaderArgs, i as WeaverseNextComponentProps, l as WeaverseNextI18n, m as WeaverseNextLoadPageInput, o as WeaverseNextPageData, x as WeaverseNextStorefront, B as WeaverseProduct } from './types-DvwaU20C.mjs';
4
+ import { g as WeaverseNextClientConfig, f as WeaverseNextClient, h as WeaverseNextCommerceContext, v as WeaverseNextRequestContext, s as WeaverseNextLoaderData, w as WeaverseNextRequestInfo, j as WeaverseNextComponentData, G as WeaverseNextThemeSettingsStore, y as WeaverseNextRuntimeInternal, x as WeaverseNextRuntimeConfig } from './seo-kwaliD-K.mjs';
5
+ export { W as WeaverseArticle, a as WeaverseBlog, b as WeaverseCollection, c as WeaverseMetaObject, i as WeaverseNextComponent, k as WeaverseNextComponentLoaderArgs, l as WeaverseNextComponentProps, n as WeaverseNextCustomPageEntry, o as WeaverseNextFetchCustomPagesOptions, q as WeaverseNextI18n, r as WeaverseNextLoadPageInput, t as WeaverseNextPageData, z as WeaverseNextSeoMetadata, D as WeaverseNextStorefront, H as WeaverseProduct, I as formatWeaverseNextSeoMetadata, J as getWeaverseNextSeoMetadata } from './seo-kwaliD-K.mjs';
6
6
  import * as react_jsx_runtime from 'react/jsx-runtime';
7
7
  import * as react from 'react';
8
8
  import { ReactNode } from 'react';
@@ -143,6 +143,37 @@ interface RevalidateItemRuntimeLike {
143
143
  */
144
144
  declare function revalidateWeaverseNextItem(runtime: RevalidateItemRuntimeLike, draftItem: WeaverseNextComponentData, endpoint?: string): Promise<void>;
145
145
 
146
+ interface WeaverseNextRootContextValue {
147
+ themeSettingsStore: WeaverseNextThemeSettingsStore;
148
+ }
149
+ interface WeaverseNextRootProviderProps {
150
+ children: ReactNode;
151
+ /** Root-loaded theme settings (published-mode fetch, no design-mode context). */
152
+ initialThemeSettings?: Record<string, unknown>;
153
+ publicEnv?: Record<string, string | undefined>;
154
+ themeSchema?: unknown;
155
+ }
156
+ /**
157
+ * Root-scoped client boundary that owns the single `WeaverseNextThemeSettingsStore`
158
+ * for the whole app session, matching Hydrogen's `withWeaverse()` root store.
159
+ * Mount once in `app/layout.tsx`, above `Header`/`Footer`/global modules and any
160
+ * route-level `WeaverseNextProvider`.
161
+ *
162
+ * Also renders `WeaverseNextContext` with a minimal value so `useThemeSettings()`
163
+ * works for components mounted directly under this provider, even without a
164
+ * route-level `WeaverseNextProvider` above them.
165
+ *
166
+ * @example
167
+ * ```tsx
168
+ * <WeaverseNextRootProvider initialThemeSettings={theme.theme} themeSchema={theme.schema}>
169
+ * <Header />
170
+ * {children}
171
+ * <Footer />
172
+ * </WeaverseNextRootProvider>
173
+ * ```
174
+ */
175
+ declare function WeaverseNextRootProvider(props: WeaverseNextRootProviderProps): react_jsx_runtime.JSX.Element;
176
+
146
177
  declare global {
147
178
  interface Window {
148
179
  __weaverse?: WeaverseNextRuntime;
@@ -177,11 +208,25 @@ interface WeaverseNextStudioBridgeProps {
177
208
  /** Page-level Studio runtime binder. */
178
209
  declare function WeaverseNextStudioBridge(props: WeaverseNextStudioBridgeProps): null;
179
210
 
211
+ interface LoadWeaverseNextStudioScriptOptions {
212
+ storefrontHostname?: string;
213
+ }
214
+ /**
215
+ * Resolve and append the Next Studio bridge script for the given request
216
+ * context, deduping by src. SSR-safe (no-op without `document`) so it can run
217
+ * unconditionally from a root layout/error boundary before any page tree or
218
+ * runtime exists — e.g. App Router `not-found.tsx` / `error.tsx` routes.
219
+ */
220
+ declare function loadWeaverseNextStudioScript(context?: WeaverseNextRequestContext, options?: LoadWeaverseNextStudioScriptOptions): void;
180
221
  interface WeaverseNextStudioConnectProps {
181
222
  context?: WeaverseNextRequestContext;
182
223
  storefrontHostname?: string;
183
224
  }
184
- /** Root-level Studio script connector for Next client boundaries. */
225
+ /**
226
+ * Root-level Studio script connector for Next client boundaries. Mount once
227
+ * near the app root (e.g. root layout) so it also covers routes that never
228
+ * render `WeaverseNextRenderer`, such as `not-found.tsx` / `error.tsx`.
229
+ */
185
230
  declare function WeaverseNextStudioConnect(props: WeaverseNextStudioConnectProps): null;
186
231
 
187
232
  /**
@@ -226,13 +271,11 @@ interface CreateWeaverseNextStudioInternalsOptions {
226
271
  declare function createWeaverseNextStudioInternals(router: WeaverseNextRouterLike, options?: CreateWeaverseNextStudioInternalsOptions): WeaverseNextStudioInternals;
227
272
 
228
273
  interface ResolveWeaverseNextStudioScriptSrcOptions {
229
- framework?: 'hydrogen' | 'next';
230
274
  storefrontHostname?: string;
231
275
  }
232
276
  /**
233
- * Resolve the Studio script URL from request/search context. v0 intentionally
234
- * reuses the existing structural Hydrogen bridge script until a concrete Builder
235
- * incompatibility requires a dedicated Next bundle.
277
+ * Resolve the Studio script URL from request/search context. `@weaverse/next`
278
+ * uses the dedicated Next bridge path served by Builder.
236
279
  */
237
280
  declare function resolveWeaverseNextStudioScriptSrc(context?: WeaverseNextRequestContext, options?: ResolveWeaverseNextStudioScriptSrcOptions): string | null;
238
281
 
@@ -278,4 +321,4 @@ interface WeaverseNextStudioProps extends CreateWeaverseNextStudioInternalsOptio
278
321
  */
279
322
  declare function WeaverseNextStudio(props: WeaverseNextStudioProps): react_jsx_runtime.JSX.Element;
280
323
 
281
- export { type CreateWeaverseNextStudioInternalsOptions, type CreateWeaverseNextThemeSettingsStoreOptions, DEFAULT_REVALIDATE_ENDPOINT, type ResolveWeaverseNextStudioScriptSrcOptions, type RevalidateItemRuntimeLike, type RunComponentLoadersArgs, WeaverseNextClient, WeaverseNextClientConfig, WeaverseNextCommerceContext, WeaverseNextComponentData, 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, revalidateWeaverseNextItem, runWeaverseComponentLoaders, useThemeSettings, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData };
324
+ export { type CreateWeaverseNextStudioInternalsOptions, type CreateWeaverseNextThemeSettingsStoreOptions, DEFAULT_REVALIDATE_ENDPOINT, type LoadWeaverseNextStudioScriptOptions, type ResolveWeaverseNextStudioScriptSrcOptions, type RevalidateItemRuntimeLike, type RunComponentLoadersArgs, WeaverseNextClient, WeaverseNextClientConfig, WeaverseNextCommerceContext, WeaverseNextComponentData, WeaverseNextLoaderData, WeaverseNextProvider, type WeaverseNextProviderProps, WeaverseNextRenderer, type WeaverseNextRendererProps, WeaverseNextRequestContext, WeaverseNextRequestInfo, type WeaverseNextRootContextValue, WeaverseNextRootProvider, type WeaverseNextRootProviderProps, type WeaverseNextRouterLike, WeaverseNextRuntime, WeaverseNextRuntimeConfig, WeaverseNextRuntimeInternal, WeaverseNextStudio, WeaverseNextStudioBridge, type WeaverseNextStudioBridgeProps, WeaverseNextStudioConnect, type WeaverseNextStudioConnectProps, type WeaverseNextStudioInternals, type WeaverseNextStudioProps, WeaverseNextThemeSettingsStore, bindWeaverseNextStudioRuntime, buildWeaverseNextRequestInfo, createWeaverseNextClient, createWeaverseNextRuntime, createWeaverseNextStudioInternals, createWeaverseNextThemeSettingsStore, loadWeaverseNextStudioScript, resolveWeaverseNextStudioScriptSrc, revalidateWeaverseNextItem, runWeaverseComponentLoaders, useThemeSettings, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Weaverse } from '@weaverse/react';
2
2
  export { isBrowser, isIframe, useChildInstances, useItemInstance, useParentInstance, useWeaverse } from '@weaverse/react';
3
3
  export { InspectorGroup, PageType, SchemaType, createSchema } from '@weaverse/schema';
4
- import { d as WeaverseNextClientConfig, c as WeaverseNextClient, e as WeaverseNextCommerceContext, q as WeaverseNextRequestContext, n as WeaverseNextLoaderData, r as WeaverseNextRequestInfo, g as WeaverseNextComponentData, t as WeaverseNextRuntimeInternal, s as WeaverseNextRuntimeConfig, A as WeaverseNextThemeSettingsStore } from './types-DvwaU20C.js';
5
- export { W as WeaverseCollection, f as WeaverseNextComponent, h as WeaverseNextComponentLoaderArgs, i as WeaverseNextComponentProps, l as WeaverseNextI18n, m as WeaverseNextLoadPageInput, o as WeaverseNextPageData, x as WeaverseNextStorefront, B as WeaverseProduct } from './types-DvwaU20C.js';
4
+ import { g as WeaverseNextClientConfig, f as WeaverseNextClient, h as WeaverseNextCommerceContext, v as WeaverseNextRequestContext, s as WeaverseNextLoaderData, w as WeaverseNextRequestInfo, j as WeaverseNextComponentData, G as WeaverseNextThemeSettingsStore, y as WeaverseNextRuntimeInternal, x as WeaverseNextRuntimeConfig } from './seo-kwaliD-K.js';
5
+ export { W as WeaverseArticle, a as WeaverseBlog, b as WeaverseCollection, c as WeaverseMetaObject, i as WeaverseNextComponent, k as WeaverseNextComponentLoaderArgs, l as WeaverseNextComponentProps, n as WeaverseNextCustomPageEntry, o as WeaverseNextFetchCustomPagesOptions, q as WeaverseNextI18n, r as WeaverseNextLoadPageInput, t as WeaverseNextPageData, z as WeaverseNextSeoMetadata, D as WeaverseNextStorefront, H as WeaverseProduct, I as formatWeaverseNextSeoMetadata, J as getWeaverseNextSeoMetadata } from './seo-kwaliD-K.js';
6
6
  import * as react_jsx_runtime from 'react/jsx-runtime';
7
7
  import * as react from 'react';
8
8
  import { ReactNode } from 'react';
@@ -143,6 +143,37 @@ interface RevalidateItemRuntimeLike {
143
143
  */
144
144
  declare function revalidateWeaverseNextItem(runtime: RevalidateItemRuntimeLike, draftItem: WeaverseNextComponentData, endpoint?: string): Promise<void>;
145
145
 
146
+ interface WeaverseNextRootContextValue {
147
+ themeSettingsStore: WeaverseNextThemeSettingsStore;
148
+ }
149
+ interface WeaverseNextRootProviderProps {
150
+ children: ReactNode;
151
+ /** Root-loaded theme settings (published-mode fetch, no design-mode context). */
152
+ initialThemeSettings?: Record<string, unknown>;
153
+ publicEnv?: Record<string, string | undefined>;
154
+ themeSchema?: unknown;
155
+ }
156
+ /**
157
+ * Root-scoped client boundary that owns the single `WeaverseNextThemeSettingsStore`
158
+ * for the whole app session, matching Hydrogen's `withWeaverse()` root store.
159
+ * Mount once in `app/layout.tsx`, above `Header`/`Footer`/global modules and any
160
+ * route-level `WeaverseNextProvider`.
161
+ *
162
+ * Also renders `WeaverseNextContext` with a minimal value so `useThemeSettings()`
163
+ * works for components mounted directly under this provider, even without a
164
+ * route-level `WeaverseNextProvider` above them.
165
+ *
166
+ * @example
167
+ * ```tsx
168
+ * <WeaverseNextRootProvider initialThemeSettings={theme.theme} themeSchema={theme.schema}>
169
+ * <Header />
170
+ * {children}
171
+ * <Footer />
172
+ * </WeaverseNextRootProvider>
173
+ * ```
174
+ */
175
+ declare function WeaverseNextRootProvider(props: WeaverseNextRootProviderProps): react_jsx_runtime.JSX.Element;
176
+
146
177
  declare global {
147
178
  interface Window {
148
179
  __weaverse?: WeaverseNextRuntime;
@@ -177,11 +208,25 @@ interface WeaverseNextStudioBridgeProps {
177
208
  /** Page-level Studio runtime binder. */
178
209
  declare function WeaverseNextStudioBridge(props: WeaverseNextStudioBridgeProps): null;
179
210
 
211
+ interface LoadWeaverseNextStudioScriptOptions {
212
+ storefrontHostname?: string;
213
+ }
214
+ /**
215
+ * Resolve and append the Next Studio bridge script for the given request
216
+ * context, deduping by src. SSR-safe (no-op without `document`) so it can run
217
+ * unconditionally from a root layout/error boundary before any page tree or
218
+ * runtime exists — e.g. App Router `not-found.tsx` / `error.tsx` routes.
219
+ */
220
+ declare function loadWeaverseNextStudioScript(context?: WeaverseNextRequestContext, options?: LoadWeaverseNextStudioScriptOptions): void;
180
221
  interface WeaverseNextStudioConnectProps {
181
222
  context?: WeaverseNextRequestContext;
182
223
  storefrontHostname?: string;
183
224
  }
184
- /** Root-level Studio script connector for Next client boundaries. */
225
+ /**
226
+ * Root-level Studio script connector for Next client boundaries. Mount once
227
+ * near the app root (e.g. root layout) so it also covers routes that never
228
+ * render `WeaverseNextRenderer`, such as `not-found.tsx` / `error.tsx`.
229
+ */
185
230
  declare function WeaverseNextStudioConnect(props: WeaverseNextStudioConnectProps): null;
186
231
 
187
232
  /**
@@ -226,13 +271,11 @@ interface CreateWeaverseNextStudioInternalsOptions {
226
271
  declare function createWeaverseNextStudioInternals(router: WeaverseNextRouterLike, options?: CreateWeaverseNextStudioInternalsOptions): WeaverseNextStudioInternals;
227
272
 
228
273
  interface ResolveWeaverseNextStudioScriptSrcOptions {
229
- framework?: 'hydrogen' | 'next';
230
274
  storefrontHostname?: string;
231
275
  }
232
276
  /**
233
- * Resolve the Studio script URL from request/search context. v0 intentionally
234
- * reuses the existing structural Hydrogen bridge script until a concrete Builder
235
- * incompatibility requires a dedicated Next bundle.
277
+ * Resolve the Studio script URL from request/search context. `@weaverse/next`
278
+ * uses the dedicated Next bridge path served by Builder.
236
279
  */
237
280
  declare function resolveWeaverseNextStudioScriptSrc(context?: WeaverseNextRequestContext, options?: ResolveWeaverseNextStudioScriptSrcOptions): string | null;
238
281
 
@@ -278,4 +321,4 @@ interface WeaverseNextStudioProps extends CreateWeaverseNextStudioInternalsOptio
278
321
  */
279
322
  declare function WeaverseNextStudio(props: WeaverseNextStudioProps): react_jsx_runtime.JSX.Element;
280
323
 
281
- export { type CreateWeaverseNextStudioInternalsOptions, type CreateWeaverseNextThemeSettingsStoreOptions, DEFAULT_REVALIDATE_ENDPOINT, type ResolveWeaverseNextStudioScriptSrcOptions, type RevalidateItemRuntimeLike, type RunComponentLoadersArgs, WeaverseNextClient, WeaverseNextClientConfig, WeaverseNextCommerceContext, WeaverseNextComponentData, 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, revalidateWeaverseNextItem, runWeaverseComponentLoaders, useThemeSettings, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData };
324
+ export { type CreateWeaverseNextStudioInternalsOptions, type CreateWeaverseNextThemeSettingsStoreOptions, DEFAULT_REVALIDATE_ENDPOINT, type LoadWeaverseNextStudioScriptOptions, type ResolveWeaverseNextStudioScriptSrcOptions, type RevalidateItemRuntimeLike, type RunComponentLoadersArgs, WeaverseNextClient, WeaverseNextClientConfig, WeaverseNextCommerceContext, WeaverseNextComponentData, WeaverseNextLoaderData, WeaverseNextProvider, type WeaverseNextProviderProps, WeaverseNextRenderer, type WeaverseNextRendererProps, WeaverseNextRequestContext, WeaverseNextRequestInfo, type WeaverseNextRootContextValue, WeaverseNextRootProvider, type WeaverseNextRootProviderProps, type WeaverseNextRouterLike, WeaverseNextRuntime, WeaverseNextRuntimeConfig, WeaverseNextRuntimeInternal, WeaverseNextStudio, WeaverseNextStudioBridge, type WeaverseNextStudioBridgeProps, WeaverseNextStudioConnect, type WeaverseNextStudioConnectProps, type WeaverseNextStudioInternals, type WeaverseNextStudioProps, WeaverseNextThemeSettingsStore, bindWeaverseNextStudioRuntime, buildWeaverseNextRequestInfo, createWeaverseNextClient, createWeaverseNextRuntime, createWeaverseNextStudioInternals, createWeaverseNextThemeSettingsStore, loadWeaverseNextStudioScript, resolveWeaverseNextStudioScriptSrc, revalidateWeaverseNextItem, runWeaverseComponentLoaders, useThemeSettings, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData };
package/dist/index.js CHANGED
@@ -158,18 +158,61 @@ function createWeaverseNextThemeSettingsStore(options = {}) {
158
158
  };
159
159
  return store;
160
160
  }
161
+ var WeaverseNextRootContext = react$1.createContext(null);
162
+ function WeaverseNextRootProvider(props) {
163
+ let { children, initialThemeSettings, themeSchema, publicEnv } = props;
164
+ let storeRef = react$1.useRef(null);
165
+ if (!storeRef.current) {
166
+ storeRef.current = createWeaverseNextThemeSettingsStore({
167
+ publicEnv,
168
+ schema: themeSchema,
169
+ settings: initialThemeSettings
170
+ });
171
+ }
172
+ let themeSettingsStore = storeRef.current;
173
+ let appliedThemeSettingsRef = react$1.useRef(initialThemeSettings);
174
+ react$1.useEffect(() => {
175
+ if (initialThemeSettings && appliedThemeSettingsRef.current !== initialThemeSettings) {
176
+ themeSettingsStore.updateThemeSettings(initialThemeSettings);
177
+ appliedThemeSettingsRef.current = initialThemeSettings;
178
+ }
179
+ }, [initialThemeSettings, themeSettingsStore]);
180
+ let rootContextValue = react$1.useMemo(
181
+ () => ({ themeSettingsStore }),
182
+ [themeSettingsStore]
183
+ );
184
+ let contextValue = react$1.useMemo(
185
+ () => ({
186
+ themeSettings: themeSettingsStore.getSnapshot(),
187
+ themeSettingsStore
188
+ }),
189
+ [themeSettingsStore]
190
+ );
191
+ return /* @__PURE__ */ jsxRuntime.jsx(WeaverseNextRootContext.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(WeaverseNextContext.Provider, { value: contextValue, children }) });
192
+ }
161
193
  var EMPTY_THEME_SETTINGS = {};
162
194
  var WeaverseNextContext = react$1.createContext(null);
163
195
  function WeaverseNextProvider(props) {
164
196
  let { children, client, rootData, pageData, commerce, themeSettings } = props;
197
+ let rootContext = react$1.useContext(WeaverseNextRootContext);
165
198
  let themeSettingsValue = themeSettings ?? client?.themeSettings ?? EMPTY_THEME_SETTINGS;
166
- let themeSettingsStore = react$1.useMemo(
167
- () => createWeaverseNextThemeSettingsStore({
199
+ let ownThemeSettingsStore = react$1.useMemo(() => {
200
+ if (rootContext) {
201
+ return null;
202
+ }
203
+ return createWeaverseNextThemeSettingsStore({
168
204
  schema: client?.themeSchema,
169
205
  settings: themeSettingsValue
170
- }),
171
- [client?.themeSchema, themeSettingsValue]
172
- );
206
+ });
207
+ }, [rootContext, client?.themeSchema, themeSettingsValue]);
208
+ let themeSettingsStore = rootContext?.themeSettingsStore ?? ownThemeSettingsStore;
209
+ let mergedIntoRootRef = react$1.useRef(void 0);
210
+ react$1.useEffect(() => {
211
+ if (rootContext && themeSettingsValue !== EMPTY_THEME_SETTINGS && mergedIntoRootRef.current !== themeSettingsValue) {
212
+ rootContext.themeSettingsStore.updateThemeSettings(themeSettingsValue);
213
+ mergedIntoRootRef.current = themeSettingsValue;
214
+ }
215
+ }, [rootContext, themeSettingsValue]);
173
216
  let value = react$1.useMemo(
174
217
  () => ({
175
218
  client,
@@ -675,6 +718,62 @@ var WeaverseNextRenderer = react$1.memo(function WeaverseNextRendererComponent(p
675
718
  ] });
676
719
  });
677
720
 
721
+ // src/seo.ts
722
+ function hasOpenGraphContent(seo) {
723
+ return Boolean(seo?.title || seo?.description || seo?.image || seo?.type);
724
+ }
725
+ function hasTwitterContent(seo) {
726
+ return Boolean(seo?.title || seo?.description || seo?.image || seo?.cardType);
727
+ }
728
+ function formatWeaverseNextSeoMetadata(seo) {
729
+ let index = seo?.robots?.index !== false;
730
+ let follow = seo?.robots?.follow !== false;
731
+ let metadata = {
732
+ robots: { index, follow }
733
+ };
734
+ if (!seo) {
735
+ return metadata;
736
+ }
737
+ if (seo.title) {
738
+ metadata.title = seo.title;
739
+ }
740
+ if (seo.description) {
741
+ metadata.description = seo.description;
742
+ }
743
+ if (seo.keywords) {
744
+ metadata.keywords = seo.keywords;
745
+ }
746
+ if (seo.canonicalUrl) {
747
+ metadata.alternates = { canonical: seo.canonicalUrl };
748
+ }
749
+ let openGraph = seo.openGraph;
750
+ if (hasOpenGraphContent(openGraph)) {
751
+ metadata.openGraph = {
752
+ title: openGraph?.title,
753
+ description: openGraph?.description,
754
+ images: openGraph?.image ? [openGraph.image] : void 0,
755
+ type: openGraph?.type || "website"
756
+ };
757
+ }
758
+ let twitter = seo.twitter;
759
+ if (hasTwitterContent(twitter)) {
760
+ metadata.twitter = {
761
+ card: twitter?.cardType || "summary",
762
+ title: twitter?.title,
763
+ description: twitter?.description,
764
+ images: twitter?.image ? [twitter.image] : void 0
765
+ };
766
+ }
767
+ return metadata;
768
+ }
769
+ function getWeaverseNextSeoMetadata(data) {
770
+ if (!data) {
771
+ return formatWeaverseNextSeoMetadata(null);
772
+ }
773
+ let page = "items" in data && "id" in data ? data : data.page ?? null;
774
+ return formatWeaverseNextSeoMetadata(page?.seo ?? null);
775
+ }
776
+
678
777
  // src/studio-script-src.ts
679
778
  var TRUSTED_STUDIO_DOMAINS = ["weaverse.io", "weaverse.dev"];
680
779
  function isLoopbackHostname(hostname) {
@@ -738,10 +837,9 @@ function resolveWeaverseNextStudioScriptSrc(context, options = {}) {
738
837
  if (!isTrustedStudioOrigin(origin, storefrontHostname)) {
739
838
  return null;
740
839
  }
741
- let framework = options.framework ?? "hydrogen";
742
840
  let bundle = isDesignMode ? "index.js" : "preview.js";
743
841
  let version = last(searchParams, "weaverseVersion");
744
- let url = `${origin}/static/studio/${framework}/${bundle}`;
842
+ let url = `${origin}/static/studio/next/${bundle}`;
745
843
  return version ? `${url}?v=${encodeURIComponent(version)}` : url;
746
844
  }
747
845
 
@@ -765,21 +863,26 @@ function loadScript(src) {
765
863
  document.head.appendChild(script);
766
864
  loadedScriptSrcs.add(src);
767
865
  }
866
+ function loadWeaverseNextStudioScript(context, options = {}) {
867
+ let resolvedContext = context;
868
+ if (!resolvedContext && typeof window !== "undefined") {
869
+ resolvedContext = {
870
+ searchParams: new URLSearchParams(window.location.search),
871
+ url: window.location.href
872
+ };
873
+ }
874
+ let src = resolveWeaverseNextStudioScriptSrc(resolvedContext, {
875
+ storefrontHostname: options.storefrontHostname ?? (typeof window === "undefined" ? void 0 : window.location.hostname)
876
+ });
877
+ if (src) {
878
+ loadScript(src);
879
+ }
880
+ }
768
881
  function WeaverseNextStudioConnect(props) {
769
882
  react$1.useEffect(() => {
770
- let context = props.context;
771
- if (!context && typeof window !== "undefined") {
772
- context = {
773
- searchParams: new URLSearchParams(window.location.search),
774
- url: window.location.href
775
- };
776
- }
777
- let src = resolveWeaverseNextStudioScriptSrc(context, {
778
- storefrontHostname: props.storefrontHostname ?? (typeof window === "undefined" ? void 0 : window.location.hostname)
883
+ loadWeaverseNextStudioScript(props.context, {
884
+ storefrontHostname: props.storefrontHostname
779
885
  });
780
- if (src) {
781
- loadScript(src);
782
- }
783
886
  }, [props.context, props.storefrontHostname]);
784
887
  return null;
785
888
  }
@@ -815,6 +918,7 @@ Object.defineProperty(exports, "createSchema", {
815
918
  exports.DEFAULT_REVALIDATE_ENDPOINT = DEFAULT_REVALIDATE_ENDPOINT;
816
919
  exports.WeaverseNextProvider = WeaverseNextProvider;
817
920
  exports.WeaverseNextRenderer = WeaverseNextRenderer;
921
+ exports.WeaverseNextRootProvider = WeaverseNextRootProvider;
818
922
  exports.WeaverseNextRuntime = WeaverseNextRuntime;
819
923
  exports.WeaverseNextStudio = WeaverseNextStudio;
820
924
  exports.WeaverseNextStudioBridge = WeaverseNextStudioBridge;
@@ -825,6 +929,9 @@ exports.createWeaverseNextClient = createWeaverseNextClient;
825
929
  exports.createWeaverseNextRuntime = createWeaverseNextRuntime;
826
930
  exports.createWeaverseNextStudioInternals = createWeaverseNextStudioInternals;
827
931
  exports.createWeaverseNextThemeSettingsStore = createWeaverseNextThemeSettingsStore;
932
+ exports.formatWeaverseNextSeoMetadata = formatWeaverseNextSeoMetadata;
933
+ exports.getWeaverseNextSeoMetadata = getWeaverseNextSeoMetadata;
934
+ exports.loadWeaverseNextStudioScript = loadWeaverseNextStudioScript;
828
935
  exports.resolveWeaverseNextStudioScriptSrc = resolveWeaverseNextStudioScriptSrc;
829
936
  exports.revalidateWeaverseNextItem = revalidateWeaverseNextItem;
830
937
  exports.runWeaverseComponentLoaders = runWeaverseComponentLoaders;