@riverbankcms/sdk 0.6.1 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/README.md +175 -0
  2. package/dist/cli/index.js +42 -95
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/cli/init-docs/content/agents-section.md +50 -0
  5. package/dist/cli/init-docs/content/cli-reference.md +574 -0
  6. package/dist/cli/init-docs/content/content-management.md +384 -0
  7. package/dist/cli/init-docs/content/context-brand.md +125 -0
  8. package/dist/cli/init-docs/content/context-brief.md +77 -0
  9. package/dist/cli/init-docs/content/context-knowledge.md +111 -0
  10. package/dist/cli/init-docs/content/getting-started.md +130 -0
  11. package/dist/cli/init-docs/content/site-workflows-readme.md +96 -0
  12. package/dist/cli/init-docs/content/workflow-add-block.md +228 -0
  13. package/dist/cli/init-docs/content/workflow-create-page.md +193 -0
  14. package/dist/cli/init-docs/content/workflow-publish.md +280 -0
  15. package/dist/client/client.d.mts +2 -2
  16. package/dist/client/client.d.ts +2 -2
  17. package/dist/client/client.js +536 -71
  18. package/dist/client/client.js.map +1 -1
  19. package/dist/client/client.mjs +536 -78
  20. package/dist/client/client.mjs.map +1 -1
  21. package/dist/client/hooks.d.mts +2 -2
  22. package/dist/client/hooks.d.ts +2 -2
  23. package/dist/client/usePage-C9tJpuKa.d.mts +6813 -0
  24. package/dist/client/usePage-Db9kzA41.d.ts +6813 -0
  25. package/dist/server/{Layout-wBtJLTVX.d.ts → Layout-Ce7PU9I5.d.ts} +1 -1
  26. package/dist/server/{Layout-B7cvis7r.d.mts → Layout-WllR8Zug.d.mts} +1 -1
  27. package/dist/server/{chunk-I7ZR2WO3.mjs → chunk-5JT452F2.mjs} +537 -76
  28. package/dist/server/chunk-5JT452F2.mjs.map +1 -0
  29. package/dist/server/{chunk-Z5ZA6Q4D.mjs → chunk-74XUVNOO.mjs} +5 -3
  30. package/dist/server/chunk-74XUVNOO.mjs.map +1 -0
  31. package/dist/server/{chunk-3B364WO2.js → chunk-7BVRA5MY.js} +4 -49
  32. package/dist/server/chunk-7BVRA5MY.js.map +1 -0
  33. package/dist/server/chunk-AET56TQX.mjs +45 -0
  34. package/dist/server/chunk-AET56TQX.mjs.map +1 -0
  35. package/dist/server/chunk-ARNCLSQT.mjs +52 -0
  36. package/dist/server/chunk-ARNCLSQT.mjs.map +1 -0
  37. package/dist/server/chunk-BNQV3PXP.js +69 -0
  38. package/dist/server/chunk-BNQV3PXP.js.map +1 -0
  39. package/dist/server/{chunk-IVHIQFJH.js → chunk-HMENX4Y7.js} +543 -82
  40. package/dist/server/chunk-HMENX4Y7.js.map +1 -0
  41. package/dist/server/{chunk-I2D7KOEA.js → chunk-JWRNMNWI.js} +5 -3
  42. package/dist/server/chunk-JWRNMNWI.js.map +1 -0
  43. package/dist/server/chunk-LQUKXIW7.mjs +13 -0
  44. package/dist/server/chunk-LQUKXIW7.mjs.map +1 -0
  45. package/dist/server/{chunk-XXFF4RVR.mjs → chunk-RBJFXNDM.mjs} +1 -46
  46. package/dist/server/chunk-RBJFXNDM.mjs.map +1 -0
  47. package/dist/server/chunk-SWYWZT3L.mjs +69 -0
  48. package/dist/server/chunk-SWYWZT3L.mjs.map +1 -0
  49. package/dist/server/chunk-T26N3P26.js +52 -0
  50. package/dist/server/chunk-T26N3P26.js.map +1 -0
  51. package/dist/server/chunk-VODFQMUW.js +45 -0
  52. package/dist/server/chunk-VODFQMUW.js.map +1 -0
  53. package/dist/server/chunk-WYNEYDXO.js +13 -0
  54. package/dist/server/chunk-WYNEYDXO.js.map +1 -0
  55. package/dist/server/{components-CICSJyp_.d.ts → components--LT61IKp.d.ts} +2 -2
  56. package/dist/server/{components-CMMwDXTW.d.mts → components-RPzRQve6.d.mts} +2 -2
  57. package/dist/server/components.d.mts +4 -4
  58. package/dist/server/components.d.ts +4 -4
  59. package/dist/server/components.js +5 -4
  60. package/dist/server/components.js.map +1 -1
  61. package/dist/server/components.mjs +5 -4
  62. package/dist/server/config-validation.js +0 -1
  63. package/dist/server/config-validation.js.map +1 -1
  64. package/dist/server/config-validation.mjs +0 -1
  65. package/dist/server/config.js +0 -1
  66. package/dist/server/config.js.map +1 -1
  67. package/dist/server/config.mjs +0 -1
  68. package/dist/server/config.mjs.map +1 -1
  69. package/dist/server/data.d.mts +1 -1
  70. package/dist/server/data.d.ts +1 -1
  71. package/dist/server/data.js +0 -1
  72. package/dist/server/data.js.map +1 -1
  73. package/dist/server/data.mjs +0 -1
  74. package/dist/server/env.d.mts +23 -0
  75. package/dist/server/env.d.ts +23 -0
  76. package/dist/server/env.js +7 -0
  77. package/dist/server/env.js.map +1 -0
  78. package/dist/server/env.mjs +7 -0
  79. package/dist/server/index-BL66CU6d.d.mts +130 -0
  80. package/dist/server/{index-Bucs6UqG.d.mts → index-Bkva0WAj.d.mts} +1 -1
  81. package/dist/server/index-CJk9iQQW.d.ts +130 -0
  82. package/dist/server/{index-Cp7tJuRt.d.ts → index-CSBWKA3r.d.ts} +1 -1
  83. package/dist/server/index.d.mts +3 -3
  84. package/dist/server/index.d.ts +3 -3
  85. package/dist/server/index.js +2 -3
  86. package/dist/server/index.js.map +1 -1
  87. package/dist/server/index.mjs +1 -2
  88. package/dist/server/index.mjs.map +1 -1
  89. package/dist/server/{loadContent-Buvmudee.d.ts → loadContent-CXUWMuzY.d.ts} +11 -3
  90. package/dist/server/{loadContent-BS-3wesN.d.mts → loadContent-F_tAS0Nl.d.mts} +11 -3
  91. package/dist/server/{loadPage-IDGVDFBB.js → loadPage-6I7F6GRF.js} +1 -2
  92. package/dist/server/loadPage-6I7F6GRF.js.map +1 -0
  93. package/dist/server/{loadPage-B8mQUUSo.d.mts → loadPage-CxlYLe5K.d.mts} +1 -1
  94. package/dist/server/{loadPage-DNQTTRHL.mjs → loadPage-JI2SML4M.mjs} +1 -2
  95. package/dist/server/{loadPage-DP3nrHBi.d.ts → loadPage-i2r-X5b9.d.ts} +1 -1
  96. package/dist/server/metadata.d.mts +8 -135
  97. package/dist/server/metadata.d.ts +8 -135
  98. package/dist/server/metadata.js +4 -65
  99. package/dist/server/metadata.js.map +1 -1
  100. package/dist/server/metadata.mjs +4 -65
  101. package/dist/server/metadata.mjs.map +1 -1
  102. package/dist/server/navigation.js +0 -1
  103. package/dist/server/navigation.js.map +1 -1
  104. package/dist/server/navigation.mjs +0 -1
  105. package/dist/server/next/revalidate.d.mts +66 -0
  106. package/dist/server/next/revalidate.d.ts +66 -0
  107. package/dist/server/next/revalidate.js +59 -0
  108. package/dist/server/next/revalidate.js.map +1 -0
  109. package/dist/server/next/revalidate.mjs +59 -0
  110. package/dist/server/next/revalidate.mjs.map +1 -0
  111. package/dist/server/next/tags.d.mts +78 -0
  112. package/dist/server/next/tags.d.ts +78 -0
  113. package/dist/server/next/tags.js +34 -0
  114. package/dist/server/next/tags.js.map +1 -0
  115. package/dist/server/next/tags.mjs +34 -0
  116. package/dist/server/next/tags.mjs.map +1 -0
  117. package/dist/server/next.d.mts +432 -0
  118. package/dist/server/next.d.ts +432 -0
  119. package/dist/server/next.js +217 -0
  120. package/dist/server/next.js.map +1 -0
  121. package/dist/server/next.mjs +217 -0
  122. package/dist/server/next.mjs.map +1 -0
  123. package/dist/server/rendering/server.d.mts +3 -3
  124. package/dist/server/rendering/server.d.ts +3 -3
  125. package/dist/server/rendering/server.js +5 -4
  126. package/dist/server/rendering/server.js.map +1 -1
  127. package/dist/server/rendering/server.mjs +5 -4
  128. package/dist/server/rendering.d.mts +6 -6
  129. package/dist/server/rendering.d.ts +6 -6
  130. package/dist/server/rendering.js +7 -6
  131. package/dist/server/rendering.js.map +1 -1
  132. package/dist/server/rendering.mjs +9 -8
  133. package/dist/server/routing.d.mts +2 -2
  134. package/dist/server/routing.d.ts +2 -2
  135. package/dist/server/routing.js +2 -4
  136. package/dist/server/routing.js.map +1 -1
  137. package/dist/server/routing.mjs +1 -3
  138. package/dist/server/routing.mjs.map +1 -1
  139. package/dist/server/server.d.mts +4 -4
  140. package/dist/server/server.d.ts +4 -4
  141. package/dist/server/server.js +4 -5
  142. package/dist/server/server.js.map +1 -1
  143. package/dist/server/server.mjs +5 -6
  144. package/dist/server/theme-bridge.js +0 -1
  145. package/dist/server/theme-bridge.js.map +1 -1
  146. package/dist/server/theme-bridge.mjs +0 -1
  147. package/dist/server/theme-bridge.mjs.map +1 -1
  148. package/dist/server/theme.js +1 -3
  149. package/dist/server/theme.js.map +1 -1
  150. package/dist/server/theme.mjs +0 -2
  151. package/dist/server/theme.mjs.map +1 -1
  152. package/dist/server/{types-BvcJU7zk.d.ts → types-DnkRh0UL.d.ts} +118 -9
  153. package/dist/server/{types-1cLz0vnq.d.mts → types-MF2AWoKv.d.mts} +118 -9
  154. package/dist/server/webhooks.d.mts +75 -0
  155. package/dist/server/webhooks.d.ts +75 -0
  156. package/dist/server/webhooks.js +11 -0
  157. package/dist/server/webhooks.js.map +1 -0
  158. package/dist/server/webhooks.mjs +11 -0
  159. package/dist/server/webhooks.mjs.map +1 -0
  160. package/package.json +33 -1
  161. package/dist/server/chunk-3B364WO2.js.map +0 -1
  162. package/dist/server/chunk-BJTO5JO5.mjs +0 -11
  163. package/dist/server/chunk-DGUM43GV.js +0 -11
  164. package/dist/server/chunk-DGUM43GV.js.map +0 -1
  165. package/dist/server/chunk-I2D7KOEA.js.map +0 -1
  166. package/dist/server/chunk-I7ZR2WO3.mjs.map +0 -1
  167. package/dist/server/chunk-IVHIQFJH.js.map +0 -1
  168. package/dist/server/chunk-XXFF4RVR.mjs.map +0 -1
  169. package/dist/server/chunk-Z5ZA6Q4D.mjs.map +0 -1
  170. package/dist/server/loadPage-IDGVDFBB.js.map +0 -1
  171. /package/dist/server/{chunk-BJTO5JO5.mjs.map → env.mjs.map} +0 -0
  172. /package/dist/server/{loadPage-DNQTTRHL.mjs.map → loadPage-JI2SML4M.mjs.map} +0 -0
