@phtngyn/cms 0.1.0-beta.1 → 0.1.0-beta.3

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 (143) hide show
  1. package/README.md +212 -12
  2. package/bin/cms.mjs +2 -0
  3. package/package.json +30 -15
  4. package/src/{Configuration-DyKo0sLS.js → Configuration-CDMYfTre.js} +26 -147
  5. package/src/Configuration-CDMYfTre.js.map +1 -0
  6. package/src/Configuration.d.ts +24 -8
  7. package/src/Configuration.js +0 -1
  8. package/src/Configuration.js.map +1 -1
  9. package/src/ContentTransfer-C3Av9sWz.js +53 -0
  10. package/src/ContentTransfer-C3Av9sWz.js.map +1 -0
  11. package/src/{DocumentEngine-DYObwMDY.js → DocumentEngine-J7g-emdf.js} +75 -27
  12. package/src/DocumentEngine-J7g-emdf.js.map +1 -0
  13. package/src/DocumentModel.d.ts +8 -9
  14. package/src/DocumentModel.js +13 -3
  15. package/src/DocumentModel.js.map +1 -1
  16. package/src/Forms-BsJMev5_.d.ts +74 -0
  17. package/src/Forms-CfcI3tPU.js +79 -0
  18. package/src/Forms-CfcI3tPU.js.map +1 -0
  19. package/src/Forms-Dj6NuW66.js +367 -0
  20. package/src/Forms-Dj6NuW66.js.map +1 -0
  21. package/src/Forms.d.ts +51 -0
  22. package/src/Forms.js +13 -0
  23. package/src/Forms.js.map +1 -0
  24. package/src/{HttpPaths-BbS21Jy8.js → HttpPaths-c9nLZ9H2.js} +6 -2
  25. package/src/HttpPaths-c9nLZ9H2.js.map +1 -0
  26. package/src/I18n.d.ts +20 -0
  27. package/src/I18n.js +1 -0
  28. package/src/Module.js +59 -14
  29. package/src/Module.js.map +1 -1
  30. package/src/S3MediaObjects-CpPSzJto.js +2777 -0
  31. package/src/S3MediaObjects-CpPSzJto.js.map +1 -0
  32. package/src/Seo-402YumpT.d.ts +198 -0
  33. package/src/cli/content.js +258 -0
  34. package/src/cli/content.js.map +1 -0
  35. package/src/cli.js +71 -0
  36. package/src/cli.js.map +1 -0
  37. package/src/{connection-CBTY-TzB.js → connection-CBAy2qGy.js} +5 -7
  38. package/src/connection-CBAy2qGy.js.map +1 -0
  39. package/src/{installation-DeuBiFRE.js → installation-CNfIriVm.js} +1007 -2246
  40. package/src/installation-CNfIriVm.js.map +1 -0
  41. package/src/internal/authoring-catalog.js +10 -4
  42. package/src/internal/authoring-catalog.js.map +1 -1
  43. package/src/internal/authoring-compiler.js +0 -1
  44. package/src/internal/authoring-compiler.js.map +1 -1
  45. package/src/internal/authoring-metadata.js +4 -4
  46. package/src/internal/authoring-metadata.js.map +1 -1
  47. package/src/internal/cms-config.js +0 -1
  48. package/src/internal/cms-config.js.map +1 -1
  49. package/src/internal/configuration.js +26 -17
  50. package/src/internal/configuration.js.map +1 -1
  51. package/src/internal/document-model.js +69 -21
  52. package/src/internal/document-model.js.map +1 -1
  53. package/src/internal/form-capabilities.js +12 -0
  54. package/src/internal/form-capabilities.js.map +1 -0
  55. package/src/internal/i18n.js +47 -0
  56. package/src/internal/i18n.js.map +1 -0
  57. package/src/internal/studio-app.js +2 -2
  58. package/src/internal/studio-app.js.map +1 -1
  59. package/src/{location-DtYv2aes.js → location-BTqdfIzX.js} +2 -3
  60. package/src/location-BTqdfIzX.js.map +1 -0
  61. package/src/{metadata-DE1Mc2td.js → metadata-BEZPWh-3.js} +3 -72
  62. package/src/metadata-BEZPWh-3.js.map +1 -0
  63. package/src/{models-C3witQBK.js → models-B4IoTmp7.js} +3 -2
  64. package/src/models-B4IoTmp7.js.map +1 -0
  65. package/src/{models-BkMgeaOL.js → models-Bah5B3bT.js} +205 -51
  66. package/src/models-Bah5B3bT.js.map +1 -0
  67. package/src/runtime/blocks.js +22 -9
  68. package/src/runtime/blocks.js.map +1 -1
  69. package/src/runtime/collaboration.js.map +1 -1
  70. package/src/runtime/delivery/DocumentRenderer.js +7 -4
  71. package/src/runtime/delivery/DocumentRenderer.js.map +1 -1
  72. package/src/runtime/delivery/blocks.js +3 -1
  73. package/src/runtime/delivery/blocks.js.map +1 -1
  74. package/src/runtime/delivery/context.js +1 -1
  75. package/src/runtime/delivery/document-page.js +12 -12
  76. package/src/runtime/delivery/document-page.js.map +1 -1
  77. package/src/runtime/delivery/document.js +4 -2
  78. package/src/runtime/delivery/document.js.map +1 -1
  79. package/src/runtime/delivery/error.js.map +1 -1
  80. package/src/runtime/delivery/plugin.js +28 -2
  81. package/src/runtime/delivery/plugin.js.map +1 -1
  82. package/src/runtime/delivery/types.d.ts +5 -0
  83. package/src/runtime/delivery/useCmsDocumentSeo.d.ts +59 -0
  84. package/src/runtime/delivery/useCmsDocumentSeo.js +101 -0
  85. package/src/runtime/delivery/useCmsDocumentSeo.js.map +1 -0
  86. package/src/runtime/delivery/useDocument.js +2 -2
  87. package/src/runtime/delivery/useDocument.js.map +1 -1
  88. package/src/runtime/delivery/useDocumentQuery.js +2 -2
  89. package/src/runtime/delivery/useDocumentQuery.js.map +1 -1
  90. package/src/runtime/forms/document.js +38 -0
  91. package/src/runtime/forms/document.js.map +1 -0
  92. package/src/runtime/forms/useCmsForm.js +190 -0
  93. package/src/runtime/forms/useCmsForm.js.map +1 -0
  94. package/src/runtime/i18n/translator.js +51 -0
  95. package/src/runtime/i18n/translator.js.map +1 -0
  96. package/src/runtime/i18n/useCmsI18n.d.ts +11 -0
  97. package/src/runtime/i18n/useCmsI18n.js +37 -0
  98. package/src/runtime/i18n/useCmsI18n.js.map +1 -0
  99. package/src/runtime/installation.js +1 -1
  100. package/src/runtime/plugin.js +3 -3
  101. package/src/runtime/plugin.js.map +1 -1
  102. package/src/runtime/preview/comark-document.js +0 -1
  103. package/src/runtime/preview/comark-document.js.map +1 -1
  104. package/src/runtime/preview/connection.js +1 -1
  105. package/src/runtime/preview/controller.js +10 -3
  106. package/src/runtime/preview/controller.js.map +1 -1
  107. package/src/runtime/preview/overlay.js.map +1 -1
  108. package/src/runtime/preview/plugin.client.js +59 -48
  109. package/src/runtime/preview/plugin.client.js.map +1 -1
  110. package/src/runtime/preview/protocol.js.map +1 -1
  111. package/src/runtime/preview/store.js +1 -1
  112. package/src/runtime/preview/targets.js +0 -1
  113. package/src/runtime/preview/targets.js.map +1 -1
  114. package/src/runtime/sitemap-entries.js +17 -0
  115. package/src/runtime/sitemap-entries.js.map +1 -0
  116. package/src/runtime/sitemap.js +24 -0
  117. package/src/runtime/sitemap.js.map +1 -0
  118. package/src/runtime/studio-app.js.map +1 -1
  119. package/src/runtime/studio-entry.js +2 -2
  120. package/src/runtime/studio-entry.js.map +1 -1
  121. package/src/runtime/studio-navigation.js +1 -1
  122. package/src/scalars-B2lgGUnj.js +26 -0
  123. package/src/scalars-B2lgGUnj.js.map +1 -0
  124. package/src/{store-CfFFx9Ua.js → store-b2CSXgMt.js} +12 -7
  125. package/src/store-b2CSXgMt.js.map +1 -0
  126. package/studio/{CreateDocumentDialog--L9lTfx6.js → CreateDocumentDialog-GGey1uBc.js} +44 -44
  127. package/studio/{collaboration-DUuu678R.js → collaboration-DcK2F6v9.js} +7 -6
  128. package/studio/{documentPlanning-BXX04Woe.js → documentPlanning-DRErYmBU.js} +7340 -6469
  129. package/studio/{editor-PexnXkJY.js → editor-Bzlh3zXt.js} +7965 -7955
  130. package/studio/host.css +1 -1
  131. package/studio/host.js +10416 -7981
  132. package/src/Configuration-DyKo0sLS.js.map +0 -1
  133. package/src/DocumentEngine-DYObwMDY.js.map +0 -1
  134. package/src/HttpPaths-BbS21Jy8.js.map +0 -1
  135. package/src/StudioHttp-jR2-bc01.js +0 -718
  136. package/src/StudioHttp-jR2-bc01.js.map +0 -1
  137. package/src/connection-CBTY-TzB.js.map +0 -1
  138. package/src/installation-DeuBiFRE.js.map +0 -1
  139. package/src/location-DtYv2aes.js.map +0 -1
  140. package/src/metadata-DE1Mc2td.js.map +0 -1
  141. package/src/models-BkMgeaOL.js.map +0 -1
  142. package/src/models-C3witQBK.js.map +0 -1
  143. package/src/store-CfFFx9Ua.js.map +0 -1
@@ -1,12 +1,13 @@
1
- import { l as validateCollectionBody, n as ComponentDefinition, t as AuthoringCatalog } from "../Configuration-DyKo0sLS.js";
1
+ import { n as formAuthoring } from "../Forms-Dj6NuW66.js";
2
+ import { l as validateCollectionBody, n as ComponentDefinition, t as AuthoringCatalog } from "../Configuration-CDMYfTre.js";
2
3
  import { resolveBlockAuthoring } from "./authoring-metadata.js";
3
- import { addTemplate, addVitePlugin, updateTemplates } from "@nuxt/kit";
4
4
  import { Crypto, Effect, Encoding, FileSystem, Path, Schema } from "effect";
5
+ import { addTemplate, addVitePlugin, updateTemplates } from "@nuxt/kit";
5
6
  import { createCheckerByJson } from "vue-component-meta";
6
7
 
7
8
  //#region src/internal/authoring-catalog.ts
8
9
  /** A complete, validated snapshot shared by Vite and Nitro through ordinary imports. */
