@riverbankcms/sdk 0.1.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 +1892 -0
- package/dist/cli/index.js +327 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/client/analytics.d.mts +103 -0
- package/dist/client/analytics.d.ts +103 -0
- package/dist/client/analytics.js +197 -0
- package/dist/client/analytics.js.map +1 -0
- package/dist/client/analytics.mjs +169 -0
- package/dist/client/analytics.mjs.map +1 -0
- package/dist/client/bookings.d.mts +89 -0
- package/dist/client/bookings.d.ts +89 -0
- package/dist/client/bookings.js +34 -0
- package/dist/client/bookings.js.map +1 -0
- package/dist/client/bookings.mjs +11 -0
- package/dist/client/bookings.mjs.map +1 -0
- package/dist/client/client.d.mts +195 -0
- package/dist/client/client.d.ts +195 -0
- package/dist/client/client.js +606 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/client.mjs +572 -0
- package/dist/client/client.mjs.map +1 -0
- package/dist/client/hooks.d.mts +71 -0
- package/dist/client/hooks.d.ts +71 -0
- package/dist/client/hooks.js +264 -0
- package/dist/client/hooks.js.map +1 -0
- package/dist/client/hooks.mjs +235 -0
- package/dist/client/hooks.mjs.map +1 -0
- package/dist/client/rendering/client.d.mts +1 -0
- package/dist/client/rendering/client.d.ts +1 -0
- package/dist/client/rendering/client.js +33 -0
- package/dist/client/rendering/client.js.map +1 -0
- package/dist/client/rendering/client.mjs +8 -0
- package/dist/client/rendering/client.mjs.map +1 -0
- package/dist/client/usePage-BvKAa3Zw.d.mts +366 -0
- package/dist/client/usePage-BvKAa3Zw.d.ts +366 -0
- package/dist/server/chunk-2RW5HAQQ.mjs +86 -0
- package/dist/server/chunk-2RW5HAQQ.mjs.map +1 -0
- package/dist/server/chunk-3KKZVGH4.mjs +179 -0
- package/dist/server/chunk-3KKZVGH4.mjs.map +1 -0
- package/dist/server/chunk-4Z3GPTCS.js +179 -0
- package/dist/server/chunk-4Z3GPTCS.js.map +1 -0
- package/dist/server/chunk-4Z5FBFRL.mjs +211 -0
- package/dist/server/chunk-4Z5FBFRL.mjs.map +1 -0
- package/dist/server/chunk-ADREPXFU.js +86 -0
- package/dist/server/chunk-ADREPXFU.js.map +1 -0
- package/dist/server/chunk-F472SMKX.js +140 -0
- package/dist/server/chunk-F472SMKX.js.map +1 -0
- package/dist/server/chunk-GWBMJPLH.mjs +57 -0
- package/dist/server/chunk-GWBMJPLH.mjs.map +1 -0
- package/dist/server/chunk-JB4LIEFS.js +85 -0
- package/dist/server/chunk-JB4LIEFS.js.map +1 -0
- package/dist/server/chunk-PEAXKTDU.mjs +140 -0
- package/dist/server/chunk-PEAXKTDU.mjs.map +1 -0
- package/dist/server/chunk-QQ6U4QX6.js +120 -0
- package/dist/server/chunk-QQ6U4QX6.js.map +1 -0
- package/dist/server/chunk-R5YGLRUG.mjs +122 -0
- package/dist/server/chunk-R5YGLRUG.mjs.map +1 -0
- package/dist/server/chunk-SW7LE4M3.js +211 -0
- package/dist/server/chunk-SW7LE4M3.js.map +1 -0
- package/dist/server/chunk-W3K7LVPS.mjs +120 -0
- package/dist/server/chunk-W3K7LVPS.mjs.map +1 -0
- package/dist/server/chunk-WKG57P2H.mjs +85 -0
- package/dist/server/chunk-WKG57P2H.mjs.map +1 -0
- package/dist/server/chunk-YHEZMVTS.js +122 -0
- package/dist/server/chunk-YHEZMVTS.js.map +1 -0
- package/dist/server/chunk-YXDDFG3N.js +57 -0
- package/dist/server/chunk-YXDDFG3N.js.map +1 -0
- package/dist/server/components.d.mts +49 -0
- package/dist/server/components.d.ts +49 -0
- package/dist/server/components.js +22 -0
- package/dist/server/components.js.map +1 -0
- package/dist/server/components.mjs +22 -0
- package/dist/server/components.mjs.map +1 -0
- package/dist/server/config-validation.d.mts +300 -0
- package/dist/server/config-validation.d.ts +300 -0
- package/dist/server/config-validation.js +50 -0
- package/dist/server/config-validation.js.map +1 -0
- package/dist/server/config-validation.mjs +50 -0
- package/dist/server/config-validation.mjs.map +1 -0
- package/dist/server/config.d.mts +38 -0
- package/dist/server/config.d.ts +38 -0
- package/dist/server/config.js +44 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/config.mjs +44 -0
- package/dist/server/config.mjs.map +1 -0
- package/dist/server/data.d.mts +108 -0
- package/dist/server/data.d.ts +108 -0
- package/dist/server/data.js +15 -0
- package/dist/server/data.js.map +1 -0
- package/dist/server/data.mjs +15 -0
- package/dist/server/data.mjs.map +1 -0
- package/dist/server/index-B0yI_V6Z.d.mts +18 -0
- package/dist/server/index-C6M0Wfjq.d.ts +18 -0
- package/dist/server/index.d.mts +5 -0
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.js +12 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/index.mjs +12 -0
- package/dist/server/index.mjs.map +1 -0
- package/dist/server/loadContent-CJcbYF3J.d.ts +152 -0
- package/dist/server/loadContent-zhlL4YSE.d.mts +152 -0
- package/dist/server/loadPage-BYmVMk0V.d.ts +216 -0
- package/dist/server/loadPage-CCf15nt8.d.mts +216 -0
- package/dist/server/loadPage-DVH3DW6E.js +9 -0
- package/dist/server/loadPage-DVH3DW6E.js.map +1 -0
- package/dist/server/loadPage-PHQZ6XQZ.mjs +9 -0
- package/dist/server/loadPage-PHQZ6XQZ.mjs.map +1 -0
- package/dist/server/metadata.d.mts +135 -0
- package/dist/server/metadata.d.ts +135 -0
- package/dist/server/metadata.js +68 -0
- package/dist/server/metadata.js.map +1 -0
- package/dist/server/metadata.mjs +68 -0
- package/dist/server/metadata.mjs.map +1 -0
- package/dist/server/rendering/server.d.mts +83 -0
- package/dist/server/rendering/server.d.ts +83 -0
- package/dist/server/rendering/server.js +14 -0
- package/dist/server/rendering/server.js.map +1 -0
- package/dist/server/rendering/server.mjs +14 -0
- package/dist/server/rendering/server.mjs.map +1 -0
- package/dist/server/rendering.d.mts +12 -0
- package/dist/server/rendering.d.ts +12 -0
- package/dist/server/rendering.js +40 -0
- package/dist/server/rendering.js.map +1 -0
- package/dist/server/rendering.mjs +40 -0
- package/dist/server/rendering.mjs.map +1 -0
- package/dist/server/routing.d.mts +115 -0
- package/dist/server/routing.d.ts +115 -0
- package/dist/server/routing.js +57 -0
- package/dist/server/routing.js.map +1 -0
- package/dist/server/routing.mjs +57 -0
- package/dist/server/routing.mjs.map +1 -0
- package/dist/server/server.d.mts +9 -0
- package/dist/server/server.d.ts +9 -0
- package/dist/server/server.js +21 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/server.mjs +21 -0
- package/dist/server/server.mjs.map +1 -0
- package/dist/server/theme-bridge.d.mts +232 -0
- package/dist/server/theme-bridge.d.ts +232 -0
- package/dist/server/theme-bridge.js +231 -0
- package/dist/server/theme-bridge.js.map +1 -0
- package/dist/server/theme-bridge.mjs +231 -0
- package/dist/server/theme-bridge.mjs.map +1 -0
- package/dist/server/theme.d.mts +40 -0
- package/dist/server/theme.d.ts +40 -0
- package/dist/server/theme.js +17 -0
- package/dist/server/theme.js.map +1 -0
- package/dist/server/theme.mjs +17 -0
- package/dist/server/theme.mjs.map +1 -0
- package/dist/server/types-BCeqWtI2.d.mts +333 -0
- package/dist/server/types-BCeqWtI2.d.ts +333 -0
- package/dist/server/types-Bbo01M7P.d.mts +76 -0
- package/dist/server/types-Bbo01M7P.d.ts +76 -0
- package/dist/server/types-C6gmRHLe.d.mts +150 -0
- package/dist/server/types-C6gmRHLe.d.ts +150 -0
- package/package.json +147 -0
- package/src/styles/index.css +10 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { R as RiverbankClient, S as SiteResponse } from './types-C6gmRHLe.mjs';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { PageOutline, Theme, ThemeTokens, RouteMap, OccurrenceContextData, PageRenderer, BlockOverrides } from '@riverbankcms/blocks';
|
|
4
|
+
import { ResolvedBlockData } from '@riverbankcms/blocks/system/data';
|
|
5
|
+
import { D as DataLoaderOverrides } from './types-Bbo01M7P.mjs';
|
|
6
|
+
|
|
7
|
+
type PageProps = {
|
|
8
|
+
page: PageOutline;
|
|
9
|
+
theme: Theme;
|
|
10
|
+
siteId: string;
|
|
11
|
+
themeTokens?: ThemeTokens;
|
|
12
|
+
resolvedData?: ResolvedBlockData;
|
|
13
|
+
routeMap?: RouteMap;
|
|
14
|
+
/**
|
|
15
|
+
* SDK site configuration containing theme palette overrides.
|
|
16
|
+
* When provided, the SDK palette tokens are merged into the theme tokens,
|
|
17
|
+
* allowing blocks to use SDK-defined color tokens for section backgrounds.
|
|
18
|
+
*/
|
|
19
|
+
sdkConfig?: RuntimeSdkConfig | null;
|
|
20
|
+
/**
|
|
21
|
+
* Additional context data for content entry pages.
|
|
22
|
+
* Used to pass occurrence context and content entry data to blocks.
|
|
23
|
+
*/
|
|
24
|
+
dataContext?: {
|
|
25
|
+
/** Occurrence context for event pages (from URL like /events/yoga/2025-01-15) */
|
|
26
|
+
occurrenceContext?: OccurrenceContextData | null;
|
|
27
|
+
/** Content entry data for template pages */
|
|
28
|
+
contentEntry?: Record<string, unknown> | null;
|
|
29
|
+
};
|
|
30
|
+
wrapBlock?: (blockId: string, rendered: React.ReactNode) => React.ReactNode;
|
|
31
|
+
registry?: Parameters<typeof PageRenderer>[0]['registry'];
|
|
32
|
+
usePlaceholders?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Custom components to override default block rendering.
|
|
35
|
+
* Keys can be full block kind ("block.hero") or short form ("hero").
|
|
36
|
+
*
|
|
37
|
+
* This is SSR-safe - no context or hooks required.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```tsx
|
|
41
|
+
* <Page
|
|
42
|
+
* {...pageData}
|
|
43
|
+
* blockOverrides={{
|
|
44
|
+
* 'hero': MyCustomHero,
|
|
45
|
+
* 'block.testimonials': MyCustomTestimonials,
|
|
46
|
+
* }}
|
|
47
|
+
* />
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
blockOverrides?: BlockOverrides;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Pure renderer for Riverbank CMS pages.
|
|
54
|
+
*
|
|
55
|
+
* This component expects all data to be provided via props.
|
|
56
|
+
* For data fetching, use:
|
|
57
|
+
* - Server-side: `await loadPage({ client, siteId, path })`
|
|
58
|
+
* - Client-side: `usePage({ client, siteId, path })`
|
|
59
|
+
*
|
|
60
|
+
* @example Server-side (Next.js App Router)
|
|
61
|
+
* ```tsx
|
|
62
|
+
* import { createRiverbankClient } from '@riverbankcms/sdk';
|
|
63
|
+
* import { loadPage, Page } from '@riverbankcms/sdk/rendering';
|
|
64
|
+
*
|
|
65
|
+
* const client = createRiverbankClient({ apiKey, baseUrl });
|
|
66
|
+
*
|
|
67
|
+
* export default async function PageRoute({ params }) {
|
|
68
|
+
* const pageData = await loadPage({
|
|
69
|
+
* client,
|
|
70
|
+
* siteId: 'site-id',
|
|
71
|
+
* path: `/${params.slug}`,
|
|
72
|
+
* });
|
|
73
|
+
*
|
|
74
|
+
* return <Page {...pageData} />;
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @example Client-side
|
|
79
|
+
* ```tsx
|
|
80
|
+
* import { createRiverbankClient } from '@riverbankcms/sdk';
|
|
81
|
+
* import { usePage, Page } from '@riverbankcms/sdk/rendering';
|
|
82
|
+
*
|
|
83
|
+
* const client = createRiverbankClient({ apiKey, baseUrl });
|
|
84
|
+
*
|
|
85
|
+
* function MyPage({ path }) {
|
|
86
|
+
* const pageData = usePage({ client, siteId: 'site-id', path });
|
|
87
|
+
*
|
|
88
|
+
* if (pageData.loading) return <LoadingState />;
|
|
89
|
+
* if (pageData.error) return <ErrorState error={pageData.error} />;
|
|
90
|
+
* if (!pageData.page) return <NotFound />;
|
|
91
|
+
*
|
|
92
|
+
* return <Page {...pageData} />;
|
|
93
|
+
* }
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
declare function Page({ page, theme, themeTokens: providedTokens, siteId, resolvedData, routeMap, wrapBlock, registry, usePlaceholders, blockOverrides, sdkConfig, dataContext, }: PageProps): react_jsx_runtime.JSX.Element;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Server-side helper to fetch all data needed for <Page> component.
|
|
100
|
+
*
|
|
101
|
+
* Use this in server components, getServerSideProps, or API routes.
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* SDK config from API response (without siteId which is stripped at storage).
|
|
106
|
+
* This is the runtime representation - for defining configs, use RiverbankSiteConfig.
|
|
107
|
+
*/
|
|
108
|
+
type RuntimeSdkConfig = NonNullable<SiteResponse['sdkConfig']>;
|
|
109
|
+
type LoadPageParams = {
|
|
110
|
+
client: RiverbankClient;
|
|
111
|
+
siteId: string;
|
|
112
|
+
path: string;
|
|
113
|
+
pageId?: string;
|
|
114
|
+
/**
|
|
115
|
+
* If true, fetches draft/unpublished content instead of published content.
|
|
116
|
+
* This affects both the page structure and block data loaders.
|
|
117
|
+
* Requires API key with site access.
|
|
118
|
+
*
|
|
119
|
+
* @default false
|
|
120
|
+
*/
|
|
121
|
+
preview?: boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Code-based data loaders for custom blocks.
|
|
124
|
+
*
|
|
125
|
+
* Use this to fetch data from external APIs (not just whitelisted CMS endpoints).
|
|
126
|
+
* Keys are block kinds (e.g., 'custom.featured-products').
|
|
127
|
+
*
|
|
128
|
+
* Config-based loaders (defined in riverbank.config.ts) run first.
|
|
129
|
+
* Code loaders run second and take precedence on key conflicts.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* const pageData = await loadPage({
|
|
134
|
+
* client,
|
|
135
|
+
* siteId: 'site-123',
|
|
136
|
+
* path: '/',
|
|
137
|
+
* dataLoaderOverrides: {
|
|
138
|
+
* 'custom.featured-products': {
|
|
139
|
+
* products: async (ctx) => {
|
|
140
|
+
* const res = await fetch(`https://api.shop.com/products?category=${ctx.content.categoryId}`);
|
|
141
|
+
* return res.json();
|
|
142
|
+
* },
|
|
143
|
+
* },
|
|
144
|
+
* },
|
|
145
|
+
* });
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
dataLoaderOverrides?: DataLoaderOverrides;
|
|
149
|
+
};
|
|
150
|
+
type LoadPageResult = Omit<PageProps, 'registry' | 'wrapBlock' | 'usePlaceholders' | 'blockOverrides'> & {
|
|
151
|
+
/**
|
|
152
|
+
* SDK site configuration, if available.
|
|
153
|
+
* Contains SDK-defined theme palette, section backgrounds, and style options.
|
|
154
|
+
*/
|
|
155
|
+
sdkConfig: RuntimeSdkConfig | null;
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Server-side helper to fetch all data needed for <Page> component.
|
|
159
|
+
*
|
|
160
|
+
* Fetches site data, page data, and prefetches block data loaders in parallel.
|
|
161
|
+
*
|
|
162
|
+
* @example Next.js App Router (published content)
|
|
163
|
+
* ```tsx
|
|
164
|
+
* import { createRiverbankClient } from '@riverbankcms/sdk';
|
|
165
|
+
* import { loadPage, Page } from '@riverbankcms/sdk/rendering';
|
|
166
|
+
*
|
|
167
|
+
* const client = createRiverbankClient({
|
|
168
|
+
* apiKey: process.env.RIVERBANK_API_KEY!,
|
|
169
|
+
* baseUrl: process.env.NEXT_PUBLIC_DASHBOARD_URL + '/api',
|
|
170
|
+
* });
|
|
171
|
+
*
|
|
172
|
+
* export default async function PageRoute({ params }) {
|
|
173
|
+
* const pageData = await loadPage({
|
|
174
|
+
* client,
|
|
175
|
+
* siteId: 'site-123',
|
|
176
|
+
* path: `/${params.slug || ''}`,
|
|
177
|
+
* });
|
|
178
|
+
*
|
|
179
|
+
* return <Page {...pageData} />;
|
|
180
|
+
* }
|
|
181
|
+
* ```
|
|
182
|
+
*
|
|
183
|
+
* @example Next.js App Router (preview/draft content)
|
|
184
|
+
* ```tsx
|
|
185
|
+
* export default async function PreviewRoute({ params, searchParams }) {
|
|
186
|
+
* const pageData = await loadPage({
|
|
187
|
+
* client,
|
|
188
|
+
* siteId: searchParams.siteId,
|
|
189
|
+
* path: `/${params.slug || ''}`,
|
|
190
|
+
* preview: true, // Fetch draft content
|
|
191
|
+
* });
|
|
192
|
+
*
|
|
193
|
+
* return <Page {...pageData} />;
|
|
194
|
+
* }
|
|
195
|
+
* ```
|
|
196
|
+
*
|
|
197
|
+
* @example Next.js Pages Router (getServerSideProps)
|
|
198
|
+
* ```tsx
|
|
199
|
+
* export async function getServerSideProps({ params }) {
|
|
200
|
+
* const pageData = await loadPage({
|
|
201
|
+
* client,
|
|
202
|
+
* siteId: 'site-123',
|
|
203
|
+
* path: `/${params.slug || ''}`,
|
|
204
|
+
* });
|
|
205
|
+
*
|
|
206
|
+
* return { props: pageData };
|
|
207
|
+
* }
|
|
208
|
+
*
|
|
209
|
+
* export default function PageRoute(props) {
|
|
210
|
+
* return <Page {...props} />;
|
|
211
|
+
* }
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
declare function loadPage(params: LoadPageParams): Promise<LoadPageResult>;
|
|
215
|
+
|
|
216
|
+
export { type LoadPageParams as L, Page as P, type RuntimeSdkConfig as R, type LoadPageResult as a, type PageProps as b, loadPage as l };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
var _chunkADREPXFUjs = require('./chunk-ADREPXFU.js');
|
|
4
|
+
require('./chunk-YXDDFG3N.js');
|
|
5
|
+
require('./chunk-QQ6U4QX6.js');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
exports.loadPage = _chunkADREPXFUjs.loadPage;
|
|
9
|
+
//# sourceMappingURL=loadPage-DVH3DW6E.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/loadPage-DVH3DW6E.js"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B;AACE;AACF,6CAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/loadPage-DVH3DW6E.js"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { a as LoadPageResult } from './loadPage-CCf15nt8.mjs';
|
|
2
|
+
import { S as SiteResponse } from './types-C6gmRHLe.mjs';
|
|
3
|
+
import 'react/jsx-runtime';
|
|
4
|
+
import '@riverbankcms/blocks';
|
|
5
|
+
import '@riverbankcms/blocks/system/data';
|
|
6
|
+
import './types-Bbo01M7P.mjs';
|
|
7
|
+
import '@riverbankcms/api';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Metadata generation helper for Next.js pages
|
|
11
|
+
*
|
|
12
|
+
* Generates SEO-optimized metadata from Builder page data for use in
|
|
13
|
+
* Next.js generateMetadata() functions.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Next.js Metadata type
|
|
18
|
+
* Simplified version to avoid requiring Next.js as a dependency
|
|
19
|
+
*/
|
|
20
|
+
type Metadata = {
|
|
21
|
+
title?: string;
|
|
22
|
+
description?: string;
|
|
23
|
+
alternates?: {
|
|
24
|
+
canonical?: string;
|
|
25
|
+
};
|
|
26
|
+
openGraph?: {
|
|
27
|
+
title?: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
url?: string;
|
|
30
|
+
siteName?: string;
|
|
31
|
+
type?: string;
|
|
32
|
+
images?: Array<{
|
|
33
|
+
url: string;
|
|
34
|
+
alt?: string;
|
|
35
|
+
}>;
|
|
36
|
+
};
|
|
37
|
+
twitter?: {
|
|
38
|
+
card?: string;
|
|
39
|
+
title?: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
images?: string[];
|
|
42
|
+
};
|
|
43
|
+
robots?: {
|
|
44
|
+
index?: boolean;
|
|
45
|
+
follow?: boolean;
|
|
46
|
+
};
|
|
47
|
+
verification?: {
|
|
48
|
+
google?: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
type PageMetadataInput = {
|
|
52
|
+
/**
|
|
53
|
+
* Page data from loadPage() or custom page object
|
|
54
|
+
*/
|
|
55
|
+
page: LoadPageResult['page'] | {
|
|
56
|
+
name: string;
|
|
57
|
+
purpose?: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Site data from client.getSite()
|
|
61
|
+
*/
|
|
62
|
+
site: SiteResponse['site'];
|
|
63
|
+
/**
|
|
64
|
+
* Current URL path (e.g., '/about', '/blog/post-1')
|
|
65
|
+
*/
|
|
66
|
+
path: string;
|
|
67
|
+
/**
|
|
68
|
+
* Full site URL for canonical and OG URLs
|
|
69
|
+
* Example: 'https://example.com'
|
|
70
|
+
*/
|
|
71
|
+
siteUrl: string;
|
|
72
|
+
/**
|
|
73
|
+
* Optional custom metadata overrides
|
|
74
|
+
*/
|
|
75
|
+
overrides?: {
|
|
76
|
+
title?: string;
|
|
77
|
+
description?: string;
|
|
78
|
+
ogImage?: string;
|
|
79
|
+
canonicalUrl?: string;
|
|
80
|
+
robots?: {
|
|
81
|
+
index?: boolean;
|
|
82
|
+
follow?: boolean;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Optional Google site verification token
|
|
87
|
+
*/
|
|
88
|
+
googleSiteVerification?: string;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Generate Next.js Metadata object from Builder page data
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```tsx
|
|
95
|
+
* import { generatePageMetadata } from '@riverbankcms/sdk/metadata';
|
|
96
|
+
* import { loadPage } from '@riverbankcms/sdk';
|
|
97
|
+
*
|
|
98
|
+
* export async function generateMetadata({ params }) {
|
|
99
|
+
* const pageData = await loadPage({ client, siteId, path: params.slug });
|
|
100
|
+
* const siteData = await client.getSite({ id: siteId });
|
|
101
|
+
*
|
|
102
|
+
* return generatePageMetadata({
|
|
103
|
+
* page: pageData.page,
|
|
104
|
+
* site: siteData.site,
|
|
105
|
+
* path: params.slug,
|
|
106
|
+
* siteUrl: 'https://example.com',
|
|
107
|
+
* });
|
|
108
|
+
* }
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
declare function generatePageMetadata(input: PageMetadataInput): Metadata;
|
|
112
|
+
/**
|
|
113
|
+
* Generate metadata for preview/staging environments
|
|
114
|
+
*
|
|
115
|
+
* This helper adds noindex/nofollow robots tags to prevent search engines
|
|
116
|
+
* from indexing preview or staging URLs.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```tsx
|
|
120
|
+
* export async function generateMetadata({ params }) {
|
|
121
|
+
* const pageData = await loadPage({ client, siteId, path: params.slug });
|
|
122
|
+
* const isPreview = process.env.VERCEL_ENV !== 'production';
|
|
123
|
+
*
|
|
124
|
+
* return generatePreviewMetadata({
|
|
125
|
+
* page: pageData.page,
|
|
126
|
+
* site: siteData.site,
|
|
127
|
+
* path: params.slug,
|
|
128
|
+
* siteUrl: 'https://example.com',
|
|
129
|
+
* });
|
|
130
|
+
* }
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
declare function generatePreviewMetadata(input: PageMetadataInput): Metadata;
|
|
134
|
+
|
|
135
|
+
export { type PageMetadataInput, generatePageMetadata, generatePreviewMetadata };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { a as LoadPageResult } from './loadPage-BYmVMk0V.js';
|
|
2
|
+
import { S as SiteResponse } from './types-C6gmRHLe.js';
|
|
3
|
+
import 'react/jsx-runtime';
|
|
4
|
+
import '@riverbankcms/blocks';
|
|
5
|
+
import '@riverbankcms/blocks/system/data';
|
|
6
|
+
import './types-Bbo01M7P.js';
|
|
7
|
+
import '@riverbankcms/api';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Metadata generation helper for Next.js pages
|
|
11
|
+
*
|
|
12
|
+
* Generates SEO-optimized metadata from Builder page data for use in
|
|
13
|
+
* Next.js generateMetadata() functions.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Next.js Metadata type
|
|
18
|
+
* Simplified version to avoid requiring Next.js as a dependency
|
|
19
|
+
*/
|
|
20
|
+
type Metadata = {
|
|
21
|
+
title?: string;
|
|
22
|
+
description?: string;
|
|
23
|
+
alternates?: {
|
|
24
|
+
canonical?: string;
|
|
25
|
+
};
|
|
26
|
+
openGraph?: {
|
|
27
|
+
title?: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
url?: string;
|
|
30
|
+
siteName?: string;
|
|
31
|
+
type?: string;
|
|
32
|
+
images?: Array<{
|
|
33
|
+
url: string;
|
|
34
|
+
alt?: string;
|
|
35
|
+
}>;
|
|
36
|
+
};
|
|
37
|
+
twitter?: {
|
|
38
|
+
card?: string;
|
|
39
|
+
title?: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
images?: string[];
|
|
42
|
+
};
|
|
43
|
+
robots?: {
|
|
44
|
+
index?: boolean;
|
|
45
|
+
follow?: boolean;
|
|
46
|
+
};
|
|
47
|
+
verification?: {
|
|
48
|
+
google?: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
type PageMetadataInput = {
|
|
52
|
+
/**
|
|
53
|
+
* Page data from loadPage() or custom page object
|
|
54
|
+
*/
|
|
55
|
+
page: LoadPageResult['page'] | {
|
|
56
|
+
name: string;
|
|
57
|
+
purpose?: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Site data from client.getSite()
|
|
61
|
+
*/
|
|
62
|
+
site: SiteResponse['site'];
|
|
63
|
+
/**
|
|
64
|
+
* Current URL path (e.g., '/about', '/blog/post-1')
|
|
65
|
+
*/
|
|
66
|
+
path: string;
|
|
67
|
+
/**
|
|
68
|
+
* Full site URL for canonical and OG URLs
|
|
69
|
+
* Example: 'https://example.com'
|
|
70
|
+
*/
|
|
71
|
+
siteUrl: string;
|
|
72
|
+
/**
|
|
73
|
+
* Optional custom metadata overrides
|
|
74
|
+
*/
|
|
75
|
+
overrides?: {
|
|
76
|
+
title?: string;
|
|
77
|
+
description?: string;
|
|
78
|
+
ogImage?: string;
|
|
79
|
+
canonicalUrl?: string;
|
|
80
|
+
robots?: {
|
|
81
|
+
index?: boolean;
|
|
82
|
+
follow?: boolean;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Optional Google site verification token
|
|
87
|
+
*/
|
|
88
|
+
googleSiteVerification?: string;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Generate Next.js Metadata object from Builder page data
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```tsx
|
|
95
|
+
* import { generatePageMetadata } from '@riverbankcms/sdk/metadata';
|
|
96
|
+
* import { loadPage } from '@riverbankcms/sdk';
|
|
97
|
+
*
|
|
98
|
+
* export async function generateMetadata({ params }) {
|
|
99
|
+
* const pageData = await loadPage({ client, siteId, path: params.slug });
|
|
100
|
+
* const siteData = await client.getSite({ id: siteId });
|
|
101
|
+
*
|
|
102
|
+
* return generatePageMetadata({
|
|
103
|
+
* page: pageData.page,
|
|
104
|
+
* site: siteData.site,
|
|
105
|
+
* path: params.slug,
|
|
106
|
+
* siteUrl: 'https://example.com',
|
|
107
|
+
* });
|
|
108
|
+
* }
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
declare function generatePageMetadata(input: PageMetadataInput): Metadata;
|
|
112
|
+
/**
|
|
113
|
+
* Generate metadata for preview/staging environments
|
|
114
|
+
*
|
|
115
|
+
* This helper adds noindex/nofollow robots tags to prevent search engines
|
|
116
|
+
* from indexing preview or staging URLs.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```tsx
|
|
120
|
+
* export async function generateMetadata({ params }) {
|
|
121
|
+
* const pageData = await loadPage({ client, siteId, path: params.slug });
|
|
122
|
+
* const isPreview = process.env.VERCEL_ENV !== 'production';
|
|
123
|
+
*
|
|
124
|
+
* return generatePreviewMetadata({
|
|
125
|
+
* page: pageData.page,
|
|
126
|
+
* site: siteData.site,
|
|
127
|
+
* path: params.slug,
|
|
128
|
+
* siteUrl: 'https://example.com',
|
|
129
|
+
* });
|
|
130
|
+
* }
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
declare function generatePreviewMetadata(input: PageMetadataInput): Metadata;
|
|
134
|
+
|
|
135
|
+
export { type PageMetadataInput, generatePageMetadata, generatePreviewMetadata };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/metadata/generatePageMetadata.ts
|
|
2
|
+
function generatePageMetadata(input) {
|
|
3
|
+
const { page, site, path, siteUrl, overrides, googleSiteVerification } = input;
|
|
4
|
+
const pageTitle = _nullishCoalesce(_optionalChain([overrides, 'optionalAccess', _ => _.title]), () => ( page.name));
|
|
5
|
+
const fullTitle = pageTitle === site.title ? pageTitle : `${pageTitle} | ${site.title}`;
|
|
6
|
+
const description = _nullishCoalesce(_optionalChain([overrides, 'optionalAccess', _2 => _2.description]), () => ( page.purpose));
|
|
7
|
+
const canonicalUrl = _nullishCoalesce(_optionalChain([overrides, 'optionalAccess', _3 => _3.canonicalUrl]), () => ( `${siteUrl}${path}`));
|
|
8
|
+
const fullUrl = `${siteUrl}${path}`;
|
|
9
|
+
const metadata = {
|
|
10
|
+
title: fullTitle,
|
|
11
|
+
description: _nullishCoalesce(description, () => ( void 0)),
|
|
12
|
+
alternates: {
|
|
13
|
+
canonical: canonicalUrl
|
|
14
|
+
},
|
|
15
|
+
openGraph: {
|
|
16
|
+
title: pageTitle,
|
|
17
|
+
description: _nullishCoalesce(description, () => ( void 0)),
|
|
18
|
+
url: fullUrl,
|
|
19
|
+
siteName: site.title,
|
|
20
|
+
type: "website",
|
|
21
|
+
..._optionalChain([overrides, 'optionalAccess', _4 => _4.ogImage]) ? {
|
|
22
|
+
images: [
|
|
23
|
+
{
|
|
24
|
+
url: overrides.ogImage,
|
|
25
|
+
alt: pageTitle
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
} : {}
|
|
29
|
+
},
|
|
30
|
+
twitter: {
|
|
31
|
+
card: "summary_large_image",
|
|
32
|
+
title: pageTitle,
|
|
33
|
+
description: _nullishCoalesce(description, () => ( void 0)),
|
|
34
|
+
..._optionalChain([overrides, 'optionalAccess', _5 => _5.ogImage]) ? {
|
|
35
|
+
images: [overrides.ogImage]
|
|
36
|
+
} : {}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
if (_optionalChain([overrides, 'optionalAccess', _6 => _6.robots])) {
|
|
40
|
+
metadata.robots = {
|
|
41
|
+
index: _nullishCoalesce(overrides.robots.index, () => ( true)),
|
|
42
|
+
follow: _nullishCoalesce(overrides.robots.follow, () => ( true))
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (googleSiteVerification) {
|
|
46
|
+
metadata.verification = {
|
|
47
|
+
google: googleSiteVerification
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return metadata;
|
|
51
|
+
}
|
|
52
|
+
function generatePreviewMetadata(input) {
|
|
53
|
+
return generatePageMetadata({
|
|
54
|
+
...input,
|
|
55
|
+
overrides: {
|
|
56
|
+
...input.overrides,
|
|
57
|
+
robots: {
|
|
58
|
+
index: false,
|
|
59
|
+
follow: false
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
exports.generatePageMetadata = generatePageMetadata; exports.generatePreviewMetadata = generatePreviewMetadata;
|
|
68
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/metadata.js","../../src/metadata/generatePageMetadata.ts"],"names":[],"mappings":"AAAA;ACgHO,SAAS,oBAAA,CAAqB,KAAA,EAAoC;AACvE,EAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,OAAA,EAAS,SAAA,EAAW,uBAAuB,EAAA,EAAI,KAAA;AAGzE,EAAA,MAAM,UAAA,mCAAY,SAAA,2BAAW,OAAA,UAAS,IAAA,CAAK,MAAA;AAC3C,EAAA,MAAM,UAAA,EAAY,UAAA,IAAc,IAAA,CAAK,MAAA,EAAQ,UAAA,EAAY,CAAA,EAAA;AAGN,EAAA;AAGO,EAAA;AACzB,EAAA;AAGN,EAAA;AAClB,IAAA;AACqB,IAAA;AAChB,IAAA;AACC,MAAA;AACb,IAAA;AACW,IAAA;AACF,MAAA;AACqB,MAAA;AACvB,MAAA;AACU,MAAA;AACT,MAAA;AAEF,MAAA;AACU,QAAA;AACN,UAAA;AACiB,YAAA;AACV,YAAA;AACP,UAAA;AACF,QAAA;AAED,MAAA;AACP,IAAA;AACS,IAAA;AACD,MAAA;AACC,MAAA;AACqB,MAAA;AAExB,MAAA;AAC4B,QAAA;AAE3B,MAAA;AACP,IAAA;AACF,EAAA;AAGuB,EAAA;AACH,IAAA;AACiB,MAAA;AACE,MAAA;AACrC,IAAA;AACF,EAAA;AAG4B,EAAA;AACF,IAAA;AACd,MAAA;AACV,IAAA;AACF,EAAA;AAEO,EAAA;AACT;AAuB4E;AAC9C,EAAA;AACvB,IAAA;AACQ,IAAA;AACA,MAAA;AACD,MAAA;AACC,QAAA;AACC,QAAA;AACV,MAAA;AACF,IAAA;AACD,EAAA;AACH;ADrJ4D;AACA;AACA;AACA","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/metadata.js","sourcesContent":[null,"/**\n * Metadata generation helper for Next.js pages\n *\n * Generates SEO-optimized metadata from Builder page data for use in\n * Next.js generateMetadata() functions.\n */\n\nimport type { LoadPageResult } from '../rendering/helpers/loadPage';\nimport type { SiteResponse } from '../client/types';\n\n/**\n * Next.js Metadata type\n * Simplified version to avoid requiring Next.js as a dependency\n */\nexport type Metadata = {\n title?: string;\n description?: string;\n alternates?: {\n canonical?: string;\n };\n openGraph?: {\n title?: string;\n description?: string;\n url?: string;\n siteName?: string;\n type?: string;\n images?: Array<{\n url: string;\n alt?: string;\n }>;\n };\n twitter?: {\n card?: string;\n title?: string;\n description?: string;\n images?: string[];\n };\n robots?: {\n index?: boolean;\n follow?: boolean;\n };\n verification?: {\n google?: string;\n };\n};\n\nexport type PageMetadataInput = {\n /**\n * Page data from loadPage() or custom page object\n */\n page: LoadPageResult['page'] | {\n name: string;\n purpose?: string;\n };\n\n /**\n * Site data from client.getSite()\n */\n site: SiteResponse['site'];\n\n /**\n * Current URL path (e.g., '/about', '/blog/post-1')\n */\n path: string;\n\n /**\n * Full site URL for canonical and OG URLs\n * Example: 'https://example.com'\n */\n siteUrl: string;\n\n /**\n * Optional custom metadata overrides\n */\n overrides?: {\n title?: string;\n description?: string;\n ogImage?: string;\n canonicalUrl?: string;\n robots?: {\n index?: boolean;\n follow?: boolean;\n };\n };\n\n /**\n * Optional Google site verification token\n */\n googleSiteVerification?: string;\n};\n\n/**\n * Generate Next.js Metadata object from Builder page data\n *\n * @example\n * ```tsx\n * import { generatePageMetadata } from '@riverbankcms/sdk/metadata';\n * import { loadPage } from '@riverbankcms/sdk';\n *\n * export async function generateMetadata({ params }) {\n * const pageData = await loadPage({ client, siteId, path: params.slug });\n * const siteData = await client.getSite({ id: siteId });\n *\n * return generatePageMetadata({\n * page: pageData.page,\n * site: siteData.site,\n * path: params.slug,\n * siteUrl: 'https://example.com',\n * });\n * }\n * ```\n */\nexport function generatePageMetadata(input: PageMetadataInput): Metadata {\n const { page, site, path, siteUrl, overrides, googleSiteVerification } = input;\n\n // Build page title\n const pageTitle = overrides?.title ?? page.name;\n const fullTitle = pageTitle === site.title ? pageTitle : `${pageTitle} | ${site.title}`;\n\n // Use page purpose as description fallback\n const description = overrides?.description ?? page.purpose;\n\n // Build full URLs\n const canonicalUrl = overrides?.canonicalUrl ?? `${siteUrl}${path}`;\n const fullUrl = `${siteUrl}${path}`;\n\n // Build metadata object\n const metadata: Metadata = {\n title: fullTitle,\n description: description ?? undefined,\n alternates: {\n canonical: canonicalUrl,\n },\n openGraph: {\n title: pageTitle,\n description: description ?? undefined,\n url: fullUrl,\n siteName: site.title,\n type: 'website',\n ...(overrides?.ogImage\n ? {\n images: [\n {\n url: overrides.ogImage,\n alt: pageTitle,\n },\n ],\n }\n : {}),\n },\n twitter: {\n card: 'summary_large_image',\n title: pageTitle,\n description: description ?? undefined,\n ...(overrides?.ogImage\n ? {\n images: [overrides.ogImage],\n }\n : {}),\n },\n };\n\n // Add robots meta if specified\n if (overrides?.robots) {\n metadata.robots = {\n index: overrides.robots.index ?? true,\n follow: overrides.robots.follow ?? true,\n };\n }\n\n // Add Google site verification if provided\n if (googleSiteVerification) {\n metadata.verification = {\n google: googleSiteVerification,\n };\n }\n\n return metadata;\n}\n\n/**\n * Generate metadata for preview/staging environments\n *\n * This helper adds noindex/nofollow robots tags to prevent search engines\n * from indexing preview or staging URLs.\n *\n * @example\n * ```tsx\n * export async function generateMetadata({ params }) {\n * const pageData = await loadPage({ client, siteId, path: params.slug });\n * const isPreview = process.env.VERCEL_ENV !== 'production';\n *\n * return generatePreviewMetadata({\n * page: pageData.page,\n * site: siteData.site,\n * path: params.slug,\n * siteUrl: 'https://example.com',\n * });\n * }\n * ```\n */\nexport function generatePreviewMetadata(input: PageMetadataInput): Metadata {\n return generatePageMetadata({\n ...input,\n overrides: {\n ...input.overrides,\n robots: {\n index: false,\n follow: false,\n },\n },\n });\n}\n"]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// src/metadata/generatePageMetadata.ts
|
|
2
|
+
function generatePageMetadata(input) {
|
|
3
|
+
const { page, site, path, siteUrl, overrides, googleSiteVerification } = input;
|
|
4
|
+
const pageTitle = overrides?.title ?? page.name;
|
|
5
|
+
const fullTitle = pageTitle === site.title ? pageTitle : `${pageTitle} | ${site.title}`;
|
|
6
|
+
const description = overrides?.description ?? page.purpose;
|
|
7
|
+
const canonicalUrl = overrides?.canonicalUrl ?? `${siteUrl}${path}`;
|
|
8
|
+
const fullUrl = `${siteUrl}${path}`;
|
|
9
|
+
const metadata = {
|
|
10
|
+
title: fullTitle,
|
|
11
|
+
description: description ?? void 0,
|
|
12
|
+
alternates: {
|
|
13
|
+
canonical: canonicalUrl
|
|
14
|
+
},
|
|
15
|
+
openGraph: {
|
|
16
|
+
title: pageTitle,
|
|
17
|
+
description: description ?? void 0,
|
|
18
|
+
url: fullUrl,
|
|
19
|
+
siteName: site.title,
|
|
20
|
+
type: "website",
|
|
21
|
+
...overrides?.ogImage ? {
|
|
22
|
+
images: [
|
|
23
|
+
{
|
|
24
|
+
url: overrides.ogImage,
|
|
25
|
+
alt: pageTitle
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
} : {}
|
|
29
|
+
},
|
|
30
|
+
twitter: {
|
|
31
|
+
card: "summary_large_image",
|
|
32
|
+
title: pageTitle,
|
|
33
|
+
description: description ?? void 0,
|
|
34
|
+
...overrides?.ogImage ? {
|
|
35
|
+
images: [overrides.ogImage]
|
|
36
|
+
} : {}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
if (overrides?.robots) {
|
|
40
|
+
metadata.robots = {
|
|
41
|
+
index: overrides.robots.index ?? true,
|
|
42
|
+
follow: overrides.robots.follow ?? true
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (googleSiteVerification) {
|
|
46
|
+
metadata.verification = {
|
|
47
|
+
google: googleSiteVerification
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return metadata;
|
|
51
|
+
}
|
|
52
|
+
function generatePreviewMetadata(input) {
|
|
53
|
+
return generatePageMetadata({
|
|
54
|
+
...input,
|
|
55
|
+
overrides: {
|
|
56
|
+
...input.overrides,
|
|
57
|
+
robots: {
|
|
58
|
+
index: false,
|
|
59
|
+
follow: false
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
generatePageMetadata,
|
|
66
|
+
generatePreviewMetadata
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=metadata.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/metadata/generatePageMetadata.ts"],"sourcesContent":["/**\n * Metadata generation helper for Next.js pages\n *\n * Generates SEO-optimized metadata from Builder page data for use in\n * Next.js generateMetadata() functions.\n */\n\nimport type { LoadPageResult } from '../rendering/helpers/loadPage';\nimport type { SiteResponse } from '../client/types';\n\n/**\n * Next.js Metadata type\n * Simplified version to avoid requiring Next.js as a dependency\n */\nexport type Metadata = {\n title?: string;\n description?: string;\n alternates?: {\n canonical?: string;\n };\n openGraph?: {\n title?: string;\n description?: string;\n url?: string;\n siteName?: string;\n type?: string;\n images?: Array<{\n url: string;\n alt?: string;\n }>;\n };\n twitter?: {\n card?: string;\n title?: string;\n description?: string;\n images?: string[];\n };\n robots?: {\n index?: boolean;\n follow?: boolean;\n };\n verification?: {\n google?: string;\n };\n};\n\nexport type PageMetadataInput = {\n /**\n * Page data from loadPage() or custom page object\n */\n page: LoadPageResult['page'] | {\n name: string;\n purpose?: string;\n };\n\n /**\n * Site data from client.getSite()\n */\n site: SiteResponse['site'];\n\n /**\n * Current URL path (e.g., '/about', '/blog/post-1')\n */\n path: string;\n\n /**\n * Full site URL for canonical and OG URLs\n * Example: 'https://example.com'\n */\n siteUrl: string;\n\n /**\n * Optional custom metadata overrides\n */\n overrides?: {\n title?: string;\n description?: string;\n ogImage?: string;\n canonicalUrl?: string;\n robots?: {\n index?: boolean;\n follow?: boolean;\n };\n };\n\n /**\n * Optional Google site verification token\n */\n googleSiteVerification?: string;\n};\n\n/**\n * Generate Next.js Metadata object from Builder page data\n *\n * @example\n * ```tsx\n * import { generatePageMetadata } from '@riverbankcms/sdk/metadata';\n * import { loadPage } from '@riverbankcms/sdk';\n *\n * export async function generateMetadata({ params }) {\n * const pageData = await loadPage({ client, siteId, path: params.slug });\n * const siteData = await client.getSite({ id: siteId });\n *\n * return generatePageMetadata({\n * page: pageData.page,\n * site: siteData.site,\n * path: params.slug,\n * siteUrl: 'https://example.com',\n * });\n * }\n * ```\n */\nexport function generatePageMetadata(input: PageMetadataInput): Metadata {\n const { page, site, path, siteUrl, overrides, googleSiteVerification } = input;\n\n // Build page title\n const pageTitle = overrides?.title ?? page.name;\n const fullTitle = pageTitle === site.title ? pageTitle : `${pageTitle} | ${site.title}`;\n\n // Use page purpose as description fallback\n const description = overrides?.description ?? page.purpose;\n\n // Build full URLs\n const canonicalUrl = overrides?.canonicalUrl ?? `${siteUrl}${path}`;\n const fullUrl = `${siteUrl}${path}`;\n\n // Build metadata object\n const metadata: Metadata = {\n title: fullTitle,\n description: description ?? undefined,\n alternates: {\n canonical: canonicalUrl,\n },\n openGraph: {\n title: pageTitle,\n description: description ?? undefined,\n url: fullUrl,\n siteName: site.title,\n type: 'website',\n ...(overrides?.ogImage\n ? {\n images: [\n {\n url: overrides.ogImage,\n alt: pageTitle,\n },\n ],\n }\n : {}),\n },\n twitter: {\n card: 'summary_large_image',\n title: pageTitle,\n description: description ?? undefined,\n ...(overrides?.ogImage\n ? {\n images: [overrides.ogImage],\n }\n : {}),\n },\n };\n\n // Add robots meta if specified\n if (overrides?.robots) {\n metadata.robots = {\n index: overrides.robots.index ?? true,\n follow: overrides.robots.follow ?? true,\n };\n }\n\n // Add Google site verification if provided\n if (googleSiteVerification) {\n metadata.verification = {\n google: googleSiteVerification,\n };\n }\n\n return metadata;\n}\n\n/**\n * Generate metadata for preview/staging environments\n *\n * This helper adds noindex/nofollow robots tags to prevent search engines\n * from indexing preview or staging URLs.\n *\n * @example\n * ```tsx\n * export async function generateMetadata({ params }) {\n * const pageData = await loadPage({ client, siteId, path: params.slug });\n * const isPreview = process.env.VERCEL_ENV !== 'production';\n *\n * return generatePreviewMetadata({\n * page: pageData.page,\n * site: siteData.site,\n * path: params.slug,\n * siteUrl: 'https://example.com',\n * });\n * }\n * ```\n */\nexport function generatePreviewMetadata(input: PageMetadataInput): Metadata {\n return generatePageMetadata({\n ...input,\n overrides: {\n ...input.overrides,\n robots: {\n index: false,\n follow: false,\n },\n },\n });\n}\n"],"mappings":";AAgHO,SAAS,qBAAqB,OAAoC;AACvE,QAAM,EAAE,MAAM,MAAM,MAAM,SAAS,WAAW,uBAAuB,IAAI;AAGzE,QAAM,YAAY,WAAW,SAAS,KAAK;AAC3C,QAAM,YAAY,cAAc,KAAK,QAAQ,YAAY,GAAG,SAAS,MAAM,KAAK,KAAK;AAGrF,QAAM,cAAc,WAAW,eAAe,KAAK;AAGnD,QAAM,eAAe,WAAW,gBAAgB,GAAG,OAAO,GAAG,IAAI;AACjE,QAAM,UAAU,GAAG,OAAO,GAAG,IAAI;AAGjC,QAAM,WAAqB;AAAA,IACzB,OAAO;AAAA,IACP,aAAa,eAAe;AAAA,IAC5B,YAAY;AAAA,MACV,WAAW;AAAA,IACb;AAAA,IACA,WAAW;AAAA,MACT,OAAO;AAAA,MACP,aAAa,eAAe;AAAA,MAC5B,KAAK;AAAA,MACL,UAAU,KAAK;AAAA,MACf,MAAM;AAAA,MACN,GAAI,WAAW,UACX;AAAA,QACE,QAAQ;AAAA,UACN;AAAA,YACE,KAAK,UAAU;AAAA,YACf,KAAK;AAAA,UACP;AAAA,QACF;AAAA,MACF,IACA,CAAC;AAAA,IACP;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa,eAAe;AAAA,MAC5B,GAAI,WAAW,UACX;AAAA,QACE,QAAQ,CAAC,UAAU,OAAO;AAAA,MAC5B,IACA,CAAC;AAAA,IACP;AAAA,EACF;AAGA,MAAI,WAAW,QAAQ;AACrB,aAAS,SAAS;AAAA,MAChB,OAAO,UAAU,OAAO,SAAS;AAAA,MACjC,QAAQ,UAAU,OAAO,UAAU;AAAA,IACrC;AAAA,EACF;AAGA,MAAI,wBAAwB;AAC1B,aAAS,eAAe;AAAA,MACtB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO;AACT;AAuBO,SAAS,wBAAwB,OAAoC;AAC1E,SAAO,qBAAqB;AAAA,IAC1B,GAAG;AAAA,IACH,WAAW;AAAA,MACT,GAAG,MAAM;AAAA,MACT,QAAQ;AAAA,QACN,OAAO;AAAA,QACP,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF,CAAC;AACH;","names":[]}
|