@riverbankcms/sdk 0.3.0 → 0.4.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 +255 -1
- package/dist/cli/index.js +249 -40
- package/dist/cli/index.js.map +1 -1
- package/dist/client/bookings.js +15 -1
- package/dist/client/bookings.js.map +1 -1
- package/dist/client/bookings.mjs +15 -1
- package/dist/client/bookings.mjs.map +1 -1
- package/dist/client/client.d.mts +2 -2
- package/dist/client/client.d.ts +2 -2
- package/dist/client/client.js +33 -5
- package/dist/client/client.js.map +1 -1
- package/dist/client/client.mjs +33 -5
- package/dist/client/client.mjs.map +1 -1
- package/dist/client/hooks.d.mts +2 -2
- package/dist/client/hooks.d.ts +2 -2
- package/dist/client/rendering/client.js +31 -33
- package/dist/client/rendering/client.js.map +1 -1
- package/dist/client/rendering/client.mjs +31 -33
- package/dist/client/rendering/client.mjs.map +1 -1
- package/dist/client/usePage-BcjWPXvh.d.mts +6388 -0
- package/dist/client/usePage-C3ZKNwY7.d.mts +6393 -0
- package/dist/client/usePage-CyYpOJud.d.ts +6388 -0
- package/dist/client/usePage-gpVaeWDy.d.ts +6393 -0
- package/dist/server/{Layout-CsAQ-0Fv.d.mts → Layout-B_zUr9ci.d.mts} +1 -1
- package/dist/server/{Layout-BM_KmCxO.d.ts → Layout-CHG77dhK.d.ts} +1 -1
- package/dist/server/blockKinds-B6MWzNWp.d.mts +16 -0
- package/dist/server/blockKinds-B6MWzNWp.d.ts +16 -0
- package/dist/server/chunk-BOHTTHY5.mjs +406 -0
- package/dist/server/chunk-BOHTTHY5.mjs.map +1 -0
- package/dist/server/{chunk-5R4NMVXA.js → chunk-BUCJWG6G.js} +5 -5
- package/dist/server/chunk-BUCJWG6G.js.map +1 -0
- package/dist/server/chunk-D2QLTPUJ.mjs +33 -0
- package/dist/server/chunk-D2QLTPUJ.mjs.map +1 -0
- package/dist/server/{chunk-62ZJI564.js → chunk-FPYK6527.js} +4 -4
- package/dist/server/{chunk-62ZJI564.js.map → chunk-FPYK6527.js.map} +1 -1
- package/dist/server/{chunk-YXDDFG3N.js → chunk-G4CKM4EN.js} +1 -1
- package/dist/server/chunk-G4CKM4EN.js.map +1 -0
- package/dist/server/chunk-GERCMTPQ.js +33 -0
- package/dist/server/chunk-GERCMTPQ.js.map +1 -0
- package/dist/server/{chunk-SF63XAX7.js → chunk-IT5ICP43.js} +24 -4
- package/dist/server/chunk-IT5ICP43.js.map +1 -0
- package/dist/server/{chunk-GWBMJPLH.mjs → chunk-M5KTLZTD.mjs} +1 -1
- package/dist/server/chunk-M5KTLZTD.mjs.map +1 -0
- package/dist/server/{chunk-QFFQTOY3.mjs → chunk-N3PX76AP.mjs} +11 -3
- package/dist/server/{chunk-QFFQTOY3.mjs.map → chunk-N3PX76AP.mjs.map} +1 -1
- package/dist/server/{chunk-O5DC7MYW.mjs → chunk-NKXS4TBK.mjs} +24 -4
- package/dist/server/chunk-NKXS4TBK.mjs.map +1 -0
- package/dist/server/{chunk-INWKF3IC.js → chunk-P6CDRJN3.js} +8 -8
- package/dist/server/{chunk-INWKF3IC.js.map → chunk-P6CDRJN3.js.map} +1 -1
- package/dist/server/{chunk-UFVCBGBY.js → chunk-R5B6IOFQ.js} +11 -3
- package/dist/server/chunk-R5B6IOFQ.js.map +1 -0
- package/dist/server/{chunk-FK64TZBT.mjs → chunk-SFQ7VF3G.mjs} +2 -2
- package/dist/server/{chunk-JTAERCX2.mjs → chunk-VVFYHAUD.mjs} +2 -2
- package/dist/server/{chunk-PN3CHDVX.mjs → chunk-XK2YIISA.mjs} +2 -2
- package/dist/server/chunk-XK2YIISA.mjs.map +1 -0
- package/dist/server/chunk-ZIM53VP6.js +406 -0
- package/dist/server/chunk-ZIM53VP6.js.map +1 -0
- package/dist/server/{components-DJBLu_yc.d.ts → components-BYxloYJm.d.ts} +3 -3
- package/dist/server/{components-CI3JiOYA.d.mts → components-Ci5nlyUj.d.mts} +3 -3
- package/dist/server/components.d.mts +7 -6
- package/dist/server/components.d.ts +7 -6
- package/dist/server/components.js +3 -3
- package/dist/server/components.mjs +2 -2
- package/dist/server/config-validation.d.mts +5 -300
- package/dist/server/config-validation.d.ts +5 -300
- package/dist/server/config-validation.js +6 -3
- package/dist/server/config-validation.js.map +1 -1
- package/dist/server/config-validation.mjs +5 -2
- package/dist/server/config.d.mts +43 -4
- package/dist/server/config.d.ts +43 -4
- package/dist/server/config.js +27 -3
- package/dist/server/config.js.map +1 -1
- package/dist/server/config.mjs +26 -2
- package/dist/server/config.mjs.map +1 -1
- package/dist/server/data.d.mts +5 -4
- package/dist/server/data.d.ts +5 -4
- package/dist/server/data.js +2 -2
- package/dist/server/data.mjs +1 -1
- package/dist/server/{index-Dus2gkY6.d.ts → index-DbSfrRA0.d.ts} +1 -1
- package/dist/server/{index-DoX3ELQn.d.mts → index-Dj7VKH34.d.mts} +1 -1
- package/dist/server/index.d.mts +5 -4
- package/dist/server/index.d.ts +5 -4
- package/dist/server/index.js +6 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +5 -1
- package/dist/server/{loadContent-CdXDGsJM.d.ts → loadContent-BqQ-VPMW.d.ts} +4 -4
- package/dist/server/{loadContent-v2n6pOlO.d.mts → loadContent-Czu7xTOU.d.mts} +4 -4
- package/dist/server/{loadPage-bejlajm9.d.ts → loadPage-BElEkA_J.d.ts} +3 -3
- package/dist/server/{loadPage-en10WQrt.d.mts → loadPage-Dw57_n5N.d.mts} +3 -3
- package/dist/server/loadPage-E3ZC6NHB.js +11 -0
- package/dist/server/{loadPage-3ECPF426.js.map → loadPage-E3ZC6NHB.js.map} +1 -1
- package/dist/server/{loadPage-LW273NYO.mjs → loadPage-E7L7NMR3.mjs} +3 -3
- package/dist/server/metadata.d.mts +5 -4
- package/dist/server/metadata.d.ts +5 -4
- package/dist/server/navigation.d.mts +2 -2
- package/dist/server/navigation.d.ts +2 -2
- package/dist/server/rendering/server.d.mts +8 -7
- package/dist/server/rendering/server.d.ts +8 -7
- package/dist/server/rendering/server.js +4 -4
- package/dist/server/rendering/server.mjs +3 -3
- package/dist/server/rendering.d.mts +9 -8
- package/dist/server/rendering.d.ts +9 -8
- package/dist/server/rendering.js +6 -6
- package/dist/server/rendering.mjs +5 -5
- package/dist/server/routing.d.mts +5 -4
- package/dist/server/routing.d.ts +5 -4
- package/dist/server/routing.js +1 -1
- package/dist/server/routing.mjs +1 -1
- package/dist/server/server.d.mts +7 -6
- package/dist/server/server.d.ts +7 -6
- package/dist/server/server.js +4 -4
- package/dist/server/server.mjs +3 -3
- package/dist/server/theme-bridge.js +7 -7
- package/dist/server/theme-bridge.mjs +1 -1
- package/dist/server/{types-Cc7lyPkN.d.ts → types-5XdVD2J1.d.ts} +2 -0
- package/dist/server/{types-nVerjjdv.d.mts → types-BA-J9K8r.d.mts} +2 -0
- package/dist/server/{types-CLusapsM.d.mts → types-BC9eB2KH.d.mts} +65 -17
- package/dist/server/{types-_nDnPHpv.d.ts → types-BuZJWVmj.d.mts} +4 -1
- package/dist/server/{types-Ls6BkLKg.d.ts → types-CAnC529E.d.ts} +65 -17
- package/dist/server/{types-D-rqOU5I.d.ts → types-CMqVHYLG.d.ts} +264 -2
- package/dist/server/{types-Bq3520hK.d.mts → types-CYfHxUhe.d.mts} +264 -2
- package/dist/server/{types-_nDnPHpv.d.mts → types-DSFvXKhO.d.ts} +4 -1
- package/dist/server/validation-C7W2Fe0i.d.ts +459 -0
- package/dist/server/validation-hg1sqhrt.d.mts +459 -0
- package/package.json +2 -1
- package/dist/server/chunk-5R4NMVXA.js.map +0 -1
- package/dist/server/chunk-BPKYRPCQ.mjs +0 -215
- package/dist/server/chunk-BPKYRPCQ.mjs.map +0 -1
- package/dist/server/chunk-GWBMJPLH.mjs.map +0 -1
- package/dist/server/chunk-O5DC7MYW.mjs.map +0 -1
- package/dist/server/chunk-PN3CHDVX.mjs.map +0 -1
- package/dist/server/chunk-SF63XAX7.js.map +0 -1
- package/dist/server/chunk-UFVCBGBY.js.map +0 -1
- package/dist/server/chunk-XLVL5WPH.js +0 -215
- package/dist/server/chunk-XLVL5WPH.js.map +0 -1
- package/dist/server/chunk-YXDDFG3N.js.map +0 -1
- package/dist/server/loadPage-3ECPF426.js +0 -11
- /package/dist/server/{chunk-FK64TZBT.mjs.map → chunk-SFQ7VF3G.mjs.map} +0 -0
- /package/dist/server/{chunk-JTAERCX2.mjs.map → chunk-VVFYHAUD.mjs.map} +0 -0
- /package/dist/server/{loadPage-LW273NYO.mjs.map → loadPage-E7L7NMR3.mjs.map} +0 -0
package/README.md
CHANGED
|
@@ -12,6 +12,7 @@ A lightweight TypeScript SDK for consuming Riverbank CMS content in React Server
|
|
|
12
12
|
- ✅ **Type-safe API client** with caching
|
|
13
13
|
- ✅ **React Server Components** compatible
|
|
14
14
|
- ✅ **Custom blocks** - Define site-specific blocks with full CMS editing support
|
|
15
|
+
- ✅ **Content scaffolding** - Define content types, pages, entries, and navigation in code
|
|
15
16
|
|
|
16
17
|
## Installation
|
|
17
18
|
|
|
@@ -1879,6 +1880,259 @@ import {
|
|
|
1879
1880
|
} from '@riverbankcms/sdk/data';
|
|
1880
1881
|
```
|
|
1881
1882
|
|
|
1883
|
+
## Content Configuration (SDK Content Scaffolding)
|
|
1884
|
+
|
|
1885
|
+
Define content types, pages, entries, navigation menus, and site settings in code. When you push your SDK config, this content is automatically synced to the CMS database.
|
|
1886
|
+
|
|
1887
|
+
### Quick Start
|
|
1888
|
+
|
|
1889
|
+
Create a `content.config.ts` file alongside your `riverbank.config.ts`:
|
|
1890
|
+
|
|
1891
|
+
```typescript
|
|
1892
|
+
// content.config.ts
|
|
1893
|
+
import { defineContentConfig } from '@riverbankcms/sdk/config';
|
|
1894
|
+
|
|
1895
|
+
export const contentConfig = defineContentConfig({
|
|
1896
|
+
// Content type definitions
|
|
1897
|
+
contentTypes: [
|
|
1898
|
+
{
|
|
1899
|
+
key: 'testimonial',
|
|
1900
|
+
name: 'Testimonial',
|
|
1901
|
+
hasPages: false,
|
|
1902
|
+
fields: [
|
|
1903
|
+
{ id: 'quote', type: 'richText', label: 'Quote', required: true },
|
|
1904
|
+
{ id: 'author', type: 'text', label: 'Author Name', required: true, multiline: false },
|
|
1905
|
+
],
|
|
1906
|
+
},
|
|
1907
|
+
],
|
|
1908
|
+
|
|
1909
|
+
// Page definitions
|
|
1910
|
+
pages: [
|
|
1911
|
+
{
|
|
1912
|
+
identifier: 'home',
|
|
1913
|
+
path: '/',
|
|
1914
|
+
title: 'Home',
|
|
1915
|
+
status: 'published',
|
|
1916
|
+
},
|
|
1917
|
+
],
|
|
1918
|
+
|
|
1919
|
+
// Content entries
|
|
1920
|
+
entries: [
|
|
1921
|
+
{
|
|
1922
|
+
identifier: 'testimonial-1',
|
|
1923
|
+
contentType: 'testimonial',
|
|
1924
|
+
title: 'First Testimonial',
|
|
1925
|
+
status: 'published',
|
|
1926
|
+
data: {
|
|
1927
|
+
quote: '<p>Great product!</p>',
|
|
1928
|
+
author: 'Jane Doe',
|
|
1929
|
+
},
|
|
1930
|
+
},
|
|
1931
|
+
],
|
|
1932
|
+
|
|
1933
|
+
// Navigation menus
|
|
1934
|
+
navigationMenus: [
|
|
1935
|
+
{
|
|
1936
|
+
identifier: 'main',
|
|
1937
|
+
name: 'Main Navigation',
|
|
1938
|
+
isPrimary: true,
|
|
1939
|
+
items: [
|
|
1940
|
+
{ label: 'Home', link: { kind: 'page', identifier: 'home' } },
|
|
1941
|
+
],
|
|
1942
|
+
},
|
|
1943
|
+
],
|
|
1944
|
+
|
|
1945
|
+
// Site settings
|
|
1946
|
+
settings: {
|
|
1947
|
+
homepagePath: '/',
|
|
1948
|
+
siteTitle: 'My Site',
|
|
1949
|
+
siteDescription: 'Welcome to my site',
|
|
1950
|
+
},
|
|
1951
|
+
});
|
|
1952
|
+
```
|
|
1953
|
+
|
|
1954
|
+
Then import it in your main config:
|
|
1955
|
+
|
|
1956
|
+
```typescript
|
|
1957
|
+
// riverbank.config.ts
|
|
1958
|
+
import { defineConfig } from '@riverbankcms/sdk/config';
|
|
1959
|
+
import { contentConfig } from './content.config';
|
|
1960
|
+
|
|
1961
|
+
export default defineConfig({
|
|
1962
|
+
siteId: 'your-site-id',
|
|
1963
|
+
theme: { /* ... */ },
|
|
1964
|
+
content: contentConfig,
|
|
1965
|
+
});
|
|
1966
|
+
```
|
|
1967
|
+
|
|
1968
|
+
### Content Types
|
|
1969
|
+
|
|
1970
|
+
Define reusable content structures:
|
|
1971
|
+
|
|
1972
|
+
```typescript
|
|
1973
|
+
contentTypes: [
|
|
1974
|
+
{
|
|
1975
|
+
key: 'blog-post', // Unique identifier
|
|
1976
|
+
name: 'Blog Post', // Display name
|
|
1977
|
+
description: 'Blog articles',
|
|
1978
|
+
hasPages: true, // Whether entries are routable
|
|
1979
|
+
routePattern: '/blog/{slug}', // URL pattern (required if hasPages)
|
|
1980
|
+
fields: [
|
|
1981
|
+
{ id: 'body', type: 'richText', label: 'Content', required: true },
|
|
1982
|
+
{ id: 'author', type: 'text', label: 'Author', required: false, multiline: false },
|
|
1983
|
+
{ id: 'featuredImage', type: 'media', label: 'Featured Image', mediaKinds: ['image'] },
|
|
1984
|
+
],
|
|
1985
|
+
titleField: 'title', // Field to use as entry title
|
|
1986
|
+
},
|
|
1987
|
+
]
|
|
1988
|
+
```
|
|
1989
|
+
|
|
1990
|
+
### Pages
|
|
1991
|
+
|
|
1992
|
+
Define pages with optional initial blocks:
|
|
1993
|
+
|
|
1994
|
+
```typescript
|
|
1995
|
+
pages: [
|
|
1996
|
+
{
|
|
1997
|
+
identifier: 'about', // Required, unique per site
|
|
1998
|
+
path: '/about', // URL path
|
|
1999
|
+
title: 'About Us',
|
|
2000
|
+
purpose: 'content', // 'content' | 'landing' | etc.
|
|
2001
|
+
status: 'draft', // 'draft' | 'published'
|
|
2002
|
+
metaTitle: 'About Us | My Site',
|
|
2003
|
+
metaDescription: 'Learn more about our company',
|
|
2004
|
+
blocks: [
|
|
2005
|
+
{
|
|
2006
|
+
kind: 'block.hero',
|
|
2007
|
+
content: { headline: 'About Us', subheadline: 'Our Story' },
|
|
2008
|
+
orderIndex: 0,
|
|
2009
|
+
},
|
|
2010
|
+
],
|
|
2011
|
+
},
|
|
2012
|
+
]
|
|
2013
|
+
```
|
|
2014
|
+
|
|
2015
|
+
### Content Entries
|
|
2016
|
+
|
|
2017
|
+
Create content entries for your content types:
|
|
2018
|
+
|
|
2019
|
+
```typescript
|
|
2020
|
+
entries: [
|
|
2021
|
+
{
|
|
2022
|
+
identifier: 'john-smith', // Required, unique per site
|
|
2023
|
+
contentType: 'team-member', // Content type key
|
|
2024
|
+
title: 'John Smith',
|
|
2025
|
+
slug: 'john-smith', // For routable entries (defaults to identifier)
|
|
2026
|
+
status: 'published',
|
|
2027
|
+
data: {
|
|
2028
|
+
bio: '<p>Our founder...</p>',
|
|
2029
|
+
role: 'CEO',
|
|
2030
|
+
},
|
|
2031
|
+
metaTitle: 'John Smith | Team',
|
|
2032
|
+
metaDescription: 'Meet John Smith, our CEO',
|
|
2033
|
+
},
|
|
2034
|
+
]
|
|
2035
|
+
```
|
|
2036
|
+
|
|
2037
|
+
### Navigation Menus
|
|
2038
|
+
|
|
2039
|
+
Define navigation structure with page/entry references:
|
|
2040
|
+
|
|
2041
|
+
```typescript
|
|
2042
|
+
navigationMenus: [
|
|
2043
|
+
{
|
|
2044
|
+
identifier: 'main',
|
|
2045
|
+
name: 'Main Navigation',
|
|
2046
|
+
isPrimary: true,
|
|
2047
|
+
items: [
|
|
2048
|
+
// Link to a page by identifier
|
|
2049
|
+
{ label: 'Home', link: { kind: 'page', identifier: 'home' } },
|
|
2050
|
+
|
|
2051
|
+
// Link to a routable content entry
|
|
2052
|
+
{ label: 'About John', link: { kind: 'entry', identifier: 'john-smith' } },
|
|
2053
|
+
|
|
2054
|
+
// External link
|
|
2055
|
+
{ label: 'GitHub', link: { kind: 'external', href: 'https://github.com' } },
|
|
2056
|
+
|
|
2057
|
+
// Dropdown with children
|
|
2058
|
+
{
|
|
2059
|
+
label: 'Resources',
|
|
2060
|
+
link: { kind: 'dropdown' },
|
|
2061
|
+
children: [
|
|
2062
|
+
{ label: 'Blog', link: { kind: 'page', identifier: 'blog' } },
|
|
2063
|
+
{ label: 'Docs', link: { kind: 'external', href: 'https://docs.example.com' } },
|
|
2064
|
+
],
|
|
2065
|
+
},
|
|
2066
|
+
],
|
|
2067
|
+
},
|
|
2068
|
+
]
|
|
2069
|
+
```
|
|
2070
|
+
|
|
2071
|
+
### Site Settings
|
|
2072
|
+
|
|
2073
|
+
Configure site-wide settings:
|
|
2074
|
+
|
|
2075
|
+
```typescript
|
|
2076
|
+
settings: {
|
|
2077
|
+
homepagePath: '/', // Path to homepage
|
|
2078
|
+
siteTitle: 'My Site', // Site title for metadata
|
|
2079
|
+
siteDescription: 'Welcome', // Site description for metadata
|
|
2080
|
+
}
|
|
2081
|
+
```
|
|
2082
|
+
|
|
2083
|
+
### Sync Behavior
|
|
2084
|
+
|
|
2085
|
+
When you run `riverbank push`:
|
|
2086
|
+
|
|
2087
|
+
1. **Creates** new content if the identifier doesn't exist
|
|
2088
|
+
2. **Updates** existing content if it hasn't been modified in the dashboard
|
|
2089
|
+
3. **Skips** content that was edited in the dashboard (preserves manual changes)
|
|
2090
|
+
4. **Never deletes** - removing from config doesn't delete from CMS
|
|
2091
|
+
|
|
2092
|
+
This "overwrite if unchanged" behavior ensures:
|
|
2093
|
+
- SDK-defined content can be version controlled
|
|
2094
|
+
- Dashboard edits are never lost
|
|
2095
|
+
- Teams can safely iterate on config
|
|
2096
|
+
|
|
2097
|
+
### Sync Order
|
|
2098
|
+
|
|
2099
|
+
Content syncs in dependency order:
|
|
2100
|
+
|
|
2101
|
+
1. Content Types (no dependencies)
|
|
2102
|
+
2. Site Settings (no dependencies)
|
|
2103
|
+
3. Pages (needed for navigation references)
|
|
2104
|
+
4. Content Entries (depend on content types)
|
|
2105
|
+
5. Navigation Menus (reference pages and entries)
|
|
2106
|
+
|
|
2107
|
+
### Validation
|
|
2108
|
+
|
|
2109
|
+
The SDK validates your content config on push:
|
|
2110
|
+
|
|
2111
|
+
- Unique identifiers per entity type
|
|
2112
|
+
- Valid content type references
|
|
2113
|
+
- Valid field definitions
|
|
2114
|
+
- Navigation references resolve to existing pages/entries
|
|
2115
|
+
- Path uniqueness for pages
|
|
2116
|
+
|
|
2117
|
+
### Types
|
|
2118
|
+
|
|
2119
|
+
```typescript
|
|
2120
|
+
import {
|
|
2121
|
+
// Helper function
|
|
2122
|
+
defineContentConfig,
|
|
2123
|
+
|
|
2124
|
+
// Types
|
|
2125
|
+
type ContentConfig,
|
|
2126
|
+
type ContentTypeConfig,
|
|
2127
|
+
type PageConfig,
|
|
2128
|
+
type EntryConfig,
|
|
2129
|
+
type BlockConfig,
|
|
2130
|
+
type NavigationMenuConfig,
|
|
2131
|
+
type NavigationItemConfig,
|
|
2132
|
+
type SiteSettingsConfig,
|
|
2133
|
+
} from '@riverbankcms/sdk/config';
|
|
2134
|
+
```
|
|
2135
|
+
|
|
1882
2136
|
## Additional Exports
|
|
1883
2137
|
|
|
1884
2138
|
- `@riverbankcms/sdk/rendering` - Low-level rendering components
|
|
@@ -1889,4 +2143,4 @@ import {
|
|
|
1889
2143
|
- `@riverbankcms/sdk/metadata` - Metadata generation helpers
|
|
1890
2144
|
- `@riverbankcms/sdk/routing` - Route resolution helpers
|
|
1891
2145
|
- `@riverbankcms/sdk/analytics` - Analytics tracking helpers
|
|
1892
|
-
- `@riverbankcms/sdk/config` - Site configuration utilities (includes `defineConfig`, `
|
|
2146
|
+
- `@riverbankcms/sdk/config` - Site configuration utilities (includes `defineConfig`, `defineContentConfig`, `RiverbankSiteConfig`, `ContentConfig`, etc.)
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
var dotenv = require('dotenv');
|
|
4
5
|
var commander = require('commander');
|
|
5
6
|
var zod = require('zod');
|
|
6
7
|
var jiti = require('jiti');
|
|
@@ -685,7 +686,7 @@ function sectionContainer(children, opts) {
|
|
|
685
686
|
var DEFAULT_SECTION_SPACING = "medium";
|
|
686
687
|
|
|
687
688
|
// ../blocks/src/system/node/fragments/styledSection.ts
|
|
688
|
-
function styledSection(
|
|
689
|
+
function styledSection(config2) {
|
|
689
690
|
const {
|
|
690
691
|
children,
|
|
691
692
|
baseClass = "px-6",
|
|
@@ -693,7 +694,7 @@ function styledSection(config) {
|
|
|
693
694
|
background = "background/base",
|
|
694
695
|
bindFrom = "_sectionStyles",
|
|
695
696
|
imageClassName = "absolute -z-10"
|
|
696
|
-
} =
|
|
697
|
+
} = config2;
|
|
697
698
|
const backgroundNodes = backgroundLayer(`${bindFrom}.background`, {
|
|
698
699
|
imageClassName
|
|
699
700
|
});
|
|
@@ -834,8 +835,8 @@ var FragmentConfigError = class extends Error {
|
|
|
834
835
|
this.name = "FragmentConfigError";
|
|
835
836
|
}
|
|
836
837
|
};
|
|
837
|
-
function defineFragment(
|
|
838
|
-
const parsed = fragmentConfigSchema.parse(
|
|
838
|
+
function defineFragment(config2) {
|
|
839
|
+
const parsed = fragmentConfigSchema.parse(config2);
|
|
839
840
|
validateFieldDefinitions(parsed.fields, parsed.id);
|
|
840
841
|
return {
|
|
841
842
|
...parsed,
|
|
@@ -1042,26 +1043,26 @@ var FragmentCompositionError = class extends Error {
|
|
|
1042
1043
|
}
|
|
1043
1044
|
};
|
|
1044
1045
|
var DOT_SCOPE_REGEX = /^[A-Za-z0-9_.-]*$/;
|
|
1045
|
-
function materializeFragment(
|
|
1046
|
-
const scope = normalizeScope(
|
|
1047
|
-
const fields4 = scopeFragmentFields(
|
|
1048
|
-
const layout = scopeFragmentLayout(
|
|
1049
|
-
const fieldPriority =
|
|
1046
|
+
function materializeFragment(config2) {
|
|
1047
|
+
const scope = normalizeScope(config2.scope);
|
|
1048
|
+
const fields4 = scopeFragmentFields(config2.fragment, scope);
|
|
1049
|
+
const layout = scopeFragmentLayout(config2.fragment, scope);
|
|
1050
|
+
const fieldPriority = config2.fieldPriority ?? 0;
|
|
1050
1051
|
let data;
|
|
1051
|
-
if (
|
|
1052
|
-
const key =
|
|
1052
|
+
if (config2.fragment.data) {
|
|
1053
|
+
const key = config2.dataKey ?? config2.fragment.data.key;
|
|
1053
1054
|
if (!key || typeof key !== "string") {
|
|
1054
1055
|
throw new FragmentCompositionError(
|
|
1055
|
-
`Fragment "${
|
|
1056
|
+
`Fragment "${config2.fragment.id}" requires a data key to compose.`
|
|
1056
1057
|
);
|
|
1057
1058
|
}
|
|
1058
1059
|
data = {
|
|
1059
1060
|
key,
|
|
1060
|
-
loader:
|
|
1061
|
+
loader: config2.fragment.data.loader ? { ...config2.fragment.data.loader } : void 0
|
|
1061
1062
|
};
|
|
1062
1063
|
}
|
|
1063
1064
|
return {
|
|
1064
|
-
fragment:
|
|
1065
|
+
fragment: config2.fragment,
|
|
1065
1066
|
scope,
|
|
1066
1067
|
fields: fields4,
|
|
1067
1068
|
layout,
|
|
@@ -2845,13 +2846,13 @@ function sectionStylesField(options = {}) {
|
|
|
2845
2846
|
}
|
|
2846
2847
|
|
|
2847
2848
|
// ../blocks/src/system/defineBlock.ts
|
|
2848
|
-
function createBlockManifest(
|
|
2849
|
-
const composition2 =
|
|
2849
|
+
function createBlockManifest(config2) {
|
|
2850
|
+
const composition2 = config2.fragments ? composeFragments(config2.fragments) : { fields: []};
|
|
2850
2851
|
const allFields = [
|
|
2851
2852
|
...composition2.fields,
|
|
2852
|
-
...
|
|
2853
|
+
...config2.additionalFields ?? []
|
|
2853
2854
|
];
|
|
2854
|
-
if (!
|
|
2855
|
+
if (!config2.skipSectionStyles) {
|
|
2855
2856
|
allFields.push(
|
|
2856
2857
|
sectionStylesField({
|
|
2857
2858
|
id: "_sectionStyles",
|
|
@@ -2860,36 +2861,36 @@ function createBlockManifest(config) {
|
|
|
2860
2861
|
);
|
|
2861
2862
|
}
|
|
2862
2863
|
const fields4 = fieldSchema.array().parse(allFields);
|
|
2863
|
-
const layout =
|
|
2864
|
-
const variants =
|
|
2865
|
-
let behaviours =
|
|
2866
|
-
if (!behaviours &&
|
|
2864
|
+
const layout = config2.layout;
|
|
2865
|
+
const variants = config2.variants;
|
|
2866
|
+
let behaviours = config2.behaviours;
|
|
2867
|
+
if (!behaviours && config2.paletteHidden !== void 0) {
|
|
2867
2868
|
behaviours = {
|
|
2868
2869
|
supportsThemeSwitching: true,
|
|
2869
2870
|
inlineEditing: true,
|
|
2870
2871
|
animation: true,
|
|
2871
|
-
paletteHidden:
|
|
2872
|
+
paletteHidden: config2.paletteHidden
|
|
2872
2873
|
};
|
|
2873
2874
|
}
|
|
2874
2875
|
const manifest = {
|
|
2875
|
-
name:
|
|
2876
|
+
name: config2.id,
|
|
2876
2877
|
version: "0.1.0",
|
|
2877
|
-
title:
|
|
2878
|
-
titleSource:
|
|
2879
|
-
description:
|
|
2880
|
-
component:
|
|
2878
|
+
title: config2.title,
|
|
2879
|
+
titleSource: config2.titleSource,
|
|
2880
|
+
description: config2.description ?? "",
|
|
2881
|
+
component: config2.component ?? deriveComponentName(config2.id),
|
|
2881
2882
|
fields: fields4,
|
|
2882
2883
|
slots: [],
|
|
2883
2884
|
// Always empty
|
|
2884
|
-
styleTokens:
|
|
2885
|
+
styleTokens: config2.styleTokens,
|
|
2885
2886
|
behaviours,
|
|
2886
|
-
category:
|
|
2887
|
-
contentTypes:
|
|
2888
|
-
tags:
|
|
2889
|
-
icon:
|
|
2887
|
+
category: config2.category,
|
|
2888
|
+
contentTypes: config2.contentTypes,
|
|
2889
|
+
tags: config2.tags ?? [],
|
|
2890
|
+
icon: config2.icon ?? "Box",
|
|
2890
2891
|
layout,
|
|
2891
2892
|
variants,
|
|
2892
|
-
defaultVariant:
|
|
2893
|
+
defaultVariant: config2.defaultVariant
|
|
2893
2894
|
};
|
|
2894
2895
|
return augmentManifest(manifest);
|
|
2895
2896
|
}
|
|
@@ -4840,6 +4841,211 @@ function getBlockDefinition(name) {
|
|
|
4840
4841
|
return blockStore.get(name);
|
|
4841
4842
|
}
|
|
4842
4843
|
|
|
4844
|
+
// ../blocks/src/system/constants/blockKinds.ts
|
|
4845
|
+
var SYSTEM_BLOCK_KINDS = [
|
|
4846
|
+
// Layout blocks
|
|
4847
|
+
"block.hero",
|
|
4848
|
+
"block.columns",
|
|
4849
|
+
"block.ctaFull",
|
|
4850
|
+
"block.singleButton",
|
|
4851
|
+
// Content blocks
|
|
4852
|
+
"block.bodyText",
|
|
4853
|
+
"block.faq",
|
|
4854
|
+
"block.testimonials",
|
|
4855
|
+
"block.embed",
|
|
4856
|
+
// Blog blocks
|
|
4857
|
+
"block.blogPost",
|
|
4858
|
+
"block.blogPlaceholder",
|
|
4859
|
+
"block.blogListing",
|
|
4860
|
+
// Site structure blocks
|
|
4861
|
+
"block.siteHeader",
|
|
4862
|
+
"block.siteFooter",
|
|
4863
|
+
// Form/booking blocks
|
|
4864
|
+
"block.form",
|
|
4865
|
+
"block.appointment-booking",
|
|
4866
|
+
"block.event-registration",
|
|
4867
|
+
// Event display blocks
|
|
4868
|
+
"block.event-spotlight",
|
|
4869
|
+
"block.event-listing",
|
|
4870
|
+
"block.event-calendar"
|
|
4871
|
+
];
|
|
4872
|
+
|
|
4873
|
+
// src/config/content-validation.ts
|
|
4874
|
+
var jsonDataSchema = zod.z.record(zod.z.string(), zod.z.any());
|
|
4875
|
+
var contentTypeKeySchema = zod.z.string().min(1).regex(
|
|
4876
|
+
/^[a-z][a-z0-9-]*$/,
|
|
4877
|
+
"Key must be lowercase, start with a letter, and contain only letters, numbers, and hyphens"
|
|
4878
|
+
);
|
|
4879
|
+
var contentTypeConfigSchema = zod.z.object({
|
|
4880
|
+
key: contentTypeKeySchema,
|
|
4881
|
+
name: zod.z.string().min(1),
|
|
4882
|
+
description: zod.z.string().optional(),
|
|
4883
|
+
hasPages: zod.z.boolean(),
|
|
4884
|
+
routePattern: zod.z.string().optional(),
|
|
4885
|
+
// Fields are validated as any[] here - deep field validation happens in @riverbankcms/blocks
|
|
4886
|
+
fields: zod.z.array(zod.z.any()).min(1, "At least one field is required"),
|
|
4887
|
+
titleField: zod.z.string().optional()
|
|
4888
|
+
}).refine(
|
|
4889
|
+
(data) => {
|
|
4890
|
+
if (data.hasPages) {
|
|
4891
|
+
return data.routePattern && data.routePattern.includes("{slug}");
|
|
4892
|
+
}
|
|
4893
|
+
return true;
|
|
4894
|
+
},
|
|
4895
|
+
{ message: "routePattern with {slug} is required when hasPages is true" }
|
|
4896
|
+
).refine(
|
|
4897
|
+
(data) => {
|
|
4898
|
+
if (!data.hasPages && data.routePattern) {
|
|
4899
|
+
return false;
|
|
4900
|
+
}
|
|
4901
|
+
return true;
|
|
4902
|
+
},
|
|
4903
|
+
{ message: "routePattern must not be defined when hasPages is false" }
|
|
4904
|
+
);
|
|
4905
|
+
var blockKindSchema = zod.z.string().refine(
|
|
4906
|
+
(kind) => {
|
|
4907
|
+
if (SYSTEM_BLOCK_KINDS.includes(kind)) {
|
|
4908
|
+
return true;
|
|
4909
|
+
}
|
|
4910
|
+
if (kind.startsWith("custom.") && kind.length > 7) {
|
|
4911
|
+
return true;
|
|
4912
|
+
}
|
|
4913
|
+
return false;
|
|
4914
|
+
},
|
|
4915
|
+
{
|
|
4916
|
+
message: 'Block kind must be a system block (e.g., "block.hero") or a custom block (e.g., "custom.myBlock")'
|
|
4917
|
+
}
|
|
4918
|
+
);
|
|
4919
|
+
var blockConfigSchema = zod.z.object({
|
|
4920
|
+
kind: blockKindSchema,
|
|
4921
|
+
content: jsonDataSchema,
|
|
4922
|
+
orderIndex: zod.z.number().optional()
|
|
4923
|
+
});
|
|
4924
|
+
var pageConfigSchema = zod.z.object({
|
|
4925
|
+
identifier: zod.z.string().min(1, "Identifier is required"),
|
|
4926
|
+
title: zod.z.string().min(1, "Title is required"),
|
|
4927
|
+
path: zod.z.string().regex(/^\//, "Path must start with /"),
|
|
4928
|
+
purpose: zod.z.string().default("content"),
|
|
4929
|
+
blocks: zod.z.array(blockConfigSchema).optional(),
|
|
4930
|
+
status: zod.z.enum(["draft", "published"]).default("draft"),
|
|
4931
|
+
metaTitle: zod.z.string().optional(),
|
|
4932
|
+
metaDescription: zod.z.string().optional()
|
|
4933
|
+
});
|
|
4934
|
+
var entryConfigSchema = zod.z.object({
|
|
4935
|
+
identifier: zod.z.string().min(1, "Identifier is required"),
|
|
4936
|
+
contentType: zod.z.string().min(1, "Content type is required"),
|
|
4937
|
+
data: jsonDataSchema,
|
|
4938
|
+
status: zod.z.enum(["draft", "published"]).default("draft"),
|
|
4939
|
+
slug: zod.z.string().optional(),
|
|
4940
|
+
title: zod.z.string().optional(),
|
|
4941
|
+
summary: zod.z.string().optional(),
|
|
4942
|
+
metaTitle: zod.z.string().optional(),
|
|
4943
|
+
metaDescription: zod.z.string().optional()
|
|
4944
|
+
});
|
|
4945
|
+
var pageLinkSchema = zod.z.object({
|
|
4946
|
+
kind: zod.z.literal("page"),
|
|
4947
|
+
identifier: zod.z.string().min(1)
|
|
4948
|
+
});
|
|
4949
|
+
var entryLinkSchema = zod.z.object({
|
|
4950
|
+
kind: zod.z.literal("entry"),
|
|
4951
|
+
identifier: zod.z.string().min(1)
|
|
4952
|
+
});
|
|
4953
|
+
var externalLinkSchema = zod.z.object({
|
|
4954
|
+
kind: zod.z.literal("external"),
|
|
4955
|
+
href: zod.z.string().url("Invalid URL")
|
|
4956
|
+
});
|
|
4957
|
+
var dropdownLinkSchema = zod.z.object({
|
|
4958
|
+
kind: zod.z.literal("dropdown")
|
|
4959
|
+
});
|
|
4960
|
+
var navigationLinkSchema = zod.z.discriminatedUnion("kind", [
|
|
4961
|
+
pageLinkSchema,
|
|
4962
|
+
entryLinkSchema,
|
|
4963
|
+
externalLinkSchema,
|
|
4964
|
+
dropdownLinkSchema
|
|
4965
|
+
]);
|
|
4966
|
+
var baseNavigationItemSchema = zod.z.object({
|
|
4967
|
+
label: zod.z.string().min(1, "Label is required"),
|
|
4968
|
+
link: navigationLinkSchema,
|
|
4969
|
+
isCta: zod.z.boolean().optional()
|
|
4970
|
+
});
|
|
4971
|
+
var navigationItemConfigSchema = baseNavigationItemSchema.extend({
|
|
4972
|
+
children: zod.z.lazy(() => zod.z.array(navigationItemConfigSchema)).optional()
|
|
4973
|
+
});
|
|
4974
|
+
var navigationMenuConfigSchema = zod.z.object({
|
|
4975
|
+
identifier: zod.z.string().min(1, "Identifier is required"),
|
|
4976
|
+
name: zod.z.string().min(1, "Name is required"),
|
|
4977
|
+
isPrimary: zod.z.boolean().optional(),
|
|
4978
|
+
items: zod.z.array(navigationItemConfigSchema)
|
|
4979
|
+
});
|
|
4980
|
+
var siteSettingsConfigSchema = zod.z.object({
|
|
4981
|
+
homepagePath: zod.z.string().optional(),
|
|
4982
|
+
siteTitle: zod.z.string().optional(),
|
|
4983
|
+
siteDescription: zod.z.string().optional(),
|
|
4984
|
+
defaultTemplates: zod.z.record(zod.z.string(), zod.z.string()).optional()
|
|
4985
|
+
});
|
|
4986
|
+
var contentConfigBaseSchema = zod.z.object({
|
|
4987
|
+
contentTypes: zod.z.array(contentTypeConfigSchema).optional(),
|
|
4988
|
+
entries: zod.z.array(entryConfigSchema).optional(),
|
|
4989
|
+
pages: zod.z.array(pageConfigSchema).optional(),
|
|
4990
|
+
navigationMenus: zod.z.array(navigationMenuConfigSchema).optional(),
|
|
4991
|
+
settings: siteSettingsConfigSchema.optional()
|
|
4992
|
+
});
|
|
4993
|
+
var contentConfigSchema = contentConfigBaseSchema.superRefine((data, ctx) => {
|
|
4994
|
+
if (data.contentTypes && data.contentTypes.length > 1) {
|
|
4995
|
+
const keys = data.contentTypes.map((ct) => ct.key);
|
|
4996
|
+
const duplicateKeys = keys.filter((key, i) => keys.indexOf(key) !== i);
|
|
4997
|
+
if (duplicateKeys.length > 0) {
|
|
4998
|
+
ctx.addIssue({
|
|
4999
|
+
code: zod.z.ZodIssueCode.custom,
|
|
5000
|
+
message: `Content type keys must be unique. Duplicates: ${duplicateKeys.join(", ")}`,
|
|
5001
|
+
path: ["contentTypes"]
|
|
5002
|
+
});
|
|
5003
|
+
}
|
|
5004
|
+
}
|
|
5005
|
+
if (data.pages && data.pages.length > 1) {
|
|
5006
|
+
const identifiers = data.pages.map((p) => p.identifier);
|
|
5007
|
+
const duplicateIds = identifiers.filter((id, i) => identifiers.indexOf(id) !== i);
|
|
5008
|
+
if (duplicateIds.length > 0) {
|
|
5009
|
+
ctx.addIssue({
|
|
5010
|
+
code: zod.z.ZodIssueCode.custom,
|
|
5011
|
+
message: `Page identifiers must be unique. Duplicates: ${duplicateIds.join(", ")}`,
|
|
5012
|
+
path: ["pages"]
|
|
5013
|
+
});
|
|
5014
|
+
}
|
|
5015
|
+
const paths = data.pages.map((p) => p.path);
|
|
5016
|
+
const duplicatePaths = paths.filter((path, i) => paths.indexOf(path) !== i);
|
|
5017
|
+
if (duplicatePaths.length > 0) {
|
|
5018
|
+
ctx.addIssue({
|
|
5019
|
+
code: zod.z.ZodIssueCode.custom,
|
|
5020
|
+
message: `Page paths must be unique. Duplicates: ${duplicatePaths.join(", ")}`,
|
|
5021
|
+
path: ["pages"]
|
|
5022
|
+
});
|
|
5023
|
+
}
|
|
5024
|
+
}
|
|
5025
|
+
if (data.entries && data.entries.length > 1) {
|
|
5026
|
+
const identifiers = data.entries.map((e) => e.identifier);
|
|
5027
|
+
const duplicateIds = identifiers.filter((id, i) => identifiers.indexOf(id) !== i);
|
|
5028
|
+
if (duplicateIds.length > 0) {
|
|
5029
|
+
ctx.addIssue({
|
|
5030
|
+
code: zod.z.ZodIssueCode.custom,
|
|
5031
|
+
message: `Entry identifiers must be unique. Duplicates: ${duplicateIds.join(", ")}`,
|
|
5032
|
+
path: ["entries"]
|
|
5033
|
+
});
|
|
5034
|
+
}
|
|
5035
|
+
}
|
|
5036
|
+
if (data.navigationMenus && data.navigationMenus.length > 1) {
|
|
5037
|
+
const identifiers = data.navigationMenus.map((m) => m.identifier);
|
|
5038
|
+
const duplicateIds = identifiers.filter((id, i) => identifiers.indexOf(id) !== i);
|
|
5039
|
+
if (duplicateIds.length > 0) {
|
|
5040
|
+
ctx.addIssue({
|
|
5041
|
+
code: zod.z.ZodIssueCode.custom,
|
|
5042
|
+
message: `Navigation menu identifiers must be unique. Duplicates: ${duplicateIds.join(", ")}`,
|
|
5043
|
+
path: ["navigationMenus"]
|
|
5044
|
+
});
|
|
5045
|
+
}
|
|
5046
|
+
}
|
|
5047
|
+
});
|
|
5048
|
+
|
|
4843
5049
|
// src/data/prefetchBlockData.ts
|
|
4844
5050
|
var SUPPORTED_LOADER_ENDPOINTS = [
|
|
4845
5051
|
"listPublishedEntries",
|
|
@@ -5026,7 +5232,8 @@ var riverbankSiteConfigSchema = zod.z.object({
|
|
|
5026
5232
|
{ message: "Block IDs must be unique" }
|
|
5027
5233
|
).optional(),
|
|
5028
5234
|
blockFieldOptions: blockFieldOptionsSchema,
|
|
5029
|
-
blockFieldExtensions: blockFieldExtensionsSchema
|
|
5235
|
+
blockFieldExtensions: blockFieldExtensionsSchema,
|
|
5236
|
+
content: contentConfigSchema.optional()
|
|
5030
5237
|
}).strict();
|
|
5031
5238
|
var DEFAULT_CONFIG_FILENAME = "riverbank.config.ts";
|
|
5032
5239
|
async function loadConfigFile(configPath) {
|
|
@@ -5045,11 +5252,11 @@ Create a riverbank.config.ts file or specify a path with --config`
|
|
|
5045
5252
|
});
|
|
5046
5253
|
try {
|
|
5047
5254
|
const configModule = await jiti$1.import(resolvedPath);
|
|
5048
|
-
const
|
|
5049
|
-
if (!
|
|
5255
|
+
const config2 = configModule.default ?? configModule.config ?? configModule;
|
|
5256
|
+
if (!config2 || typeof config2 !== "object") {
|
|
5050
5257
|
throw new Error("Config file must export a configuration object");
|
|
5051
5258
|
}
|
|
5052
|
-
return
|
|
5259
|
+
return config2;
|
|
5053
5260
|
} catch (error) {
|
|
5054
5261
|
if (error instanceof Error) {
|
|
5055
5262
|
throw new Error(`Failed to load config: ${error.message}`);
|
|
@@ -5069,7 +5276,7 @@ function resolveConfigPath(configPath) {
|
|
|
5069
5276
|
}
|
|
5070
5277
|
|
|
5071
5278
|
// src/cli/push-config.ts
|
|
5072
|
-
async function pushToDashboard(dashboardUrl, siteId, apiKey,
|
|
5279
|
+
async function pushToDashboard(dashboardUrl, siteId, apiKey, config2) {
|
|
5073
5280
|
const pushUrl = `${dashboardUrl}/api/sites/${siteId}/sdk-config`;
|
|
5074
5281
|
console.log(`Pushing config to ${pushUrl}...`);
|
|
5075
5282
|
let response;
|
|
@@ -5080,7 +5287,7 @@ async function pushToDashboard(dashboardUrl, siteId, apiKey, config) {
|
|
|
5080
5287
|
"Content-Type": "application/json",
|
|
5081
5288
|
"X-API-Key": apiKey
|
|
5082
5289
|
},
|
|
5083
|
-
body: JSON.stringify({ config }),
|
|
5290
|
+
body: JSON.stringify({ config: config2 }),
|
|
5084
5291
|
signal: AbortSignal.timeout(3e4)
|
|
5085
5292
|
});
|
|
5086
5293
|
} catch (error) {
|
|
@@ -5150,6 +5357,8 @@ var pushConfigCommand = new commander.Command("push-config").description("Push S
|
|
|
5150
5357
|
});
|
|
5151
5358
|
|
|
5152
5359
|
// src/cli/index.ts
|
|
5360
|
+
dotenv.config({ path: ".env.local" });
|
|
5361
|
+
dotenv.config({ path: ".env" });
|
|
5153
5362
|
var program = new commander.Command();
|
|
5154
5363
|
program.name("riverbankcms").description("Builder SDK CLI tools").version("0.1.0");
|
|
5155
5364
|
program.addCommand(pushConfigCommand);
|