@@ -0,0 +1,69 @@
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
+
65
+ export {
66
+ generatePageMetadata,
67
+ generatePreviewMetadata
68
+ };
69
+ //# sourceMappingURL=chunk-SWYWZT3L.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":[]}
@@ -0,0 +1,52 @@
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; }
2
+
3
+
4
+ var _chunk7UPVCT3Kjs = require('./chunk-7UPVCT3K.js');
5
+
6
+ // src/rendering/components/Page.tsx
7
+ var _jsxruntime = require('react/jsx-runtime');
8
+ function Page({
9
+ page,
10
+ theme,
11
+ themeTokens: providedTokens,
12
+ siteId,
13
+ resolvedData,
14
+ routeMap,
15
+ wrapBlock,
16
+ registry,
17
+ usePlaceholders = false,
18
+ blockOverrides,
19
+ sdkConfig,
20
+ supabaseUrl,
21
+ dataContext
22
+ }) {
23
+ const baseTokens = _nullishCoalesce(providedTokens, () => ( _chunk7UPVCT3Kjs.buildThemeRuntime.call(void 0, theme).tokens));
24
+ const themeTokens = _optionalChain([sdkConfig, 'optionalAccess', _ => _.theme, 'optionalAccess', _2 => _2.palette]) ? { ...baseTokens, palette: { ...baseTokens.palette, ...sdkConfig.theme.palette } } : baseTokens;
25
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
26
+ _chunk7UPVCT3Kjs.PageRenderer,
27
+ {
28
+ theme,
29
+ page,
30
+ themeTokens,
31
+ usePlaceholders,
32
+ dataContext: {
33
+ siteId,
34
+ resolvedData,
35
+ routes: routeMap,
36
+ occurrenceContext: _nullishCoalesce(_optionalChain([dataContext, 'optionalAccess', _3 => _3.occurrenceContext]), () => ( null)),
37
+ contentEntry: _nullishCoalesce(_optionalChain([dataContext, 'optionalAccess', _4 => _4.contentEntry]), () => ( null)),
38
+ supabaseUrl
39
+ },
40
+ routeMap,
41
+ wrapBlock,
42
+ registry,
43
+ blockOverrides,
44
+ sdkConfig
45
+ }
46
+ );
47
+ }
48
+
49
+
50
+
51
+ exports.Page = Page;
52
+ //# sourceMappingURL=chunk-T26N3P26.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-T26N3P26.js","../../src/rendering/components/Page.tsx"],"names":[],"mappings":"AAAA;AACE;AACA;AACF,sDAA4B;AAC5B;AACA;AC0II,+CAAA;AAzBG,SAAS,IAAA,CAAK;AAAA,EACnB,IAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA,EAAa,cAAA;AAAA,EACb,MAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,gBAAA,EAAkB,KAAA;AAAA,EAClB,cAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA,EAAc;AAEZ,EAAA,MAAM,WAAA,mBAAa,cAAA,UAAkB,gDAAA,KAAuB,CAAA,CAAE,QAAA;AAI9D,EAAA,MAAM,YAAA,kBAAc,SAAA,2BAAW,KAAA,6BAAO,UAAA,EAClC,EAAE,GAAG,UAAA,EAAY,OAAA,EAAS,EAAE,GAAG,UAAA,CAAW,OAAA,EAAS,GAAG,SAAA,CAAU,KAAA,CAAM,QAAQ,EAAE,EAAA,EAChF,UAAA;AAEJ,EAAA,uBACE,6BAAA;AAAA,IAAC,6BAAA;AAAA,IAAA;AAAA,MACC,KAAA;AAAA,MACA,IAAA;AAAA,MACA,WAAA;AAAA,MACA,eAAA;AAAA,MACA,WAAA,EAAa;AAAA,QACX,MAAA;AAAA,QACA,YAAA;AAAA,QACA,MAAA,EAAQ,QAAA;AAAA,QACR,iBAAA,mCAAmB,WAAA,6BAAa,mBAAA,UAAqB,MAAA;AAAA,QACrD,YAAA,mCAAc,WAAA,6BAAa,cAAA,UAAgB,MAAA;AAAA,QAC3C;AAAA,MACF,CAAA;AAAA,MACA,QAAA;AAAA,MACA,SAAA;AAAA,MACA,QAAA;AAAA,MACA,cAAA;AAAA,MACA;AAAA,IAAA;AAAA,EACF,CAAA;AAEJ;ADpHA;AACA;AACE;AACF,oBAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-T26N3P26.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"]}
@@ -0,0 +1,45 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// src/webhooks/verify.ts
2
+ var _crypto = require('crypto'); var _crypto2 = _interopRequireDefault(_crypto);
3
+ var _zod = require('zod');
4
+ var WebhookPayloadSchema = _zod.z.object({
5
+ /** Event type (e.g., 'page.published', 'entry.published') */
6
+ event: _zod.z.string(),
7
+ /** ISO timestamp of when the event occurred */
8
+ timestamp: _zod.z.string(),
9
+ /** Site ID that triggered the event */
10
+ siteId: _zod.z.string(),
11
+ /** Event-specific data (varies by event type) */
12
+ data: _zod.z.record(_zod.z.string(), _zod.z.any()),
13
+ /** Cache invalidation tags (for tag-based revalidation) */
14
+ tags: _zod.z.array(_zod.z.string()).optional()
15
+ });
16
+ function verifyWebhookSignature(payload, signature, secret) {
17
+ const expectedSignature = _crypto2.default.createHmac("sha256", secret).update(payload).digest("hex");
18
+ if (signature.length !== expectedSignature.length) {
19
+ return false;
20
+ }
21
+ return _crypto2.default.timingSafeEqual(
22
+ Buffer.from(signature),
23
+ Buffer.from(expectedSignature)
24
+ );
25
+ }
26
+ function parseWebhookPayload(body) {
27
+ let parsed;
28
+ try {
29
+ parsed = JSON.parse(body);
30
+ } catch (e) {
31
+ return { success: false, error: "Invalid JSON" };
32
+ }
33
+ const result = WebhookPayloadSchema.safeParse(parsed);
34
+ if (!result.success) {
35
+ return { success: false, error: `Invalid payload: ${result.error.message}` };
36
+ }
37
+ return { success: true, payload: result.data };
38
+ }
39
+
40
+
41
+
42
+
43
+
44
+ exports.WebhookPayloadSchema = WebhookPayloadSchema; exports.verifyWebhookSignature = verifyWebhookSignature; exports.parseWebhookPayload = parseWebhookPayload;
45
+ //# sourceMappingURL=chunk-VODFQMUW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-VODFQMUW.js","../../src/webhooks/verify.ts"],"names":[],"mappings":"AAAA;ACMA,gFAAmB;AACnB,0BAAkB;AAKX,IAAM,qBAAA,EAAuB,MAAA,CAAE,MAAA,CAAO;AAAA;AAAA,EAE3C,KAAA,EAAO,MAAA,CAAE,MAAA,CAAO,CAAA;AAAA;AAAA,EAEhB,SAAA,EAAW,MAAA,CAAE,MAAA,CAAO,CAAA;AAAA;AAAA,EAEpB,MAAA,EAAQ,MAAA,CAAE,MAAA,CAAO,CAAA;AAAA;AAAA,EAEjB,IAAA,EAAM,MAAA,CAAE,MAAA,CAAO,MAAA,CAAE,MAAA,CAAO,CAAA,EAAG,MAAA,CAAE,GAAA,CAAI,CAAC,CAAA;AAAA;AAAA,EAElC,IAAA,EAAM,MAAA,CAAE,KAAA,CAAM,MAAA,CAAE,MAAA,CAAO,CAAC,CAAA,CAAE,QAAA,CAAS;AACrC,CAAC,CAAA;AA4BM,SAAS,sBAAA,CACd,OAAA,EACA,SAAA,EACA,MAAA,EACS;AACT,EAAA,MAAM,kBAAA,EAAoB,gBAAA,CACvB,UAAA,CAAW,QAAA,EAAU,MAAM,CAAA,CAC3B,MAAA,CAAO,OAAO,CAAA,CACd,MAAA,CAAO,KAAK,CAAA;AAIf,EAAA,GAAA,CAAI,SAAA,CAAU,OAAA,IAAW,iBAAA,CAAkB,MAAA,EAAQ;AACjD,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,OAAO,gBAAA,CAAO,eAAA;AAAA,IACZ,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA;AAAA,IACrB,MAAA,CAAO,IAAA,CAAK,iBAAiB;AAAA,EAC/B,CAAA;AACF;AA2BO,SAAS,mBAAA,CAAoB,IAAA,EAAkC;AACpE,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,OAAA,EAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAAA,EAC1B,EAAA,UAAQ;AACN,IAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,eAAe,CAAA;AAAA,EACjD;AAEA,EAAA,MAAM,OAAA,EAAS,oBAAA,CAAqB,SAAA,CAAU,MAAM,CAAA;AACpD,EAAA,GAAA,CAAI,CAAC,MAAA,CAAO,OAAA,EAAS;AACnB,IAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,CAAA,iBAAA,EAAoB,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,EAAA;AAC1E,EAAA;AAE6C,EAAA;AAC/C;AD3E6E;AACA;AACA;AACA;AACA;AACA","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-VODFQMUW.js","sourcesContent":[null,"/**\n * Webhook verification utilities for Riverbank SDK\n *\n * Provides framework-agnostic webhook signature verification and payload parsing.\n */\n\nimport crypto from 'crypto';\nimport { z } from 'zod';\n\n/**\n * Zod schema for webhook payload validation.\n */\nexport const WebhookPayloadSchema = z.object({\n /** Event type (e.g., 'page.published', 'entry.published') */\n event: z.string(),\n /** ISO timestamp of when the event occurred */\n timestamp: z.string(),\n /** Site ID that triggered the event */\n siteId: z.string(),\n /** Event-specific data (varies by event type) */\n data: z.record(z.string(), z.any()),\n /** Cache invalidation tags (for tag-based revalidation) */\n tags: z.array(z.string()).optional(),\n});\n\n/**\n * Webhook payload structure sent by the CMS.\n */\nexport type WebhookPayload = z.infer<typeof WebhookPayloadSchema>;\n\n/**\n * Verify a webhook signature using HMAC-SHA256.\n *\n * Uses timing-safe comparison to prevent timing attacks.\n *\n * @param payload - The raw request body as a string\n * @param signature - The X-Riverbank-Signature header value\n * @param secret - The webhook signing secret (RIVERBANK_WEBHOOK_SECRET)\n * @returns true if signature is valid, false otherwise\n *\n * @example\n * ```ts\n * const body = await request.text();\n * const signature = request.headers.get('x-riverbank-signature');\n * const secret = process.env.RIVERBANK_WEBHOOK_SECRET;\n *\n * if (!verifyWebhookSignature(body, signature, secret)) {\n * return new Response('Invalid signature', { status: 401 });\n * }\n * ```\n */\nexport function verifyWebhookSignature(\n payload: string,\n signature: string,\n secret: string\n): boolean {\n const expectedSignature = crypto\n .createHmac('sha256', secret)\n .update(payload)\n .digest('hex');\n\n // Length check before timing-safe comparison\n // timingSafeEqual throws if lengths differ\n if (signature.length !== expectedSignature.length) {\n return false;\n }\n\n // Timing-safe comparison to prevent timing attacks\n return crypto.timingSafeEqual(\n Buffer.from(signature),\n Buffer.from(expectedSignature)\n );\n}\n\n/**\n * Result type for webhook payload parsing.\n */\nexport type ParseWebhookResult =\n | { success: true; payload: WebhookPayload }\n | { success: false; error: string };\n\n/**\n * Parse and validate a webhook payload from the request body.\n *\n * Uses Zod schema validation to ensure the payload has the expected structure.\n *\n * @param body - The raw request body as a string\n * @returns A result object with either the validated payload or an error message\n *\n * @example\n * ```ts\n * const body = await request.text();\n * const result = parseWebhookPayload(body);\n * if (!result.success) {\n * return new Response(result.error, { status: 400 });\n * }\n * console.log(`Received ${result.payload.event} for site ${result.payload.siteId}`);\n * ```\n */\nexport function parseWebhookPayload(body: string): ParseWebhookResult {\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n return { success: false, error: 'Invalid JSON' };\n }\n\n const result = WebhookPayloadSchema.safeParse(parsed);\n if (!result.success) {\n return { success: false, error: `Invalid payload: ${result.error.message}` };\n }\n\n return { success: true, payload: result.data };\n}\n"]}
@@ -0,0 +1,13 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/env.ts
2
+ function isPreviewMode() {
3
+ const explicit = process.env.RIVERBANK_PREVIEW;
4
+ if (explicit !== void 0 && explicit !== "") {
5
+ return explicit === "true";
6
+ }
7
+ return process.env.VERCEL_ENV === "preview";
8
+ }
9
+
10
+
11
+
12
+ exports.isPreviewMode = isPreviewMode;
13
+ //# sourceMappingURL=chunk-WYNEYDXO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-WYNEYDXO.js","../../src/env.ts"],"names":[],"mappings":"AAAA;ACqBO,SAAS,aAAA,CAAA,EAAyB;AACvC,EAAA,MAAM,SAAA,EAAW,OAAA,CAAQ,GAAA,CAAI,iBAAA;AAG7B,EAAA,GAAA,CAAI,SAAA,IAAa,KAAA,EAAA,GAAa,SAAA,IAAa,EAAA,EAAI;AAC7C,IAAA,OAAO,SAAA,IAAa,MAAA;AAAA,EACtB;AAGA,EAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,WAAA,IAAe,SAAA;AACpC;ADvBA;AACA;AACE;AACF,sCAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-WYNEYDXO.js","sourcesContent":[null,"/**\n * Environment detection utilities for SDK\n *\n * Provides helpers for detecting preview mode and other environment states.\n */\n\n/**\n * Detects if the current environment is in preview mode.\n *\n * Precedence:\n * 1. RIVERBANK_PREVIEW env var (explicit override) - 'true' or 'false'\n * 2. VERCEL_ENV === 'preview' (Vercel preview deployments)\n * 3. Default: false (production behavior)\n *\n * In preview mode:\n * - Draft content is visible\n * - ISR revalidation is more aggressive\n * - Cache bypass may be enabled\n *\n * @returns true if in preview mode, false otherwise\n */\nexport function isPreviewMode(): boolean {\n const explicit = process.env.RIVERBANK_PREVIEW;\n\n // Explicit override takes precedence\n if (explicit !== undefined && explicit !== '') {\n return explicit === 'true';\n }\n\n // Fall back to Vercel environment detection\n return process.env.VERCEL_ENV === 'preview';\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { f as ResolverContext } from './loadPage-DP3nrHBi.js';
2
- import './Layout-wBtJLTVX.js';
1
+ import { f as ResolverContext } from './loadPage-i2r-X5b9.js';
2
+ import './Layout-Ce7PU9I5.js';
3
3
  import { T as Theme, H as HydratedTheme, E as ExpandedPalette } from './types-CVykEqXN.js';
4
4
  import './schema-Z6-afHJG.js';
5
5
  import { a as ThemeTokens, T as TransformRegistry } from './core-DsNWrl3o.js';