9
- const registerAuthoringCatalog = Effect.fn("CmsAuthoring.register")(function* (nuxt, documents) {
10
+ const registerAuthoringCatalog = Effect.fn("CmsAuthoring.register")(function* (nuxt, documents, forms = {}) {
10
11
  const fs = yield* FileSystem.FileSystem;
11
12
  const path = yield* Path.Path;
12
13
  const crypto = yield* Crypto.Crypto;
@@ -55,7 +56,11 @@ const registerAuthoringCatalog = Effect.fn("CmsAuthoring.register")(function* (n
55
56
  if (!component.filePath.endsWith(".vue") || component.filePath.includes("/node_modules/")) continue;
56
57
  if (!(yield* fs.exists(component.filePath))) continue;
57
58
  const source = yield* fs.readFileString(component.filePath);
58
- const definition = yield* resolveBlockAuthoring(checker, component.filePath, component.kebabName, source);
59
+ const form = forms[component.kebabName];
60
+ const definition = form ? ComponentDefinition.make({
61
+ name: component.kebabName,
62
+ authoring: formAuthoring(form)
63
+ }) : yield* resolveBlockAuthoring(checker, component.filePath, component.kebabName, source);
59
64
  if (!definition) continue;
60
65
  if (definitions.some((existing) => existing.name === definition.name)) throw new Error(`Duplicate authoring block ${definition.name}.`);
61
66
  definitions.push(definition);
@@ -65,6 +70,7 @@ const registerAuthoringCatalog = Effect.fn("CmsAuthoring.register")(function* (n
65
70
  filePath: component.filePath
66
71
  });
67
72
  }
73
+ for (const name of Object.keys(forms)) if (!definitions.some((definition) => definition.name === name)) throw new Error(`Missing Vue form renderer ${name}.`);
68
74
  const components = definitions.sort((left, right) => left.name.localeCompare(right.name));
69
75
  for (const collection of documents.types) {
70
76
  const issues = validateCollectionBody(components, collection.body);
@@ -1 +1 @@
1
- {"version":3,"file":"authoring-catalog.js","names":[],"sources":["../../../../src/internal/authoring-catalog.ts"],"sourcesContent":["import { validateCollectionBody } from '@internal/document/AuthoringSchema'\nimport type { DocumentConfiguration } from '@internal/protocol/Configuration'\nimport type { ViteDevServer } from 'vite'\nimport type { Nuxt } from '@nuxt/schema'\nimport type { Component } from '@nuxt/schema'\nimport { AuthoringCatalog, ComponentDefinition } from '@internal/protocol/Configuration'\nimport { addTemplate, addVitePlugin, updateTemplates } from '@nuxt/kit'\nimport { Crypto, Effect, Encoding, FileSystem, Path, Schema } from 'effect'\nimport { createCheckerByJson } from 'vue-component-meta'\nimport { resolveBlockAuthoring } from './authoring-metadata'\n\n/** A complete, validated snapshot shared by Vite and Nitro through ordinary imports. */\nexport const registerAuthoringCatalog = Effect.fn('CmsAuthoring.register')(function* (\n nuxt: Nuxt,\n documents: DocumentConfiguration,\n) {\n const fs = yield* FileSystem.FileSystem\n const path = yield* Path.Path\n const crypto = yield* Crypto.Crypto\n const run = Effect.runPromiseWith(yield* Effect.context<never>())\n let contents = 'export default { revision: \"empty\", components: [] }\\n'\n let blockContents = 'export default {}\\n'\n let discovered: Component[] = []\n let dependencies = new Set<string>()\n let queue = Promise.resolve()\n const servers = new Set<ViteDevServer>()\n let initialized = false\n let rejected = false\n const template = addTemplate({\n filename: 'cms/authoring.mjs',\n write: true,\n getContents: () => contents,\n })\n const blocks = addTemplate({ filename: 'cms/blocks.mjs', write: true, getContents: () => blockContents })\n nuxt.options.alias['#cms/blocks'] = blocks.dst\n nuxt.options.alias['#cms/authoring'] = template.dst\n nuxt.hook('nitro:config', (config) => {\n config.externals ||= {}\n config.externals.inline ||= []\n config.externals.inline.push(template.dst)\n })\n\n const compile = Effect.fn('CmsAuthoring.compile')(function* () {\n const checker = createCheckerByJson(\n nuxt.options.rootDir,\n {\n compilerOptions: {\n strict: true,\n target: 'ESNext',\n module: 'ESNext',\n moduleResolution: 'Bundler',\n baseUrl: nuxt.options.rootDir,\n paths: Object.fromEntries(\n Object.entries(nuxt.options.alias).map(([key, value]) => [`${key}/*`, [`${value}/*`]]),\n ),\n },\n files: [],\n },\n { schema: true },\n )\n const definitions: ComponentDefinition[] = []\n const registrations: { name: string; filePath: string }[] = []\n try {\n for (const component of discovered) {\n if (!component.filePath.endsWith('.vue') || component.filePath.includes('/node_modules/')) continue\n if (!(yield* fs.exists(component.filePath))) continue\n const source = yield* fs.readFileString(component.filePath)\n const definition = yield* resolveBlockAuthoring(checker, component.filePath, component.kebabName, source)\n if (!definition) continue\n if (definitions.some((existing) => existing.name === definition.name))\n throw new Error(`Duplicate authoring block ${definition.name}.`)\n definitions.push(definition)\n component.global = false\n registrations.push({ name: definition.name, filePath: component.filePath })\n }\n const components = definitions.sort((left, right) => left.name.localeCompare(right.name))\n for (const collection of documents.types) {\n const issues = validateCollectionBody(components, collection.body)\n if (issues.length) throw new Error(`${collection.label}: ${issues.join(' ')}`)\n }\n const encoded = yield* Schema.encodeEffect(Schema.fromJsonString(Schema.Array(ComponentDefinition)))(components)\n const revision = Encoding.encodeHex(yield* crypto.digest('SHA-256', new TextEncoder().encode(encoded)))\n const catalog = yield* Schema.encodeEffect(Schema.fromJsonString(AuthoringCatalog))({ revision, components })\n const next = `export default ${catalog}\\n`\n registrations.sort((left, right) => left.name.localeCompare(right.name))\n const nextBlocks = [\n ...registrations.map((component, index) => `import Block${index} from ${JSON.stringify(component.filePath)}`),\n `export default { ${registrations.map((component, index) => `${JSON.stringify(component.name)}: Block${index}`).join(', ')} }`,\n ].join('\\n')\n const changed = next !== contents || nextBlocks !== blockContents\n blockContents = nextBlocks\n if (rejected) {\n rejected = false\n for (const server of servers) server.ws.send({ type: 'update', updates: [] })\n }\n if (!changed) return false\n contents = next\n return true\n } finally {\n const discoveredDependencies = new Set(\n checker\n .getProgram()\n ?.getSourceFiles()\n .map((file) => path.resolve(file.fileName))\n .filter((file) => !file.includes('/node_modules/')),\n )\n // Keep failed candidate dependencies too, so fixing an imported type can recover the catalog.\n dependencies = new Set([...dependencies, ...discoveredDependencies])\n for (const server of servers) server.watcher.add([...dependencies])\n }\n })\n function rebuild() {\n const current = queue.then(() => run(compile()))\n queue = current.then(\n () => undefined,\n () => undefined,\n )\n return current\n }\n function report(error: Error) {\n rejected = true\n for (const server of servers)\n server.ws.send({\n type: 'error',\n err: { message: error.message, stack: error.stack ?? '', plugin: 'cms-authoring' },\n })\n return run(Effect.logError('Authoring update rejected; keeping the last valid catalog.', error))\n }\n function update() {\n return rebuild()\n .then((changed) =>\n changed\n ? updateTemplates({ filter: (candidate) => [template.dst, blocks.dst].includes(candidate.dst) })\n : undefined,\n )\n .catch((error) => report(error instanceof Error ? error : new Error(String(error))))\n }\n nuxt.hook('components:extend', (components) => {\n discovered = components\n // This hook runs inside template generation. Its caller writes the new snapshot.\n const candidate = rebuild().then(() => undefined)\n if (initialized)\n return candidate.catch((error) => report(error instanceof Error ? error : new Error(String(error))))\n initialized = true\n return candidate\n })\n addVitePlugin({\n name: 'cms-authoring-catalog',\n configureServer(server) {\n servers.add(server)\n server.watcher.add([...dependencies])\n const changed = (filename: string) => {\n const absolute = path.resolve(filename)\n if (dependencies.has(absolute) || discovered.some((component) => component.filePath === absolute)) void update()\n }\n server.watcher.on('change', changed)\n server.httpServer?.once('close', () => {\n servers.delete(server)\n server.watcher.off('change', changed)\n })\n },\n })\n return template\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"authoring-catalog.js","names":[],"sources":["../../../../src/internal/authoring-catalog.ts"],"sourcesContent":["import { formAuthoring } from '@internal/document/Forms'\nimport type { FormCapabilities } from '@internal/protocol/Forms'\nimport { validateCollectionBody } from '@internal/document/AuthoringSchema'\nimport type { DocumentConfiguration } from '@internal/protocol/Configuration'\nimport type { Nuxt } from '@nuxt/schema'\nimport type { Component } from '@nuxt/schema'\nimport { AuthoringCatalog, ComponentDefinition } from '@internal/protocol/Configuration'\nimport { addTemplate, addVitePlugin, updateTemplates } from '@nuxt/kit'\nimport { Crypto, Effect, Encoding, FileSystem, Path, Schema } from 'effect'\nimport { createCheckerByJson } from 'vue-component-meta'\nimport { resolveBlockAuthoring } from './authoring-metadata'\n\ntype AuthoringServer = {\n ws: {\n send: (\n payload:\n | { type: 'update'; updates: [] }\n | { type: 'error'; err: { message: string; stack: string; plugin: string } },\n ) => void\n }\n watcher: { add: (paths: string[]) => void }\n}\n\n/** A complete, validated snapshot shared by Vite and Nitro through ordinary imports. */\nexport const registerAuthoringCatalog = Effect.fn('CmsAuthoring.register')(function* (\n nuxt: Nuxt,\n documents: DocumentConfiguration,\n forms: Readonly<Record<string, FormCapabilities>> = {},\n) {\n const fs = yield* FileSystem.FileSystem\n const path = yield* Path.Path\n const crypto = yield* Crypto.Crypto\n const run = Effect.runPromiseWith(yield* Effect.context<never>())\n let contents = 'export default { revision: \"empty\", components: [] }\\n'\n let blockContents = 'export default {}\\n'\n let discovered: Component[] = []\n let dependencies = new Set<string>()\n let queue = Promise.resolve()\n const servers = new Set<AuthoringServer>()\n let initialized = false\n let rejected = false\n\n const template = addTemplate({\n filename: 'cms/authoring.mjs',\n write: true,\n getContents: () => contents,\n })\n\n const blocks = addTemplate({ filename: 'cms/blocks.mjs', write: true, getContents: () => blockContents })\n nuxt.options.alias['#cms/blocks'] = blocks.dst\n nuxt.options.alias['#cms/authoring'] = template.dst\n nuxt.hook('nitro:config', (config) => {\n config.externals ||= {}\n config.externals.inline ||= []\n config.externals.inline.push(template.dst)\n })\n\n const compile = Effect.fn('CmsAuthoring.compile')(function* () {\n const checker = createCheckerByJson(\n nuxt.options.rootDir,\n {\n compilerOptions: {\n strict: true,\n target: 'ESNext',\n module: 'ESNext',\n moduleResolution: 'Bundler',\n baseUrl: nuxt.options.rootDir,\n paths: Object.fromEntries(\n Object.entries(nuxt.options.alias).map(([key, value]) => [`${key}/*`, [`${value}/*`]]),\n ),\n },\n files: [],\n },\n { schema: true },\n )\n\n const definitions: ComponentDefinition[] = []\n const registrations: { name: string; filePath: string }[] = []\n\n try {\n for (const component of discovered) {\n if (!component.filePath.endsWith('.vue') || component.filePath.includes('/node_modules/')) continue\n\n if (!(yield* fs.exists(component.filePath))) continue\n const source = yield* fs.readFileString(component.filePath)\n const form = forms[component.kebabName]\n\n const definition = form\n ? ComponentDefinition.make({ name: component.kebabName, authoring: formAuthoring(form) })\n : yield* resolveBlockAuthoring(checker, component.filePath, component.kebabName, source)\n\n if (!definition) continue\n\n if (definitions.some((existing) => existing.name === definition.name))\n throw new Error(`Duplicate authoring block ${definition.name}.`)\n definitions.push(definition)\n component.global = false\n registrations.push({ name: definition.name, filePath: component.filePath })\n }\n\n for (const name of Object.keys(forms))\n if (!definitions.some((definition) => definition.name === name))\n throw new Error(`Missing Vue form renderer ${name}.`)\n const components = definitions.sort((left, right) => left.name.localeCompare(right.name))\n\n for (const collection of documents.types) {\n const issues = validateCollectionBody(components, collection.body)\n\n if (issues.length) throw new Error(`${collection.label}: ${issues.join(' ')}`)\n }\n\n const encoded = yield* Schema.encodeEffect(Schema.fromJsonString(Schema.Array(ComponentDefinition)))(components)\n const revision = Encoding.encodeHex(yield* crypto.digest('SHA-256', new TextEncoder().encode(encoded)))\n const catalog = yield* Schema.encodeEffect(Schema.fromJsonString(AuthoringCatalog))({ revision, components })\n const next = `export default ${catalog}\\n`\n registrations.sort((left, right) => left.name.localeCompare(right.name))\n\n const nextBlocks = [\n ...registrations.map((component, index) => `import Block${index} from ${JSON.stringify(component.filePath)}`),\n `export default { ${registrations.map((component, index) => `${JSON.stringify(component.name)}: Block${index}`).join(', ')} }`,\n ].join('\\n')\n\n const changed = next !== contents || nextBlocks !== blockContents\n blockContents = nextBlocks\n\n if (rejected) {\n rejected = false\n\n for (const server of servers) server.ws.send({ type: 'update', updates: [] })\n }\n\n if (!changed) return false\n contents = next\n\n return true\n } finally {\n const discoveredDependencies = new Set(\n checker\n .getProgram()\n ?.getSourceFiles()\n .map((file) => path.resolve(file.fileName))\n .filter((file) => !file.includes('/node_modules/')),\n )\n\n // Keep failed candidate dependencies too, so fixing an imported type can recover the catalog.\n dependencies = new Set([...dependencies, ...discoveredDependencies])\n\n for (const server of servers) server.watcher.add([...dependencies])\n }\n })\n\n function rebuild() {\n const current = queue.then(() => run(compile()))\n queue = current.then(\n () => undefined,\n () => undefined,\n )\n\n return current\n }\n\n function report(error: Error) {\n rejected = true\n\n for (const server of servers)\n server.ws.send({\n type: 'error',\n err: { message: error.message, stack: error.stack ?? '', plugin: 'cms-authoring' },\n })\n\n return run(Effect.logError('Authoring update rejected; keeping the last valid catalog.', error))\n }\n\n function update() {\n return rebuild()\n .then((changed) =>\n changed\n ? updateTemplates({ filter: (candidate) => [template.dst, blocks.dst].includes(candidate.dst) })\n : undefined,\n )\n .catch((error) => report(error instanceof Error ? error : new Error(String(error))))\n }\n\n nuxt.hook('components:extend', (components) => {\n discovered = components\n // This hook runs inside template generation. Its caller writes the new snapshot.\n const candidate = rebuild().then(() => undefined)\n\n if (initialized)\n return candidate.catch((error) => report(error instanceof Error ? error : new Error(String(error))))\n initialized = true\n\n return candidate\n })\n addVitePlugin({\n name: 'cms-authoring-catalog',\n configureServer(server) {\n servers.add(server)\n server.watcher.add([...dependencies])\n\n const changed = (filename: string) => {\n const absolute = path.resolve(filename)\n\n if (dependencies.has(absolute) || discovered.some((component) => component.filePath === absolute)) void update()\n }\n\n server.watcher.on('change', changed)\n server.httpServer?.once('close', () => {\n servers.delete(server)\n server.watcher.off('change', changed)\n })\n },\n })\n\n return template\n})\n"],"mappings":"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"}
@@ -2,7 +2,6 @@ import { MagicString, babelParse, parse, walkIdentifiers } from "@vue/compiler-s
2
2
 
3
3
  //#region src/internal/authoring-compiler.ts
4
4
  const authoringImport = "@phtngyn/cms/Authoring";
5
- /** Reads static authoring data and erases the macro before Vue compiles the SFC. */
6
5
  function compileCmsBlock(source, filename) {
7
6
  if (!source.includes(authoringImport)) return void 0;
8
7
  const { descriptor, errors } = parse(source, { filename });
@@ -1 +1 @@
1
- {"version":3,"file":"authoring-compiler.js","names":[],"sources":["../../../../src/internal/authoring-compiler.ts"],"sourcesContent":["import { babelParse, MagicString, parse, walkIdentifiers } from '@vue/compiler-sfc'\nimport type { Schema } from 'effect'\n\nconst authoringImport = '@phtngyn/cms/Authoring'\ntype Statement = ReturnType<typeof babelParse>['program']['body'][number]\ntype Expression = Extract<Statement, { type: 'ExpressionStatement' }>['expression']\ntype Call = Extract<Expression, { type: 'CallExpression' }>\n\n/** Reads static authoring data and erases the macro before Vue compiles the SFC. */\nexport function compileCmsBlock(source: string, filename: string) {\n if (!source.includes(authoringImport)) return undefined\n const { descriptor, errors } = parse(source, { filename })\n if (errors.length) throw new Error(`${filename}: ${errors.join('\\n')}`)\n if (descriptor.script?.content.includes(authoringImport)) {\n const script = babelParse(descriptor.script.content, { sourceType: 'module', plugins: ['typescript'] })\n if (\n script.program.body.some(\n (statement) =>\n statement.type === 'ImportDeclaration' &&\n statement.source.value === authoringImport &&\n statement.importKind !== 'type' &&\n statement.specifiers.some(\n (specifier) => specifier.type !== 'ImportSpecifier' || specifier.importKind !== 'type',\n ),\n )\n )\n throw new Error(`${filename}: defineCmsBlock requires <script setup lang=\"ts\">.`)\n }\n const setup = descriptor.scriptSetup\n if (!setup) return undefined\n const ast = babelParse(setup.content, { sourceType: 'module', plugins: ['typescript'] })\n const imports = ast.program.body.filter(\n (statement) =>\n statement.type === 'ImportDeclaration' &&\n statement.source.value === authoringImport &&\n statement.importKind !== 'type',\n )\n if (!imports.length) return undefined\n const imported = imports[0]\n if (imported?.type !== 'ImportDeclaration') return undefined\n const specifier = imported.specifiers[0]\n if (\n imports.length !== 1 ||\n imported.specifiers.length !== 1 ||\n specifier?.type !== 'ImportSpecifier' ||\n specifier.importKind === 'type' ||\n specifier.imported.type !== 'Identifier' ||\n specifier.imported.name !== 'defineCmsBlock'\n ) {\n throw new Error(`${filename}: use a dedicated named import for defineCmsBlock.`)\n }\n if (setup.lang !== 'ts' || setup.attrs.generic) {\n throw new Error(`${filename}: defineCmsBlock requires a non-generic <script setup lang=\"ts\">.`)\n }\n const calls = ast.program.body.filter(\n (statement) =>\n statement.type === 'ExpressionStatement' &&\n statement.expression.type === 'CallExpression' &&\n statement.expression.callee.type === 'Identifier' &&\n statement.expression.callee.name === specifier.local.name,\n )\n const statement = calls[0]\n if (\n calls.length !== 1 ||\n statement?.type !== 'ExpressionStatement' ||\n statement.expression.type !== 'CallExpression'\n ) {\n throw new Error(`${filename}: defineCmsBlock must be called exactly once as a top-level statement.`)\n }\n const call = statement.expression\n const argument = call.arguments[0]\n if (call.arguments.length !== 1 || argument?.type !== 'ObjectExpression') {\n throw new Error(`${filename}: defineCmsBlock requires one object literal.`)\n }\n const types = call.typeParameters?.type === 'TSTypeParameterInstantiation' ? call.typeParameters.params : []\n if (types.length !== 2)\n throw new Error(`${filename}: share named Props and Slots types with defineProps and defineSlots.`)\n const names = types.map((type) => {\n if (type.type !== 'TSTypeReference' || type.typeName.type !== 'Identifier' || type.typeParameters) {\n throw new Error(`${filename}: defineCmsBlock type arguments must be named, non-generic types.`)\n }\n return type.typeName.name\n })\n const vueCalls = new Map<string, Call>()\n walkIdentifiers(ast.program, (identifier, parent, _stack, isReference) => {\n if (!isReference) return\n if (identifier.name === specifier.local.name && identifier !== call.callee) {\n throw new Error(`${filename}: defineCmsBlock may only be used in its top-level declaration.`)\n }\n if (\n (identifier.name === 'defineProps' || identifier.name === 'defineSlots') &&\n parent?.type === 'CallExpression' &&\n parent.callee === identifier\n ) {\n vueCalls.set(identifier.name, parent)\n }\n })\n for (const [index, macro] of ['defineProps', 'defineSlots'].entries()) {\n const vueCall = vueCalls.get(macro)\n const parameters = vueCall?.typeParameters\n const type = parameters?.type === 'TSTypeParameterInstantiation' ? parameters.params[0] : undefined\n if (\n type?.type !== 'TSTypeReference' ||\n type.typeName.type !== 'Identifier' ||\n type.typeParameters !== undefined ||\n type.typeName.name !== names[index]\n ) {\n throw new Error(`${filename}: ${macro} must use the same ${names[index]} type as defineCmsBlock.`)\n }\n }\n const declaration = staticValue(argument, filename)\n const code = new MagicString(source)\n for (const node of [imported, statement]) {\n if (node.start === null || node.start === undefined || node.end === null || node.end === undefined) {\n throw new Error(`${filename}: missing authoring declaration source location.`)\n }\n code.remove(setup.loc.start.offset + node.start, setup.loc.start.offset + node.end)\n }\n return {\n declaration,\n code: code.toString(),\n map: code.generateMap({ source: filename, includeContent: true, hires: true }),\n }\n}\n\nfunction staticValue(expression: Parameters<typeof walkIdentifiers>[0], filename: string): Schema.Json {\n switch (expression.type) {\n case 'StringLiteral':\n case 'BooleanLiteral':\n return expression.value\n case 'NumericLiteral':\n if (Number.isFinite(expression.value)) return expression.value\n break\n case 'NullLiteral':\n return null\n case 'UnaryExpression':\n if (\n expression.operator === '-' &&\n expression.argument.type === 'NumericLiteral' &&\n Number.isFinite(expression.argument.value)\n ) {\n return -expression.argument.value\n }\n break\n case 'ArrayExpression':\n return expression.elements.map((element) => {\n if (!element || element.type === 'SpreadElement')\n throw new Error(`${filename}: authoring arrays require literal entries.`)\n return staticValue(element, filename)\n })\n case 'ObjectExpression': {\n const entries = expression.properties.map((property): [string, Schema.Json] => {\n if (\n property.type !== 'ObjectProperty' ||\n property.computed ||\n property.shorthand ||\n (property.key.type !== 'Identifier' && property.key.type !== 'StringLiteral')\n ) {\n throw new Error(\n `${filename}: authoring objects require literal named properties; spreads and methods are unsupported.`,\n )\n }\n return [\n property.key.type === 'Identifier' ? property.key.name : property.key.value,\n staticValue(property.value, filename),\n ]\n })\n if (new Set(entries.map(([key]) => key)).size !== entries.length)\n throw new Error(`${filename}: duplicate authoring property.`)\n return Object.fromEntries(entries)\n }\n }\n throw new Error(`${filename}: authoring metadata must contain only JSON literals; ${expression.type} is unsupported.`)\n}\n\n/** Reads Vue's printed default expression without evaluating application code. */\nexport function readAuthoringDefault(source: string, filename: string): Schema.Json {\n const expression = babelParse(`(${source})`, { sourceType: 'module', plugins: ['typescript'] }).program.body[0]\n if (expression?.type !== 'ExpressionStatement') throw new Error(`${filename}: expected a literal Vue default.`)\n const value = expression.expression\n return staticValue(\n value.type === 'ArrowFunctionExpression' && value.body.type !== 'BlockStatement' ? value.body : value,\n filename,\n )\n}\n\nexport function cmsAuthoringPlugin() {\n return {\n name: 'cms:authoring',\n enforce: 'pre' as const,\n transform(source: string, id: string) {\n if (!id.endsWith('.vue')) return undefined\n const compiled = compileCmsBlock(source, id)\n return compiled ? { code: compiled.code, map: compiled.map } : undefined\n },\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"authoring-compiler.js","names":[],"sources":["../../../../src/internal/authoring-compiler.ts"],"sourcesContent":["import { babelParse, MagicString, parse, walkIdentifiers } from '@vue/compiler-sfc'\nimport type { Schema } from 'effect'\n\nconst authoringImport = '@phtngyn/cms/Authoring'\n\ntype Statement = ReturnType<typeof babelParse>['program']['body'][number]\n\ntype Expression = Extract<Statement, { type: 'ExpressionStatement' }>['expression']\n\ntype Call = Extract<Expression, { type: 'CallExpression' }>\n\nexport function compileCmsBlock(source: string, filename: string) {\n if (!source.includes(authoringImport)) return undefined\n const { descriptor, errors } = parse(source, { filename })\n\n if (errors.length) throw new Error(`${filename}: ${errors.join('\\n')}`)\n\n if (descriptor.script?.content.includes(authoringImport)) {\n const script = babelParse(descriptor.script.content, { sourceType: 'module', plugins: ['typescript'] })\n\n if (\n script.program.body.some(\n (statement) =>\n statement.type === 'ImportDeclaration' &&\n statement.source.value === authoringImport &&\n statement.importKind !== 'type' &&\n statement.specifiers.some(\n (specifier) => specifier.type !== 'ImportSpecifier' || specifier.importKind !== 'type',\n ),\n )\n )\n throw new Error(`${filename}: defineCmsBlock requires <script setup lang=\"ts\">.`)\n }\n\n const setup = descriptor.scriptSetup\n\n if (!setup) return undefined\n const ast = babelParse(setup.content, { sourceType: 'module', plugins: ['typescript'] })\n\n const imports = ast.program.body.filter(\n (statement) =>\n statement.type === 'ImportDeclaration' &&\n statement.source.value === authoringImport &&\n statement.importKind !== 'type',\n )\n\n if (!imports.length) return undefined\n const imported = imports[0]\n\n if (imported?.type !== 'ImportDeclaration') return undefined\n const specifier = imported.specifiers[0]\n\n if (\n imports.length !== 1 ||\n imported.specifiers.length !== 1 ||\n specifier?.type !== 'ImportSpecifier' ||\n specifier.importKind === 'type' ||\n specifier.imported.type !== 'Identifier' ||\n specifier.imported.name !== 'defineCmsBlock'\n ) {\n throw new Error(`${filename}: use a dedicated named import for defineCmsBlock.`)\n }\n\n if (setup.lang !== 'ts' || setup.attrs.generic) {\n throw new Error(`${filename}: defineCmsBlock requires a non-generic <script setup lang=\"ts\">.`)\n }\n\n const calls = ast.program.body.filter(\n (statement) =>\n statement.type === 'ExpressionStatement' &&\n statement.expression.type === 'CallExpression' &&\n statement.expression.callee.type === 'Identifier' &&\n statement.expression.callee.name === specifier.local.name,\n )\n\n const statement = calls[0]\n\n if (\n calls.length !== 1 ||\n statement?.type !== 'ExpressionStatement' ||\n statement.expression.type !== 'CallExpression'\n ) {\n throw new Error(`${filename}: defineCmsBlock must be called exactly once as a top-level statement.`)\n }\n\n const call = statement.expression\n const argument = call.arguments[0]\n\n if (call.arguments.length !== 1 || argument?.type !== 'ObjectExpression') {\n throw new Error(`${filename}: defineCmsBlock requires one object literal.`)\n }\n\n const types = call.typeParameters?.type === 'TSTypeParameterInstantiation' ? call.typeParameters.params : []\n\n if (types.length !== 2)\n throw new Error(`${filename}: share named Props and Slots types with defineProps and defineSlots.`)\n\n const names = types.map((type) => {\n if (type.type !== 'TSTypeReference' || type.typeName.type !== 'Identifier' || type.typeParameters) {\n throw new Error(`${filename}: defineCmsBlock type arguments must be named, non-generic types.`)\n }\n\n return type.typeName.name\n })\n\n const vueCalls = new Map<string, Call>()\n walkIdentifiers(ast.program, (identifier, parent, _stack, isReference) => {\n if (!isReference) return\n\n if (identifier.name === specifier.local.name && identifier !== call.callee) {\n throw new Error(`${filename}: defineCmsBlock may only be used in its top-level declaration.`)\n }\n\n if (\n (identifier.name === 'defineProps' || identifier.name === 'defineSlots') &&\n parent?.type === 'CallExpression' &&\n parent.callee === identifier\n ) {\n vueCalls.set(identifier.name, parent)\n }\n })\n\n for (const [index, macro] of ['defineProps', 'defineSlots'].entries()) {\n const vueCall = vueCalls.get(macro)\n const parameters = vueCall?.typeParameters\n const type = parameters?.type === 'TSTypeParameterInstantiation' ? parameters.params[0] : undefined\n\n if (\n type?.type !== 'TSTypeReference' ||\n type.typeName.type !== 'Identifier' ||\n type.typeParameters !== undefined ||\n type.typeName.name !== names[index]\n ) {\n throw new Error(`${filename}: ${macro} must use the same ${names[index]} type as defineCmsBlock.`)\n }\n }\n\n const declaration = staticValue(argument, filename)\n const code = new MagicString(source)\n\n for (const node of [imported, statement]) {\n if (node.start === null || node.start === undefined || node.end === null || node.end === undefined) {\n throw new Error(`${filename}: missing authoring declaration source location.`)\n }\n\n code.remove(setup.loc.start.offset + node.start, setup.loc.start.offset + node.end)\n }\n\n return {\n declaration,\n code: code.toString(),\n map: code.generateMap({ source: filename, includeContent: true, hires: true }),\n }\n}\n\nfunction staticValue(expression: Parameters<typeof walkIdentifiers>[0], filename: string): Schema.Json {\n switch (expression.type) {\n case 'StringLiteral':\n case 'BooleanLiteral':\n return expression.value\n case 'NumericLiteral':\n if (Number.isFinite(expression.value)) return expression.value\n break\n case 'NullLiteral':\n return null\n case 'UnaryExpression':\n if (\n expression.operator === '-' &&\n expression.argument.type === 'NumericLiteral' &&\n Number.isFinite(expression.argument.value)\n ) {\n return -expression.argument.value\n }\n\n break\n case 'ArrayExpression':\n return expression.elements.map((element) => {\n if (!element || element.type === 'SpreadElement')\n throw new Error(`${filename}: authoring arrays require literal entries.`)\n\n return staticValue(element, filename)\n })\n case 'ObjectExpression': {\n const entries = expression.properties.map((property): [string, Schema.Json] => {\n if (\n property.type !== 'ObjectProperty' ||\n property.computed ||\n property.shorthand ||\n (property.key.type !== 'Identifier' && property.key.type !== 'StringLiteral')\n ) {\n throw new Error(\n `${filename}: authoring objects require literal named properties; spreads and methods are unsupported.`,\n )\n }\n\n return [\n property.key.type === 'Identifier' ? property.key.name : property.key.value,\n staticValue(property.value, filename),\n ]\n })\n\n if (new Set(entries.map(([key]) => key)).size !== entries.length)\n throw new Error(`${filename}: duplicate authoring property.`)\n\n return Object.fromEntries(entries)\n }\n }\n\n throw new Error(`${filename}: authoring metadata must contain only JSON literals; ${expression.type} is unsupported.`)\n}\n\n/** Reads Vue's printed default expression without evaluating application code. */\nexport function readAuthoringDefault(source: string, filename: string): Schema.Json {\n const expression = babelParse(`(${source})`, { sourceType: 'module', plugins: ['typescript'] }).program.body[0]\n\n if (expression?.type !== 'ExpressionStatement') throw new Error(`${filename}: expected a literal Vue default.`)\n const value = expression.expression\n\n return staticValue(\n value.type === 'ArrowFunctionExpression' && value.body.type !== 'BlockStatement' ? value.body : value,\n filename,\n )\n}\n\nexport function cmsAuthoringPlugin() {\n return {\n name: 'cms:authoring',\n enforce: 'pre' as const,\n transform(source: string, id: string) {\n if (!id.endsWith('.vue')) return undefined\n const compiled = compileCmsBlock(source, id)\n\n return compiled ? { code: compiled.code, map: compiled.map } : undefined\n },\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { a as BlockAuthoring, n as ComponentDefinition, o as createAuthoringSchema, s as parseAuthoringContent } from "../Configuration-DyKo0sLS.js";
1
+ import { a as BlockAuthoring, c as parseAuthoringContent, n as ComponentDefinition, s as createAuthoringSchema } from "../Configuration-CDMYfTre.js";
2
2
  import { compileCmsBlock, readAuthoringDefault } from "./authoring-compiler.js";
3
- import { Effect, Schema } from "effect";
3
+ import { Effect, Result, Schema } from "effect";
4
4
  import ts from "typescript";
5
5
 
6
6
  //#region src/internal/authoring-metadata.ts
@@ -137,7 +137,7 @@ function resolveProp(raw, name, required, presentation, checker, filename, defau
137
137
  array: ["list"]
138
138
  }[type].includes(presentation.input) || presentation.input === "select" && !choices.length) throw new Error(`${filename}: ${name} has an incompatible authoring input ${presentation.input}.`);
139
139
  for (const key of Object.keys(presentation.optionLabels ?? {})) if (!choices.includes(key)) throw new Error(`${filename}: ${key} is not a Vue union choice.`);
140
- return Schema.decodeUnknownSync(BlockAuthoring.fields.props.value)({
140
+ return Result.getOrThrow(Schema.decodeUnknownResult(BlockAuthoring.fields.props.value)({
141
141
  name,
142
142
  label: presentation.label,
143
143
  type,
@@ -151,7 +151,7 @@ function resolveProp(raw, name, required, presentation, checker, filename, defau
151
151
  value,
152
152
  label: presentation.optionLabels?.[value] ?? value
153
153
  }))
154
- });
154
+ }));
155
155
  }
156
156
  function vueSlots(checker, filename) {
157
157
  const program = checker.getProgram();
@@ -1 +1 @@
1
- {"version":3,"file":"authoring-metadata.js","names":[],"sources":["../../../../src/internal/authoring-metadata.ts"],"sourcesContent":["import type { ComponentMetaChecker } from 'vue-component-meta'\nimport type { BlockProp, BlockSlot } from '@internal/protocol/Authoring'\nimport { createAuthoringSchema, parseAuthoringContent } from '@internal/document/AuthoringSchema'\nimport { BlockAuthoring } from '@internal/protocol/Authoring'\nimport { ComponentDefinition } from '@internal/protocol/Configuration'\nimport { Effect, Schema } from 'effect'\nimport ts from 'typescript'\nimport { compileCmsBlock, readAuthoringDefault } from './authoring-compiler'\n\ninterface Presentation {\n readonly label: string\n readonly help?: string\n readonly input: string\n readonly optionLabels?: Readonly<Record<string, string>>\n readonly features?: ReadonlyArray<'bold' | 'italic' | 'link' | 'bullet-list' | 'code'>\n readonly blocks?: ReadonlyArray<string>\n readonly groups?: ReadonlyArray<string>\n readonly fields?: Readonly<Record<string, Presentation>>\n}\nconst Presentation: Schema.Codec<Presentation> = Schema.Struct({\n fields: Schema.optionalKey(\n Schema.Record(\n Schema.String,\n Schema.suspend(() => Presentation),\n ),\n ),\n blocks: Schema.optionalKey(Schema.Array(Schema.NonEmptyString)),\n groups: Schema.optionalKey(Schema.Array(Schema.NonEmptyString)),\n label: Schema.NonEmptyString,\n help: Schema.optionalKey(Schema.String),\n input: Schema.String,\n optionLabels: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),\n features: Schema.optionalKey(Schema.Array(Schema.Literals(['bold', 'italic', 'link', 'bullet-list', 'code']))),\n})\nconst Declaration = Schema.Struct({\n label: Schema.NonEmptyString,\n description: Schema.optionalKey(Schema.String),\n group: Schema.optionalKey(Schema.String),\n icon: Schema.optionalKey(Schema.String),\n props: Schema.Record(Schema.String, Presentation),\n slots: Schema.Record(Schema.String, Presentation),\n initial: Schema.optionalKey(\n Schema.Struct({\n props: Schema.optionalKey(Schema.JsonObject),\n slots: Schema.optionalKey(\n Schema.Record(\n Schema.String,\n Schema.Union([Schema.Struct({ text: Schema.String }), Schema.Struct({ markdown: Schema.String })]),\n ),\n ),\n }),\n ),\n})\n\n/** Resolves one opted-in SFC. No framework metadata or executable defaults cross this seam. */\nexport const resolveBlockAuthoring = Effect.fn('NuxtAuthoring.resolve')(function* (\n checker: ComponentMetaChecker,\n filename: string,\n name: string,\n source: string,\n) {\n const compiled = compileCmsBlock(source, filename)\n if (!compiled) return undefined\n const declared = yield* Schema.decodeUnknownEffect(Declaration)(compiled.declaration, { onExcessProperty: 'error' })\n checker.updateFile(filename, source)\n const metadata = checker.getComponentMeta(filename)\n const props = Object.entries(declared.props).map(([key, presentation]): BlockProp => {\n const prop = metadata.props.find((candidate) => candidate.name === key && !candidate.global)\n if (!prop) throw new Error(`${filename}: unknown Vue prop ${key}.`)\n const typeChecker = checker.getProgram()?.getTypeChecker()\n if (!typeChecker) throw new Error(`${filename}: Vue type information is unavailable.`)\n return resolveProp(prop.getTypeObject(), key, prop.required, presentation, typeChecker, filename, prop.default)\n })\n for (const prop of metadata.props) {\n if (!prop.global && prop.required && prop.default === undefined && !Object.hasOwn(declared.props, prop.name))\n throw new Error(`${filename}: required prop ${prop.name} needs an authoring declaration and initial value.`)\n }\n const slotTypes = vueSlots(checker, filename)\n const slots: BlockSlot[] = []\n for (const [key, presentation] of Object.entries(declared.slots)) {\n const slot = slotTypes.get(key)\n if (!slot) throw new Error(`${filename}: unknown Vue slot ${key}.`)\n if (slot.scoped) throw new Error(`${filename}: scoped slot ${key} cannot be authored.`)\n const seed = declared.initial?.slots?.[key]\n const initial = seed\n ? 'text' in seed\n ? [['p', {}, seed.text]]\n : yield* parseAuthoringContent(seed.markdown)\n : undefined\n slots.push(\n yield* Schema.decodeUnknownEffect(BlockAuthoring.fields.slots.value)({\n name: key,\n label: presentation.label,\n ...(presentation.help === undefined ? undefined : { help: presentation.help }),\n input: presentation.input,\n required: slot.required,\n features: presentation.features ?? [],\n ...(presentation.blocks === undefined ? undefined : { blocks: presentation.blocks }),\n ...(presentation.groups === undefined ? undefined : { groups: presentation.groups }),\n ...(initial === undefined ? undefined : { initial }),\n }),\n )\n if (slot.required && !seed) throw new Error(`${filename}: required slot ${key} needs initial content.`)\n }\n for (const [key, slot] of slotTypes)\n if (slot.required && !Object.hasOwn(declared.slots, key))\n throw new Error(`${filename}: required slot ${key} must be declared.`)\n for (const key of Object.keys(declared.initial?.slots ?? {}))\n if (!slotTypes.has(key) || !Object.hasOwn(declared.slots, key))\n throw new Error(`${filename}: initial content refers to undeclared slot ${key}.`)\n const authoring = BlockAuthoring.make({\n version: 1,\n label: declared.label,\n props,\n slots,\n initialProps: declared.initial?.props ?? {},\n ...(declared.description === undefined ? undefined : { description: declared.description }),\n ...(declared.group === undefined ? undefined : { group: declared.group }),\n ...(declared.icon === undefined ? undefined : { icon: declared.icon }),\n })\n createAuthoringSchema(name, authoring)\n return ComponentDefinition.make({\n name,\n authoring,\n })\n})\n\nfunction resolveProp(\n raw: ts.Type,\n name: string,\n required: boolean,\n presentation: Presentation,\n checker: ts.TypeChecker,\n filename: string,\n defaultSource?: string,\n depth = 0,\n): BlockProp {\n if (depth > 12) throw new Error(`${filename}: ${name} exceeds the supported property nesting depth.`)\n const union = raw.isUnion() ? raw.types : [raw]\n const members = union.filter((type) => !(type.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Null)))\n const nullable = union.some((type) => Boolean(type.flags & ts.TypeFlags.Null))\n const choices = members.flatMap((type) => (type.isStringLiteral() ? [type.value] : [])).sort()\n const valueType = checker.getNonNullableType(raw)\n let type: BlockProp['type']\n let fields: BlockProp[] | undefined\n if (members.length && members.every((type) => Boolean(type.flags & ts.TypeFlags.StringLike))) type = 'string'\n else if (members.length === 1 && members[0]?.flags === ts.TypeFlags.Number) type = 'number'\n else if (members.length && members.every((type) => Boolean(type.flags & ts.TypeFlags.BooleanLike))) type = 'boolean'\n else if (presentation.input === 'object' || presentation.input === 'list') {\n type = presentation.input === 'list' ? 'array' : 'object'\n const item = type === 'array' ? checker.getIndexTypeOfType(valueType, ts.IndexKind.Number) : valueType\n if (!item || !(item.flags & ts.TypeFlags.Object) || item.getCallSignatures().length)\n throw new Error(`${filename}: ${name} needs an object${type === 'array' ? ' list' : ''} type.`)\n if (type === 'array') {\n const id = item.getProperty('id')\n const declaration = id?.valueDeclaration ?? id?.declarations?.[0]\n if (\n !id ||\n !declaration ||\n id.flags & ts.SymbolFlags.Optional ||\n checker.getTypeOfSymbolAtLocation(id, declaration).flags !== ts.TypeFlags.String\n )\n throw new Error(`${filename}: ${name} list items need a required string id for stable editing.`)\n }\n fields = Object.entries(presentation.fields ?? {}).map(([key, field]) => {\n if (type === 'array' && key === 'id') throw new Error(`${filename}: list item ids are managed by Studio.`)\n const property = item.getProperty(key)\n const declaration = property?.valueDeclaration ?? property?.declarations?.[0]\n if (!property || !declaration) throw new Error(`${filename}: unknown field ${name}.${key}.`)\n return resolveProp(\n checker.getTypeOfSymbolAtLocation(property, declaration),\n key,\n !(property.flags & ts.SymbolFlags.Optional),\n field,\n checker,\n filename,\n undefined,\n depth + 1,\n )\n })\n for (const property of item.getProperties()) {\n if (type === 'array' && property.name === 'id') continue\n if (!(property.flags & ts.SymbolFlags.Optional) && !fields.some((field) => field.name === property.name))\n throw new Error(`${filename}: required field ${name}.${property.name} needs an authoring declaration.`)\n }\n } else throw new Error(`${filename}: unsupported editable prop ${name}.`)\n const inputs = {\n string: ['text', 'textarea', 'select', 'image', 'link'],\n number: ['number'],\n boolean: ['toggle'],\n object: ['object'],\n array: ['list'],\n }\n if (!inputs[type].includes(presentation.input) || (presentation.input === 'select' && !choices.length))\n throw new Error(`${filename}: ${name} has an incompatible authoring input ${presentation.input}.`)\n for (const key of Object.keys(presentation.optionLabels ?? {}))\n if (!choices.includes(key)) throw new Error(`${filename}: ${key} is not a Vue union choice.`)\n return Schema.decodeUnknownSync(BlockAuthoring.fields.props.value)({\n name,\n label: presentation.label,\n type,\n input: presentation.input,\n required,\n nullable,\n ...(presentation.help === undefined ? undefined : { help: presentation.help }),\n ...(fields === undefined ? undefined : { fields }),\n ...(defaultSource === undefined\n ? undefined\n : { defaultValue: readAuthoringDefault(defaultSource, `${filename} prop ${name}`) }),\n options: choices.map((value) => ({ value, label: presentation.optionLabels?.[value] ?? value })),\n })\n}\n\nfunction vueSlots(checker: ComponentMetaChecker, filename: string) {\n const program = checker.getProgram()\n const file = program?.getSourceFile(filename)\n if (!program || !file) throw new Error(`${filename}: Vue type information is unavailable.`)\n const typeChecker = program.getTypeChecker()\n const result = new Map<string, { required: boolean; scoped: boolean }>()\n function visit(node: ts.Node): void {\n if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === 'defineSlots') {\n const type = node.typeArguments?.[0]\n if (type)\n for (const property of typeChecker.getTypeAtLocation(type).getProperties()) {\n const declaration = property.valueDeclaration ?? property.declarations?.[0]\n const signature = declaration\n ? typeChecker\n .getNonNullableType(typeChecker.getTypeOfSymbolAtLocation(property, declaration))\n .getCallSignatures()\n : []\n result.set(property.name, {\n required: !(property.flags & ts.SymbolFlags.Optional),\n scoped: signature.length !== 1 || signature.some((signature) => signature.parameters.length > 0),\n })\n }\n }\n ts.forEachChild(node, visit)\n }\n visit(file)\n return result\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"authoring-metadata.js","names":[],"sources":["../../../../src/internal/authoring-metadata.ts"],"sourcesContent":["import type { ComponentMetaChecker } from 'vue-component-meta'\nimport type { BlockProp, BlockSlot } from '@internal/protocol/Authoring'\nimport { createAuthoringSchema, parseAuthoringContent } from '@internal/document/AuthoringSchema'\nimport { BlockAuthoring } from '@internal/protocol/Authoring'\nimport { ComponentDefinition } from '@internal/protocol/Configuration'\nimport { Result, Effect, Schema } from 'effect'\nimport ts from 'typescript'\nimport { compileCmsBlock, readAuthoringDefault } from './authoring-compiler'\n\ninterface Presentation {\n readonly label: string\n readonly help?: string\n readonly input: string\n readonly optionLabels?: Readonly<Record<string, string>>\n readonly features?: ReadonlyArray<'bold' | 'italic' | 'link' | 'bullet-list' | 'code'>\n readonly blocks?: ReadonlyArray<string>\n readonly groups?: ReadonlyArray<string>\n readonly fields?: Readonly<Record<string, Presentation>>\n}\n\nconst Presentation: Schema.Codec<Presentation> = Schema.Struct({\n fields: Schema.optionalKey(\n Schema.Record(\n Schema.String,\n Schema.suspend(() => Presentation),\n ),\n ),\n blocks: Schema.optionalKey(Schema.Array(Schema.NonEmptyString)),\n groups: Schema.optionalKey(Schema.Array(Schema.NonEmptyString)),\n label: Schema.NonEmptyString,\n help: Schema.optionalKey(Schema.String),\n input: Schema.String,\n optionLabels: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),\n features: Schema.optionalKey(Schema.Array(Schema.Literals(['bold', 'italic', 'link', 'bullet-list', 'code']))),\n})\n\nconst Declaration = Schema.Struct({\n label: Schema.NonEmptyString,\n description: Schema.optionalKey(Schema.String),\n group: Schema.optionalKey(Schema.String),\n icon: Schema.optionalKey(Schema.String),\n props: Schema.Record(Schema.String, Presentation),\n slots: Schema.Record(Schema.String, Presentation),\n initial: Schema.optionalKey(\n Schema.Struct({\n props: Schema.optionalKey(Schema.JsonObject),\n slots: Schema.optionalKey(\n Schema.Record(\n Schema.String,\n Schema.Union([Schema.Struct({ text: Schema.String }), Schema.Struct({ markdown: Schema.String })]),\n ),\n ),\n }),\n ),\n})\n\n/** Resolves one opted-in SFC. No framework metadata or executable defaults cross this seam. */\nexport const resolveBlockAuthoring = Effect.fn('NuxtAuthoring.resolve')(function* (\n checker: ComponentMetaChecker,\n filename: string,\n name: string,\n source: string,\n) {\n const compiled = compileCmsBlock(source, filename)\n\n if (!compiled) return undefined\n const declared = yield* Schema.decodeUnknownEffect(Declaration)(compiled.declaration, { onExcessProperty: 'error' })\n checker.updateFile(filename, source)\n const metadata = checker.getComponentMeta(filename)\n\n const props = Object.entries(declared.props).map(([key, presentation]): BlockProp => {\n const prop = metadata.props.find((candidate) => candidate.name === key && !candidate.global)\n\n if (!prop) throw new Error(`${filename}: unknown Vue prop ${key}.`)\n const typeChecker = checker.getProgram()?.getTypeChecker()\n\n if (!typeChecker) throw new Error(`${filename}: Vue type information is unavailable.`)\n\n return resolveProp(prop.getTypeObject(), key, prop.required, presentation, typeChecker, filename, prop.default)\n })\n\n for (const prop of metadata.props) {\n if (!prop.global && prop.required && prop.default === undefined && !Object.hasOwn(declared.props, prop.name))\n throw new Error(`${filename}: required prop ${prop.name} needs an authoring declaration and initial value.`)\n }\n\n const slotTypes = vueSlots(checker, filename)\n const slots: BlockSlot[] = []\n\n for (const [key, presentation] of Object.entries(declared.slots)) {\n const slot = slotTypes.get(key)\n\n if (!slot) throw new Error(`${filename}: unknown Vue slot ${key}.`)\n\n if (slot.scoped) throw new Error(`${filename}: scoped slot ${key} cannot be authored.`)\n const seed = declared.initial?.slots?.[key]\n\n const initial = seed\n ? 'text' in seed\n ? [['p', {}, seed.text]]\n : yield* parseAuthoringContent(seed.markdown)\n : undefined\n\n slots.push(\n yield* Schema.decodeUnknownEffect(BlockAuthoring.fields.slots.value)({\n name: key,\n label: presentation.label,\n ...(presentation.help === undefined ? undefined : { help: presentation.help }),\n input: presentation.input,\n required: slot.required,\n features: presentation.features ?? [],\n ...(presentation.blocks === undefined ? undefined : { blocks: presentation.blocks }),\n ...(presentation.groups === undefined ? undefined : { groups: presentation.groups }),\n ...(initial === undefined ? undefined : { initial }),\n }),\n )\n\n if (slot.required && !seed) throw new Error(`${filename}: required slot ${key} needs initial content.`)\n }\n\n for (const [key, slot] of slotTypes)\n if (slot.required && !Object.hasOwn(declared.slots, key))\n throw new Error(`${filename}: required slot ${key} must be declared.`)\n\n for (const key of Object.keys(declared.initial?.slots ?? {}))\n if (!slotTypes.has(key) || !Object.hasOwn(declared.slots, key))\n throw new Error(`${filename}: initial content refers to undeclared slot ${key}.`)\n\n const authoring = BlockAuthoring.make({\n version: 1,\n label: declared.label,\n props,\n slots,\n initialProps: declared.initial?.props ?? {},\n ...(declared.description === undefined ? undefined : { description: declared.description }),\n ...(declared.group === undefined ? undefined : { group: declared.group }),\n ...(declared.icon === undefined ? undefined : { icon: declared.icon }),\n })\n\n createAuthoringSchema(name, authoring)\n\n return ComponentDefinition.make({\n name,\n authoring,\n })\n})\n\nfunction resolveProp(\n raw: ts.Type,\n name: string,\n required: boolean,\n presentation: Presentation,\n checker: ts.TypeChecker,\n filename: string,\n defaultSource?: string,\n depth = 0,\n): BlockProp {\n if (depth > 12) throw new Error(`${filename}: ${name} exceeds the supported property nesting depth.`)\n const union = raw.isUnion() ? raw.types : [raw]\n const members = union.filter((type) => !(type.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Null)))\n const nullable = union.some((type) => Boolean(type.flags & ts.TypeFlags.Null))\n const choices = members.flatMap((type) => (type.isStringLiteral() ? [type.value] : [])).sort()\n const valueType = checker.getNonNullableType(raw)\n let type: BlockProp['type']\n let fields: BlockProp[] | undefined\n\n if (members.length && members.every((type) => Boolean(type.flags & ts.TypeFlags.StringLike))) type = 'string'\n else if (members.length === 1 && members[0]?.flags === ts.TypeFlags.Number) type = 'number'\n else if (members.length && members.every((type) => Boolean(type.flags & ts.TypeFlags.BooleanLike))) type = 'boolean'\n else if (presentation.input === 'object' || presentation.input === 'list') {\n type = presentation.input === 'list' ? 'array' : 'object'\n const item = type === 'array' ? checker.getIndexTypeOfType(valueType, ts.IndexKind.Number) : valueType\n\n if (!item || !(item.flags & ts.TypeFlags.Object) || item.getCallSignatures().length)\n throw new Error(`${filename}: ${name} needs an object${type === 'array' ? ' list' : ''} type.`)\n\n if (type === 'array') {\n const id = item.getProperty('id')\n const declaration = id?.valueDeclaration ?? id?.declarations?.[0]\n\n if (\n !id ||\n !declaration ||\n id.flags & ts.SymbolFlags.Optional ||\n checker.getTypeOfSymbolAtLocation(id, declaration).flags !== ts.TypeFlags.String\n )\n throw new Error(`${filename}: ${name} list items need a required string id for stable editing.`)\n }\n\n fields = Object.entries(presentation.fields ?? {}).map(([key, field]) => {\n if (type === 'array' && key === 'id') throw new Error(`${filename}: list item ids are managed by Studio.`)\n const property = item.getProperty(key)\n const declaration = property?.valueDeclaration ?? property?.declarations?.[0]\n\n if (!property || !declaration) throw new Error(`${filename}: unknown field ${name}.${key}.`)\n\n return resolveProp(\n checker.getTypeOfSymbolAtLocation(property, declaration),\n key,\n !(property.flags & ts.SymbolFlags.Optional),\n field,\n checker,\n filename,\n undefined,\n depth + 1,\n )\n })\n\n for (const property of item.getProperties()) {\n if (type === 'array' && property.name === 'id') continue\n\n if (!(property.flags & ts.SymbolFlags.Optional) && !fields.some((field) => field.name === property.name))\n throw new Error(`${filename}: required field ${name}.${property.name} needs an authoring declaration.`)\n }\n } else throw new Error(`${filename}: unsupported editable prop ${name}.`)\n\n const inputs = {\n string: ['text', 'textarea', 'select', 'image', 'link'],\n number: ['number'],\n boolean: ['toggle'],\n object: ['object'],\n array: ['list'],\n }\n\n if (!inputs[type].includes(presentation.input) || (presentation.input === 'select' && !choices.length))\n throw new Error(`${filename}: ${name} has an incompatible authoring input ${presentation.input}.`)\n\n for (const key of Object.keys(presentation.optionLabels ?? {}))\n if (!choices.includes(key)) throw new Error(`${filename}: ${key} is not a Vue union choice.`)\n\n return Result.getOrThrow(\n Schema.decodeUnknownResult(BlockAuthoring.fields.props.value)({\n name,\n label: presentation.label,\n type,\n input: presentation.input,\n required,\n nullable,\n ...(presentation.help === undefined ? undefined : { help: presentation.help }),\n ...(fields === undefined ? undefined : { fields }),\n ...(defaultSource === undefined\n ? undefined\n : { defaultValue: readAuthoringDefault(defaultSource, `${filename} prop ${name}`) }),\n options: choices.map((value) => ({ value, label: presentation.optionLabels?.[value] ?? value })),\n }),\n )\n}\n\nfunction vueSlots(checker: ComponentMetaChecker, filename: string) {\n const program = checker.getProgram()\n const file = program?.getSourceFile(filename)\n\n if (!program || !file) throw new Error(`${filename}: Vue type information is unavailable.`)\n const typeChecker = program.getTypeChecker()\n const result = new Map<string, { required: boolean; scoped: boolean }>()\n\n function visit(node: ts.Node): void {\n if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === 'defineSlots') {\n const type = node.typeArguments?.[0]\n\n if (type)\n for (const property of typeChecker.getTypeAtLocation(type).getProperties()) {\n const declaration = property.valueDeclaration ?? property.declarations?.[0]\n\n const signature = declaration\n ? typeChecker\n .getNonNullableType(typeChecker.getTypeOfSymbolAtLocation(property, declaration))\n .getCallSignatures()\n : []\n\n result.set(property.name, {\n required: !(property.flags & ts.SymbolFlags.Optional),\n scoped: signature.length !== 1 || signature.some((signature) => signature.parameters.length > 0),\n })\n }\n }\n\n ts.forEachChild(node, visit)\n }\n\n visit(file)\n\n return result\n}\n"],"mappings":"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"}
@@ -13,7 +13,6 @@ var CmsConfigurationLoadFailed = class extends Schema.TaggedError()("CmsConfigur
13
13
  cause: Schema.Defect(),
14
14
  operation: Schema.String
15
15
  }) {};
16
- /** Loads the conventional executable CMS configuration without routing it through Nuxt options. */
17
16
  const loadCmsConfiguration = Effect.fn("CmsConfiguration.load")(function* (rootDir) {
18
17
  const fileSystem = yield* FileSystem.FileSystem;
19
18
  const paths = yield* Path.Path;
@@ -1 +1 @@
1
- {"version":3,"file":"cms-config.js","names":[],"sources":["../../../../src/internal/cms-config.ts"],"sourcesContent":["import type { CmsConfiguration } from '../Configuration'\nimport { Effect, FileSystem, Path, Schema } from 'effect'\nimport { createJiti } from 'jiti'\n\nconst CMS_CONFIG_NAMES = ['cms.config.ts', 'cms.config.mts', 'cms.config.js', 'cms.config.mjs']\nconst jiti = createJiti(import.meta.url)\n\nclass CmsConfigurationLoadFailed extends Schema.TaggedError<CmsConfigurationLoadFailed>()(\n 'CmsConfigurationLoadFailed',\n { cause: Schema.Defect(), operation: Schema.String },\n) {}\n\n/** Loads the conventional executable CMS configuration without routing it through Nuxt options. */\nexport const loadCmsConfiguration = Effect.fn('CmsConfiguration.load')(function* (rootDir: string) {\n const fileSystem = yield* FileSystem.FileSystem\n const paths = yield* Path.Path\n let configurationPath: string | undefined\n for (const name of CMS_CONFIG_NAMES) {\n const candidate = paths.join(rootDir, name)\n if (yield* fileSystem.exists(candidate)) {\n configurationPath = candidate\n break\n }\n }\n if (!configurationPath) {\n return yield* new CmsConfigurationLoadFailed({\n cause: new Error(`CMS configuration is missing. Create ${paths.join(rootDir, 'cms.config.ts')}.`),\n operation: 'CmsConfiguration.locate',\n })\n }\n const configuration = yield* Effect.tryPromise({\n try: () => jiti.import<CmsConfiguration>(configurationPath, { default: true }),\n catch: (cause) => new CmsConfigurationLoadFailed({ cause, operation: 'CmsConfiguration.import' }),\n })\n return { configuration, path: configurationPath }\n})\n"],"mappings":";;;;AAIA,MAAM,mBAAmB;CAAC;CAAiB;CAAkB;CAAiB;AAAgB;AAC9F,MAAM,OAAO,WAAW,YAAY,GAAG;AAEvC,IAAM,6BAAN,cAAyC,OAAO,YAAwC,CAAC,CACvF,8BACA;CAAE,OAAO,OAAO,OAAO;CAAG,WAAW,OAAO;AAAO,CACrD,CAAC,CAAC,CAAC;;AAGH,MAAa,uBAAuB,OAAO,GAAG,uBAAuB,CAAC,CAAC,WAAW,SAAiB;CACjG,MAAM,aAAa,OAAO,WAAW;CACrC,MAAM,QAAQ,OAAO,KAAK;CAC1B,IAAI;CACJ,KAAK,MAAM,QAAQ,kBAAkB;EACnC,MAAM,YAAY,MAAM,KAAK,SAAS,IAAI;EAC1C,IAAI,OAAO,WAAW,OAAO,SAAS,GAAG;GACvC,oBAAoB;GACpB;EACF;CACF;CACA,IAAI,CAAC,mBACH,OAAO,OAAO,IAAI,2BAA2B;EAC3C,uBAAO,IAAI,MAAM,wCAAwC,MAAM,KAAK,SAAS,eAAe,EAAE,EAAE;EAChG,WAAW;CACb,CAAC;CAMH,OAAO;EAAE,sBAJoB,OAAO,WAAW;GAC7C,WAAW,KAAK,OAAyB,mBAAmB,EAAE,SAAS,KAAK,CAAC;GAC7E,QAAQ,UAAU,IAAI,2BAA2B;IAAE;IAAO,WAAW;GAA0B,CAAC;EAClG,CAAC;EACuB,MAAM;CAAkB;AAClD,CAAC"}
1
+ {"version":3,"file":"cms-config.js","names":[],"sources":["../../../../src/internal/cms-config.ts"],"sourcesContent":["import type { CmsConfiguration } from '../Configuration'\nimport { Effect, FileSystem, Path, Schema } from 'effect'\nimport { createJiti } from 'jiti'\n\nconst CMS_CONFIG_NAMES = ['cms.config.ts', 'cms.config.mts', 'cms.config.js', 'cms.config.mjs']\n\nconst jiti = createJiti(import.meta.url)\n\nclass CmsConfigurationLoadFailed extends Schema.TaggedError<CmsConfigurationLoadFailed>()(\n 'CmsConfigurationLoadFailed',\n { cause: Schema.Defect(), operation: Schema.String },\n) {}\n\nexport const loadCmsConfiguration = Effect.fn('CmsConfiguration.load')(function* (rootDir: string) {\n const fileSystem = yield* FileSystem.FileSystem\n const paths = yield* Path.Path\n let configurationPath: string | undefined\n\n for (const name of CMS_CONFIG_NAMES) {\n const candidate = paths.join(rootDir, name)\n\n if (yield* fileSystem.exists(candidate)) {\n configurationPath = candidate\n break\n }\n }\n\n if (!configurationPath) {\n return yield* new CmsConfigurationLoadFailed({\n cause: new Error(`CMS configuration is missing. Create ${paths.join(rootDir, 'cms.config.ts')}.`),\n operation: 'CmsConfiguration.locate',\n })\n }\n\n const configuration = yield* Effect.tryPromise({\n try: () => jiti.import<CmsConfiguration>(configurationPath, { default: true }),\n catch: (cause) => new CmsConfigurationLoadFailed({ cause, operation: 'CmsConfiguration.import' }),\n })\n\n return { configuration, path: configurationPath }\n})\n"],"mappings":";;;;AAIA,MAAM,mBAAmB;CAAC;CAAiB;CAAkB;CAAiB;AAAgB;AAE9F,MAAM,OAAO,WAAW,YAAY,GAAG;AAEvC,IAAM,6BAAN,cAAyC,OAAO,YAAwC,CAAC,CACvF,8BACA;CAAE,OAAO,OAAO,OAAO;CAAG,WAAW,OAAO;AAAO,CACrD,CAAC,CAAC,CAAC;AAEH,MAAa,uBAAuB,OAAO,GAAG,uBAAuB,CAAC,CAAC,WAAW,SAAiB;CACjG,MAAM,aAAa,OAAO,WAAW;CACrC,MAAM,QAAQ,OAAO,KAAK;CAC1B,IAAI;CAEJ,KAAK,MAAM,QAAQ,kBAAkB;EACnC,MAAM,YAAY,MAAM,KAAK,SAAS,IAAI;EAE1C,IAAI,OAAO,WAAW,OAAO,SAAS,GAAG;GACvC,oBAAoB;GACpB;EACF;CACF;CAEA,IAAI,CAAC,mBACH,OAAO,OAAO,IAAI,2BAA2B;EAC3C,uBAAO,IAAI,MAAM,wCAAwC,MAAM,KAAK,SAAS,eAAe,EAAE,EAAE;EAChG,WAAW;CACb,CAAC;CAQH,OAAO;EAAE,sBALoB,OAAO,WAAW;GAC7C,WAAW,KAAK,OAAyB,mBAAmB,EAAE,SAAS,KAAK,CAAC;GAC7E,QAAQ,UAAU,IAAI,2BAA2B;IAAE;IAAO,WAAW;GAA0B,CAAC;EAClG,CAAC;EAEuB,MAAM;CAAkB;AAClD,CAAC"}
@@ -1,8 +1,10 @@
1
- import { u as DocumentImportSource } from "../models-BkMgeaOL.js";
2
- import { a as StudioBootstrap } from "../StudioHttp-jR2-bc01.js";
3
- import { i as PreviewOrigin } from "../models-C3witQBK.js";
1
+ import { validateFormCapabilities } from "./form-capabilities.js";
2
+ import { R as SeoConfiguration } from "../models-Bah5B3bT.js";
3
+ import { j as StudioBootstrap, t as maxS3SingleCopyBytes, u as makeDefaultSeoOptions } from "../S3MediaObjects-CpPSzJto.js";
4
+ import { compileCmsI18n } from "./i18n.js";
5
+ import { i as PreviewOrigin } from "../models-B4IoTmp7.js";
4
6
  import { compileCmsDocumentModel } from "./document-model.js";
5
- import { Result, Schema } from "effect";
7
+ import { Predicate, Result, Schema } from "effect";
6
8
 
7
9
  //#region src/internal/configuration.ts
8
10
  const DEFAULT_CLEANUP_INTERVAL_MILLIS = 864e5;
@@ -18,7 +20,10 @@ const InstallationConfiguration = Schema.Struct({
18
20
  databaseUrl: Schema.NonEmptyString,
19
21
  initializationToken: Schema.NonEmptyString.check(Schema.isMinLength(32)),
20
22
  media: Schema.optionalKey(Schema.Union([Schema.Literals([false]), Schema.Struct({
21
- maxUploadBytes: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThan(0))),
23
+ maxUploadBytes: Schema.optionalKey(Schema.Int.check(Schema.isBetween({
24
+ minimum: 1,
25
+ maximum: maxS3SingleCopyBytes
26
+ }))),
22
27
  publicBaseUrl: Schema.NonEmptyString,
23
28
  storage: Schema.Struct({
24
29
  bucket: Schema.NonEmptyString,
@@ -33,38 +38,43 @@ const InstallationConfiguration = Schema.Struct({
33
38
  region: Schema.NonEmptyString
34
39
  })
35
40
  })])),
41
+ seo: Schema.optionalKey(SeoConfiguration),
36
42
  secret: Schema.NonEmptyString.check(Schema.isMinLength(32))
37
43
  });
38
- /** Compiles every authored, executable concern once through the owning document interface. */
39
- function compileCmsConfiguration(configuration, initialSources = []) {
44
+ function compileCmsConfiguration(configuration) {
40
45
  const decodedConfiguration = Schema.decodeResult(InstallationConfiguration)(configuration);
41
46
  if (Result.isFailure(decodedConfiguration)) throw new Error(`Invalid CMS configuration: ${String(decodedConfiguration.failure)}`);
42
- const documents = compileCmsDocumentModel(configuration.documents);
43
- const decodedSources = Schema.decodeResult(Schema.Array(DocumentImportSource))(initialSources);
44
- if (Result.isFailure(decodedSources)) throw new Error(`Invalid CMS initial sources: ${String(decodedSources.failure)}`);
47
+ for (const [name, form] of Object.entries(configuration.forms ?? {})) {
48
+ if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u.test(name)) throw new Error(`Form ${name} needs a kebab-case Vue component name.`);
49
+ validateFormCapabilities(form.definition);
50
+ if (!Predicate.isFunction(form.onSubmit)) throw new Error(`Form ${name} needs a server submission handler.`);
51
+ }
52
+ const i18n = compileCmsI18n(configuration.i18n);
53
+ const documents = compileCmsDocumentModel(configuration.documents, configuration.i18n);
45
54
  return {
55
+ i18n,
46
56
  documentModel: documents.executable,
47
57
  documents: documents.authoring,
48
- initialSources: decodedSources.success,
49
58
  installation: decodedConfiguration.success
50
59
  };
51
60
  }
52
- /** Produces the single input consumed by the Node installation from the authored CMS configuration. */
53
- function resolveCmsInstallation(authored, authoring, initialSources = []) {
54
- const compiled = compileCmsConfiguration(authored, initialSources);
61
+ function resolveCmsInstallation(authored, authoring) {
62
+ const compiled = compileCmsConfiguration(authored);
55
63
  const configuration = compiled.installation;
56
64
  const cleanup = configuration.cleanup === false ? void 0 : configuration.cleanup;
57
65
  const media = configuration.media === false ? void 0 : configuration.media;
58
- const bootstrap = Schema.decodeSync(StudioBootstrap)({
66
+ const bootstrap = Result.getOrThrow(Schema.decodeResult(StudioBootstrap)({
59
67
  basePath: "/",
60
68
  documents: compiled.documents,
61
69
  media: {
62
70
  enabled: media !== void 0,
63
71
  maxUploadBytes: media?.maxUploadBytes ?? DEFAULT_MEDIA_MAX_UPLOAD_BYTES
64
72
  },
73
+ seo: configuration.seo ?? makeDefaultSeoOptions(configuration.baseUrl),
65
74
  version: "1"
66
- });
75
+ }));
67
76
  return {
77
+ formHandlers: Object.fromEntries(Object.entries(authored.forms ?? {}).map(([name, form]) => [name, form.onSubmit])),
68
78
  authoring,
69
79
  baseUrl: configuration.baseUrl,
70
80
  bootstrap,
@@ -75,7 +85,6 @@ function resolveCmsInstallation(authored, authoring, initialSources = []) {
75
85
  },
76
86
  databaseUrl: configuration.databaseUrl,
77
87
  documentModel: compiled.documentModel,
78
- initialSources: compiled.initialSources,
79
88
  initializationToken: configuration.initializationToken,
80
89
  ...media === void 0 ? void 0 : { media: {
81
90
  publicBaseUrl: media.publicBaseUrl,
@@ -1 +1 @@
1
- {"version":3,"file":"configuration.js","names":["PreviewOriginSchema","DocumentImportSourceSchema"],"sources":["../../../../src/internal/configuration.ts"],"sourcesContent":["import type { ExecutableDocumentModel } from '@internal/document/DocumentEngine'\nimport type { AuthoringCatalog, DocumentConfiguration } from '@internal/protocol/Configuration'\nimport type { DocumentImportSource } from '@internal/protocol/Documents'\nimport type { CmsConfiguration, CmsInitialDocument } from '../Configuration'\nimport type { NuxtCmsInstallationOptions } from '../runtime/installation'\nimport { DocumentImportSource as DocumentImportSourceSchema } from '@internal/protocol/Documents'\nimport { PreviewOrigin as PreviewOriginSchema } from '@internal/protocol/Preview'\nimport { StudioBootstrap } from '@internal/protocol/StudioHttp'\nimport { Result, Schema } from 'effect'\nimport { compileCmsDocumentModel } from './document-model'\n\nconst DEFAULT_CLEANUP_INTERVAL_MILLIS = 24 * 60 * 60_000\nconst DEFAULT_CLEANUP_INITIAL_DELAY_MILLIS = 60_000\nconst DEFAULT_MEDIA_MAX_UPLOAD_BYTES = 10_000_000\n\nconst optionalString = Schema.optionalKey(Schema.NonEmptyString)\nconst InstallationConfiguration = Schema.Struct({\n baseUrl: PreviewOriginSchema,\n cleanup: Schema.optionalKey(\n Schema.Union([\n Schema.Literals([false]),\n Schema.Struct({\n initialDelayMillis: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),\n intervalMillis: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThan(0))),\n }),\n ]),\n ),\n databaseUrl: Schema.NonEmptyString,\n initializationToken: Schema.NonEmptyString.check(Schema.isMinLength(32)),\n media: Schema.optionalKey(\n Schema.Union([\n Schema.Literals([false]),\n Schema.Struct({\n maxUploadBytes: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThan(0))),\n publicBaseUrl: Schema.NonEmptyString,\n storage: Schema.Struct({\n bucket: Schema.NonEmptyString,\n credentials: Schema.optionalKey(\n Schema.Struct({\n accessKeyId: Schema.NonEmptyString,\n secretAccessKey: Schema.NonEmptyString,\n sessionToken: optionalString,\n }),\n ),\n endpoint: optionalString,\n forcePathStyle: Schema.optionalKey(Schema.Boolean),\n provisionBucket: Schema.optionalKey(Schema.Boolean),\n region: Schema.NonEmptyString,\n }),\n }),\n ]),\n ),\n secret: Schema.NonEmptyString.check(Schema.isMinLength(32)),\n})\ntype CmsInstallationConfiguration = Schema.Schema.Type<typeof InstallationConfiguration>\n\nexport interface CompiledCmsConfiguration {\n readonly documents: DocumentConfiguration\n readonly documentModel: ExecutableDocumentModel\n readonly initialSources: ReadonlyArray<DocumentImportSource>\n readonly installation: CmsInstallationConfiguration\n}\n\n/** Compiles every authored, executable concern once through the owning document interface. */\nexport function compileCmsConfiguration(\n configuration: CmsConfiguration,\n initialSources: ReadonlyArray<CmsInitialDocument> = [],\n): CompiledCmsConfiguration {\n const decodedConfiguration = Schema.decodeResult(InstallationConfiguration)(configuration)\n if (Result.isFailure(decodedConfiguration)) {\n throw new Error(`Invalid CMS configuration: ${String(decodedConfiguration.failure)}`)\n }\n const documents = compileCmsDocumentModel(configuration.documents)\n const decodedSources = Schema.decodeResult(Schema.Array(DocumentImportSourceSchema))(initialSources)\n if (Result.isFailure(decodedSources)) {\n throw new Error(`Invalid CMS initial sources: ${String(decodedSources.failure)}`)\n }\n return {\n documentModel: documents.executable,\n documents: documents.authoring,\n initialSources: decodedSources.success,\n installation: decodedConfiguration.success,\n }\n}\n\n/** Produces the single input consumed by the Node installation from the authored CMS configuration. */\nexport function resolveCmsInstallation(\n authored: CmsConfiguration,\n authoring: AuthoringCatalog,\n initialSources: ReadonlyArray<CmsInitialDocument> = [],\n): NuxtCmsInstallationOptions {\n const compiled = compileCmsConfiguration(authored, initialSources)\n const configuration = compiled.installation\n const cleanup = configuration.cleanup === false ? undefined : configuration.cleanup\n const media = configuration.media === false ? undefined : configuration.media\n const bootstrap = Schema.decodeSync(StudioBootstrap)({\n basePath: '/',\n documents: compiled.documents,\n media: {\n enabled: media !== undefined,\n maxUploadBytes: media?.maxUploadBytes ?? DEFAULT_MEDIA_MAX_UPLOAD_BYTES,\n },\n version: '1',\n })\n\n return {\n authoring,\n baseUrl: configuration.baseUrl,\n bootstrap,\n cleanup: {\n enabled: configuration.cleanup !== false,\n initialDelayMillis: cleanup?.initialDelayMillis ?? DEFAULT_CLEANUP_INITIAL_DELAY_MILLIS,\n intervalMillis: cleanup?.intervalMillis ?? DEFAULT_CLEANUP_INTERVAL_MILLIS,\n },\n databaseUrl: configuration.databaseUrl,\n documentModel: compiled.documentModel,\n initialSources: compiled.initialSources,\n initializationToken: configuration.initializationToken,\n ...(media === undefined\n ? undefined\n : {\n media: {\n publicBaseUrl: media.publicBaseUrl,\n ...media.storage,\n forcePathStyle: media.storage.forcePathStyle ?? false,\n provisionBucket: media.storage.provisionBucket ?? false,\n },\n }),\n secret: configuration.secret,\n }\n}\n"],"mappings":";;;;;;;AAWA,MAAM,kCAAkC;AACxC,MAAM,uCAAuC;AAC7C,MAAM,iCAAiC;AAEvC,MAAM,iBAAiB,OAAO,YAAY,OAAO,cAAc;AAC/D,MAAM,4BAA4B,OAAO,OAAO;CAC9C,SAASA;CACT,SAAS,OAAO,YACd,OAAO,MAAM,CACX,OAAO,SAAS,CAAC,KAAK,CAAC,GACvB,OAAO,OAAO;EACZ,oBAAoB,OAAO,YAAY,OAAO,IAAI,MAAM,OAAO,uBAAuB,CAAC,CAAC,CAAC;EACzF,gBAAgB,OAAO,YAAY,OAAO,IAAI,MAAM,OAAO,cAAc,CAAC,CAAC,CAAC;CAC9E,CAAC,CACH,CAAC,CACH;CACA,aAAa,OAAO;CACpB,qBAAqB,OAAO,eAAe,MAAM,OAAO,YAAY,EAAE,CAAC;CACvE,OAAO,OAAO,YACZ,OAAO,MAAM,CACX,OAAO,SAAS,CAAC,KAAK,CAAC,GACvB,OAAO,OAAO;EACZ,gBAAgB,OAAO,YAAY,OAAO,IAAI,MAAM,OAAO,cAAc,CAAC,CAAC,CAAC;EAC5E,eAAe,OAAO;EACtB,SAAS,OAAO,OAAO;GACrB,QAAQ,OAAO;GACf,aAAa,OAAO,YAClB,OAAO,OAAO;IACZ,aAAa,OAAO;IACpB,iBAAiB,OAAO;IACxB,cAAc;GAChB,CAAC,CACH;GACA,UAAU;GACV,gBAAgB,OAAO,YAAY,OAAO,OAAO;GACjD,iBAAiB,OAAO,YAAY,OAAO,OAAO;GAClD,QAAQ,OAAO;EACjB,CAAC;CACH,CAAC,CACH,CAAC,CACH;CACA,QAAQ,OAAO,eAAe,MAAM,OAAO,YAAY,EAAE,CAAC;AAC5D,CAAC;;AAWD,SAAgB,wBACd,eACA,iBAAoD,CAAC,GAC3B;CAC1B,MAAM,uBAAuB,OAAO,aAAa,yBAAyB,CAAC,CAAC,aAAa;CACzF,IAAI,OAAO,UAAU,oBAAoB,GACvC,MAAM,IAAI,MAAM,8BAA8B,OAAO,qBAAqB,OAAO,GAAG;CAEtF,MAAM,YAAY,wBAAwB,cAAc,SAAS;CACjE,MAAM,iBAAiB,OAAO,aAAa,OAAO,MAAMC,oBAA0B,CAAC,CAAC,CAAC,cAAc;CACnG,IAAI,OAAO,UAAU,cAAc,GACjC,MAAM,IAAI,MAAM,gCAAgC,OAAO,eAAe,OAAO,GAAG;CAElF,OAAO;EACL,eAAe,UAAU;EACzB,WAAW,UAAU;EACrB,gBAAgB,eAAe;EAC/B,cAAc,qBAAqB;CACrC;AACF;;AAGA,SAAgB,uBACd,UACA,WACA,iBAAoD,CAAC,GACzB;CAC5B,MAAM,WAAW,wBAAwB,UAAU,cAAc;CACjE,MAAM,gBAAgB,SAAS;CAC/B,MAAM,UAAU,cAAc,YAAY,QAAQ,SAAY,cAAc;CAC5E,MAAM,QAAQ,cAAc,UAAU,QAAQ,SAAY,cAAc;CACxE,MAAM,YAAY,OAAO,WAAW,eAAe,CAAC,CAAC;EACnD,UAAU;EACV,WAAW,SAAS;EACpB,OAAO;GACL,SAAS,UAAU;GACnB,gBAAgB,OAAO,kBAAkB;EAC3C;EACA,SAAS;CACX,CAAC;CAED,OAAO;EACL;EACA,SAAS,cAAc;EACvB;EACA,SAAS;GACP,SAAS,cAAc,YAAY;GACnC,oBAAoB,SAAS,sBAAsB;GACnD,gBAAgB,SAAS,kBAAkB;EAC7C;EACA,aAAa,cAAc;EAC3B,eAAe,SAAS;EACxB,gBAAgB,SAAS;EACzB,qBAAqB,cAAc;EACnC,GAAI,UAAU,SACV,SACA,EACE,OAAO;GACL,eAAe,MAAM;GACrB,GAAG,MAAM;GACT,gBAAgB,MAAM,QAAQ,kBAAkB;GAChD,iBAAiB,MAAM,QAAQ,mBAAmB;EACpD,EACF;EACJ,QAAQ,cAAc;CACxB;AACF"}
1
+ {"version":3,"file":"configuration.js","names":["PreviewOriginSchema"],"sources":["../../../../src/internal/configuration.ts"],"sourcesContent":["import { compileCmsI18n, type CompiledCmsI18n } from './i18n'\nimport type { ExecutableDocumentModel } from '@internal/document/DocumentEngine'\nimport type { AuthoringCatalog, DocumentConfiguration } from '@internal/protocol/Configuration'\nimport type { CmsConfiguration } from '../Configuration'\nimport type { NuxtCmsInstallationOptions } from '../runtime/installation'\nimport { PreviewOrigin as PreviewOriginSchema } from '@internal/protocol/Preview'\nimport { StudioBootstrap } from '@internal/protocol/StudioHttp'\nimport { SeoConfiguration } from '@internal/protocol/Seo'\nimport { makeDefaultSeoOptions } from '@internal/server/Seo'\nimport { maxS3SingleCopyBytes } from '@internal/s3/S3MediaObjects'\nimport { Predicate, Result, Schema } from 'effect'\nimport { compileCmsDocumentModel } from './document-model'\nimport { validateFormCapabilities } from './form-capabilities'\n\nconst DEFAULT_CLEANUP_INTERVAL_MILLIS = 24 * 60 * 60_000\n\nconst DEFAULT_CLEANUP_INITIAL_DELAY_MILLIS = 60_000\n\nconst DEFAULT_MEDIA_MAX_UPLOAD_BYTES = 10_000_000\n\nconst optionalString = Schema.optionalKey(Schema.NonEmptyString)\n\nconst InstallationConfiguration = Schema.Struct({\n baseUrl: PreviewOriginSchema,\n cleanup: Schema.optionalKey(\n Schema.Union([\n Schema.Literals([false]),\n Schema.Struct({\n initialDelayMillis: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),\n intervalMillis: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThan(0))),\n }),\n ]),\n ),\n databaseUrl: Schema.NonEmptyString,\n initializationToken: Schema.NonEmptyString.check(Schema.isMinLength(32)),\n media: Schema.optionalKey(\n Schema.Union([\n Schema.Literals([false]),\n Schema.Struct({\n maxUploadBytes: Schema.optionalKey(\n Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: maxS3SingleCopyBytes })),\n ),\n publicBaseUrl: Schema.NonEmptyString,\n storage: Schema.Struct({\n bucket: Schema.NonEmptyString,\n credentials: Schema.optionalKey(\n Schema.Struct({\n accessKeyId: Schema.NonEmptyString,\n secretAccessKey: Schema.NonEmptyString,\n sessionToken: optionalString,\n }),\n ),\n endpoint: optionalString,\n forcePathStyle: Schema.optionalKey(Schema.Boolean),\n provisionBucket: Schema.optionalKey(Schema.Boolean),\n region: Schema.NonEmptyString,\n }),\n }),\n ]),\n ),\n seo: Schema.optionalKey(SeoConfiguration),\n secret: Schema.NonEmptyString.check(Schema.isMinLength(32)),\n})\n\ntype CmsInstallationConfiguration = Schema.Schema.Type<typeof InstallationConfiguration>\n\nexport interface CompiledCmsConfiguration {\n readonly i18n: CompiledCmsI18n\n readonly documents: DocumentConfiguration\n readonly documentModel: ExecutableDocumentModel\n readonly installation: CmsInstallationConfiguration\n}\n\nexport function compileCmsConfiguration(configuration: CmsConfiguration): CompiledCmsConfiguration {\n const decodedConfiguration = Schema.decodeResult(InstallationConfiguration)(configuration)\n\n if (Result.isFailure(decodedConfiguration)) {\n throw new Error(`Invalid CMS configuration: ${String(decodedConfiguration.failure)}`)\n }\n\n for (const [name, form] of Object.entries(configuration.forms ?? {})) {\n if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u.test(name))\n throw new Error(`Form ${name} needs a kebab-case Vue component name.`)\n validateFormCapabilities(form.definition)\n\n if (!Predicate.isFunction(form.onSubmit)) throw new Error(`Form ${name} needs a server submission handler.`)\n }\n\n const i18n = compileCmsI18n(configuration.i18n)\n const documents = compileCmsDocumentModel(configuration.documents, configuration.i18n)\n\n return {\n i18n,\n documentModel: documents.executable,\n documents: documents.authoring,\n installation: decodedConfiguration.success,\n }\n}\n\nexport function resolveCmsInstallation(\n authored: CmsConfiguration,\n authoring: AuthoringCatalog,\n): NuxtCmsInstallationOptions {\n const compiled = compileCmsConfiguration(authored)\n const configuration = compiled.installation\n const cleanup = configuration.cleanup === false ? undefined : configuration.cleanup\n const media = configuration.media === false ? undefined : configuration.media\n\n const bootstrap = Result.getOrThrow(\n Schema.decodeResult(StudioBootstrap)({\n basePath: '/',\n documents: compiled.documents,\n media: {\n enabled: media !== undefined,\n maxUploadBytes: media?.maxUploadBytes ?? DEFAULT_MEDIA_MAX_UPLOAD_BYTES,\n },\n seo: configuration.seo ?? makeDefaultSeoOptions(configuration.baseUrl),\n version: '1',\n }),\n )\n\n return {\n formHandlers: Object.fromEntries(Object.entries(authored.forms ?? {}).map(([name, form]) => [name, form.onSubmit])),\n authoring,\n baseUrl: configuration.baseUrl,\n bootstrap,\n cleanup: {\n enabled: configuration.cleanup !== false,\n initialDelayMillis: cleanup?.initialDelayMillis ?? DEFAULT_CLEANUP_INITIAL_DELAY_MILLIS,\n intervalMillis: cleanup?.intervalMillis ?? DEFAULT_CLEANUP_INTERVAL_MILLIS,\n },\n databaseUrl: configuration.databaseUrl,\n documentModel: compiled.documentModel,\n initializationToken: configuration.initializationToken,\n ...(media === undefined\n ? undefined\n : {\n media: {\n publicBaseUrl: media.publicBaseUrl,\n ...media.storage,\n forcePathStyle: media.storage.forcePathStyle ?? false,\n provisionBucket: media.storage.provisionBucket ?? false,\n },\n }),\n secret: configuration.secret,\n }\n}\n"],"mappings":"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"}
@@ -1,8 +1,7 @@
1
1
  import { FIELD_INPUT_METADATA } from "./field-metadata.js";
2
- import { t as createDocumentEngine } from "../DocumentEngine-DYObwMDY.js";
3
- import { r as DocumentConfiguration } from "../Configuration-DyKo0sLS.js";
4
- import { Effect, Result, Schema } from "effect";
5
- import { z } from "zod";
2
+ import { r as DocumentConfiguration } from "../Configuration-CDMYfTre.js";
3
+ import { t as createDocumentEngine } from "../DocumentEngine-J7g-emdf.js";
4
+ import { Effect, Predicate, Result, Schema } from "effect";
6
5
 
7
6
  //#region src/internal/document-model.ts
8
7
  const isJsonObject = Schema.is(Schema.JsonObject);
@@ -11,16 +10,15 @@ var CmsDocumentModelInvalid = class extends Schema.TaggedError()("Cms.DocumentMo
11
10
  path: Schema.NonEmptyString
12
11
  }) {};
13
12
  const isCmsDocumentModelInvalid = Schema.is(CmsDocumentModelInvalid);
14
- /** Compiles authored Zod schemas into the portable and server-only halves of the CMS document model. */
15
- function compileCmsDocumentModel(documents) {
13
+ function compileCmsDocumentModel(documents, i18n) {
16
14
  try {
17
15
  const compiled = Object.entries(documents.collections).map(([collection, options]) => compileCollection(collection, options));
18
16
  const decoded = Schema.decodeResult(DocumentConfiguration)({
19
- ...documents.locales === void 0 ? void 0 : { locales: {
20
- ...documents.locales,
21
- fallbackLocale: documents.locales.fallbackLocale ?? null,
22
- locales: [...documents.locales.locales],
23
- prefixDefaultLocale: documents.locales.prefixDefaultLocale ?? false
17
+ ...i18n === void 0 ? void 0 : { locales: {
18
+ defaultLocale: i18n.defaultLocale,
19
+ fallbackLocale: i18n.fallbackLocale ?? null,
20
+ locales: Object.keys(i18n.locales),
21
+ prefixDefaultLocale: i18n.prefixDefaultLocale ?? false
24
22
  } },
25
23
  types: compiled.map((entry) => entry.authoring)
26
24
  });
@@ -40,21 +38,28 @@ function compileCollection(collection, options) {
40
38
  const path = `documents.collections.${collection}`;
41
39
  let generated;
42
40
  try {
43
- generated = z.toJSONSchema(options.schema, {
44
- cycles: "throw",
45
- io: "input",
46
- reused: "inline",
47
- target: "draft-2020-12",
48
- unrepresentable: "throw"
49
- });
41
+ if (isEffectCollectionSchema(options.schema)) {
42
+ const document = Schema.toJsonSchemaDocument(options.schema, {
43
+ includeAnnotationKey: (key) => key === FIELD_INPUT_METADATA,
44
+ referencePolicy: () => void 0
45
+ });
46
+ generated = {
47
+ ...document.schema,
48
+ $defs: document.definitions
49
+ };
50
+ } else {
51
+ if (!Predicate.isFunction(options.schema["~standard"]?.jsonSchema?.input)) throw new Error("Studio needs Standard JSON Schema V1 input conversion (or an adapter that supplies it).");
52
+ generated = options.schema["~standard"].jsonSchema.input({ target: "draft-2020-12" });
53
+ }
50
54
  } catch (cause) {
51
55
  throw invalid(`${path}.schema`, cause instanceof Error ? cause.message : String(cause));
52
56
  }
53
57
  const decoded = Schema.decodeUnknownResult(Schema.JsonObject)(generated);
54
58
  if (Result.isFailure(decoded)) throw invalid(`${path}.schema`, "The generated input structure is not serializable.");
55
- const input = decoded.success;
56
- if (input.type !== "object") throw invalid(`${path}.schema`, "A collection schema must be a Zod object.");
59
+ const input = resolveInputStructure(decoded.success, `${path}.schema`);
60
+ if (input.type !== "object") throw invalid(`${path}.schema`, "A collection schema must describe an object input.");
57
61
  const projection = compileProjection(input, `${path}.schema`);
62
+ const validator = isEffectCollectionSchema(options.schema) ? Schema.toStandardSchemaV1(options.schema) : options.schema;
58
63
  return {
59
64
  authoring: {
60
65
  addressPattern: options.route,
@@ -69,7 +74,7 @@ function compileCollection(collection, options) {
69
74
  },
70
75
  executable: {
71
76
  project: projection,
72
- validate: (value) => Effect.tryPromise(() => Promise.resolve(options.schema["~standard"].validate(value)))
77
+ validate: (value) => Effect.tryPromise(() => Promise.resolve(validator["~standard"].validate(value)))
73
78
  }
74
79
  };
75
80
  }
@@ -231,6 +236,49 @@ function invalid(path, message) {
231
236
  path
232
237
  });
233
238
  }
239
+ /** Resolve local input references while rejecting recursive or ambiguous editor structures. */
240
+ function resolveInputStructure(root, path) {
241
+ function visit(node, currentPath, ancestors) {
242
+ if (node.$ref !== void 0) {
243
+ const decodedRef = Schema.decodeUnknownResult(Schema.String)(node.$ref);
244
+ if (Result.isFailure(decodedRef)) throw invalid(currentPath, "Expected a string schema reference.");
245
+ const ref = decodedRef.success;
246
+ if (!ref.startsWith("#/") || ancestors.has(ref)) throw invalid(currentPath, "Studio requires non-recursive local schema references.");
247
+ let target = root;
248
+ for (const segment of ref.slice(2).split("/")) target = isJsonObject(target) ? target[segment.replace(/~1/gu, "/").replace(/~0/gu, "~")] : void 0;
249
+ const { $ref: _, ...siblings } = node;
250
+ return visit(Object.assign({}, requireObject(target, currentPath), siblings), currentPath, /* @__PURE__ */ new Set([...ancestors, ref]));
251
+ }
252
+ if (node.anyOf !== void 0 || node.oneOf !== void 0) throw invalid(currentPath, "Studio requires a single supported input type per field.");
253
+ const out = Object.fromEntries(Object.entries(node));
254
+ if (node.allOf !== void 0) {
255
+ if (!Array.isArray(node.allOf)) throw invalid(currentPath, "Expected an array of schema constraints.");
256
+ for (const constraint of node.allOf) {
257
+ const part = visit(requireObject(constraint, currentPath), currentPath, ancestors);
258
+ if (part.properties !== void 0 || part.items !== void 0 || part.type !== void 0 && part.type !== node.type) throw invalid(currentPath, "Studio cannot combine structural schema intersections.");
259
+ for (const key of [
260
+ "title",
261
+ "description",
262
+ "default",
263
+ "format",
264
+ "enum",
265
+ FIELD_INPUT_METADATA
266
+ ]) {
267
+ if (part[key] === void 0) continue;
268
+ if (out[key] !== void 0 && JSON.stringify(out[key]) !== JSON.stringify(part[key])) throw invalid(currentPath, `Conflicting field metadata "${key}" in schema intersection.`);
269
+ out[key] = part[key];
270
+ }
271
+ }
272
+ }
273
+ if (node.properties !== void 0) out.properties = Object.fromEntries(Object.entries(requireObject(node.properties, currentPath)).map(([name, value]) => [name, visit(requireObject(value, `${currentPath}.${name}`), `${currentPath}.${name}`, ancestors)]));
274
+ if (node.items !== void 0) out.items = visit(requireObject(node.items, `${currentPath}[]`), `${currentPath}[]`, ancestors);
275
+ return out;
276
+ }
277
+ return visit(root, path, /* @__PURE__ */ new Set());
278
+ }
279
+ function isEffectCollectionSchema(schema) {
280
+ return Schema.isSchema(schema);
281
+ }
234
282
 
235
283
  //#endregion
236
284
  export { CmsDocumentModelInvalid, compileCmsDocumentModel };