@riverbankcms/sdk 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +239 -0
- package/dist/cli/index.js +22 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/client/client.js +1 -1
- package/dist/client/client.js.map +1 -1
- package/dist/client/client.mjs +1 -1
- package/dist/client/client.mjs.map +1 -1
- package/dist/server/{Layout-BClXUTsd.d.mts → Layout-B7cvis7r.d.mts} +3 -3
- package/dist/server/{Layout-UXGjXv8M.d.ts → Layout-wBtJLTVX.d.ts} +3 -3
- package/dist/server/{chunk-Z5ZA6Q4D.mjs → chunk-74XUVNOO.mjs} +5 -3
- package/dist/server/chunk-74XUVNOO.mjs.map +1 -0
- package/dist/server/{chunk-PHS2KWJX.js → chunk-7BVRA5MY.js} +7 -52
- package/dist/server/chunk-7BVRA5MY.js.map +1 -0
- package/dist/server/{chunk-SQMGHEJM.mjs → chunk-7FIJSGHU.mjs} +2 -2
- package/dist/server/{chunk-SQMGHEJM.mjs.map → chunk-7FIJSGHU.mjs.map} +1 -1
- package/dist/server/chunk-ARNCLSQT.mjs +52 -0
- package/dist/server/chunk-ARNCLSQT.mjs.map +1 -0
- package/dist/server/chunk-BNQV3PXP.js +69 -0
- package/dist/server/chunk-BNQV3PXP.js.map +1 -0
- package/dist/server/{chunk-SSS7CCRR.js → chunk-EIVISR62.js} +15 -57
- package/dist/server/chunk-EIVISR62.js.map +1 -0
- package/dist/server/{chunk-I2D7KOEA.js → chunk-JWRNMNWI.js} +5 -3
- package/dist/server/chunk-JWRNMNWI.js.map +1 -0
- package/dist/server/{chunk-EOWGKCUZ.js → chunk-P7UVAMK6.js} +2 -2
- package/dist/server/{chunk-EOWGKCUZ.js.map → chunk-P7UVAMK6.js.map} +1 -1
- package/dist/server/{chunk-2HXHFSMI.mjs → chunk-RBJFXNDM.mjs} +6 -51
- package/dist/server/chunk-RBJFXNDM.mjs.map +1 -0
- package/dist/server/chunk-SWYWZT3L.mjs +69 -0
- package/dist/server/chunk-SWYWZT3L.mjs.map +1 -0
- package/dist/server/chunk-T26N3P26.js +52 -0
- package/dist/server/chunk-T26N3P26.js.map +1 -0
- package/dist/server/{chunk-PMHLZ3FW.mjs → chunk-YXA4GAAQ.mjs} +15 -57
- package/dist/server/chunk-YXA4GAAQ.mjs.map +1 -0
- package/dist/server/{components-DppHY5oD.d.ts → components-CICSJyp_.d.ts} +1 -1
- package/dist/server/{components-BmaJxgCV.d.mts → components-CMMwDXTW.d.mts} +1 -1
- package/dist/server/components.d.mts +2 -2
- package/dist/server/components.d.ts +2 -2
- package/dist/server/components.js +5 -3
- package/dist/server/components.js.map +1 -1
- package/dist/server/components.mjs +5 -3
- package/dist/server/index-BTwWvSBu.d.ts +130 -0
- package/dist/server/index-DI_qlYx3.d.mts +130 -0
- package/dist/server/index.js +2 -2
- package/dist/server/index.mjs +1 -1
- package/dist/server/{loadContent-BS-3wesN.d.mts → loadContent-C-YYUKQa.d.mts} +10 -2
- package/dist/server/{loadContent-Buvmudee.d.ts → loadContent-DmgpFcFC.d.ts} +10 -2
- package/dist/server/metadata.d.mts +8 -135
- package/dist/server/metadata.d.ts +8 -135
- package/dist/server/metadata.js +5 -65
- package/dist/server/metadata.js.map +1 -1
- package/dist/server/metadata.mjs +4 -64
- package/dist/server/metadata.mjs.map +1 -1
- package/dist/server/navigation.d.mts +80 -145
- package/dist/server/navigation.d.ts +80 -145
- package/dist/server/navigation.js +2 -10
- package/dist/server/navigation.js.map +1 -1
- package/dist/server/navigation.mjs +7 -15
- package/dist/server/next.d.mts +274 -0
- package/dist/server/next.d.ts +274 -0
- package/dist/server/next.js +150 -0
- package/dist/server/next.js.map +1 -0
- package/dist/server/next.mjs +150 -0
- package/dist/server/next.mjs.map +1 -0
- package/dist/server/rendering/server.d.mts +1 -1
- package/dist/server/rendering/server.d.ts +1 -1
- package/dist/server/rendering/server.js +5 -3
- package/dist/server/rendering/server.js.map +1 -1
- package/dist/server/rendering/server.mjs +5 -3
- package/dist/server/rendering.d.mts +4 -4
- package/dist/server/rendering.d.ts +4 -4
- package/dist/server/rendering.js +6 -4
- package/dist/server/rendering.js.map +1 -1
- package/dist/server/rendering.mjs +6 -4
- package/dist/server/server.d.mts +1 -1
- package/dist/server/server.d.ts +1 -1
- package/dist/server/server.js +3 -3
- package/dist/server/server.mjs +2 -2
- package/package.json +13 -1
- package/dist/server/chunk-2HXHFSMI.mjs.map +0 -1
- package/dist/server/chunk-I2D7KOEA.js.map +0 -1
- package/dist/server/chunk-PHS2KWJX.js.map +0 -1
- package/dist/server/chunk-PMHLZ3FW.mjs.map +0 -1
- package/dist/server/chunk-SSS7CCRR.js.map +0 -1
- package/dist/server/chunk-Z5ZA6Q4D.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/next.js","../../src/next/catch-all.tsx"],"names":["Page"],"mappings":"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","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/next.js","sourcesContent":[null,"/**\n * Next.js catch-all page factory for Riverbank CMS.\n *\n * Provides a simple, opinionated way to render CMS content in Next.js catch-all routes.\n * Reduces typical page.tsx boilerplate from ~160 lines to ~10 lines.\n *\n * @example\n * ```tsx\n * // src/app/[[...slug]]/page.tsx\n * import { createCatchAllPage } from '@riverbankcms/sdk/next';\n * import { getRiverbankClient } from '@/lib/builder-client';\n * import config from '@/riverbank.config';\n *\n * const { Page, generateMetadata } = createCatchAllPage({\n * getClient: getRiverbankClient,\n * config,\n * blockOverrides: { hero: MyCustomHero },\n * });\n *\n * export default Page;\n * export { generateMetadata };\n * ```\n */\n\n// Note: next is a peerDependency - this module only works in Next.js projects.\n// We use require() with a type cast because Next.js's notFound() is typed as () => never\n// but TypeScript doesn't infer this from the dynamic import, causing false\n// \"unreachable code\" warnings without explicit type information.\nconst { notFound } = require('next/navigation') as { notFound: () => never };\n\nimport {\n loadContent,\n isPageContent,\n isEntryContent,\n} from '../rendering/helpers/loadContent';\nimport type { LoadContentResult } from '../rendering/helpers/loadContent';\nimport { Page as PageComponent } from '../rendering/components/Page';\nimport {\n generatePageMetadata,\n generatePreviewMetadata,\n type Metadata,\n} from '../metadata/generatePageMetadata';\nimport type {\n CreateCatchAllPageOptions,\n CatchAllPageProps,\n CreateCatchAllPageResult,\n} from './types';\n\n/**\n * Detect preview mode from environment variable.\n *\n * Sites can enable preview mode by setting:\n * ```\n * RIVERBANK_PREVIEW_MODE=true\n * ```\n *\n * This is typically set in preview/staging environments to fetch\n * draft content instead of published content.\n */\nfunction isPreviewMode(): boolean {\n return process.env.RIVERBANK_PREVIEW_MODE === 'true';\n}\n\n/**\n * Convert URL slug segments to a path string.\n *\n * @example\n * ```\n * slugToPath(undefined) // '/'\n * slugToPath([]) // '/'\n * slugToPath(['about']) // '/about'\n * slugToPath(['blog', 'post']) // '/blog/post'\n * ```\n */\nfunction slugToPath(slug?: string[]): string {\n if (!slug || slug.length === 0) return '/';\n return '/' + slug.join('/');\n}\n\n/**\n * Factory function to create a Next.js catch-all page component and metadata generator.\n *\n * This provides a simple, opinionated setup for rendering Riverbank CMS content\n * in external SDK sites. It handles:\n *\n * - Page and content entry routing\n * - Preview mode detection (via `RIVERBANK_PREVIEW_MODE` env var)\n * - SEO metadata generation\n * - Block overrides for custom components\n * - 404 handling for missing content\n *\n * ## Escape Hatches\n *\n * For customization beyond the defaults, use these options:\n *\n * - `beforeRender`: Intercept before rendering (maintenance mode, access control)\n * - `customMetadata`: Full control over SEO metadata\n * - `wrapper`: Wrap all content (analytics, error boundaries)\n *\n * For maximum control, use the lower-level helpers directly:\n * - `loadContent()` from `@riverbankcms/sdk/rendering`\n * - `Page` component from `@riverbankcms/sdk/rendering`\n * - `generatePageMetadata()` from `@riverbankcms/sdk/metadata`\n *\n * @param options - Configuration options\n * @returns Object with `Page` component and `generateMetadata` function\n *\n * @example Basic usage\n * ```tsx\n * const { Page, generateMetadata } = createCatchAllPage({\n * getClient: getRiverbankClient,\n * config,\n * });\n *\n * export default Page;\n * export { generateMetadata };\n * ```\n *\n * @example With maintenance mode\n * ```tsx\n * const { Page, generateMetadata } = createCatchAllPage({\n * getClient,\n * config,\n * beforeRender: async () => {\n * if (process.env.MAINTENANCE_MODE === 'true') {\n * return <MaintenancePage />;\n * }\n * return null;\n * },\n * });\n * ```\n */\nexport function createCatchAllPage(\n options: CreateCatchAllPageOptions\n): CreateCatchAllPageResult {\n const {\n getClient,\n config,\n blockOverrides,\n siteUrl,\n beforeRender,\n customMetadata,\n wrapper: Wrapper,\n } = options;\n\n /**\n * Main page component that loads and renders CMS content.\n */\n async function Page({ params, searchParams: searchParamsPromise }: CatchAllPageProps): Promise<React.ReactNode> {\n const [{ slug }, searchParams] = await Promise.all([\n params,\n searchParamsPromise ?? Promise.resolve({}),\n ]);\n const path = slugToPath(slug);\n const preview = isPreviewMode();\n const client = getClient();\n\n // Load content (page or entry)\n let content: LoadContentResult;\n try {\n content = await loadContent({\n client,\n siteId: config.siteId,\n path,\n preview,\n });\n } catch (error) {\n // Log the error for debugging - could be a network error, auth failure, etc.\n // We treat all errors as \"not found\" since the page can't be rendered\n console.debug('[createCatchAllPage] Failed to load content for path:', path, error);\n return notFound();\n }\n\n // ESCAPE HATCH: beforeRender for maintenance mode, access control, etc.\n if (beforeRender) {\n const intercepted = await beforeRender({ content, path, preview, searchParams });\n if (intercepted !== null) {\n return Wrapper ? <Wrapper>{intercepted}</Wrapper> : intercepted;\n }\n }\n\n let rendered: React.ReactNode;\n\n // Render page content\n if (isPageContent(content)) {\n rendered = (\n <PageComponent\n page={content.page}\n theme={content.theme}\n siteId={content.siteId}\n resolvedData={content.resolvedData}\n blockOverrides={blockOverrides}\n />\n );\n }\n // Render entry content with template\n else if (isEntryContent(content)) {\n // Entries without template pages should 404\n if (!content.templatePage) {\n return notFound();\n }\n\n rendered = (\n <PageComponent\n page={content.templatePage}\n theme={content.theme}\n siteId={content.siteId}\n resolvedData={content.resolvedData}\n blockOverrides={blockOverrides}\n dataContext={{\n contentEntry: content.dataContext.contentEntry,\n }}\n />\n );\n }\n // Unexpected content type - should never happen\n else {\n return notFound();\n }\n\n return Wrapper ? <Wrapper>{rendered}</Wrapper> : rendered;\n }\n\n /**\n * Generate SEO metadata for the page.\n */\n async function generateMetadataFn({ params, searchParams: searchParamsPromise }: CatchAllPageProps): Promise<Metadata> {\n const [{ slug }, searchParams] = await Promise.all([\n params,\n searchParamsPromise ?? Promise.resolve({}),\n ]);\n const path = slugToPath(slug);\n const preview = isPreviewMode();\n\n try {\n const content = await loadContent({\n client: getClient(),\n siteId: config.siteId,\n path,\n preview,\n });\n\n // ESCAPE HATCH: Custom metadata generation\n if (customMetadata) {\n return customMetadata({ content, path, preview, searchParams });\n }\n\n // Resolve site URL (use config URLs as fallback)\n const resolvedUrl =\n siteUrl ?? (preview ? config.previewUrl : config.liveUrl) ?? '';\n\n // Warn if no site URL is configured - OG/Twitter tags require absolute URLs\n if (!resolvedUrl) {\n console.warn(\n '[createCatchAllPage] No siteUrl configured. OpenGraph and Twitter tags will have relative URLs which may cause social sharing previews to fail. ' +\n 'Set siteUrl option, or config.liveUrl/config.previewUrl in your riverbank.config.'\n );\n }\n\n // Build page object for metadata\n // For entries, we use metaTitle/metaDescription; purpose is used as description fallback\n const page = isPageContent(content)\n ? content.page\n : isEntryContent(content)\n ? {\n name: content.entry.metaTitle ?? content.entry.title,\n purpose: content.entry.metaDescription ?? undefined,\n }\n : { name: 'Page' };\n\n // Use preview metadata (noindex) in preview mode\n const metadataGenerator = preview\n ? generatePreviewMetadata\n : generatePageMetadata;\n\n // Use site data from loadContent result (no duplicate API call needed)\n return metadataGenerator({\n page,\n site: content.site,\n path,\n siteUrl: resolvedUrl,\n });\n } catch (error) {\n // Log the error for debugging purposes\n console.debug('[createCatchAllPage] Failed to generate metadata for path:', path, error);\n // Return minimal metadata on error - page will handle the actual 404\n return {\n title: 'Page Not Found',\n robots: { index: false, follow: false },\n };\n }\n }\n\n return {\n Page,\n generateMetadata: generateMetadataFn,\n };\n}\n"]}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import {
|
|
2
|
+
generatePageMetadata,
|
|
3
|
+
generatePreviewMetadata
|
|
4
|
+
} from "./chunk-SWYWZT3L.mjs";
|
|
5
|
+
import {
|
|
6
|
+
isEntryContent,
|
|
7
|
+
isPageContent,
|
|
8
|
+
loadContent
|
|
9
|
+
} from "./chunk-74XUVNOO.mjs";
|
|
10
|
+
import {
|
|
11
|
+
Page
|
|
12
|
+
} from "./chunk-ARNCLSQT.mjs";
|
|
13
|
+
import "./chunk-LNOUXALA.mjs";
|
|
14
|
+
import "./chunk-AEFWG657.mjs";
|
|
15
|
+
import "./chunk-BYBJA6SP.mjs";
|
|
16
|
+
import {
|
|
17
|
+
__require
|
|
18
|
+
} from "./chunk-BJTO5JO5.mjs";
|
|
19
|
+
|
|
20
|
+
// src/next/catch-all.tsx
|
|
21
|
+
import { jsx } from "react/jsx-runtime";
|
|
22
|
+
var { notFound } = __require("next/navigation");
|
|
23
|
+
function isPreviewMode() {
|
|
24
|
+
return process.env.RIVERBANK_PREVIEW_MODE === "true";
|
|
25
|
+
}
|
|
26
|
+
function slugToPath(slug) {
|
|
27
|
+
if (!slug || slug.length === 0) return "/";
|
|
28
|
+
return "/" + slug.join("/");
|
|
29
|
+
}
|
|
30
|
+
function createCatchAllPage(options) {
|
|
31
|
+
const {
|
|
32
|
+
getClient,
|
|
33
|
+
config,
|
|
34
|
+
blockOverrides,
|
|
35
|
+
siteUrl,
|
|
36
|
+
beforeRender,
|
|
37
|
+
customMetadata,
|
|
38
|
+
wrapper: Wrapper
|
|
39
|
+
} = options;
|
|
40
|
+
async function Page2({ params, searchParams: searchParamsPromise }) {
|
|
41
|
+
const [{ slug }, searchParams] = await Promise.all([
|
|
42
|
+
params,
|
|
43
|
+
searchParamsPromise ?? Promise.resolve({})
|
|
44
|
+
]);
|
|
45
|
+
const path = slugToPath(slug);
|
|
46
|
+
const preview = isPreviewMode();
|
|
47
|
+
const client = getClient();
|
|
48
|
+
let content;
|
|
49
|
+
try {
|
|
50
|
+
content = await loadContent({
|
|
51
|
+
client,
|
|
52
|
+
siteId: config.siteId,
|
|
53
|
+
path,
|
|
54
|
+
preview
|
|
55
|
+
});
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.debug("[createCatchAllPage] Failed to load content for path:", path, error);
|
|
58
|
+
return notFound();
|
|
59
|
+
}
|
|
60
|
+
if (beforeRender) {
|
|
61
|
+
const intercepted = await beforeRender({ content, path, preview, searchParams });
|
|
62
|
+
if (intercepted !== null) {
|
|
63
|
+
return Wrapper ? /* @__PURE__ */ jsx(Wrapper, { children: intercepted }) : intercepted;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
let rendered;
|
|
67
|
+
if (isPageContent(content)) {
|
|
68
|
+
rendered = /* @__PURE__ */ jsx(
|
|
69
|
+
Page,
|
|
70
|
+
{
|
|
71
|
+
page: content.page,
|
|
72
|
+
theme: content.theme,
|
|
73
|
+
siteId: content.siteId,
|
|
74
|
+
resolvedData: content.resolvedData,
|
|
75
|
+
blockOverrides
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
} else if (isEntryContent(content)) {
|
|
79
|
+
if (!content.templatePage) {
|
|
80
|
+
return notFound();
|
|
81
|
+
}
|
|
82
|
+
rendered = /* @__PURE__ */ jsx(
|
|
83
|
+
Page,
|
|
84
|
+
{
|
|
85
|
+
page: content.templatePage,
|
|
86
|
+
theme: content.theme,
|
|
87
|
+
siteId: content.siteId,
|
|
88
|
+
resolvedData: content.resolvedData,
|
|
89
|
+
blockOverrides,
|
|
90
|
+
dataContext: {
|
|
91
|
+
contentEntry: content.dataContext.contentEntry
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
} else {
|
|
96
|
+
return notFound();
|
|
97
|
+
}
|
|
98
|
+
return Wrapper ? /* @__PURE__ */ jsx(Wrapper, { children: rendered }) : rendered;
|
|
99
|
+
}
|
|
100
|
+
async function generateMetadataFn({ params, searchParams: searchParamsPromise }) {
|
|
101
|
+
const [{ slug }, searchParams] = await Promise.all([
|
|
102
|
+
params,
|
|
103
|
+
searchParamsPromise ?? Promise.resolve({})
|
|
104
|
+
]);
|
|
105
|
+
const path = slugToPath(slug);
|
|
106
|
+
const preview = isPreviewMode();
|
|
107
|
+
try {
|
|
108
|
+
const content = await loadContent({
|
|
109
|
+
client: getClient(),
|
|
110
|
+
siteId: config.siteId,
|
|
111
|
+
path,
|
|
112
|
+
preview
|
|
113
|
+
});
|
|
114
|
+
if (customMetadata) {
|
|
115
|
+
return customMetadata({ content, path, preview, searchParams });
|
|
116
|
+
}
|
|
117
|
+
const resolvedUrl = siteUrl ?? (preview ? config.previewUrl : config.liveUrl) ?? "";
|
|
118
|
+
if (!resolvedUrl) {
|
|
119
|
+
console.warn(
|
|
120
|
+
"[createCatchAllPage] No siteUrl configured. OpenGraph and Twitter tags will have relative URLs which may cause social sharing previews to fail. Set siteUrl option, or config.liveUrl/config.previewUrl in your riverbank.config."
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
const page = isPageContent(content) ? content.page : isEntryContent(content) ? {
|
|
124
|
+
name: content.entry.metaTitle ?? content.entry.title,
|
|
125
|
+
purpose: content.entry.metaDescription ?? void 0
|
|
126
|
+
} : { name: "Page" };
|
|
127
|
+
const metadataGenerator = preview ? generatePreviewMetadata : generatePageMetadata;
|
|
128
|
+
return metadataGenerator({
|
|
129
|
+
page,
|
|
130
|
+
site: content.site,
|
|
131
|
+
path,
|
|
132
|
+
siteUrl: resolvedUrl
|
|
133
|
+
});
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.debug("[createCatchAllPage] Failed to generate metadata for path:", path, error);
|
|
136
|
+
return {
|
|
137
|
+
title: "Page Not Found",
|
|
138
|
+
robots: { index: false, follow: false }
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
Page: Page2,
|
|
144
|
+
generateMetadata: generateMetadataFn
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
export {
|
|
148
|
+
createCatchAllPage
|
|
149
|
+
};
|
|
150
|
+
//# sourceMappingURL=next.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/next/catch-all.tsx"],"sourcesContent":["/**\n * Next.js catch-all page factory for Riverbank CMS.\n *\n * Provides a simple, opinionated way to render CMS content in Next.js catch-all routes.\n * Reduces typical page.tsx boilerplate from ~160 lines to ~10 lines.\n *\n * @example\n * ```tsx\n * // src/app/[[...slug]]/page.tsx\n * import { createCatchAllPage } from '@riverbankcms/sdk/next';\n * import { getRiverbankClient } from '@/lib/builder-client';\n * import config from '@/riverbank.config';\n *\n * const { Page, generateMetadata } = createCatchAllPage({\n * getClient: getRiverbankClient,\n * config,\n * blockOverrides: { hero: MyCustomHero },\n * });\n *\n * export default Page;\n * export { generateMetadata };\n * ```\n */\n\n// Note: next is a peerDependency - this module only works in Next.js projects.\n// We use require() with a type cast because Next.js's notFound() is typed as () => never\n// but TypeScript doesn't infer this from the dynamic import, causing false\n// \"unreachable code\" warnings without explicit type information.\nconst { notFound } = require('next/navigation') as { notFound: () => never };\n\nimport {\n loadContent,\n isPageContent,\n isEntryContent,\n} from '../rendering/helpers/loadContent';\nimport type { LoadContentResult } from '../rendering/helpers/loadContent';\nimport { Page as PageComponent } from '../rendering/components/Page';\nimport {\n generatePageMetadata,\n generatePreviewMetadata,\n type Metadata,\n} from '../metadata/generatePageMetadata';\nimport type {\n CreateCatchAllPageOptions,\n CatchAllPageProps,\n CreateCatchAllPageResult,\n} from './types';\n\n/**\n * Detect preview mode from environment variable.\n *\n * Sites can enable preview mode by setting:\n * ```\n * RIVERBANK_PREVIEW_MODE=true\n * ```\n *\n * This is typically set in preview/staging environments to fetch\n * draft content instead of published content.\n */\nfunction isPreviewMode(): boolean {\n return process.env.RIVERBANK_PREVIEW_MODE === 'true';\n}\n\n/**\n * Convert URL slug segments to a path string.\n *\n * @example\n * ```\n * slugToPath(undefined) // '/'\n * slugToPath([]) // '/'\n * slugToPath(['about']) // '/about'\n * slugToPath(['blog', 'post']) // '/blog/post'\n * ```\n */\nfunction slugToPath(slug?: string[]): string {\n if (!slug || slug.length === 0) return '/';\n return '/' + slug.join('/');\n}\n\n/**\n * Factory function to create a Next.js catch-all page component and metadata generator.\n *\n * This provides a simple, opinionated setup for rendering Riverbank CMS content\n * in external SDK sites. It handles:\n *\n * - Page and content entry routing\n * - Preview mode detection (via `RIVERBANK_PREVIEW_MODE` env var)\n * - SEO metadata generation\n * - Block overrides for custom components\n * - 404 handling for missing content\n *\n * ## Escape Hatches\n *\n * For customization beyond the defaults, use these options:\n *\n * - `beforeRender`: Intercept before rendering (maintenance mode, access control)\n * - `customMetadata`: Full control over SEO metadata\n * - `wrapper`: Wrap all content (analytics, error boundaries)\n *\n * For maximum control, use the lower-level helpers directly:\n * - `loadContent()` from `@riverbankcms/sdk/rendering`\n * - `Page` component from `@riverbankcms/sdk/rendering`\n * - `generatePageMetadata()` from `@riverbankcms/sdk/metadata`\n *\n * @param options - Configuration options\n * @returns Object with `Page` component and `generateMetadata` function\n *\n * @example Basic usage\n * ```tsx\n * const { Page, generateMetadata } = createCatchAllPage({\n * getClient: getRiverbankClient,\n * config,\n * });\n *\n * export default Page;\n * export { generateMetadata };\n * ```\n *\n * @example With maintenance mode\n * ```tsx\n * const { Page, generateMetadata } = createCatchAllPage({\n * getClient,\n * config,\n * beforeRender: async () => {\n * if (process.env.MAINTENANCE_MODE === 'true') {\n * return <MaintenancePage />;\n * }\n * return null;\n * },\n * });\n * ```\n */\nexport function createCatchAllPage(\n options: CreateCatchAllPageOptions\n): CreateCatchAllPageResult {\n const {\n getClient,\n config,\n blockOverrides,\n siteUrl,\n beforeRender,\n customMetadata,\n wrapper: Wrapper,\n } = options;\n\n /**\n * Main page component that loads and renders CMS content.\n */\n async function Page({ params, searchParams: searchParamsPromise }: CatchAllPageProps): Promise<React.ReactNode> {\n const [{ slug }, searchParams] = await Promise.all([\n params,\n searchParamsPromise ?? Promise.resolve({}),\n ]);\n const path = slugToPath(slug);\n const preview = isPreviewMode();\n const client = getClient();\n\n // Load content (page or entry)\n let content: LoadContentResult;\n try {\n content = await loadContent({\n client,\n siteId: config.siteId,\n path,\n preview,\n });\n } catch (error) {\n // Log the error for debugging - could be a network error, auth failure, etc.\n // We treat all errors as \"not found\" since the page can't be rendered\n console.debug('[createCatchAllPage] Failed to load content for path:', path, error);\n return notFound();\n }\n\n // ESCAPE HATCH: beforeRender for maintenance mode, access control, etc.\n if (beforeRender) {\n const intercepted = await beforeRender({ content, path, preview, searchParams });\n if (intercepted !== null) {\n return Wrapper ? <Wrapper>{intercepted}</Wrapper> : intercepted;\n }\n }\n\n let rendered: React.ReactNode;\n\n // Render page content\n if (isPageContent(content)) {\n rendered = (\n <PageComponent\n page={content.page}\n theme={content.theme}\n siteId={content.siteId}\n resolvedData={content.resolvedData}\n blockOverrides={blockOverrides}\n />\n );\n }\n // Render entry content with template\n else if (isEntryContent(content)) {\n // Entries without template pages should 404\n if (!content.templatePage) {\n return notFound();\n }\n\n rendered = (\n <PageComponent\n page={content.templatePage}\n theme={content.theme}\n siteId={content.siteId}\n resolvedData={content.resolvedData}\n blockOverrides={blockOverrides}\n dataContext={{\n contentEntry: content.dataContext.contentEntry,\n }}\n />\n );\n }\n // Unexpected content type - should never happen\n else {\n return notFound();\n }\n\n return Wrapper ? <Wrapper>{rendered}</Wrapper> : rendered;\n }\n\n /**\n * Generate SEO metadata for the page.\n */\n async function generateMetadataFn({ params, searchParams: searchParamsPromise }: CatchAllPageProps): Promise<Metadata> {\n const [{ slug }, searchParams] = await Promise.all([\n params,\n searchParamsPromise ?? Promise.resolve({}),\n ]);\n const path = slugToPath(slug);\n const preview = isPreviewMode();\n\n try {\n const content = await loadContent({\n client: getClient(),\n siteId: config.siteId,\n path,\n preview,\n });\n\n // ESCAPE HATCH: Custom metadata generation\n if (customMetadata) {\n return customMetadata({ content, path, preview, searchParams });\n }\n\n // Resolve site URL (use config URLs as fallback)\n const resolvedUrl =\n siteUrl ?? (preview ? config.previewUrl : config.liveUrl) ?? '';\n\n // Warn if no site URL is configured - OG/Twitter tags require absolute URLs\n if (!resolvedUrl) {\n console.warn(\n '[createCatchAllPage] No siteUrl configured. OpenGraph and Twitter tags will have relative URLs which may cause social sharing previews to fail. ' +\n 'Set siteUrl option, or config.liveUrl/config.previewUrl in your riverbank.config.'\n );\n }\n\n // Build page object for metadata\n // For entries, we use metaTitle/metaDescription; purpose is used as description fallback\n const page = isPageContent(content)\n ? content.page\n : isEntryContent(content)\n ? {\n name: content.entry.metaTitle ?? content.entry.title,\n purpose: content.entry.metaDescription ?? undefined,\n }\n : { name: 'Page' };\n\n // Use preview metadata (noindex) in preview mode\n const metadataGenerator = preview\n ? generatePreviewMetadata\n : generatePageMetadata;\n\n // Use site data from loadContent result (no duplicate API call needed)\n return metadataGenerator({\n page,\n site: content.site,\n path,\n siteUrl: resolvedUrl,\n });\n } catch (error) {\n // Log the error for debugging purposes\n console.debug('[createCatchAllPage] Failed to generate metadata for path:', path, error);\n // Return minimal metadata on error - page will handle the actual 404\n return {\n title: 'Page Not Found',\n robots: { index: false, follow: false },\n };\n }\n }\n\n return {\n Page,\n generateMetadata: generateMetadataFn,\n };\n}\n"],"mappings":"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","names":["Page"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { b as Page, P as PageProps } from '../loadPage-B8mQUUSo.mjs';
|
|
2
|
-
export { H as HeaderData, L as Layout, a as LayoutProps } from '../Layout-
|
|
2
|
+
export { H as HeaderData, L as Layout, a as LayoutProps } from '../Layout-B7cvis7r.mjs';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { T as Theme } from '../types-Dsu9wsUh.mjs';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { b as Page, P as PageProps } from '../loadPage-DP3nrHBi.js';
|
|
2
|
-
export { H as HeaderData, L as Layout, a as LayoutProps } from '../Layout-
|
|
2
|
+
export { H as HeaderData, L as Layout, a as LayoutProps } from '../Layout-wBtJLTVX.js';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { T as Theme } from '../types-CVykEqXN.js';
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
var _chunkTT5JWA4Xjs = require('../chunk-TT5JWA4X.js');
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
var _chunk7BVRA5MYjs = require('../chunk-7BVRA5MY.js');
|
|
7
|
+
require('../chunk-EIVISR62.js');
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
require('../chunk-
|
|
9
|
+
|
|
10
|
+
var _chunkT26N3P26js = require('../chunk-T26N3P26.js');
|
|
9
11
|
require('../chunk-7UPVCT3K.js');
|
|
10
12
|
require('../chunk-RVDS7VSP.js');
|
|
11
13
|
require('../chunk-YYO3RIFO.js');
|
|
@@ -14,5 +16,5 @@ require('../chunk-DGUM43GV.js');
|
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
|
|
17
|
-
exports.Block = _chunkTT5JWA4Xjs.Block; exports.Layout =
|
|
19
|
+
exports.Block = _chunkTT5JWA4Xjs.Block; exports.Layout = _chunk7BVRA5MYjs.Layout; exports.Page = _chunkT26N3P26js.Page;
|
|
18
20
|
//# sourceMappingURL=server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/rendering/server.js"],"names":[],"mappings":"AAAA;AACE;AACF,uDAA6B;AAC7B;AACE;
|
|
1
|
+
{"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/rendering/server.js"],"names":[],"mappings":"AAAA;AACE;AACF,uDAA6B;AAC7B;AACE;AACF,uDAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACF,uDAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACF,uHAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/rendering/server.js"}
|
|
@@ -2,10 +2,12 @@ import {
|
|
|
2
2
|
Block
|
|
3
3
|
} from "../chunk-OSF34JTQ.mjs";
|
|
4
4
|
import {
|
|
5
|
-
Layout
|
|
5
|
+
Layout
|
|
6
|
+
} from "../chunk-RBJFXNDM.mjs";
|
|
7
|
+
import "../chunk-YXA4GAAQ.mjs";
|
|
8
|
+
import {
|
|
6
9
|
Page
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-PMHLZ3FW.mjs";
|
|
10
|
+
} from "../chunk-ARNCLSQT.mjs";
|
|
9
11
|
import "../chunk-LNOUXALA.mjs";
|
|
10
12
|
import "../chunk-AEFWG657.mjs";
|
|
11
13
|
import "../chunk-BYBJA6SP.mjs";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export { d as BlockOverrideComponent, e as BlockOverrideProps, B as BlockOverrides, L as LoadPageParams, a as LoadPageResult, b as Page, P as PageProps, c as PageRenderer, l as loadPage } from './loadPage-B8mQUUSo.mjs';
|
|
2
|
-
export { H as HeaderData, L as Layout, a as LayoutProps } from './Layout-
|
|
2
|
+
export { H as HeaderData, L as Layout, a as LayoutProps } from './Layout-B7cvis7r.mjs';
|
|
3
3
|
export { Block, BlockProps } from './rendering/server.mjs';
|
|
4
|
-
export { C as ContentEntryData, L as LoadContentParams, b as LoadContentResult, a as isEntryContent, i as isPageContent, l as loadContent } from './loadContent-
|
|
4
|
+
export { C as ContentEntryData, L as LoadContentParams, b as LoadContentResult, S as SiteData, a as isEntryContent, i as isPageContent, l as loadContent } from './loadContent-C-YYUKQa.mjs';
|
|
5
5
|
export { c as SiteFooterContent, S as SiteHeaderContent, T as Theme } from './types-Dsu9wsUh.mjs';
|
|
6
6
|
export { P as PageOutline } from './schema-Z6-afHJG.mjs';
|
|
7
|
-
import { G as GradientConfig } from './components-
|
|
8
|
-
export { f as BackgroundInput, B as BodyTextContent, H as HeroContent, a as HeroMedia, g as ResolvedBackground, R as RichText, c as RichTextPrimitiveProps, e as SectionBackground, h as SectionBackgroundProps, S as SystemBlockComponentProps, b as buildThemeRuntime, d as resolveBackground, r as resolveImageUrl } from './components-
|
|
7
|
+
import { G as GradientConfig } from './components-CMMwDXTW.mjs';
|
|
8
|
+
export { f as BackgroundInput, B as BodyTextContent, H as HeroContent, a as HeroMedia, g as ResolvedBackground, R as RichText, c as RichTextPrimitiveProps, e as SectionBackground, h as SectionBackgroundProps, S as SystemBlockComponentProps, b as buildThemeRuntime, d as resolveBackground, r as resolveImageUrl } from './components-CMMwDXTW.mjs';
|
|
9
9
|
export { R as RouteMap, a as ThemeTokens } from './core-DsNWrl3o.mjs';
|
|
10
10
|
import { M as Media } from './richTextSchema-DURiozvD.mjs';
|
|
11
11
|
export { T as TipTapNode } from './richTextSchema-DURiozvD.mjs';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export { d as BlockOverrideComponent, e as BlockOverrideProps, B as BlockOverrides, L as LoadPageParams, a as LoadPageResult, b as Page, P as PageProps, c as PageRenderer, l as loadPage } from './loadPage-DP3nrHBi.js';
|
|
2
|
-
export { H as HeaderData, L as Layout, a as LayoutProps } from './Layout-
|
|
2
|
+
export { H as HeaderData, L as Layout, a as LayoutProps } from './Layout-wBtJLTVX.js';
|
|
3
3
|
export { Block, BlockProps } from './rendering/server.js';
|
|
4
|
-
export { C as ContentEntryData, L as LoadContentParams, b as LoadContentResult, a as isEntryContent, i as isPageContent, l as loadContent } from './loadContent-
|
|
4
|
+
export { C as ContentEntryData, L as LoadContentParams, b as LoadContentResult, S as SiteData, a as isEntryContent, i as isPageContent, l as loadContent } from './loadContent-DmgpFcFC.js';
|
|
5
5
|
export { c as SiteFooterContent, S as SiteHeaderContent, T as Theme } from './types-CVykEqXN.js';
|
|
6
6
|
export { P as PageOutline } from './schema-Z6-afHJG.js';
|
|
7
|
-
import { G as GradientConfig } from './components-
|
|
8
|
-
export { f as BackgroundInput, B as BodyTextContent, H as HeroContent, a as HeroMedia, g as ResolvedBackground, R as RichText, c as RichTextPrimitiveProps, e as SectionBackground, h as SectionBackgroundProps, S as SystemBlockComponentProps, b as buildThemeRuntime, d as resolveBackground, r as resolveImageUrl } from './components-
|
|
7
|
+
import { G as GradientConfig } from './components-CICSJyp_.js';
|
|
8
|
+
export { f as BackgroundInput, B as BodyTextContent, H as HeroContent, a as HeroMedia, g as ResolvedBackground, R as RichText, c as RichTextPrimitiveProps, e as SectionBackground, h as SectionBackgroundProps, S as SystemBlockComponentProps, b as buildThemeRuntime, d as resolveBackground, r as resolveImageUrl } from './components-CICSJyp_.js';
|
|
9
9
|
export { R as RouteMap, a as ThemeTokens } from './core-DsNWrl3o.js';
|
|
10
10
|
import { M as Media } from './richTextSchema-DURiozvD.js';
|
|
11
11
|
export { T as TipTapNode } from './richTextSchema-DURiozvD.js';
|
package/dist/server/rendering.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var _chunkJWRNMNWIjs = require('./chunk-JWRNMNWI.js');
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
var _chunkP3NNN73Gjs = require('./chunk-P3NNN73G.js');
|
|
@@ -11,9 +11,11 @@ var _chunkP3NNN73Gjs = require('./chunk-P3NNN73G.js');
|
|
|
11
11
|
var _chunkTT5JWA4Xjs = require('./chunk-TT5JWA4X.js');
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
var _chunk7BVRA5MYjs = require('./chunk-7BVRA5MY.js');
|
|
15
|
+
require('./chunk-EIVISR62.js');
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
require('./chunk-
|
|
17
|
+
|
|
18
|
+
var _chunkT26N3P26js = require('./chunk-T26N3P26.js');
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
|
|
@@ -40,5 +42,5 @@ require('./chunk-DGUM43GV.js');
|
|
|
40
42
|
|
|
41
43
|
|
|
42
44
|
|
|
43
|
-
exports.Block = _chunkTT5JWA4Xjs.Block; exports.Layout =
|
|
45
|
+
exports.Block = _chunkTT5JWA4Xjs.Block; exports.Layout = _chunk7BVRA5MYjs.Layout; exports.Page = _chunkT26N3P26js.Page; exports.PageRenderer = _chunk7UPVCT3Kjs.PageRenderer; exports.RichText = _chunk7UPVCT3Kjs.RichText; exports.SectionBackground = _chunk7UPVCT3Kjs.SectionBackground; exports.buildThemeRuntime = _chunk7UPVCT3Kjs.buildThemeRuntime; exports.isEntryContent = _chunkJWRNMNWIjs.isEntryContent; exports.isPageContent = _chunkJWRNMNWIjs.isPageContent; exports.loadContent = _chunkJWRNMNWIjs.loadContent; exports.loadPage = _chunkP3NNN73Gjs.loadPage; exports.resolveBackground = _chunk7UPVCT3Kjs.resolveBackground; exports.resolveImageUrl = _chunk7UPVCT3Kjs.resolveImageUrl;
|
|
44
46
|
//# sourceMappingURL=rendering.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/rendering.js"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;
|
|
1
|
+
{"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/rendering.js"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B,+BAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACA;AACA;AACA;AACA;AACA;AACF,sDAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,2qBAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/rendering.js"}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
isEntryContent,
|
|
3
3
|
isPageContent,
|
|
4
4
|
loadContent
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-74XUVNOO.mjs";
|
|
6
6
|
import {
|
|
7
7
|
loadPage
|
|
8
8
|
} from "./chunk-C6FIJC7T.mjs";
|
|
@@ -10,10 +10,12 @@ import {
|
|
|
10
10
|
Block
|
|
11
11
|
} from "./chunk-OSF34JTQ.mjs";
|
|
12
12
|
import {
|
|
13
|
-
Layout
|
|
13
|
+
Layout
|
|
14
|
+
} from "./chunk-RBJFXNDM.mjs";
|
|
15
|
+
import "./chunk-YXA4GAAQ.mjs";
|
|
16
|
+
import {
|
|
14
17
|
Page
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-PMHLZ3FW.mjs";
|
|
18
|
+
} from "./chunk-ARNCLSQT.mjs";
|
|
17
19
|
import {
|
|
18
20
|
PageRenderer,
|
|
19
21
|
RichText,
|
package/dist/server/server.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { c as createRiverbankClient } from './index-Bucs6UqG.mjs';
|
|
2
2
|
export { E as EntriesResponse, b as EntryResponse, P as PageResponse, R as RiverbankClient, a as RiverbankClientConfig, S as SiteResponse } from './types-1cLz0vnq.mjs';
|
|
3
3
|
export { L as LoadPageParams, a as LoadPageResult, R as RuntimeSdkConfig, l as loadPage } from './loadPage-B8mQUUSo.mjs';
|
|
4
|
-
export { C as ContentEntryData, E as EntryContentResult, L as LoadContentParams, b as LoadContentResult, P as PageContentResult, a as isEntryContent, i as isPageContent, l as loadContent } from './loadContent-
|
|
4
|
+
export { C as ContentEntryData, E as EntryContentResult, L as LoadContentParams, b as LoadContentResult, P as PageContentResult, a as isEntryContent, i as isPageContent, l as loadContent } from './loadContent-C-YYUKQa.mjs';
|
|
5
5
|
import './schema-Z6-afHJG.mjs';
|
|
6
6
|
import 'zod';
|
|
7
7
|
import './types-Dsu9wsUh.mjs';
|
package/dist/server/server.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { c as createRiverbankClient } from './index-Cp7tJuRt.js';
|
|
2
2
|
export { E as EntriesResponse, b as EntryResponse, P as PageResponse, R as RiverbankClient, a as RiverbankClientConfig, S as SiteResponse } from './types-BvcJU7zk.js';
|
|
3
3
|
export { L as LoadPageParams, a as LoadPageResult, R as RuntimeSdkConfig, l as loadPage } from './loadPage-DP3nrHBi.js';
|
|
4
|
-
export { C as ContentEntryData, E as EntryContentResult, L as LoadContentParams, b as LoadContentResult, P as PageContentResult, a as isEntryContent, i as isPageContent, l as loadContent } from './loadContent-
|
|
4
|
+
export { C as ContentEntryData, E as EntryContentResult, L as LoadContentParams, b as LoadContentResult, P as PageContentResult, a as isEntryContent, i as isPageContent, l as loadContent } from './loadContent-DmgpFcFC.js';
|
|
5
5
|
import './schema-Z6-afHJG.js';
|
|
6
6
|
import 'zod';
|
|
7
7
|
import './types-CVykEqXN.js';
|
package/dist/server/server.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkP7UVAMK6js = require('./chunk-P7UVAMK6.js');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var _chunkJWRNMNWIjs = require('./chunk-JWRNMNWI.js');
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
var _chunkP3NNN73Gjs = require('./chunk-P3NNN73G.js');
|
|
@@ -19,5 +19,5 @@ require('./chunk-DGUM43GV.js');
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
exports.createRiverbankClient =
|
|
22
|
+
exports.createRiverbankClient = _chunkP7UVAMK6js.createRiverbankClient; exports.isEntryContent = _chunkJWRNMNWIjs.isEntryContent; exports.isPageContent = _chunkJWRNMNWIjs.isPageContent; exports.loadContent = _chunkJWRNMNWIjs.loadContent; exports.loadPage = _chunkP3NNN73Gjs.loadPage;
|
|
23
23
|
//# sourceMappingURL=server.js.map
|
package/dist/server/server.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createRiverbankClient
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7FIJSGHU.mjs";
|
|
4
4
|
import {
|
|
5
5
|
isEntryContent,
|
|
6
6
|
isPageContent,
|
|
7
7
|
loadContent
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-74XUVNOO.mjs";
|
|
9
9
|
import {
|
|
10
10
|
loadPage
|
|
11
11
|
} from "./chunk-C6FIJC7T.mjs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riverbankcms/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Riverbank CMS SDK for headless content consumption",
|
|
5
5
|
"main": "./dist/server/index.js",
|
|
6
6
|
"module": "./dist/server/index.mjs",
|
|
@@ -74,6 +74,11 @@
|
|
|
74
74
|
"import": "./dist/server/navigation.mjs",
|
|
75
75
|
"require": "./dist/server/navigation.js"
|
|
76
76
|
},
|
|
77
|
+
"./next": {
|
|
78
|
+
"types": "./dist/server/next.d.ts",
|
|
79
|
+
"import": "./dist/server/next.mjs",
|
|
80
|
+
"require": "./dist/server/next.js"
|
|
81
|
+
},
|
|
77
82
|
"./analytics": {
|
|
78
83
|
"types": "./dist/client/analytics.d.ts",
|
|
79
84
|
"import": "./dist/client/analytics.mjs",
|
|
@@ -123,9 +128,15 @@
|
|
|
123
128
|
"zod": "^4.1.1"
|
|
124
129
|
},
|
|
125
130
|
"peerDependencies": {
|
|
131
|
+
"next": "^14.0.0 || ^15.0.0",
|
|
126
132
|
"react": "^19.2.1",
|
|
127
133
|
"react-dom": "^19.2.1"
|
|
128
134
|
},
|
|
135
|
+
"peerDependenciesMeta": {
|
|
136
|
+
"next": {
|
|
137
|
+
"optional": true
|
|
138
|
+
}
|
|
139
|
+
},
|
|
129
140
|
"devDependencies": {
|
|
130
141
|
"@riverbankcms/api": "workspace:*",
|
|
131
142
|
"@riverbankcms/blocks": "workspace:*",
|
|
@@ -136,6 +147,7 @@
|
|
|
136
147
|
"@types/react": "^19.1.0",
|
|
137
148
|
"@types/react-dom": "^19.1.0",
|
|
138
149
|
"eslint": "^9.15.0",
|
|
150
|
+
"next": "^15.0.0",
|
|
139
151
|
"tsup": "^8.3.5",
|
|
140
152
|
"typescript": "^5.6.3",
|
|
141
153
|
"vitest": "^1.6.1"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/rendering/components/Page.tsx","../../src/rendering/components/Layout.tsx"],"sourcesContent":["/**\n * Pure Page renderer component for Riverbank CMS.\n *\n * This component expects all data to be provided via props.\n * For data fetching, use:\n * - Server-side: `await loadPage({ client, siteId, path })`\n * - Client-side: `usePage({ client, siteId, path })`\n */\n\nimport { PageRenderer, buildThemeRuntime } from '@riverbankcms/blocks';\nimport type { PageOutline, RouteMap, Theme, ThemeTokens, BlockOverrides, OccurrenceContextData } from '@riverbankcms/blocks';\nimport type { ResolvedBlockData } from '../../data';\nimport type { RuntimeSdkConfig } from '../helpers/loadPage';\n\n// Re-export OccurrenceContextData for SDK consumers\nexport type { OccurrenceContextData };\n\nexport type PageProps = {\n // Required data (must be provided by caller)\n page: PageOutline;\n theme: Theme;\n siteId: string;\n\n // Optional data\n themeTokens?: ThemeTokens; // If not provided, will be built from theme\n resolvedData?: ResolvedBlockData; // Pre-fetched block data\n routeMap?: RouteMap;\n /**\n * SDK site configuration containing theme palette overrides.\n * When provided, the SDK palette tokens are merged into the theme tokens,\n * allowing blocks to use SDK-defined color tokens for section backgrounds.\n */\n sdkConfig?: RuntimeSdkConfig | null;\n /**\n * Supabase storage URL for direct image access.\n * SDK sites receive this from the API instead of requiring NEXT_PUBLIC_SUPABASE_URL env var.\n */\n supabaseUrl?: string;\n\n /**\n * Additional context data for content entry pages.\n * Used to pass occurrence context and content entry data to blocks.\n */\n dataContext?: {\n /** Occurrence context for event pages (from URL like /events/yoga/2025-01-15) */\n occurrenceContext?: OccurrenceContextData | null;\n /** Content entry data for template pages */\n contentEntry?: Record<string, unknown> | null;\n };\n\n // Customization\n wrapBlock?: (blockId: string, rendered: React.ReactNode) => React.ReactNode;\n registry?: Parameters<typeof PageRenderer>[0]['registry'];\n usePlaceholders?: boolean;\n /**\n * Custom components to override default block rendering.\n * Keys can be full block kind (\"block.hero\") or short form (\"hero\").\n *\n * This is SSR-safe - no context or hooks required.\n *\n * @example\n * ```tsx\n * <Page\n * {...pageData}\n * blockOverrides={{\n * 'hero': MyCustomHero,\n * 'block.testimonials': MyCustomTestimonials,\n * }}\n * />\n * ```\n */\n blockOverrides?: BlockOverrides;\n};\n\n/**\n * Pure renderer for Riverbank CMS pages.\n *\n * This component expects all data to be provided via props.\n * For data fetching, use:\n * - Server-side: `await loadPage({ client, siteId, path })`\n * - Client-side: `usePage({ client, siteId, path })`\n *\n * @example Server-side (Next.js App Router)\n * ```tsx\n * import { createRiverbankClient } from '@riverbankcms/sdk';\n * import { loadPage, Page } from '@riverbankcms/sdk/rendering';\n *\n * const client = createRiverbankClient({ apiKey, baseUrl });\n *\n * export default async function PageRoute({ params }) {\n * const pageData = await loadPage({\n * client,\n * siteId: 'site-id',\n * path: `/${params.slug}`,\n * });\n *\n * return <Page {...pageData} />;\n * }\n * ```\n *\n * @example Client-side\n * ```tsx\n * import { createRiverbankClient } from '@riverbankcms/sdk';\n * import { usePage, Page } from '@riverbankcms/sdk/rendering';\n *\n * const client = createRiverbankClient({ apiKey, baseUrl });\n *\n * function MyPage({ path }) {\n * const pageData = usePage({ client, siteId: 'site-id', path });\n *\n * if (pageData.loading) return <LoadingState />;\n * if (pageData.error) return <ErrorState error={pageData.error} />;\n * if (!pageData.page) return <NotFound />;\n *\n * return <Page {...pageData} />;\n * }\n * ```\n */\nexport function Page({\n page,\n theme,\n themeTokens: providedTokens,\n siteId,\n resolvedData,\n routeMap,\n wrapBlock,\n registry,\n usePlaceholders = false,\n blockOverrides,\n sdkConfig,\n supabaseUrl,\n dataContext,\n}: PageProps) {\n // Build theme tokens if not provided\n const baseTokens = providedTokens ?? buildThemeRuntime(theme).tokens;\n\n // Merge SDK palette tokens into theme tokens\n // This allows blocks to resolve SDK-defined color tokens (e.g., 'primary' -> '#6d28d9')\n const themeTokens = sdkConfig?.theme?.palette\n ? { ...baseTokens, palette: { ...baseTokens.palette, ...sdkConfig.theme.palette } }\n : baseTokens;\n\n return (\n <PageRenderer\n theme={theme}\n page={page}\n themeTokens={themeTokens}\n usePlaceholders={usePlaceholders}\n dataContext={{\n siteId,\n resolvedData,\n routes: routeMap,\n occurrenceContext: dataContext?.occurrenceContext ?? null,\n contentEntry: dataContext?.contentEntry ?? null,\n supabaseUrl,\n }}\n routeMap={routeMap}\n wrapBlock={wrapBlock}\n registry={registry}\n blockOverrides={blockOverrides}\n sdkConfig={sdkConfig}\n />\n );\n}\n","/**\n * Layout component with header and footer\n *\n * Renders site header and footer around content. Fetches site data if not provided.\n */\n\nimport { renderBlock, siteFooterManifest, siteHeaderManifest, buildThemeRuntime } from '@riverbankcms/blocks';\nimport { buildSimpleMenu, buildSimpleLogo } from '../../navigation';\nimport type { RiverbankClient, SiteResponse } from '../../client/types';\n\nexport type HeaderData = {\n menu: ReturnType<typeof buildSimpleMenu>;\n logo: ReturnType<typeof buildSimpleLogo>;\n site: SiteResponse['site'];\n theme: SiteResponse['theme'];\n routes: SiteResponse['routes'];\n};\n\nexport type LayoutProps = {\n // Option 1: Pass pre-fetched site data\n siteData?: SiteResponse;\n\n // Option 2: Fetch site data (provide client + identifier)\n client?: RiverbankClient;\n siteId?: string;\n slug?: string;\n domain?: string;\n\n // Content\n children: React.ReactNode;\n\n // Control rendering\n header?: boolean | ((data: HeaderData) => React.ReactNode);\n footer?: boolean;\n\n // Header variant override (if using default header)\n headerVariant?: 'classic' | 'centered' | 'transparent' | 'floating' | 'editorial';\n};\n\n/**\n * Layout component that wraps content with site header and footer.\n *\n * @example With pre-fetched site data (recommended)\n * ```tsx\n * const site = await client.getSite({ slug: 'my-site' });\n *\n * <Layout siteData={site}>\n * <Page {...pageData} />\n * </Layout>\n * ```\n *\n * @example With automatic fetching\n * ```tsx\n * <Layout client={client} slug=\"my-site\">\n * <Page {...pageData} />\n * </Layout>\n * ```\n */\nexport async function Layout({\n siteData: providedSiteData,\n client,\n siteId,\n slug,\n domain,\n children,\n header = true,\n footer = true,\n headerVariant,\n}: LayoutProps) {\n // Fetch site data if not provided\n let siteData = providedSiteData;\n if (!siteData) {\n if (!client) {\n throw new Error('Layout: must provide either siteData or client');\n }\n if (!siteId && !slug && !domain) {\n throw new Error('Layout: must provide siteId, slug, or domain when using client');\n }\n\n siteData = await client.getSite({ id: siteId, slug, domain });\n }\n\n const { site, theme, navigation, layout, routes } = siteData;\n const themeRuntime = buildThemeRuntime(theme);\n\n // Build view models for header/footer\n const menuViewModel = buildSimpleMenu(navigation, routes);\n const logoViewModel = buildSimpleLogo(layout.logo ?? null, site.title);\n\n // Prepare header data for custom headers\n const headerData: HeaderData = {\n menu: menuViewModel,\n logo: logoViewModel,\n site,\n theme,\n routes,\n };\n\n // Override header variant if specified\n const headerContent = headerVariant\n ? { ...layout.header, variant: headerVariant }\n : layout.header;\n\n // Override theme header variant if specified\n const themeWithVariant = headerVariant\n ? {\n ...theme,\n header: { ...theme.header, variant: headerVariant },\n }\n : theme;\n\n const viewModelOverrides = {\n $root: {\n siteId: site.id,\n routes,\n theme: themeWithVariant,\n },\n site,\n menu: menuViewModel,\n content: {\n logo: logoViewModel,\n },\n };\n\n // Render header based on type\n let headerElement: React.ReactNode = null;\n if (header === true) {\n // Default header rendering\n headerElement = renderBlock(siteHeaderManifest, headerContent, {\n theme: themeRuntime.tokens,\n themeConfig: themeWithVariant,\n viewModelOverrides,\n });\n } else if (typeof header === 'function') {\n // Custom header rendering\n headerElement = header(headerData);\n }\n\n return (\n <>\n {headerElement}\n\n {children}\n\n {footer && renderBlock(siteFooterManifest, layout.footer, {\n theme: themeRuntime.tokens,\n themeConfig: theme,\n viewModelOverrides,\n })}\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AA+II;AAzBG,SAAS,KAAK;AAAA,EACnB;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAc;AAEZ,QAAM,aAAa,kBAAkB,kBAAkB,KAAK,EAAE;AAI9D,QAAM,cAAc,WAAW,OAAO,UAClC,EAAE,GAAG,YAAY,SAAS,EAAE,GAAG,WAAW,SAAS,GAAG,UAAU,MAAM,QAAQ,EAAE,IAChF;AAEJ,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa;AAAA,QACX;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,mBAAmB,aAAa,qBAAqB;AAAA,QACrD,cAAc,aAAa,gBAAgB;AAAA,QAC3C;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF;AAEJ;;;ACxBI;AAjFJ,eAAsB,OAAO;AAAA,EAC3B,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT,SAAS;AAAA,EACT;AACF,GAAgB;AAEd,MAAI,WAAW;AACf,MAAI,CAAC,UAAU;AACb,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AACA,QAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ;AAC/B,YAAM,IAAI,MAAM,gEAAgE;AAAA,IAClF;AAEA,eAAW,MAAM,OAAO,QAAQ,EAAE,IAAI,QAAQ,MAAM,OAAO,CAAC;AAAA,EAC9D;AAEA,QAAM,EAAE,MAAM,OAAO,YAAY,QAAQ,OAAO,IAAI;AACpD,QAAM,eAAe,kBAAkB,KAAK;AAG5C,QAAM,gBAAgB,gBAAgB,YAAY,MAAM;AACxD,QAAM,gBAAgB,gBAAgB,OAAO,QAAQ,MAAM,KAAK,KAAK;AAGrE,QAAM,aAAyB;AAAA,IAC7B,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,QAAM,gBAAgB,gBAClB,EAAE,GAAG,OAAO,QAAQ,SAAS,cAAc,IAC3C,OAAO;AAGX,QAAM,mBAAmB,gBACrB;AAAA,IACE,GAAG;AAAA,IACH,QAAQ,EAAE,GAAG,MAAM,QAAQ,SAAS,cAAc;AAAA,EACpD,IACA;AAEJ,QAAM,qBAAqB;AAAA,IACzB,OAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,OAAO;AAAA,IACT;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,SAAS;AAAA,MACP,MAAM;AAAA,IACR;AAAA,EACF;AAGA,MAAI,gBAAiC;AACrC,MAAI,WAAW,MAAM;AAEnB,oBAAgB,YAAY,oBAAoB,eAAe;AAAA,MAC7D,OAAO,aAAa;AAAA,MACpB,aAAa;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH,WAAW,OAAO,WAAW,YAAY;AAEvC,oBAAgB,OAAO,UAAU;AAAA,EACnC;AAEA,SACE,iCACG;AAAA;AAAA,IAEA;AAAA,IAEA,UAAU,YAAY,oBAAoB,OAAO,QAAQ;AAAA,MACxD,OAAO,aAAa;AAAA,MACpB,aAAa;AAAA,MACb;AAAA,IACF,CAAC;AAAA,KACH;AAEJ;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-I2D7KOEA.js","../../src/rendering/helpers/loadContent.ts"],"names":["resolvedData"],"mappings":"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","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-I2D7KOEA.js","sourcesContent":[null,"/**\n * Server-side helper to fetch content (page or entry) by path.\n *\n * Use this for dynamic routing where a path could resolve to either\n * a page or a content entry.\n */\n\nimport type { Theme } from '@riverbankcms/blocks';\nimport type { RiverbankClient, PageResponse } from '../../client/types';\nimport type { PageProps } from '../components/Page';\nimport { prefetchBlockData } from '../../data/prefetchBlockData';\nimport type { ResolvedBlockData } from '../../data/prefetchBlockData';\n\nexport type LoadContentParams = {\n client: RiverbankClient;\n siteId: string;\n path: string;\n /**\n * If true, fetches draft/unpublished content instead of published content.\n * This affects both pages and entries.\n * Requires API key with site access.\n *\n * @default false\n */\n preview?: boolean;\n};\n\n/**\n * Content entry data returned when a path resolves to an entry\n */\nexport type ContentEntryData = {\n id: string;\n /** Content type key (e.g., 'blog-post', 'product') */\n type: string | null;\n title: string;\n slug: string | null;\n path: string | null;\n status: string;\n publishAt: string | null;\n /** The raw content fields - use these to render your own UI */\n content: Record<string, unknown>;\n metaTitle: string | null;\n metaDescription: string | null;\n createdAt: string;\n updatedAt: string;\n};\n\n/**\n * Result when path resolves to a page\n */\nexport type PageContentResult = {\n type: 'page';\n /** Page outline ready for rendering with <Page> component */\n page: PageProps['page'];\n /** Site theme for styling */\n theme: Theme;\n /** Site ID */\n siteId: string;\n /** Pre-fetched block data for data loaders */\n resolvedData: ResolvedBlockData;\n};\n\n/**\n * Result when path resolves to a content entry\n */\nexport type EntryContentResult = {\n type: 'entry';\n /** Raw entry data - render this however you want */\n entry: ContentEntryData;\n /** Template page for rendering the entry (if available) */\n templatePage: PageProps['page'] | null;\n /** Pre-fetched block data for template page data loaders */\n resolvedData: ResolvedBlockData;\n /** Data context for template blocks (includes entry content for bindings) */\n dataContext: { contentEntry: Record<string, unknown> };\n /** Site theme for styling (useful if rendering with SDK components) */\n theme: Theme;\n /** Site ID */\n siteId: string;\n};\n\n/**\n * Discriminated union result from loadContent\n */\nexport type LoadContentResult = PageContentResult | EntryContentResult;\n\n/**\n * Type guard to check if result is a page\n */\nexport function isPageContent(result: LoadContentResult): result is PageContentResult {\n return result.type === 'page';\n}\n\n/**\n * Type guard to check if result is an entry\n */\nexport function isEntryContent(result: LoadContentResult): result is EntryContentResult {\n return result.type === 'entry';\n}\n\n/**\n * Server-side helper to fetch content by path.\n *\n * Returns a discriminated union - either page data (ready for `<Page>` component)\n * or raw entry data (for custom rendering).\n *\n * @example Dynamic routing with both pages and entries\n * ```tsx\n * import { loadContent, Page, isPageContent } from '@riverbankcms/sdk';\n *\n * export default async function DynamicRoute({ params }) {\n * const content = await loadContent({\n * client,\n * siteId: 'site-123',\n * path: `/${params.slug?.join('/') || ''}`,\n * });\n *\n * if (isPageContent(content)) {\n * return <Page {...content} />;\n * }\n *\n * // Render entry with custom UI\n * return (\n * <article>\n * <h1>{content.entry.title}</h1>\n * <div>{content.entry.content.body}</div>\n * </article>\n * );\n * }\n * ```\n *\n * @example Entry-specific rendering based on content type\n * ```tsx\n * const content = await loadContent({ client, siteId, path });\n *\n * if (content.type === 'entry') {\n * switch (content.entry.type) {\n * case 'blog-post':\n * return <BlogPost entry={content.entry} theme={content.theme} />;\n * case 'product':\n * return <ProductPage entry={content.entry} theme={content.theme} />;\n * default:\n * return <GenericEntry entry={content.entry} />;\n * }\n * }\n *\n * return <Page {...content} />;\n * ```\n *\n * @example Preview mode for draft content\n * ```tsx\n * const content = await loadContent({\n * client,\n * siteId,\n * path,\n * preview: true, // Fetches draft content for both pages and entries\n * });\n * ```\n */\nexport async function loadContent(params: LoadContentParams): Promise<LoadContentResult> {\n const { client, siteId, path, preview = false } = params;\n\n // Fetch site and content in parallel\n const [site, contentResponse] = await Promise.all([\n client.getSite({ id: siteId }),\n client.getPage({ siteId, path, preview }),\n ]);\n\n // Check if response is an entry\n if (isEntryResponse(contentResponse)) {\n const entryData = contentResponse.entry;\n\n const entry: ContentEntryData = {\n id: entryData.id,\n type: entryData.type,\n title: entryData.title,\n slug: entryData.slug,\n path: entryData.path,\n status: entryData.status,\n publishAt: entryData.publishAt,\n // Use draft content in preview mode, otherwise use published content\n content: preview\n ? (entryData.draftContent ?? entryData.content)\n : entryData.content,\n metaTitle: preview\n ? (entryData.draftMetaTitle ?? entryData.metaTitle)\n : entryData.metaTitle,\n metaDescription: preview\n ? (entryData.draftMetaDescription ?? entryData.metaDescription)\n : entryData.metaDescription,\n createdAt: entryData.createdAt,\n updatedAt: entryData.updatedAt,\n };\n\n // Process template if available (uses first template from content type)\n const { templatePage, resolvedData } = await processEntryTemplate(\n contentResponse.templates as Template[] | undefined,\n entry,\n { siteId, preview },\n client\n );\n\n return {\n type: 'entry',\n entry,\n templatePage,\n resolvedData,\n dataContext: { contentEntry: entry.content },\n theme: site.theme,\n siteId,\n };\n }\n\n // Handle page response\n const { page: pageData } = contentResponse;\n\n // Convert API response blocks to PageOutline format with validation\n const blocks = pageData.blocks.map((block) => validateAndConvertBlock(block, 'page'));\n\n const pageOutline = {\n name: pageData.name,\n path: pageData.path,\n purpose: pageData.purpose,\n blocks,\n };\n\n // Prefetch block data loaders for pages\n const resolvedData = await prefetchBlockData(\n pageOutline,\n {\n siteId,\n pageId: pageData.id,\n previewStage: preview ? 'preview' : 'published',\n },\n client\n );\n\n return {\n type: 'page',\n page: pageOutline,\n theme: site.theme,\n siteId,\n resolvedData,\n };\n}\n\n/**\n * Type guard to check if API response is an entry\n */\nfunction isEntryResponse(response: PageResponse): response is Extract<PageResponse, { type: 'entry' }> {\n return 'type' in response && response.type === 'entry';\n}\n\n/**\n * Validates and converts a raw block from API response to PageOutline block format.\n * Used for both page blocks and template blocks to ensure consistent validation.\n */\nfunction validateAndConvertBlock(\n block: unknown,\n source: 'page' | 'template'\n): { id: string | null; kind: string; purpose: string; content?: Record<string, unknown> } {\n if (!block || typeof block !== 'object') {\n throw new Error(`Invalid block format in ${source} API response`);\n }\n\n const blockRecord = block as Record<string, unknown>;\n\n // Template blocks use 'blockKind', page blocks use 'kind'\n const kindField = source === 'template' ? 'blockKind' : 'kind';\n const kindValue = blockRecord[kindField];\n\n if (typeof blockRecord.id !== 'string' && blockRecord.id !== null) {\n throw new Error(`Invalid block id in ${source}: expected string or null, got ${typeof blockRecord.id}`);\n }\n if (typeof kindValue !== 'string') {\n throw new Error(`Invalid block ${kindField} in ${source}: expected string, got ${typeof kindValue}`);\n }\n\n // Template blocks derive purpose from scope, page blocks have explicit purpose\n if (source === 'page') {\n if (typeof blockRecord.purpose !== 'string') {\n throw new Error(`Invalid block purpose in ${source}: expected string, got ${typeof blockRecord.purpose}`);\n }\n return {\n id: blockRecord.id as string | null,\n kind: kindValue,\n purpose: blockRecord.purpose,\n };\n }\n\n // Template block: derive purpose from scope, include content\n const scope = blockRecord.scope as 'entry' | 'template' | undefined;\n const content = (blockRecord.content as Record<string, unknown> | null) ?? {};\n\n return {\n id: blockRecord.id as string | null,\n kind: kindValue,\n purpose: scope === 'entry' ? 'entry-content' : 'template-layout',\n content,\n };\n}\n\n/** Template block structure from API response */\ntype TemplateBlock = {\n id: string;\n blockKind: string;\n scope: 'entry' | 'template';\n content: Record<string, unknown> | null;\n};\n\n/** Template structure from API response */\ntype Template = {\n id: string;\n name: string;\n templateKey: string;\n blocks: TemplateBlock[];\n};\n\n/**\n * Processes an entry's template into a PageOutline format and prefetches block data.\n * Returns null templatePage if no valid template with blocks is available.\n */\nasync function processEntryTemplate(\n templates: Template[] | undefined,\n entry: ContentEntryData,\n context: { siteId: string; preview: boolean },\n client: RiverbankClient\n): Promise<{ templatePage: PageProps['page'] | null; resolvedData: ResolvedBlockData }> {\n const template = templates?.[0];\n\n // Templates without blocks are treated as \"no template\" - the entry should be\n // rendered with custom UI rather than an empty template page\n if (!template || !template.blocks?.length) {\n return { templatePage: null, resolvedData: {} };\n }\n\n // Convert template blocks to PageOutline format with validation\n const blocks = template.blocks.map((block) => validateAndConvertBlock(block, 'template'));\n\n const templatePage: PageProps['page'] = {\n name: template.name || 'Entry Template',\n path: entry.path || '/',\n purpose: 'entry-template',\n blocks,\n };\n\n // Prefetch block data for template\n const resolvedData = await prefetchBlockData(\n templatePage,\n {\n siteId: context.siteId,\n pageId: template.id,\n previewStage: context.preview ? 'preview' : 'published',\n },\n client\n );\n\n return { templatePage, resolvedData };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-PHS2KWJX.js","../../src/rendering/components/Page.tsx","../../src/rendering/components/Layout.tsx"],"names":[],"mappings":"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","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-PHS2KWJX.js","sourcesContent":[null,"/**\n * Pure Page renderer component for Riverbank CMS.\n *\n * This component expects all data to be provided via props.\n * For data fetching, use:\n * - Server-side: `await loadPage({ client, siteId, path })`\n * - Client-side: `usePage({ client, siteId, path })`\n */\n\nimport { PageRenderer, buildThemeRuntime } from '@riverbankcms/blocks';\nimport type { PageOutline, RouteMap, Theme, ThemeTokens, BlockOverrides, OccurrenceContextData } from '@riverbankcms/blocks';\nimport type { ResolvedBlockData } from '../../data';\nimport type { RuntimeSdkConfig } from '../helpers/loadPage';\n\n// Re-export OccurrenceContextData for SDK consumers\nexport type { OccurrenceContextData };\n\nexport type PageProps = {\n // Required data (must be provided by caller)\n page: PageOutline;\n theme: Theme;\n siteId: string;\n\n // Optional data\n themeTokens?: ThemeTokens; // If not provided, will be built from theme\n resolvedData?: ResolvedBlockData; // Pre-fetched block data\n routeMap?: RouteMap;\n /**\n * SDK site configuration containing theme palette overrides.\n * When provided, the SDK palette tokens are merged into the theme tokens,\n * allowing blocks to use SDK-defined color tokens for section backgrounds.\n */\n sdkConfig?: RuntimeSdkConfig | null;\n /**\n * Supabase storage URL for direct image access.\n * SDK sites receive this from the API instead of requiring NEXT_PUBLIC_SUPABASE_URL env var.\n */\n supabaseUrl?: string;\n\n /**\n * Additional context data for content entry pages.\n * Used to pass occurrence context and content entry data to blocks.\n */\n dataContext?: {\n /** Occurrence context for event pages (from URL like /events/yoga/2025-01-15) */\n occurrenceContext?: OccurrenceContextData | null;\n /** Content entry data for template pages */\n contentEntry?: Record<string, unknown> | null;\n };\n\n // Customization\n wrapBlock?: (blockId: string, rendered: React.ReactNode) => React.ReactNode;\n registry?: Parameters<typeof PageRenderer>[0]['registry'];\n usePlaceholders?: boolean;\n /**\n * Custom components to override default block rendering.\n * Keys can be full block kind (\"block.hero\") or short form (\"hero\").\n *\n * This is SSR-safe - no context or hooks required.\n *\n * @example\n * ```tsx\n * <Page\n * {...pageData}\n * blockOverrides={{\n * 'hero': MyCustomHero,\n * 'block.testimonials': MyCustomTestimonials,\n * }}\n * />\n * ```\n */\n blockOverrides?: BlockOverrides;\n};\n\n/**\n * Pure renderer for Riverbank CMS pages.\n *\n * This component expects all data to be provided via props.\n * For data fetching, use:\n * - Server-side: `await loadPage({ client, siteId, path })`\n * - Client-side: `usePage({ client, siteId, path })`\n *\n * @example Server-side (Next.js App Router)\n * ```tsx\n * import { createRiverbankClient } from '@riverbankcms/sdk';\n * import { loadPage, Page } from '@riverbankcms/sdk/rendering';\n *\n * const client = createRiverbankClient({ apiKey, baseUrl });\n *\n * export default async function PageRoute({ params }) {\n * const pageData = await loadPage({\n * client,\n * siteId: 'site-id',\n * path: `/${params.slug}`,\n * });\n *\n * return <Page {...pageData} />;\n * }\n * ```\n *\n * @example Client-side\n * ```tsx\n * import { createRiverbankClient } from '@riverbankcms/sdk';\n * import { usePage, Page } from '@riverbankcms/sdk/rendering';\n *\n * const client = createRiverbankClient({ apiKey, baseUrl });\n *\n * function MyPage({ path }) {\n * const pageData = usePage({ client, siteId: 'site-id', path });\n *\n * if (pageData.loading) return <LoadingState />;\n * if (pageData.error) return <ErrorState error={pageData.error} />;\n * if (!pageData.page) return <NotFound />;\n *\n * return <Page {...pageData} />;\n * }\n * ```\n */\nexport function Page({\n page,\n theme,\n themeTokens: providedTokens,\n siteId,\n resolvedData,\n routeMap,\n wrapBlock,\n registry,\n usePlaceholders = false,\n blockOverrides,\n sdkConfig,\n supabaseUrl,\n dataContext,\n}: PageProps) {\n // Build theme tokens if not provided\n const baseTokens = providedTokens ?? buildThemeRuntime(theme).tokens;\n\n // Merge SDK palette tokens into theme tokens\n // This allows blocks to resolve SDK-defined color tokens (e.g., 'primary' -> '#6d28d9')\n const themeTokens = sdkConfig?.theme?.palette\n ? { ...baseTokens, palette: { ...baseTokens.palette, ...sdkConfig.theme.palette } }\n : baseTokens;\n\n return (\n <PageRenderer\n theme={theme}\n page={page}\n themeTokens={themeTokens}\n usePlaceholders={usePlaceholders}\n dataContext={{\n siteId,\n resolvedData,\n routes: routeMap,\n occurrenceContext: dataContext?.occurrenceContext ?? null,\n contentEntry: dataContext?.contentEntry ?? null,\n supabaseUrl,\n }}\n routeMap={routeMap}\n wrapBlock={wrapBlock}\n registry={registry}\n blockOverrides={blockOverrides}\n sdkConfig={sdkConfig}\n />\n );\n}\n","/**\n * Layout component with header and footer\n *\n * Renders site header and footer around content. Fetches site data if not provided.\n */\n\nimport { renderBlock, siteFooterManifest, siteHeaderManifest, buildThemeRuntime } from '@riverbankcms/blocks';\nimport { buildSimpleMenu, buildSimpleLogo } from '../../navigation';\nimport type { RiverbankClient, SiteResponse } from '../../client/types';\n\nexport type HeaderData = {\n menu: ReturnType<typeof buildSimpleMenu>;\n logo: ReturnType<typeof buildSimpleLogo>;\n site: SiteResponse['site'];\n theme: SiteResponse['theme'];\n routes: SiteResponse['routes'];\n};\n\nexport type LayoutProps = {\n // Option 1: Pass pre-fetched site data\n siteData?: SiteResponse;\n\n // Option 2: Fetch site data (provide client + identifier)\n client?: RiverbankClient;\n siteId?: string;\n slug?: string;\n domain?: string;\n\n // Content\n children: React.ReactNode;\n\n // Control rendering\n header?: boolean | ((data: HeaderData) => React.ReactNode);\n footer?: boolean;\n\n // Header variant override (if using default header)\n headerVariant?: 'classic' | 'centered' | 'transparent' | 'floating' | 'editorial';\n};\n\n/**\n * Layout component that wraps content with site header and footer.\n *\n * @example With pre-fetched site data (recommended)\n * ```tsx\n * const site = await client.getSite({ slug: 'my-site' });\n *\n * <Layout siteData={site}>\n * <Page {...pageData} />\n * </Layout>\n * ```\n *\n * @example With automatic fetching\n * ```tsx\n * <Layout client={client} slug=\"my-site\">\n * <Page {...pageData} />\n * </Layout>\n * ```\n */\nexport async function Layout({\n siteData: providedSiteData,\n client,\n siteId,\n slug,\n domain,\n children,\n header = true,\n footer = true,\n headerVariant,\n}: LayoutProps) {\n // Fetch site data if not provided\n let siteData = providedSiteData;\n if (!siteData) {\n if (!client) {\n throw new Error('Layout: must provide either siteData or client');\n }\n if (!siteId && !slug && !domain) {\n throw new Error('Layout: must provide siteId, slug, or domain when using client');\n }\n\n siteData = await client.getSite({ id: siteId, slug, domain });\n }\n\n const { site, theme, navigation, layout, routes } = siteData;\n const themeRuntime = buildThemeRuntime(theme);\n\n // Build view models for header/footer\n const menuViewModel = buildSimpleMenu(navigation, routes);\n const logoViewModel = buildSimpleLogo(layout.logo ?? null, site.title);\n\n // Prepare header data for custom headers\n const headerData: HeaderData = {\n menu: menuViewModel,\n logo: logoViewModel,\n site,\n theme,\n routes,\n };\n\n // Override header variant if specified\n const headerContent = headerVariant\n ? { ...layout.header, variant: headerVariant }\n : layout.header;\n\n // Override theme header variant if specified\n const themeWithVariant = headerVariant\n ? {\n ...theme,\n header: { ...theme.header, variant: headerVariant },\n }\n : theme;\n\n const viewModelOverrides = {\n $root: {\n siteId: site.id,\n routes,\n theme: themeWithVariant,\n },\n site,\n menu: menuViewModel,\n content: {\n logo: logoViewModel,\n },\n };\n\n // Render header based on type\n let headerElement: React.ReactNode = null;\n if (header === true) {\n // Default header rendering\n headerElement = renderBlock(siteHeaderManifest, headerContent, {\n theme: themeRuntime.tokens,\n themeConfig: themeWithVariant,\n viewModelOverrides,\n });\n } else if (typeof header === 'function') {\n // Custom header rendering\n headerElement = header(headerData);\n }\n\n return (\n <>\n {headerElement}\n\n {children}\n\n {footer && renderBlock(siteFooterManifest, layout.footer, {\n theme: themeRuntime.tokens,\n themeConfig: theme,\n viewModelOverrides,\n })}\n </>\n );\n}\n"]}
|