@@ -1,5 +1,5 @@
1
- import { f as ResolverContext } from './loadPage-B8mQUUSo.mjs';
2
- import './Layout-B7cvis7r.mjs';
1
+ import { f as ResolverContext } from './loadPage-CxlYLe5K.mjs';
2
+ import './Layout-WllR8Zug.mjs';
3
3
  import { T as Theme, H as HydratedTheme, E as ExpandedPalette } from './types-Dsu9wsUh.mjs';
4
4
  import './schema-Z6-afHJG.mjs';
5
5
  import { a as ThemeTokens, T as TransformRegistry } from './core-DsNWrl3o.mjs';
@@ -1,11 +1,11 @@
1
- export { d as BlockOverrideComponent, B as BlockOverrides, b as Page, P as PageProps, c as PageRenderer } from './loadPage-B8mQUUSo.mjs';
2
- export { H as HeaderData, L as Layout, a as LayoutProps } from './Layout-B7cvis7r.mjs';
1
+ export { d as BlockOverrideComponent, B as BlockOverrides, b as Page, P as PageProps, c as PageRenderer } from './loadPage-CxlYLe5K.mjs';
2
+ export { H as HeaderData, L as Layout, a as LayoutProps } from './Layout-WllR8Zug.mjs';
3
3
  export { T as Theme } from './types-Dsu9wsUh.mjs';
4
4
  export { P as PageOutline } from './schema-Z6-afHJG.mjs';
5
- export { f as BackgroundInput, B as BodyTextContent, H as HeroContent, 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';
5
+ export { f as BackgroundInput, B as BodyTextContent, H as HeroContent, 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-RPzRQve6.mjs';
6
6
  export { R as RouteMap, a as ThemeTokens } from './core-DsNWrl3o.mjs';
7
7
  export { T as TipTapNode } from './richTextSchema-DURiozvD.mjs';
8
- import './types-1cLz0vnq.mjs';
8
+ import './types-MF2AWoKv.mjs';
9
9
  import 'react/jsx-runtime';
10
10
  import 'react';
11
11
  import './types-CbagRQ_7.mjs';
@@ -1,11 +1,11 @@
1
- export { d as BlockOverrideComponent, B as BlockOverrides, b as Page, P as PageProps, c as PageRenderer } from './loadPage-DP3nrHBi.js';
2
- export { H as HeaderData, L as Layout, a as LayoutProps } from './Layout-wBtJLTVX.js';
1
+ export { d as BlockOverrideComponent, B as BlockOverrides, b as Page, P as PageProps, c as PageRenderer } from './loadPage-i2r-X5b9.js';
2
+ export { H as HeaderData, L as Layout, a as LayoutProps } from './Layout-Ce7PU9I5.js';
3
3
  export { T as Theme } from './types-CVykEqXN.js';
4
4
  export { P as PageOutline } from './schema-Z6-afHJG.js';
5
- export { f as BackgroundInput, B as BodyTextContent, H as HeroContent, 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';
5
+ export { f as BackgroundInput, B as BodyTextContent, H as HeroContent, 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--LT61IKp.js';
6
6
  export { R as RouteMap, a as ThemeTokens } from './core-DsNWrl3o.js';
7
7
  export { T as TipTapNode } from './richTextSchema-DURiozvD.js';
8
- import './types-BvcJU7zk.js';
8
+ import './types-DnkRh0UL.js';
9
9
  import 'react/jsx-runtime';
10
10
  import 'react';
11
11
  import './types-DuQCNVV0.js';
@@ -1,10 +1,12 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
-
4
- var _chunk3B364WO2js = require('./chunk-3B364WO2.js');
3
+ var _chunk7BVRA5MYjs = require('./chunk-7BVRA5MY.js');
5
4
  require('./chunk-EIVISR62.js');
6
5
 
7
6
 
7
+ var _chunkT26N3P26js = require('./chunk-T26N3P26.js');
8
+
9
+
8
10
 
9
11
 
10
12
 
@@ -12,7 +14,6 @@ require('./chunk-EIVISR62.js');
12
14
 
13
15
  var _chunk7UPVCT3Kjs = require('./chunk-7UPVCT3K.js');
14
16
  require('./chunk-YYO3RIFO.js');
15
- require('./chunk-DGUM43GV.js');
16
17
 
17
18
 
18
19
 
@@ -22,5 +23,5 @@ require('./chunk-DGUM43GV.js');
22
23
 
23
24
 
24
25
 
25
- exports.Layout = _chunk3B364WO2js.Layout; exports.Page = _chunk3B364WO2js.Page; exports.PageRenderer = _chunk7UPVCT3Kjs.PageRenderer; exports.RichText = _chunk7UPVCT3Kjs.RichText; exports.SectionBackground = _chunk7UPVCT3Kjs.SectionBackground; exports.buildThemeRuntime = _chunk7UPVCT3Kjs.buildThemeRuntime; exports.resolveBackground = _chunk7UPVCT3Kjs.resolveBackground; exports.resolveImageUrl = _chunk7UPVCT3Kjs.resolveImageUrl;
26
+ 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.resolveBackground = _chunk7UPVCT3Kjs.resolveBackground; exports.resolveImageUrl = _chunk7UPVCT3Kjs.resolveImageUrl;
26
27
  //# sourceMappingURL=components.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/components.js"],"names":[],"mappings":"AAAA;AACE;AACA;AACF,sDAA4B;AAC5B,+BAA4B;AAC5B;AACE;AACA;AACA;AACA;AACA;AACA;AACF,sDAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,+aAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/components.js"}
1
+ {"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/components.js"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B,+BAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACA;AACA;AACA;AACA;AACA;AACF,sDAA4B;AAC5B,+BAA4B;AAC5B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,+aAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/components.js"}
@@ -1,8 +1,10 @@
1
1
  import {
2
- Layout,
3
- Page
4
- } from "./chunk-XXFF4RVR.mjs";
2
+ Layout
3
+ } from "./chunk-RBJFXNDM.mjs";
5
4
  import "./chunk-YXA4GAAQ.mjs";
5
+ import {
6
+ Page
7
+ } from "./chunk-ARNCLSQT.mjs";
6
8
  import {
7
9
  PageRenderer,
8
10
  RichText,
@@ -12,7 +14,6 @@ import {
12
14
  resolveImageUrl
13
15
  } from "./chunk-LNOUXALA.mjs";
14
16
  import "./chunk-BYBJA6SP.mjs";
15
- import "./chunk-BJTO5JO5.mjs";
16
17
  export {
17
18
  Layout,
18
19
  Page,
@@ -29,7 +29,6 @@ require('./chunk-GERCMTPQ.js');
29
29
  require('./chunk-7UPVCT3K.js');
30
30
  require('./chunk-RVDS7VSP.js');
31
31
  require('./chunk-YYO3RIFO.js');
32
- require('./chunk-DGUM43GV.js');
33
32
 
34
33
 
35
34
 
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/config-validation.js"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,sDAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,2yDAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/config-validation.js"}
1
+ {"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/config-validation.js"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,2yDAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/config-validation.js"}
@@ -29,7 +29,6 @@ import "./chunk-D2QLTPUJ.mjs";
29
29
  import "./chunk-LNOUXALA.mjs";
30
30
  import "./chunk-AEFWG657.mjs";
31
31
  import "./chunk-BYBJA6SP.mjs";
32
- import "./chunk-BJTO5JO5.mjs";
33
32
  export {
34
33
  blockFieldConfigSchema,
35
34
  blockFieldExtensionSchema,
@@ -30,7 +30,6 @@ var _chunkGERCMTPQjs = require('./chunk-GERCMTPQ.js');
30
30
  require('./chunk-7UPVCT3K.js');
31
31
  require('./chunk-RVDS7VSP.js');
32
32
  require('./chunk-YYO3RIFO.js');
33
- require('./chunk-DGUM43GV.js');
34
33
 
35
34
  // src/config/typed-entries.ts
36
35
  function defineTypedContentType(config) {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/config.js","../../src/config/typed-entries.ts","../../src/config/index.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B;AACA;AC8KO,SAAS,sBAAA,CAGd,MAAA,EAAwD;AACxD,EAAA,OAAO,MAAA;AACT;AAwDO,SAAS,WAAA,CAId,WAAA,EACA,KAAA,EACa;AACb,EAAA,OAAO;AAAA,IACL,GAAG,KAAA;AAAA,IACH,WAAA,EAAa,WAAA,CAAY;AAAA,EAC3B,CAAA;AACF;AA2BO,IAAM,OAAA,EAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpB,KAAA,CAAA,EAAoB;AAClB,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,OAAA,EAAS,CAAC,EAAE,CAAA;AAAA,EACpC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAA,CAAU,IAAA,EAA0B;AAClC,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,KAAA;AAAA,MACN,OAAA,EAAS;AAAA,QACP;AAAA,UACE,IAAA,EAAM,WAAA;AAAA,UACN,OAAA,EAAS,KAAA,EAAO,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAK,CAAC,EAAA,EAAI,CAAC;AAAA,QAC9C;AAAA,MACF;AAAA,IACF,CAAA;AAAA,EACF,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,GAAA,CAAI,OAAA,EAAmC;AACrC,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,QAAQ,CAAA;AAAA,EAChC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAA,CAAQ,KAAA,EAA8B,IAAA,EAA0B;AAC9D,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,SAAA;AAAA,MACN,KAAA,EAAO,EAAE,MAAM,CAAA;AAAA,MACf,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAK,CAAC;AAAA,IAClC,CAAA;AAAA,EACF;AACF,CAAA;ADzQA;AACA;AEiCO,SAAS,YAAA,CAAa,MAAA,EAAkD;AAC7E,EAAA,OAAO,MAAA;AACT;AAuCO,SAAS,mBAAA,CAAoB,MAAA,EAAsC;AACxE,EAAA,OAAO,MAAA;AACT;AFrEA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,0/DAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/config.js","sourcesContent":[null,"/**\n * Type-Safe Content Entries\n *\n * This module provides type-safe helpers for defining content types and entries\n * in SDK site configurations. When used with `as const`, TypeScript can infer\n * the exact shape of entry data from the content type's field definitions.\n *\n * @example\n * ```typescript\n * import { defineTypedContentType, createEntry, tiptap } from '@riverbankcms/sdk/config';\n *\n * // Define content type with `as const` for type inference\n * export const testimonialType = defineTypedContentType({\n * key: 'testimonial',\n * name: 'Testimonial',\n * hasPages: false,\n * fields: [\n * { id: 'name', type: 'text', label: 'Name', required: true, multiline: false },\n * { id: 'quote', type: 'richText', label: 'Quote', required: true, format: 'html' },\n * ],\n * } as const);\n *\n * // Create entry with full type safety\n * const entry = createEntry(testimonialType, {\n * identifier: 'testimonial-1',\n * data: {\n * name: 'John Doe', // TypeScript knows this is string\n * quote: tiptap.paragraph('Great service!'), // TypeScript knows this is TipTapNode\n * },\n * });\n * ```\n */\n\nimport type {\n FieldDefinition,\n TextFieldDefinition,\n RichTextFieldDefinition,\n MediaFieldDefinition,\n BooleanFieldDefinition,\n NumberFieldDefinition,\n DateFieldDefinition,\n TimeFieldDefinition,\n DateTimeFieldDefinition,\n SlugFieldDefinition,\n UrlFieldDefinition,\n LinkFieldDefinition,\n SelectFieldDefinition,\n ReferenceFieldDefinition,\n RepeaterFieldDefinition,\n GroupFieldDefinition,\n ModalFieldDefinition,\n TabGroupFieldDefinition,\n PresetOrCustomFieldDefinition,\n ContentTypeSelectFieldDefinition,\n EntryPickerFieldDefinition,\n TipTapNode,\n Media,\n LinkValue,\n} from '@riverbankcms/blocks';\nimport type { ContentTypeConfig, EntryConfig } from './content-types';\n\n// Re-export value types for convenience\nexport type { TipTapNode, Media, LinkValue } from '@riverbankcms/blocks';\nexport type {\n InternalLinkValue,\n ExternalLinkValue,\n CustomLinkValue,\n} from '@riverbankcms/blocks';\n\n// =============================================================================\n// Type Infrastructure\n// =============================================================================\n\n/**\n * Infers the data object shape from tabGroup tabs (flattens all tab fields).\n * TabGroup fields flatten all their tab fields into a single data object.\n */\ntype InferDataFromTabs<Tabs extends readonly { fields: readonly FieldDefinition[] }[]> =\n InferDataFromFields<Tabs[number]['fields']>;\n\n// NOTE: Polymorphic repeater type inference would require a helper like this,\n// but TypeScript's mapped types don't distribute correctly over union keys\n// when nested inside conditional types. Left as documentation for future work.\n// type PolymorphicItemData<K, IT> = K extends string\n// ? K extends keyof IT\n// ? IT[K] extends { fields: infer F extends readonly FieldDefinition[] }\n// ? { _type: K } & InferDataFromFields<F>\n// : never\n// : never\n// : never;\n\n/**\n * Maps a field definition to its TypeScript value type.\n * Uses conditional types to infer the correct type based on field.type.\n *\n * Coverage:\n * - Simple primitives: text, boolean, number\n * - Complex types: richText (TipTapNode), media (Media | null), link (LinkValue | null)\n * - Date/time: date, time, datetime (all ISO strings)\n * - String-value: slug, url, reference, presetOrCustom, contentTypeSelect\n * - Select: single (string) vs multiple (string[])\n * - Entry picker: string | null\n * - Nested: group, modal (nested InferDataFromFields)\n * - Repeater: monomorphic (array) and polymorphic (discriminated union array)\n * - TabGroup: flattened fields from all tabs\n */\nexport type FieldValueType<F extends FieldDefinition> =\n // Simple primitives - use specific field types for better inference\n F extends TextFieldDefinition ? string :\n F extends BooleanFieldDefinition ? boolean :\n F extends NumberFieldDefinition ? number :\n // Complex types\n F extends RichTextFieldDefinition ? TipTapNode :\n F extends MediaFieldDefinition ? Media | null :\n F extends LinkFieldDefinition ? LinkValue | null :\n // Date/time types (all stored as ISO strings)\n F extends DateFieldDefinition ? string :\n F extends TimeFieldDefinition ? string :\n F extends DateTimeFieldDefinition ? string :\n // String-value types\n F extends SlugFieldDefinition ? string :\n F extends UrlFieldDefinition ? string :\n F extends ReferenceFieldDefinition ? string :\n F extends PresetOrCustomFieldDefinition ? string :\n F extends ContentTypeSelectFieldDefinition ? string :\n // Select: check multiple flag first (more specific match)\n F extends SelectFieldDefinition & { multiple: true } ? string[] :\n F extends SelectFieldDefinition ? string :\n // Entry picker\n F extends EntryPickerFieldDefinition ? string | null :\n // Nested types (group, modal)\n F extends GroupFieldDefinition & { schema: { fields: infer GF } } ?\n GF extends readonly FieldDefinition[] ? InferDataFromFields<GF> : never :\n F extends ModalFieldDefinition & { schema: { fields: infer MF } } ?\n MF extends readonly FieldDefinition[] ? InferDataFromFields<MF> : never :\n // Repeater types (polymorphic first - more specific, then monomorphic)\n // TODO: Polymorphic repeaters need more complex type distribution.\n // For now, return unknown[] - the runtime data is still correct.\n F extends { type: 'repeater'; polymorphic: true } ? unknown[] :\n F extends RepeaterFieldDefinition & { schema: { fields: infer RF } } ?\n RF extends readonly FieldDefinition[] ? InferDataFromFields<RF>[] : never :\n // TabGroup (flattens all tab fields)\n F extends TabGroupFieldDefinition & { tabs: infer T } ?\n T extends readonly { fields: readonly FieldDefinition[] }[] ?\n InferDataFromTabs<T> : never :\n // Fallback for unknown types\n unknown;\n\n/**\n * Infers the data object shape from an array of field definitions.\n * Required fields are non-optional, optional fields are `| undefined`.\n *\n * @example\n * ```typescript\n * const fields = [\n * { id: 'name', type: 'text', required: true },\n * { id: 'bio', type: 'text', required: false },\n * ] as const;\n *\n * type Data = InferDataFromFields<typeof fields>;\n * // { name: string; bio: string | undefined }\n * ```\n */\nexport type InferDataFromFields<Fields extends readonly FieldDefinition[]> = {\n [F in Fields[number] as F['id']]: F extends { required: true }\n ? FieldValueType<F>\n : FieldValueType<F> | undefined;\n};\n\n// =============================================================================\n// TypedContentType\n// =============================================================================\n\n/**\n * A content type definition with preserved field types for type inference.\n * Extends ContentTypeConfig to ensure all required fields are present.\n * The generic parameters capture the literal types from `as const`.\n */\nexport interface TypedContentType<\n K extends string = string,\n F extends readonly FieldDefinition[] = readonly FieldDefinition[]\n> extends Omit<ContentTypeConfig, 'key' | 'fields'> {\n key: K;\n fields: F;\n}\n\n/**\n * Define a content type with preserved field types for type inference.\n *\n * IMPORTANT: Use `as const` on the config object to enable type inference.\n * Without `as const`, TypeScript widens literal types and inference won't work.\n *\n * @param config - The content type configuration\n * @returns The same config object with preserved types\n *\n * @example\n * ```typescript\n * export const testimonialType = defineTypedContentType({\n * key: 'testimonial',\n * name: 'Testimonial',\n * hasPages: false,\n * fields: [\n * { id: 'name', type: 'text', label: 'Name', required: true, multiline: false },\n * { id: 'quote', type: 'richText', label: 'Quote', required: true, format: 'html' },\n * ],\n * } as const);\n * ```\n */\nexport function defineTypedContentType<\n K extends string,\n F extends readonly FieldDefinition[]\n>(config: TypedContentType<K, F>): TypedContentType<K, F> {\n return config;\n}\n\n// =============================================================================\n// TypedEntryConfig and createEntry\n// =============================================================================\n\n/**\n * Entry configuration with typed data field.\n * Used internally by createEntry to enforce type safety.\n */\nexport interface TypedEntryConfig<Data extends Record<string, unknown>> {\n /** Unique identifier for this entry. Required for SDK sync. */\n identifier: string;\n /** Title for the entry */\n title?: string;\n /** Slug for routable entries */\n slug?: string;\n /** Status: 'draft' or 'published' */\n status?: 'draft' | 'published';\n /** Summary/description */\n summary?: string;\n /** SEO meta title */\n metaTitle?: string;\n /** SEO meta description */\n metaDescription?: string;\n /** Entry data matching the content type's field definitions */\n data: Data;\n}\n\n/**\n * Create a type-safe content entry for a typed content type.\n *\n * The data field is validated against the content type's field definitions.\n * TypeScript will error if:\n * - A required field is missing\n * - A field name is misspelled\n * - A field value has the wrong type\n * - An extra field is provided (with strict mode)\n *\n * @param contentType - The typed content type definition\n * @param entry - The entry configuration with typed data\n * @returns EntryConfig compatible with SDK content configuration\n *\n * @example\n * ```typescript\n * const entry = createEntry(testimonialType, {\n * identifier: 'testimonial-1',\n * title: 'John Doe',\n * status: 'published',\n * data: {\n * name: 'John Doe',\n * quote: tiptap.paragraph('Great service!'),\n * },\n * });\n * ```\n */\nexport function createEntry<\n K extends string,\n F extends readonly FieldDefinition[]\n>(\n contentType: TypedContentType<K, F>,\n entry: TypedEntryConfig<InferDataFromFields<F>>\n): EntryConfig {\n return {\n ...entry,\n contentType: contentType.key,\n };\n}\n\n// =============================================================================\n// TipTap Helpers\n// =============================================================================\n\n/**\n * Helpers for creating TipTap document structures.\n *\n * Use these helpers when populating richText fields to avoid manually\n * constructing the TipTap JSON structure.\n *\n * @example\n * ```typescript\n * // Simple paragraph\n * const body = tiptap.paragraph('Hello, world!');\n *\n * // Empty document\n * const emptyDoc = tiptap.empty();\n *\n * // Complex document\n * const doc = tiptap.doc([\n * tiptap.heading(1, 'Welcome'),\n * { type: 'paragraph', content: [{ type: 'text', text: 'Introduction...' }] },\n * ]);\n * ```\n */\nexport const tiptap = {\n /**\n * Create an empty TipTap document.\n *\n * @returns An empty TipTap document node\n */\n empty(): TipTapNode {\n return { type: 'doc', content: [] };\n },\n\n /**\n * Create a TipTap document with a single paragraph.\n *\n * @param text - The paragraph text content\n * @returns A TipTap document with one paragraph\n */\n paragraph(text: string): TipTapNode {\n return {\n type: 'doc',\n content: [\n {\n type: 'paragraph',\n content: text ? [{ type: 'text', text }] : [],\n },\n ],\n };\n },\n\n /**\n * Create a TipTap document with custom content nodes.\n *\n * @param content - Array of TipTap nodes to include in the document\n * @returns A TipTap document wrapping the content\n */\n doc(content: TipTapNode[]): TipTapNode {\n return { type: 'doc', content };\n },\n\n /**\n * Create a heading node.\n *\n * Note: This returns a heading node, not a document. Use with tiptap.doc()\n * to create a complete document.\n *\n * @param level - Heading level (1-6)\n * @param text - Heading text content\n * @returns A TipTap heading node\n */\n heading(level: 1 | 2 | 3 | 4 | 5 | 6, text: string): TipTapNode {\n return {\n type: 'heading',\n attrs: { level },\n content: [{ type: 'text', text }],\n };\n },\n};\n","/**\n * SDK Site Configuration\n *\n * Types and utilities for defining site-level configuration\n * that SDK sites expose to the dashboard.\n */\n\nimport type { RiverbankSiteConfig, ContentConfig } from './types';\n\n// Types\nexport type {\n RiverbankSiteConfig,\n SiteStyleConfig,\n SectionBackground,\n SectionOptionsConfig,\n ContainerOptionsConfig,\n SectionSpacing,\n ContainerMaxWidth,\n ContainerAlignment,\n SdkThemeConfig,\n SdkThemePalette,\n SdkCustomBlock,\n FieldSelectOption,\n BlockFieldConfig,\n BlockFieldOptionsMap,\n BlockFieldExtension,\n BlockFieldExtensionsMap,\n FieldDefinition,\n // Content scaffolding types\n ContentConfig,\n ContentTypeConfig,\n PageConfig,\n EntryConfig,\n BlockConfig,\n NavigationMenuConfig,\n NavigationItemConfig,\n NavigationLinkType,\n SiteSettingsConfig,\n} from './types';\n\n// Validation schemas\nexport {\n riverbankSiteConfigSchema,\n siteStyleConfigSchema,\n sectionBackgroundSchema,\n sectionSpacingSchema,\n containerMaxWidthSchema,\n containerAlignmentSchema,\n sectionOptionsSchema,\n containerOptionsSchema,\n sdkThemeConfigSchema,\n sdkThemePaletteSchema,\n sdkCustomBlockSchema,\n fieldSelectOptionSchema,\n blockFieldConfigSchema,\n blockFieldOptionsSchema,\n blockFieldExtensionSchema,\n blockFieldExtensionsSchema,\n // Content scaffolding schemas\n contentConfigSchema,\n} from './validation';\n\n// Content validation schemas for more granular use\nexport {\n contentTypeConfigSchema,\n pageConfigSchema,\n entryConfigSchema,\n navigationMenuConfigSchema,\n navigationItemConfigSchema,\n siteSettingsConfigSchema,\n blockConfigSchema,\n} from './content-validation';\n\nexport type {\n ValidatedRiverbankSiteConfig,\n ValidatedSdkCustomBlock,\n ContentConfigInput,\n ContentConfigOutput,\n} from './validation';\n\n// Block kind types (single source of truth from @riverbankcms/blocks)\nexport {\n SYSTEM_BLOCK_KINDS,\n type SystemBlockKind,\n type CustomBlockKind,\n type BlockKind,\n} from '../types';\n\n// Type-safe content entry helpers\nexport {\n defineTypedContentType,\n createEntry,\n tiptap,\n type TypedContentType,\n type TypedEntryConfig,\n type InferDataFromFields,\n type FieldValueType,\n} from './typed-entries';\n\n// Re-export value types for convenience when building entry data\nexport type {\n TipTapNode,\n Media,\n LinkValue,\n InternalLinkValue,\n ExternalLinkValue,\n CustomLinkValue,\n} from './typed-entries';\n\n/**\n * Helper function to define a Builder site configuration with type checking.\n *\n * @example\n * ```typescript\n * import { defineConfig } from '@riverbankcms/sdk/config';\n *\n * export default defineConfig({\n * siteId: '123e4567-e89b-12d3-a456-426614174000',\n * theme: {\n * palette: {\n * primary: '#6d28d9',\n * },\n * },\n * styles: {\n * sectionBackgrounds: [\n * { id: 'primary', label: 'Purple', token: 'primary' },\n * ],\n * },\n * });\n * ```\n */\nexport function defineConfig(config: RiverbankSiteConfig): RiverbankSiteConfig {\n return config;\n}\n\n/**\n * Helper function to define content scaffolding configuration with type checking.\n *\n * This can be used to define content configuration in a separate file,\n * which is then imported into riverbank.config.ts.\n *\n * @example\n * ```typescript\n * // content.config.ts\n * import { defineContentConfig } from '@riverbankcms/sdk/config';\n *\n * export const contentConfig = defineContentConfig({\n * contentTypes: [\n * {\n * key: 'testimonial',\n * name: 'Testimonial',\n * hasPages: false,\n * fields: [\n * { id: 'quote', type: 'richText', label: 'Quote', required: true },\n * ],\n * },\n * ],\n * pages: [\n * { identifier: 'home', title: 'Home', path: '/' },\n * ],\n * });\n *\n * // riverbank.config.ts\n * import { defineConfig } from '@riverbankcms/sdk/config';\n * import { contentConfig } from './content.config';\n *\n * export default defineConfig({\n * siteId: '...',\n * content: contentConfig,\n * });\n * ```\n */\nexport function defineContentConfig(config: ContentConfig): ContentConfig {\n return config;\n}\n"]}
1
+ {"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/config.js","../../src/config/typed-entries.ts","../../src/config/index.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B;AACA;AC+KO,SAAS,sBAAA,CAGd,MAAA,EAAwD;AACxD,EAAA,OAAO,MAAA;AACT;AAwDO,SAAS,WAAA,CAId,WAAA,EACA,KAAA,EACa;AACb,EAAA,OAAO;AAAA,IACL,GAAG,KAAA;AAAA,IACH,WAAA,EAAa,WAAA,CAAY;AAAA,EAC3B,CAAA;AACF;AA2BO,IAAM,OAAA,EAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpB,KAAA,CAAA,EAAoB;AAClB,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,OAAA,EAAS,CAAC,EAAE,CAAA;AAAA,EACpC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAA,CAAU,IAAA,EAA0B;AAClC,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,KAAA;AAAA,MACN,OAAA,EAAS;AAAA,QACP;AAAA,UACE,IAAA,EAAM,WAAA;AAAA,UACN,OAAA,EAAS,KAAA,EAAO,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAK,CAAC,EAAA,EAAI,CAAC;AAAA,QAC9C;AAAA,MACF;AAAA,IACF,CAAA;AAAA,EACF,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,GAAA,CAAI,OAAA,EAAmC;AACrC,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,QAAQ,CAAA;AAAA,EAChC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAA,CAAQ,KAAA,EAA8B,IAAA,EAA0B;AAC9D,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,SAAA;AAAA,MACN,KAAA,EAAO,EAAE,MAAM,CAAA;AAAA,MACf,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAK,CAAC;AAAA,IAClC,CAAA;AAAA,EACF;AACF,CAAA;AD1QA;AACA;AEkCO,SAAS,YAAA,CAAa,MAAA,EAAkD;AAC7E,EAAA,OAAO,MAAA;AACT;AAuCO,SAAS,mBAAA,CAAoB,MAAA,EAAsC;AACxE,EAAA,OAAO,MAAA;AACT;AFtEA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,0/DAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/config.js","sourcesContent":[null,"/**\n * Type-Safe Content Entries\n *\n * This module provides type-safe helpers for defining content types and entries\n * in SDK site configurations. When used with `as const`, TypeScript can infer\n * the exact shape of entry data from the content type's field definitions.\n *\n * @example\n * ```typescript\n * import { defineTypedContentType, createEntry, tiptap } from '@riverbankcms/sdk/config';\n *\n * // Define content type with `as const` for type inference\n * export const testimonialType = defineTypedContentType({\n * key: 'testimonial',\n * name: 'Testimonial',\n * hasPages: false,\n * fields: [\n * { id: 'name', type: 'text', label: 'Name', required: true, multiline: false },\n * { id: 'quote', type: 'richText', label: 'Quote', required: true, format: 'html' },\n * ],\n * } as const);\n *\n * // Create entry with full type safety\n * const entry = createEntry(testimonialType, {\n * identifier: 'testimonial-1',\n * data: {\n * name: 'John Doe', // TypeScript knows this is string\n * quote: tiptap.paragraph('Great service!'), // TypeScript knows this is TipTapNode\n * },\n * });\n * ```\n */\n\nimport type {\n FieldDefinition,\n TextFieldDefinition,\n RichTextFieldDefinition,\n MediaFieldDefinition,\n BooleanFieldDefinition,\n NumberFieldDefinition,\n DateFieldDefinition,\n TimeFieldDefinition,\n DateTimeFieldDefinition,\n SlugFieldDefinition,\n UrlFieldDefinition,\n LinkFieldDefinition,\n SelectFieldDefinition,\n ReferenceFieldDefinition,\n RepeaterFieldDefinition,\n GroupFieldDefinition,\n ModalFieldDefinition,\n TabGroupFieldDefinition,\n PresetOrCustomFieldDefinition,\n ContentTypeSelectFieldDefinition,\n EntryPickerFieldDefinition,\n TipTapNode,\n Media,\n LinkValue,\n} from '@riverbankcms/blocks';\nimport type { ContentTypeConfig, EntryConfig } from './content-types';\n\n// Re-export value types for convenience\nexport type { TipTapNode, Media, LinkValue } from '@riverbankcms/blocks';\nexport type {\n InternalLinkValue,\n ExternalLinkValue,\n CustomLinkValue,\n} from '@riverbankcms/blocks';\n\n// =============================================================================\n// Type Infrastructure\n// =============================================================================\n\n/**\n * Infers the data object shape from tabGroup tabs (flattens all tab fields).\n * TabGroup fields flatten all their tab fields into a single data object.\n */\ntype InferDataFromTabs<Tabs extends readonly { fields: readonly FieldDefinition[] }[]> =\n InferDataFromFields<Tabs[number]['fields']>;\n\n// NOTE: Polymorphic repeater type inference would require a helper like this,\n// but TypeScript's mapped types don't distribute correctly over union keys\n// when nested inside conditional types. Left as documentation for future work.\n// type PolymorphicItemData<K, IT> = K extends string\n// ? K extends keyof IT\n// ? IT[K] extends { fields: infer F extends readonly FieldDefinition[] }\n// ? { _type: K } & InferDataFromFields<F>\n// : never\n// : never\n// : never;\n\n/**\n * Maps a field definition to its TypeScript value type.\n * Uses conditional types to infer the correct type based on field.type.\n *\n * Coverage:\n * - Simple primitives: text, boolean, number\n * - Complex types: richText (TipTapNode), media (Media | null), link (LinkValue | null)\n * - Date/time: date, time, datetime (all ISO strings)\n * - String-value: slug, url, reference, presetOrCustom, contentTypeSelect\n * - Select: single (string) vs multiple (string[])\n * - Entry picker: string | null\n * - Nested: group, modal (nested InferDataFromFields)\n * - Repeater: monomorphic (array) and polymorphic (discriminated union array)\n * - TabGroup: flattened fields from all tabs\n */\nexport type FieldValueType<F extends FieldDefinition> =\n // Simple primitives - use specific field types for better inference\n F extends TextFieldDefinition ? string :\n F extends BooleanFieldDefinition ? boolean :\n F extends NumberFieldDefinition ? number :\n // Complex types\n F extends RichTextFieldDefinition ? TipTapNode :\n F extends MediaFieldDefinition ? Media | null :\n F extends LinkFieldDefinition ? LinkValue | null :\n // Date/time types (all stored as ISO strings)\n F extends DateFieldDefinition ? string :\n F extends TimeFieldDefinition ? string :\n F extends DateTimeFieldDefinition ? string :\n // String-value types\n F extends SlugFieldDefinition ? string :\n F extends UrlFieldDefinition ? string :\n F extends ReferenceFieldDefinition ? string :\n F extends PresetOrCustomFieldDefinition ? string :\n F extends ContentTypeSelectFieldDefinition ? string :\n // Select: check multiple flag first (more specific match)\n F extends SelectFieldDefinition & { multiple: true } ? string[] :\n F extends SelectFieldDefinition ? string :\n // Entry picker\n F extends EntryPickerFieldDefinition ? string | null :\n // Nested types (group, modal)\n F extends GroupFieldDefinition & { schema: { fields: infer GF } } ?\n GF extends readonly FieldDefinition[] ? InferDataFromFields<GF> : never :\n F extends ModalFieldDefinition & { schema: { fields: infer MF } } ?\n MF extends readonly FieldDefinition[] ? InferDataFromFields<MF> : never :\n // Repeater types (polymorphic first - more specific, then monomorphic)\n // TODO: Polymorphic repeaters need more complex type distribution.\n // For now, return unknown[] - the runtime data is still correct.\n F extends { type: 'repeater'; polymorphic: true } ? unknown[] :\n F extends RepeaterFieldDefinition & { schema: { fields: infer RF } } ?\n RF extends readonly FieldDefinition[] ? InferDataFromFields<RF>[] : never :\n // TabGroup (flattens all tab fields)\n F extends TabGroupFieldDefinition & { tabs: infer T } ?\n T extends readonly { fields: readonly FieldDefinition[] }[] ?\n InferDataFromTabs<T> : never :\n // Fallback for unknown types\n unknown;\n\n/**\n * Infers the data object shape from an array of field definitions.\n * Required fields are non-optional, optional fields are `| undefined`.\n *\n * @example\n * ```typescript\n * const fields = [\n * { id: 'name', type: 'text', required: true },\n * { id: 'bio', type: 'text', required: false },\n * ] as const;\n *\n * type Data = InferDataFromFields<typeof fields>;\n * // { name: string; bio: string | undefined }\n * ```\n */\nexport type InferDataFromFields<Fields extends readonly FieldDefinition[]> = {\n [F in Fields[number] as F['id']]: F extends { required: true }\n ? FieldValueType<F>\n : FieldValueType<F> | undefined;\n};\n\n// =============================================================================\n// TypedContentType\n// =============================================================================\n\n/**\n * A content type definition with preserved field types for type inference.\n * Extends ContentTypeConfig to ensure all required fields are present.\n * The generic parameters capture the literal types from `as const`.\n */\nexport interface TypedContentType<\n K extends string = string,\n F extends readonly FieldDefinition[] = readonly FieldDefinition[]\n> extends Omit<ContentTypeConfig, 'key' | 'fields'> {\n key: K;\n fields: F;\n}\n\n/**\n * Define a content type with preserved field types for type inference.\n *\n * IMPORTANT: Use `as const` on the config object to enable type inference.\n * Without `as const`, TypeScript widens literal types and inference won't work.\n *\n * @param config - The content type configuration\n * @returns The same config object with preserved types\n *\n * @example\n * ```typescript\n * export const testimonialType = defineTypedContentType({\n * key: 'testimonial',\n * name: 'Testimonial',\n * hasPages: false,\n * fields: [\n * { id: 'name', type: 'text', label: 'Name', required: true, multiline: false },\n * { id: 'quote', type: 'richText', label: 'Quote', required: true, format: 'html' },\n * ],\n * } as const);\n * ```\n */\nexport function defineTypedContentType<\n K extends string,\n F extends readonly FieldDefinition[]\n>(config: TypedContentType<K, F>): TypedContentType<K, F> {\n return config;\n}\n\n// =============================================================================\n// TypedEntryConfig and createEntry\n// =============================================================================\n\n/**\n * Entry configuration with typed data field.\n * Used internally by createEntry to enforce type safety.\n */\nexport interface TypedEntryConfig<Data extends Record<string, unknown>> {\n /** Unique identifier for this entry. Required for SDK sync. */\n identifier: string;\n /** Title for the entry */\n title?: string;\n /** Slug for routable entries */\n slug?: string;\n /** Status: 'draft' or 'published' */\n status?: 'draft' | 'published';\n /** Summary/description */\n summary?: string;\n /** SEO meta title */\n metaTitle?: string;\n /** SEO meta description */\n metaDescription?: string;\n /** Entry data matching the content type's field definitions */\n data: Data;\n}\n\n/**\n * Create a type-safe content entry for a typed content type.\n *\n * The data field is validated against the content type's field definitions.\n * TypeScript will error if:\n * - A required field is missing\n * - A field name is misspelled\n * - A field value has the wrong type\n * - An extra field is provided (with strict mode)\n *\n * @param contentType - The typed content type definition\n * @param entry - The entry configuration with typed data\n * @returns EntryConfig compatible with SDK content configuration\n *\n * @example\n * ```typescript\n * const entry = createEntry(testimonialType, {\n * identifier: 'testimonial-1',\n * title: 'John Doe',\n * status: 'published',\n * data: {\n * name: 'John Doe',\n * quote: tiptap.paragraph('Great service!'),\n * },\n * });\n * ```\n */\nexport function createEntry<\n K extends string,\n F extends readonly FieldDefinition[]\n>(\n contentType: TypedContentType<K, F>,\n entry: TypedEntryConfig<InferDataFromFields<F>>\n): EntryConfig {\n return {\n ...entry,\n contentType: contentType.key,\n };\n}\n\n// =============================================================================\n// TipTap Helpers\n// =============================================================================\n\n/**\n * Helpers for creating TipTap document structures.\n *\n * Use these helpers when populating richText fields to avoid manually\n * constructing the TipTap JSON structure.\n *\n * @example\n * ```typescript\n * // Simple paragraph\n * const body = tiptap.paragraph('Hello, world!');\n *\n * // Empty document\n * const emptyDoc = tiptap.empty();\n *\n * // Complex document\n * const doc = tiptap.doc([\n * tiptap.heading(1, 'Welcome'),\n * { type: 'paragraph', content: [{ type: 'text', text: 'Introduction...' }] },\n * ]);\n * ```\n */\nexport const tiptap = {\n /**\n * Create an empty TipTap document.\n *\n * @returns An empty TipTap document node\n */\n empty(): TipTapNode {\n return { type: 'doc', content: [] };\n },\n\n /**\n * Create a TipTap document with a single paragraph.\n *\n * @param text - The paragraph text content\n * @returns A TipTap document with one paragraph\n */\n paragraph(text: string): TipTapNode {\n return {\n type: 'doc',\n content: [\n {\n type: 'paragraph',\n content: text ? [{ type: 'text', text }] : [],\n },\n ],\n };\n },\n\n /**\n * Create a TipTap document with custom content nodes.\n *\n * @param content - Array of TipTap nodes to include in the document\n * @returns A TipTap document wrapping the content\n */\n doc(content: TipTapNode[]): TipTapNode {\n return { type: 'doc', content };\n },\n\n /**\n * Create a heading node.\n *\n * Note: This returns a heading node, not a document. Use with tiptap.doc()\n * to create a complete document.\n *\n * @param level - Heading level (1-6)\n * @param text - Heading text content\n * @returns A TipTap heading node\n */\n heading(level: 1 | 2 | 3 | 4 | 5 | 6, text: string): TipTapNode {\n return {\n type: 'heading',\n attrs: { level },\n content: [{ type: 'text', text }],\n };\n },\n};\n","/**\n * SDK Site Configuration\n *\n * Types and utilities for defining site-level configuration\n * that SDK sites expose to the dashboard.\n */\n\nimport type { RiverbankSiteConfig, ContentConfig } from './types';\n\n// Types\nexport type {\n RiverbankSiteConfig,\n SiteStyleConfig,\n SectionBackground,\n SectionOptionsConfig,\n ContainerOptionsConfig,\n SectionSpacing,\n ContainerMaxWidth,\n ContainerAlignment,\n SdkThemeConfig,\n SdkThemePalette,\n SdkCustomBlock,\n FieldSelectOption,\n BlockFieldConfig,\n BlockFieldOptionsMap,\n BlockFieldExtension,\n BlockFieldExtensionsMap,\n FieldDefinition,\n // Content scaffolding types\n ContentConfig,\n ContentTypeConfig,\n PageConfig,\n EntryConfig,\n BlockConfig,\n NavigationMenuConfig,\n NavigationItemConfig,\n NavigationLinkType,\n SiteSettingsConfig,\n} from './types';\n\n// Validation schemas\nexport {\n riverbankSiteConfigSchema,\n siteStyleConfigSchema,\n sectionBackgroundSchema,\n sectionSpacingSchema,\n containerMaxWidthSchema,\n containerAlignmentSchema,\n sectionOptionsSchema,\n containerOptionsSchema,\n sdkThemeConfigSchema,\n sdkThemePaletteSchema,\n sdkCustomBlockSchema,\n fieldSelectOptionSchema,\n blockFieldConfigSchema,\n blockFieldOptionsSchema,\n blockFieldExtensionSchema,\n blockFieldExtensionsSchema,\n // Content scaffolding schemas\n contentConfigSchema,\n} from './validation';\n\n// Content validation schemas for more granular use\nexport {\n contentTypeConfigSchema,\n pageConfigSchema,\n entryConfigSchema,\n navigationMenuConfigSchema,\n navigationItemConfigSchema,\n siteSettingsConfigSchema,\n blockConfigSchema,\n} from './content-validation';\n\nexport type {\n ValidatedRiverbankSiteConfig,\n ValidatedSdkCustomBlock,\n ContentConfigInput,\n ContentConfigOutput,\n} from './validation';\n\n// Block kind types (single source of truth from @riverbankcms/blocks)\nexport {\n SYSTEM_BLOCK_KINDS,\n type SystemBlockKind,\n type CustomBlockKind,\n type BlockKind,\n} from '../types';\n\n// Type-safe content entry helpers\nexport {\n defineTypedContentType,\n createEntry,\n tiptap,\n type TypedContentType,\n type TypedEntryConfig,\n type InferDataFromFields,\n type FieldValueType,\n} from './typed-entries';\n\n// Re-export value types for convenience when building entry data\nexport type {\n TipTapNode,\n Media,\n LinkValue,\n InternalLinkValue,\n ExternalLinkValue,\n CustomLinkValue,\n} from './typed-entries';\n\n/**\n * Helper function to define a Builder site configuration with type checking.\n *\n * @example\n * ```typescript\n * import { defineConfig } from '@riverbankcms/sdk/config';\n *\n * export default defineConfig({\n * siteId: '123e4567-e89b-12d3-a456-426614174000',\n * theme: {\n * palette: {\n * primary: '#6d28d9',\n * },\n * },\n * styles: {\n * sectionBackgrounds: [\n * { id: 'primary', label: 'Purple', token: 'primary' },\n * ],\n * },\n * });\n * ```\n */\nexport function defineConfig(config: RiverbankSiteConfig): RiverbankSiteConfig {\n return config;\n}\n\n/**\n * Helper function to define content scaffolding configuration with type checking.\n *\n * This can be used to define content configuration in a separate file,\n * which is then imported into riverbank.config.ts.\n *\n * @example\n * ```typescript\n * // content.config.ts\n * import { defineContentConfig } from '@riverbankcms/sdk/config';\n *\n * export const contentConfig = defineContentConfig({\n * contentTypes: [\n * {\n * key: 'testimonial',\n * name: 'Testimonial',\n * hasPages: false,\n * fields: [\n * { id: 'quote', type: 'richText', label: 'Quote', required: true },\n * ],\n * },\n * ],\n * pages: [\n * { identifier: 'home', title: 'Home', path: '/' },\n * ],\n * });\n *\n * // riverbank.config.ts\n * import { defineConfig } from '@riverbankcms/sdk/config';\n * import { contentConfig } from './content.config';\n *\n * export default defineConfig({\n * siteId: '...',\n * content: contentConfig,\n * });\n * ```\n */\nexport function defineContentConfig(config: ContentConfig): ContentConfig {\n return config;\n}\n"]}
@@ -30,7 +30,6 @@ import {
30
30
  import "./chunk-LNOUXALA.mjs";
31
31
  import "./chunk-AEFWG657.mjs";
32
32
  import "./chunk-BYBJA6SP.mjs";
33
- import "./chunk-BJTO5JO5.mjs";
34
33
 
35
34
  // src/config/typed-entries.ts
36
35
  function defineTypedContentType(config) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/config/typed-entries.ts","../../src/config/index.ts"],"sourcesContent":["/**\n * Type-Safe Content Entries\n *\n * This module provides type-safe helpers for defining content types and entries\n * in SDK site configurations. When used with `as const`, TypeScript can infer\n * the exact shape of entry data from the content type's field definitions.\n *\n * @example\n * ```typescript\n * import { defineTypedContentType, createEntry, tiptap } from '@riverbankcms/sdk/config';\n *\n * // Define content type with `as const` for type inference\n * export const testimonialType = defineTypedContentType({\n * key: 'testimonial',\n * name: 'Testimonial',\n * hasPages: false,\n * fields: [\n * { id: 'name', type: 'text', label: 'Name', required: true, multiline: false },\n * { id: 'quote', type: 'richText', label: 'Quote', required: true, format: 'html' },\n * ],\n * } as const);\n *\n * // Create entry with full type safety\n * const entry = createEntry(testimonialType, {\n * identifier: 'testimonial-1',\n * data: {\n * name: 'John Doe', // TypeScript knows this is string\n * quote: tiptap.paragraph('Great service!'), // TypeScript knows this is TipTapNode\n * },\n * });\n * ```\n */\n\nimport type {\n FieldDefinition,\n TextFieldDefinition,\n RichTextFieldDefinition,\n MediaFieldDefinition,\n BooleanFieldDefinition,\n NumberFieldDefinition,\n DateFieldDefinition,\n TimeFieldDefinition,\n DateTimeFieldDefinition,\n SlugFieldDefinition,\n UrlFieldDefinition,\n LinkFieldDefinition,\n SelectFieldDefinition,\n ReferenceFieldDefinition,\n RepeaterFieldDefinition,\n GroupFieldDefinition,\n ModalFieldDefinition,\n TabGroupFieldDefinition,\n PresetOrCustomFieldDefinition,\n ContentTypeSelectFieldDefinition,\n EntryPickerFieldDefinition,\n TipTapNode,\n Media,\n LinkValue,\n} from '@riverbankcms/blocks';\nimport type { ContentTypeConfig, EntryConfig } from './content-types';\n\n// Re-export value types for convenience\nexport type { TipTapNode, Media, LinkValue } from '@riverbankcms/blocks';\nexport type {\n InternalLinkValue,\n ExternalLinkValue,\n CustomLinkValue,\n} from '@riverbankcms/blocks';\n\n// =============================================================================\n// Type Infrastructure\n// =============================================================================\n\n/**\n * Infers the data object shape from tabGroup tabs (flattens all tab fields).\n * TabGroup fields flatten all their tab fields into a single data object.\n */\ntype InferDataFromTabs<Tabs extends readonly { fields: readonly FieldDefinition[] }[]> =\n InferDataFromFields<Tabs[number]['fields']>;\n\n// NOTE: Polymorphic repeater type inference would require a helper like this,\n// but TypeScript's mapped types don't distribute correctly over union keys\n// when nested inside conditional types. Left as documentation for future work.\n// type PolymorphicItemData<K, IT> = K extends string\n// ? K extends keyof IT\n// ? IT[K] extends { fields: infer F extends readonly FieldDefinition[] }\n// ? { _type: K } & InferDataFromFields<F>\n// : never\n// : never\n// : never;\n\n/**\n * Maps a field definition to its TypeScript value type.\n * Uses conditional types to infer the correct type based on field.type.\n *\n * Coverage:\n * - Simple primitives: text, boolean, number\n * - Complex types: richText (TipTapNode), media (Media | null), link (LinkValue | null)\n * - Date/time: date, time, datetime (all ISO strings)\n * - String-value: slug, url, reference, presetOrCustom, contentTypeSelect\n * - Select: single (string) vs multiple (string[])\n * - Entry picker: string | null\n * - Nested: group, modal (nested InferDataFromFields)\n * - Repeater: monomorphic (array) and polymorphic (discriminated union array)\n * - TabGroup: flattened fields from all tabs\n */\nexport type FieldValueType<F extends FieldDefinition> =\n // Simple primitives - use specific field types for better inference\n F extends TextFieldDefinition ? string :\n F extends BooleanFieldDefinition ? boolean :\n F extends NumberFieldDefinition ? number :\n // Complex types\n F extends RichTextFieldDefinition ? TipTapNode :\n F extends MediaFieldDefinition ? Media | null :\n F extends LinkFieldDefinition ? LinkValue | null :\n // Date/time types (all stored as ISO strings)\n F extends DateFieldDefinition ? string :\n F extends TimeFieldDefinition ? string :\n F extends DateTimeFieldDefinition ? string :\n // String-value types\n F extends SlugFieldDefinition ? string :\n F extends UrlFieldDefinition ? string :\n F extends ReferenceFieldDefinition ? string :\n F extends PresetOrCustomFieldDefinition ? string :\n F extends ContentTypeSelectFieldDefinition ? string :\n // Select: check multiple flag first (more specific match)\n F extends SelectFieldDefinition & { multiple: true } ? string[] :\n F extends SelectFieldDefinition ? string :\n // Entry picker\n F extends EntryPickerFieldDefinition ? string | null :\n // Nested types (group, modal)\n F extends GroupFieldDefinition & { schema: { fields: infer GF } } ?\n GF extends readonly FieldDefinition[] ? InferDataFromFields<GF> : never :\n F extends ModalFieldDefinition & { schema: { fields: infer MF } } ?\n MF extends readonly FieldDefinition[] ? InferDataFromFields<MF> : never :\n // Repeater types (polymorphic first - more specific, then monomorphic)\n // TODO: Polymorphic repeaters need more complex type distribution.\n // For now, return unknown[] - the runtime data is still correct.\n F extends { type: 'repeater'; polymorphic: true } ? unknown[] :\n F extends RepeaterFieldDefinition & { schema: { fields: infer RF } } ?\n RF extends readonly FieldDefinition[] ? InferDataFromFields<RF>[] : never :\n // TabGroup (flattens all tab fields)\n F extends TabGroupFieldDefinition & { tabs: infer T } ?\n T extends readonly { fields: readonly FieldDefinition[] }[] ?\n InferDataFromTabs<T> : never :\n // Fallback for unknown types\n unknown;\n\n/**\n * Infers the data object shape from an array of field definitions.\n * Required fields are non-optional, optional fields are `| undefined`.\n *\n * @example\n * ```typescript\n * const fields = [\n * { id: 'name', type: 'text', required: true },\n * { id: 'bio', type: 'text', required: false },\n * ] as const;\n *\n * type Data = InferDataFromFields<typeof fields>;\n * // { name: string; bio: string | undefined }\n * ```\n */\nexport type InferDataFromFields<Fields extends readonly FieldDefinition[]> = {\n [F in Fields[number] as F['id']]: F extends { required: true }\n ? FieldValueType<F>\n : FieldValueType<F> | undefined;\n};\n\n// =============================================================================\n// TypedContentType\n// =============================================================================\n\n/**\n * A content type definition with preserved field types for type inference.\n * Extends ContentTypeConfig to ensure all required fields are present.\n * The generic parameters capture the literal types from `as const`.\n */\nexport interface TypedContentType<\n K extends string = string,\n F extends readonly FieldDefinition[] = readonly FieldDefinition[]\n> extends Omit<ContentTypeConfig, 'key' | 'fields'> {\n key: K;\n fields: F;\n}\n\n/**\n * Define a content type with preserved field types for type inference.\n *\n * IMPORTANT: Use `as const` on the config object to enable type inference.\n * Without `as const`, TypeScript widens literal types and inference won't work.\n *\n * @param config - The content type configuration\n * @returns The same config object with preserved types\n *\n * @example\n * ```typescript\n * export const testimonialType = defineTypedContentType({\n * key: 'testimonial',\n * name: 'Testimonial',\n * hasPages: false,\n * fields: [\n * { id: 'name', type: 'text', label: 'Name', required: true, multiline: false },\n * { id: 'quote', type: 'richText', label: 'Quote', required: true, format: 'html' },\n * ],\n * } as const);\n * ```\n */\nexport function defineTypedContentType<\n K extends string,\n F extends readonly FieldDefinition[]\n>(config: TypedContentType<K, F>): TypedContentType<K, F> {\n return config;\n}\n\n// =============================================================================\n// TypedEntryConfig and createEntry\n// =============================================================================\n\n/**\n * Entry configuration with typed data field.\n * Used internally by createEntry to enforce type safety.\n */\nexport interface TypedEntryConfig<Data extends Record<string, unknown>> {\n /** Unique identifier for this entry. Required for SDK sync. */\n identifier: string;\n /** Title for the entry */\n title?: string;\n /** Slug for routable entries */\n slug?: string;\n /** Status: 'draft' or 'published' */\n status?: 'draft' | 'published';\n /** Summary/description */\n summary?: string;\n /** SEO meta title */\n metaTitle?: string;\n /** SEO meta description */\n metaDescription?: string;\n /** Entry data matching the content type's field definitions */\n data: Data;\n}\n\n/**\n * Create a type-safe content entry for a typed content type.\n *\n * The data field is validated against the content type's field definitions.\n * TypeScript will error if:\n * - A required field is missing\n * - A field name is misspelled\n * - A field value has the wrong type\n * - An extra field is provided (with strict mode)\n *\n * @param contentType - The typed content type definition\n * @param entry - The entry configuration with typed data\n * @returns EntryConfig compatible with SDK content configuration\n *\n * @example\n * ```typescript\n * const entry = createEntry(testimonialType, {\n * identifier: 'testimonial-1',\n * title: 'John Doe',\n * status: 'published',\n * data: {\n * name: 'John Doe',\n * quote: tiptap.paragraph('Great service!'),\n * },\n * });\n * ```\n */\nexport function createEntry<\n K extends string,\n F extends readonly FieldDefinition[]\n>(\n contentType: TypedContentType<K, F>,\n entry: TypedEntryConfig<InferDataFromFields<F>>\n): EntryConfig {\n return {\n ...entry,\n contentType: contentType.key,\n };\n}\n\n// =============================================================================\n// TipTap Helpers\n// =============================================================================\n\n/**\n * Helpers for creating TipTap document structures.\n *\n * Use these helpers when populating richText fields to avoid manually\n * constructing the TipTap JSON structure.\n *\n * @example\n * ```typescript\n * // Simple paragraph\n * const body = tiptap.paragraph('Hello, world!');\n *\n * // Empty document\n * const emptyDoc = tiptap.empty();\n *\n * // Complex document\n * const doc = tiptap.doc([\n * tiptap.heading(1, 'Welcome'),\n * { type: 'paragraph', content: [{ type: 'text', text: 'Introduction...' }] },\n * ]);\n * ```\n */\nexport const tiptap = {\n /**\n * Create an empty TipTap document.\n *\n * @returns An empty TipTap document node\n */\n empty(): TipTapNode {\n return { type: 'doc', content: [] };\n },\n\n /**\n * Create a TipTap document with a single paragraph.\n *\n * @param text - The paragraph text content\n * @returns A TipTap document with one paragraph\n */\n paragraph(text: string): TipTapNode {\n return {\n type: 'doc',\n content: [\n {\n type: 'paragraph',\n content: text ? [{ type: 'text', text }] : [],\n },\n ],\n };\n },\n\n /**\n * Create a TipTap document with custom content nodes.\n *\n * @param content - Array of TipTap nodes to include in the document\n * @returns A TipTap document wrapping the content\n */\n doc(content: TipTapNode[]): TipTapNode {\n return { type: 'doc', content };\n },\n\n /**\n * Create a heading node.\n *\n * Note: This returns a heading node, not a document. Use with tiptap.doc()\n * to create a complete document.\n *\n * @param level - Heading level (1-6)\n * @param text - Heading text content\n * @returns A TipTap heading node\n */\n heading(level: 1 | 2 | 3 | 4 | 5 | 6, text: string): TipTapNode {\n return {\n type: 'heading',\n attrs: { level },\n content: [{ type: 'text', text }],\n };\n },\n};\n","/**\n * SDK Site Configuration\n *\n * Types and utilities for defining site-level configuration\n * that SDK sites expose to the dashboard.\n */\n\nimport type { RiverbankSiteConfig, ContentConfig } from './types';\n\n// Types\nexport type {\n RiverbankSiteConfig,\n SiteStyleConfig,\n SectionBackground,\n SectionOptionsConfig,\n ContainerOptionsConfig,\n SectionSpacing,\n ContainerMaxWidth,\n ContainerAlignment,\n SdkThemeConfig,\n SdkThemePalette,\n SdkCustomBlock,\n FieldSelectOption,\n BlockFieldConfig,\n BlockFieldOptionsMap,\n BlockFieldExtension,\n BlockFieldExtensionsMap,\n FieldDefinition,\n // Content scaffolding types\n ContentConfig,\n ContentTypeConfig,\n PageConfig,\n EntryConfig,\n BlockConfig,\n NavigationMenuConfig,\n NavigationItemConfig,\n NavigationLinkType,\n SiteSettingsConfig,\n} from './types';\n\n// Validation schemas\nexport {\n riverbankSiteConfigSchema,\n siteStyleConfigSchema,\n sectionBackgroundSchema,\n sectionSpacingSchema,\n containerMaxWidthSchema,\n containerAlignmentSchema,\n sectionOptionsSchema,\n containerOptionsSchema,\n sdkThemeConfigSchema,\n sdkThemePaletteSchema,\n sdkCustomBlockSchema,\n fieldSelectOptionSchema,\n blockFieldConfigSchema,\n blockFieldOptionsSchema,\n blockFieldExtensionSchema,\n blockFieldExtensionsSchema,\n // Content scaffolding schemas\n contentConfigSchema,\n} from './validation';\n\n// Content validation schemas for more granular use\nexport {\n contentTypeConfigSchema,\n pageConfigSchema,\n entryConfigSchema,\n navigationMenuConfigSchema,\n navigationItemConfigSchema,\n siteSettingsConfigSchema,\n blockConfigSchema,\n} from './content-validation';\n\nexport type {\n ValidatedRiverbankSiteConfig,\n ValidatedSdkCustomBlock,\n ContentConfigInput,\n ContentConfigOutput,\n} from './validation';\n\n// Block kind types (single source of truth from @riverbankcms/blocks)\nexport {\n SYSTEM_BLOCK_KINDS,\n type SystemBlockKind,\n type CustomBlockKind,\n type BlockKind,\n} from '../types';\n\n// Type-safe content entry helpers\nexport {\n defineTypedContentType,\n createEntry,\n tiptap,\n type TypedContentType,\n type TypedEntryConfig,\n type InferDataFromFields,\n type FieldValueType,\n} from './typed-entries';\n\n// Re-export value types for convenience when building entry data\nexport type {\n TipTapNode,\n Media,\n LinkValue,\n InternalLinkValue,\n ExternalLinkValue,\n CustomLinkValue,\n} from './typed-entries';\n\n/**\n * Helper function to define a Builder site configuration with type checking.\n *\n * @example\n * ```typescript\n * import { defineConfig } from '@riverbankcms/sdk/config';\n *\n * export default defineConfig({\n * siteId: '123e4567-e89b-12d3-a456-426614174000',\n * theme: {\n * palette: {\n * primary: '#6d28d9',\n * },\n * },\n * styles: {\n * sectionBackgrounds: [\n * { id: 'primary', label: 'Purple', token: 'primary' },\n * ],\n * },\n * });\n * ```\n */\nexport function defineConfig(config: RiverbankSiteConfig): RiverbankSiteConfig {\n return config;\n}\n\n/**\n * Helper function to define content scaffolding configuration with type checking.\n *\n * This can be used to define content configuration in a separate file,\n * which is then imported into riverbank.config.ts.\n *\n * @example\n * ```typescript\n * // content.config.ts\n * import { defineContentConfig } from '@riverbankcms/sdk/config';\n *\n * export const contentConfig = defineContentConfig({\n * contentTypes: [\n * {\n * key: 'testimonial',\n * name: 'Testimonial',\n * hasPages: false,\n * fields: [\n * { id: 'quote', type: 'richText', label: 'Quote', required: true },\n * ],\n * },\n * ],\n * pages: [\n * { identifier: 'home', title: 'Home', path: '/' },\n * ],\n * });\n *\n * // riverbank.config.ts\n * import { defineConfig } from '@riverbankcms/sdk/config';\n * import { contentConfig } from './content.config';\n *\n * export default defineConfig({\n * siteId: '...',\n * content: contentConfig,\n * });\n * ```\n */\nexport function defineContentConfig(config: ContentConfig): ContentConfig {\n return config;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgNO,SAAS,uBAGd,QAAwD;AACxD,SAAO;AACT;AAwDO,SAAS,YAId,aACA,OACa;AACb,SAAO;AAAA,IACL,GAAG;AAAA,IACH,aAAa,YAAY;AAAA,EAC3B;AACF;AA2BO,IAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpB,QAAoB;AAClB,WAAO,EAAE,MAAM,OAAO,SAAS,CAAC,EAAE;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU,MAA0B;AAClC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,SAAS,OAAO,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,IAAI,CAAC;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,SAAmC;AACrC,WAAO,EAAE,MAAM,OAAO,QAAQ;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,QAAQ,OAA8B,MAA0B;AAC9D,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO,EAAE,MAAM;AAAA,MACf,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,IAClC;AAAA,EACF;AACF;;;ACvOO,SAAS,aAAa,QAAkD;AAC7E,SAAO;AACT;AAuCO,SAAS,oBAAoB,QAAsC;AACxE,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/config/typed-entries.ts","../../src/config/index.ts"],"sourcesContent":["/**\n * Type-Safe Content Entries\n *\n * This module provides type-safe helpers for defining content types and entries\n * in SDK site configurations. When used with `as const`, TypeScript can infer\n * the exact shape of entry data from the content type's field definitions.\n *\n * @example\n * ```typescript\n * import { defineTypedContentType, createEntry, tiptap } from '@riverbankcms/sdk/config';\n *\n * // Define content type with `as const` for type inference\n * export const testimonialType = defineTypedContentType({\n * key: 'testimonial',\n * name: 'Testimonial',\n * hasPages: false,\n * fields: [\n * { id: 'name', type: 'text', label: 'Name', required: true, multiline: false },\n * { id: 'quote', type: 'richText', label: 'Quote', required: true, format: 'html' },\n * ],\n * } as const);\n *\n * // Create entry with full type safety\n * const entry = createEntry(testimonialType, {\n * identifier: 'testimonial-1',\n * data: {\n * name: 'John Doe', // TypeScript knows this is string\n * quote: tiptap.paragraph('Great service!'), // TypeScript knows this is TipTapNode\n * },\n * });\n * ```\n */\n\nimport type {\n FieldDefinition,\n TextFieldDefinition,\n RichTextFieldDefinition,\n MediaFieldDefinition,\n BooleanFieldDefinition,\n NumberFieldDefinition,\n DateFieldDefinition,\n TimeFieldDefinition,\n DateTimeFieldDefinition,\n SlugFieldDefinition,\n UrlFieldDefinition,\n LinkFieldDefinition,\n SelectFieldDefinition,\n ReferenceFieldDefinition,\n RepeaterFieldDefinition,\n GroupFieldDefinition,\n ModalFieldDefinition,\n TabGroupFieldDefinition,\n PresetOrCustomFieldDefinition,\n ContentTypeSelectFieldDefinition,\n EntryPickerFieldDefinition,\n TipTapNode,\n Media,\n LinkValue,\n} from '@riverbankcms/blocks';\nimport type { ContentTypeConfig, EntryConfig } from './content-types';\n\n// Re-export value types for convenience\nexport type { TipTapNode, Media, LinkValue } from '@riverbankcms/blocks';\nexport type {\n InternalLinkValue,\n ExternalLinkValue,\n CustomLinkValue,\n} from '@riverbankcms/blocks';\n\n// =============================================================================\n// Type Infrastructure\n// =============================================================================\n\n/**\n * Infers the data object shape from tabGroup tabs (flattens all tab fields).\n * TabGroup fields flatten all their tab fields into a single data object.\n */\ntype InferDataFromTabs<Tabs extends readonly { fields: readonly FieldDefinition[] }[]> =\n InferDataFromFields<Tabs[number]['fields']>;\n\n// NOTE: Polymorphic repeater type inference would require a helper like this,\n// but TypeScript's mapped types don't distribute correctly over union keys\n// when nested inside conditional types. Left as documentation for future work.\n// type PolymorphicItemData<K, IT> = K extends string\n// ? K extends keyof IT\n// ? IT[K] extends { fields: infer F extends readonly FieldDefinition[] }\n// ? { _type: K } & InferDataFromFields<F>\n// : never\n// : never\n// : never;\n\n/**\n * Maps a field definition to its TypeScript value type.\n * Uses conditional types to infer the correct type based on field.type.\n *\n * Coverage:\n * - Simple primitives: text, boolean, number\n * - Complex types: richText (TipTapNode), media (Media | null), link (LinkValue | null)\n * - Date/time: date, time, datetime (all ISO strings)\n * - String-value: slug, url, reference, presetOrCustom, contentTypeSelect\n * - Select: single (string) vs multiple (string[])\n * - Entry picker: string | null\n * - Nested: group, modal (nested InferDataFromFields)\n * - Repeater: monomorphic (array) and polymorphic (discriminated union array)\n * - TabGroup: flattened fields from all tabs\n */\nexport type FieldValueType<F extends FieldDefinition> =\n // Simple primitives - use specific field types for better inference\n F extends TextFieldDefinition ? string :\n F extends BooleanFieldDefinition ? boolean :\n F extends NumberFieldDefinition ? number :\n // Complex types\n F extends RichTextFieldDefinition ? TipTapNode :\n F extends MediaFieldDefinition ? Media | null :\n F extends LinkFieldDefinition ? LinkValue | null :\n // Date/time types (all stored as ISO strings)\n F extends DateFieldDefinition ? string :\n F extends TimeFieldDefinition ? string :\n F extends DateTimeFieldDefinition ? string :\n // String-value types\n F extends SlugFieldDefinition ? string :\n F extends UrlFieldDefinition ? string :\n F extends ReferenceFieldDefinition ? string :\n F extends PresetOrCustomFieldDefinition ? string :\n F extends ContentTypeSelectFieldDefinition ? string :\n // Select: check multiple flag first (more specific match)\n F extends SelectFieldDefinition & { multiple: true } ? string[] :\n F extends SelectFieldDefinition ? string :\n // Entry picker\n F extends EntryPickerFieldDefinition ? string | null :\n // Nested types (group, modal)\n F extends GroupFieldDefinition & { schema: { fields: infer GF } } ?\n GF extends readonly FieldDefinition[] ? InferDataFromFields<GF> : never :\n F extends ModalFieldDefinition & { schema: { fields: infer MF } } ?\n MF extends readonly FieldDefinition[] ? InferDataFromFields<MF> : never :\n // Repeater types (polymorphic first - more specific, then monomorphic)\n // TODO: Polymorphic repeaters need more complex type distribution.\n // For now, return unknown[] - the runtime data is still correct.\n F extends { type: 'repeater'; polymorphic: true } ? unknown[] :\n F extends RepeaterFieldDefinition & { schema: { fields: infer RF } } ?\n RF extends readonly FieldDefinition[] ? InferDataFromFields<RF>[] : never :\n // TabGroup (flattens all tab fields)\n F extends TabGroupFieldDefinition & { tabs: infer T } ?\n T extends readonly { fields: readonly FieldDefinition[] }[] ?\n InferDataFromTabs<T> : never :\n // Fallback for unknown types\n unknown;\n\n/**\n * Infers the data object shape from an array of field definitions.\n * Required fields are non-optional, optional fields are `| undefined`.\n *\n * @example\n * ```typescript\n * const fields = [\n * { id: 'name', type: 'text', required: true },\n * { id: 'bio', type: 'text', required: false },\n * ] as const;\n *\n * type Data = InferDataFromFields<typeof fields>;\n * // { name: string; bio: string | undefined }\n * ```\n */\nexport type InferDataFromFields<Fields extends readonly FieldDefinition[]> = {\n [F in Fields[number] as F['id']]: F extends { required: true }\n ? FieldValueType<F>\n : FieldValueType<F> | undefined;\n};\n\n// =============================================================================\n// TypedContentType\n// =============================================================================\n\n/**\n * A content type definition with preserved field types for type inference.\n * Extends ContentTypeConfig to ensure all required fields are present.\n * The generic parameters capture the literal types from `as const`.\n */\nexport interface TypedContentType<\n K extends string = string,\n F extends readonly FieldDefinition[] = readonly FieldDefinition[]\n> extends Omit<ContentTypeConfig, 'key' | 'fields'> {\n key: K;\n fields: F;\n}\n\n/**\n * Define a content type with preserved field types for type inference.\n *\n * IMPORTANT: Use `as const` on the config object to enable type inference.\n * Without `as const`, TypeScript widens literal types and inference won't work.\n *\n * @param config - The content type configuration\n * @returns The same config object with preserved types\n *\n * @example\n * ```typescript\n * export const testimonialType = defineTypedContentType({\n * key: 'testimonial',\n * name: 'Testimonial',\n * hasPages: false,\n * fields: [\n * { id: 'name', type: 'text', label: 'Name', required: true, multiline: false },\n * { id: 'quote', type: 'richText', label: 'Quote', required: true, format: 'html' },\n * ],\n * } as const);\n * ```\n */\nexport function defineTypedContentType<\n K extends string,\n F extends readonly FieldDefinition[]\n>(config: TypedContentType<K, F>): TypedContentType<K, F> {\n return config;\n}\n\n// =============================================================================\n// TypedEntryConfig and createEntry\n// =============================================================================\n\n/**\n * Entry configuration with typed data field.\n * Used internally by createEntry to enforce type safety.\n */\nexport interface TypedEntryConfig<Data extends Record<string, unknown>> {\n /** Unique identifier for this entry. Required for SDK sync. */\n identifier: string;\n /** Title for the entry */\n title?: string;\n /** Slug for routable entries */\n slug?: string;\n /** Status: 'draft' or 'published' */\n status?: 'draft' | 'published';\n /** Summary/description */\n summary?: string;\n /** SEO meta title */\n metaTitle?: string;\n /** SEO meta description */\n metaDescription?: string;\n /** Entry data matching the content type's field definitions */\n data: Data;\n}\n\n/**\n * Create a type-safe content entry for a typed content type.\n *\n * The data field is validated against the content type's field definitions.\n * TypeScript will error if:\n * - A required field is missing\n * - A field name is misspelled\n * - A field value has the wrong type\n * - An extra field is provided (with strict mode)\n *\n * @param contentType - The typed content type definition\n * @param entry - The entry configuration with typed data\n * @returns EntryConfig compatible with SDK content configuration\n *\n * @example\n * ```typescript\n * const entry = createEntry(testimonialType, {\n * identifier: 'testimonial-1',\n * title: 'John Doe',\n * status: 'published',\n * data: {\n * name: 'John Doe',\n * quote: tiptap.paragraph('Great service!'),\n * },\n * });\n * ```\n */\nexport function createEntry<\n K extends string,\n F extends readonly FieldDefinition[]\n>(\n contentType: TypedContentType<K, F>,\n entry: TypedEntryConfig<InferDataFromFields<F>>\n): EntryConfig {\n return {\n ...entry,\n contentType: contentType.key,\n };\n}\n\n// =============================================================================\n// TipTap Helpers\n// =============================================================================\n\n/**\n * Helpers for creating TipTap document structures.\n *\n * Use these helpers when populating richText fields to avoid manually\n * constructing the TipTap JSON structure.\n *\n * @example\n * ```typescript\n * // Simple paragraph\n * const body = tiptap.paragraph('Hello, world!');\n *\n * // Empty document\n * const emptyDoc = tiptap.empty();\n *\n * // Complex document\n * const doc = tiptap.doc([\n * tiptap.heading(1, 'Welcome'),\n * { type: 'paragraph', content: [{ type: 'text', text: 'Introduction...' }] },\n * ]);\n * ```\n */\nexport const tiptap = {\n /**\n * Create an empty TipTap document.\n *\n * @returns An empty TipTap document node\n */\n empty(): TipTapNode {\n return { type: 'doc', content: [] };\n },\n\n /**\n * Create a TipTap document with a single paragraph.\n *\n * @param text - The paragraph text content\n * @returns A TipTap document with one paragraph\n */\n paragraph(text: string): TipTapNode {\n return {\n type: 'doc',\n content: [\n {\n type: 'paragraph',\n content: text ? [{ type: 'text', text }] : [],\n },\n ],\n };\n },\n\n /**\n * Create a TipTap document with custom content nodes.\n *\n * @param content - Array of TipTap nodes to include in the document\n * @returns A TipTap document wrapping the content\n */\n doc(content: TipTapNode[]): TipTapNode {\n return { type: 'doc', content };\n },\n\n /**\n * Create a heading node.\n *\n * Note: This returns a heading node, not a document. Use with tiptap.doc()\n * to create a complete document.\n *\n * @param level - Heading level (1-6)\n * @param text - Heading text content\n * @returns A TipTap heading node\n */\n heading(level: 1 | 2 | 3 | 4 | 5 | 6, text: string): TipTapNode {\n return {\n type: 'heading',\n attrs: { level },\n content: [{ type: 'text', text }],\n };\n },\n};\n","/**\n * SDK Site Configuration\n *\n * Types and utilities for defining site-level configuration\n * that SDK sites expose to the dashboard.\n */\n\nimport type { RiverbankSiteConfig, ContentConfig } from './types';\n\n// Types\nexport type {\n RiverbankSiteConfig,\n SiteStyleConfig,\n SectionBackground,\n SectionOptionsConfig,\n ContainerOptionsConfig,\n SectionSpacing,\n ContainerMaxWidth,\n ContainerAlignment,\n SdkThemeConfig,\n SdkThemePalette,\n SdkCustomBlock,\n FieldSelectOption,\n BlockFieldConfig,\n BlockFieldOptionsMap,\n BlockFieldExtension,\n BlockFieldExtensionsMap,\n FieldDefinition,\n // Content scaffolding types\n ContentConfig,\n ContentTypeConfig,\n PageConfig,\n EntryConfig,\n BlockConfig,\n NavigationMenuConfig,\n NavigationItemConfig,\n NavigationLinkType,\n SiteSettingsConfig,\n} from './types';\n\n// Validation schemas\nexport {\n riverbankSiteConfigSchema,\n siteStyleConfigSchema,\n sectionBackgroundSchema,\n sectionSpacingSchema,\n containerMaxWidthSchema,\n containerAlignmentSchema,\n sectionOptionsSchema,\n containerOptionsSchema,\n sdkThemeConfigSchema,\n sdkThemePaletteSchema,\n sdkCustomBlockSchema,\n fieldSelectOptionSchema,\n blockFieldConfigSchema,\n blockFieldOptionsSchema,\n blockFieldExtensionSchema,\n blockFieldExtensionsSchema,\n // Content scaffolding schemas\n contentConfigSchema,\n} from './validation';\n\n// Content validation schemas for more granular use\nexport {\n contentTypeConfigSchema,\n pageConfigSchema,\n entryConfigSchema,\n navigationMenuConfigSchema,\n navigationItemConfigSchema,\n siteSettingsConfigSchema,\n blockConfigSchema,\n} from './content-validation';\n\nexport type {\n ValidatedRiverbankSiteConfig,\n ValidatedSdkCustomBlock,\n ContentConfigInput,\n ContentConfigOutput,\n} from './validation';\n\n// Block kind types (single source of truth from @riverbankcms/blocks)\nexport {\n SYSTEM_BLOCK_KINDS,\n type SystemBlockKind,\n type CustomBlockKind,\n type BlockKind,\n} from '../types';\n\n// Type-safe content entry helpers\nexport {\n defineTypedContentType,\n createEntry,\n tiptap,\n type TypedContentType,\n type TypedEntryConfig,\n type InferDataFromFields,\n type FieldValueType,\n} from './typed-entries';\n\n// Re-export value types for convenience when building entry data\nexport type {\n TipTapNode,\n Media,\n LinkValue,\n InternalLinkValue,\n ExternalLinkValue,\n CustomLinkValue,\n} from './typed-entries';\n\n/**\n * Helper function to define a Builder site configuration with type checking.\n *\n * @example\n * ```typescript\n * import { defineConfig } from '@riverbankcms/sdk/config';\n *\n * export default defineConfig({\n * siteId: '123e4567-e89b-12d3-a456-426614174000',\n * theme: {\n * palette: {\n * primary: '#6d28d9',\n * },\n * },\n * styles: {\n * sectionBackgrounds: [\n * { id: 'primary', label: 'Purple', token: 'primary' },\n * ],\n * },\n * });\n * ```\n */\nexport function defineConfig(config: RiverbankSiteConfig): RiverbankSiteConfig {\n return config;\n}\n\n/**\n * Helper function to define content scaffolding configuration with type checking.\n *\n * This can be used to define content configuration in a separate file,\n * which is then imported into riverbank.config.ts.\n *\n * @example\n * ```typescript\n * // content.config.ts\n * import { defineContentConfig } from '@riverbankcms/sdk/config';\n *\n * export const contentConfig = defineContentConfig({\n * contentTypes: [\n * {\n * key: 'testimonial',\n * name: 'Testimonial',\n * hasPages: false,\n * fields: [\n * { id: 'quote', type: 'richText', label: 'Quote', required: true },\n * ],\n * },\n * ],\n * pages: [\n * { identifier: 'home', title: 'Home', path: '/' },\n * ],\n * });\n *\n * // riverbank.config.ts\n * import { defineConfig } from '@riverbankcms/sdk/config';\n * import { contentConfig } from './content.config';\n *\n * export default defineConfig({\n * siteId: '...',\n * content: contentConfig,\n * });\n * ```\n */\nexport function defineContentConfig(config: ContentConfig): ContentConfig {\n return config;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgNO,SAAS,uBAGd,QAAwD;AACxD,SAAO;AACT;AAwDO,SAAS,YAId,aACA,OACa;AACb,SAAO;AAAA,IACL,GAAG;AAAA,IACH,aAAa,YAAY;AAAA,EAC3B;AACF;AA2BO,IAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpB,QAAoB;AAClB,WAAO,EAAE,MAAM,OAAO,SAAS,CAAC,EAAE;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU,MAA0B;AAClC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,SAAS,OAAO,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,IAAI,CAAC;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,SAAmC;AACrC,WAAO,EAAE,MAAM,OAAO,QAAQ;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,QAAQ,OAA8B,MAA0B;AAC9D,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO,EAAE,MAAM;AAAA,MACf,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,IAClC;AAAA,EACF;AACF;;;ACvOO,SAAS,aAAa,QAAkD;AAC7E,SAAO;AACT;AAuCO,SAAS,oBAAoB,QAAsC;AACxE,SAAO;AACT;","names":[]}
@@ -1,7 +1,7 @@
1
1
  import { P as PageOutline, S as SdkCustomBlock } from './schema-Z6-afHJG.mjs';
2
2
  import { P as PrefetchContext, R as ResolvedBlockData, D as DataLoaderOverrides } from './types-CbagRQ_7.mjs';
3
3
  export { B as BlockLoaderMap, a as DataLoaderContext, b as DataLoaderFn } from './types-CbagRQ_7.mjs';
4
- import { R as RiverbankClient } from './types-1cLz0vnq.mjs';
4
+ import { R as RiverbankClient } from './types-MF2AWoKv.mjs';
5
5
  import 'zod';
6
6
  import './blockKinds-B6MWzNWp.mjs';
7
7
  import './types-Dsu9wsUh.mjs';
@@ -1,7 +1,7 @@
1
1
  import { P as PageOutline, S as SdkCustomBlock } from './schema-Z6-afHJG.js';
2
2
  import { P as PrefetchContext, R as ResolvedBlockData, D as DataLoaderOverrides } from './types-DuQCNVV0.js';
3
3
  export { B as BlockLoaderMap, a as DataLoaderContext, b as DataLoaderFn } from './types-DuQCNVV0.js';
4
- import { R as RiverbankClient } from './types-BvcJU7zk.js';
4
+ import { R as RiverbankClient } from './types-DnkRh0UL.js';
5
5
  import 'zod';
6
6
  import './blockKinds-B6MWzNWp.js';
7
7
  import './types-CVykEqXN.js';
@@ -7,7 +7,6 @@ var _chunkY7347JMZjs = require('./chunk-Y7347JMZ.js');
7
7
 
8
8
  var _chunkRVDS7VSPjs = require('./chunk-RVDS7VSP.js');
9
9
  require('./chunk-YYO3RIFO.js');
10
- require('./chunk-DGUM43GV.js');
11
10
 
12
11
 
13
12