@phtngyn/cms 0.1.0-beta.4 → 0.2.0-beta.1

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 (93) hide show
  1. package/README.md +85 -5
  2. package/package.json +12 -1
  3. package/src/ApplicationTypes.d.ts +82 -0
  4. package/src/ApplicationTypes.js +1 -0
  5. package/src/{Configuration-CDMYfTre.js → Configuration-CjVUBBwa.js} +3 -3
  6. package/src/{Configuration-CDMYfTre.js.map → Configuration-CjVUBBwa.js.map} +1 -1
  7. package/src/Configuration.d.ts +9 -4
  8. package/src/Configuration.js.map +1 -1
  9. package/src/Content.d.ts +67 -0
  10. package/src/Content.js +291 -0
  11. package/src/Content.js.map +1 -0
  12. package/src/ContentTransfer-CRQet3QJ.d.ts +48 -0
  13. package/src/{ContentTransfer-C3Av9sWz.js → ContentTransfer-CTzGGKFV.js} +8 -4
  14. package/src/ContentTransfer-CTzGGKFV.js.map +1 -0
  15. package/src/{DocumentEngine-J7g-emdf.js → DocumentEngine-BbhfnTAc.js} +4 -4
  16. package/src/{DocumentEngine-J7g-emdf.js.map → DocumentEngine-BbhfnTAc.js.map} +1 -1
  17. package/src/DocumentModel.d.ts +8 -1
  18. package/src/DocumentModel.js +29 -2
  19. package/src/DocumentModel.js.map +1 -1
  20. package/src/{Forms-Dj6NuW66.js → Forms-02-p8qEw.js} +2 -2
  21. package/src/{Forms-Dj6NuW66.js.map → Forms-02-p8qEw.js.map} +1 -1
  22. package/src/{Forms-BsJMev5_.d.ts → Forms-BorTcIlp.d.ts} +2 -5
  23. package/src/Forms.d.ts +25 -14
  24. package/src/Forms.js.map +1 -1
  25. package/src/I18n-BXlVunfa.d.ts +27 -0
  26. package/src/I18n.d.ts +2 -20
  27. package/src/Module.js +14 -5
  28. package/src/Module.js.map +1 -1
  29. package/src/{S3MediaObjects-CpPSzJto.js → S3MediaObjects-DC0c8sYC.js} +54 -35
  30. package/src/{S3MediaObjects-CpPSzJto.js.map → S3MediaObjects-DC0c8sYC.js.map} +1 -1
  31. package/src/cli/content.js +63 -221
  32. package/src/cli/content.js.map +1 -1
  33. package/src/cli.js +93 -4
  34. package/src/cli.js.map +1 -1
  35. package/src/{connection-CBAy2qGy.js → connection-BPf4BQUZ.js} +2 -2
  36. package/src/{connection-CBAy2qGy.js.map → connection-BPf4BQUZ.js.map} +1 -1
  37. package/src/dev-lifecycle-vQLxwCFq.js +428 -0
  38. package/src/dev-lifecycle-vQLxwCFq.js.map +1 -0
  39. package/src/{installation-CNfIriVm.js → installation-DsGst1BH.js} +578 -457
  40. package/src/installation-DsGst1BH.js.map +1 -0
  41. package/src/internal/application-types.js +43 -0
  42. package/src/internal/application-types.js.map +1 -0
  43. package/src/internal/authoring-catalog.js +9 -4
  44. package/src/internal/authoring-catalog.js.map +1 -1
  45. package/src/internal/authoring-metadata.js +1 -1
  46. package/src/internal/configuration.js +10 -6
  47. package/src/internal/configuration.js.map +1 -1
  48. package/src/internal/dev-lifecycle.js +3 -0
  49. package/src/internal/document-model.js +2 -2
  50. package/src/internal/document-model.js.map +1 -1
  51. package/src/internal/i18n.js +21 -0
  52. package/src/internal/i18n.js.map +1 -1
  53. package/src/{location-BTqdfIzX.js → location-BgYhXEZp.js} +2 -2
  54. package/src/{location-BTqdfIzX.js.map → location-BgYhXEZp.js.map} +1 -1
  55. package/src/{models-Bah5B3bT.js → models-DgkGTFus.js} +6 -1
  56. package/src/models-DgkGTFus.js.map +1 -0
  57. package/src/{models-B4IoTmp7.js → models-k2nXyD6q.js} +2 -2
  58. package/src/{models-B4IoTmp7.js.map → models-k2nXyD6q.js.map} +1 -1
  59. package/src/runtime/delivery/context.js +1 -1
  60. package/src/runtime/delivery/plugin.js +27 -5
  61. package/src/runtime/delivery/plugin.js.map +1 -1
  62. package/src/runtime/delivery/preview.d.ts +1 -1
  63. package/src/runtime/delivery/types.d.ts +2 -85
  64. package/src/runtime/delivery/useCmsDocumentSeo.d.ts +8 -1
  65. package/src/runtime/delivery/useCmsDocumentSeo.js +19 -7
  66. package/src/runtime/delivery/useCmsDocumentSeo.js.map +1 -1
  67. package/src/runtime/delivery/useDocument.d.ts +2 -2
  68. package/src/runtime/delivery/useDocument.js.map +1 -1
  69. package/src/runtime/delivery/useDocumentQuery.d.ts +3 -3
  70. package/src/runtime/delivery/useDocumentQuery.js.map +1 -1
  71. package/src/runtime/forms/document.js +1 -1
  72. package/src/runtime/forms/useCmsForm.js +81 -41
  73. package/src/runtime/forms/useCmsForm.js.map +1 -1
  74. package/src/runtime/i18n/useCmsI18n.d.ts +9 -7
  75. package/src/runtime/i18n/useCmsI18n.js +5 -4
  76. package/src/runtime/i18n/useCmsI18n.js.map +1 -1
  77. package/src/runtime/installation.js +2 -2
  78. package/src/runtime/plugin.js +1 -1
  79. package/src/runtime/preview/connection.js +1 -1
  80. package/src/runtime/preview/controller.js +2 -2
  81. package/src/runtime/preview/plugin.client.js +3 -3
  82. package/src/runtime/preview/store.js +1 -1
  83. package/src/runtime/sitemap.js +1 -1
  84. package/src/scalars-CA6kyipS.d.ts +7 -0
  85. package/src/{store-b2CSXgMt.js → store-BYgSt7E3.js} +3 -3
  86. package/src/{store-b2CSXgMt.js.map → store-BYgSt7E3.js.map} +1 -1
  87. package/src/types-DutFRtaG.d.ts +90 -0
  88. package/studio/{CreateDocumentDialog-GGey1uBc.js → CreateDocumentDialog-BdiM77bb.js} +1 -1
  89. package/studio/{documentPlanning-DRErYmBU.js → documentPlanning-B7fyUj9r.js} +7072 -7065
  90. package/studio/host.js +2 -2
  91. package/src/ContentTransfer-C3Av9sWz.js.map +0 -1
  92. package/src/installation-CNfIriVm.js.map +0 -1
  93. package/src/models-Bah5B3bT.js.map +0 -1
@@ -0,0 +1,43 @@
1
+ //#region src/internal/application-types.ts
2
+ function generateCmsApplicationTypes(input) {
3
+ const locale = union(Object.keys(input.i18n.locales));
4
+ const messageKey = union(Object.keys(input.i18n.messageParameters));
5
+ const blockName = union(input.blockNames);
6
+ const parameters = Object.entries(input.i18n.messageParameters).map(([key, names]) => `${JSON.stringify(key)}: { ${names.map((name) => `readonly ${JSON.stringify(name)}: string | number`).join("; ")} }`).join("; ");
7
+ return [
8
+ `import '@phtngyn/cms/ApplicationTypes'`,
9
+ `import '@phtngyn/cms/I18n'`,
10
+ `declare module '@phtngyn/cms/ApplicationTypes' {`,
11
+ ` interface CmsApplicationRegistry {`,
12
+ ` configuration: typeof import(${JSON.stringify(input.configurationPath)}).default`,
13
+ ` blockName: ${blockName}`,
14
+ ` }`,
15
+ `}`,
16
+ `declare module '@phtngyn/cms/I18n' {`,
17
+ ` interface CmsI18nRegistry {`,
18
+ ` locale: ${locale}`,
19
+ ` messageKey: ${messageKey}`,
20
+ ` messageParameters: { ${parameters} }`,
21
+ ` }`,
22
+ `}`,
23
+ `export type CmsBlockName = import('@phtngyn/cms/ApplicationTypes').CmsBlockName`,
24
+ `export type CmsCollectionName = import('@phtngyn/cms/ApplicationTypes').CmsCollectionName`,
25
+ `export type CmsCollection<Name extends CmsCollectionName> = import('@phtngyn/cms/ApplicationTypes').CmsCollection<Name>`,
26
+ `export type CmsDocumentPage<Name extends CmsCollectionName> = import('@phtngyn/cms/ApplicationTypes').CmsDocumentPage<Name>`,
27
+ `export type CmsDocumentQuery<Name extends CmsCollectionName = CmsCollectionName> = import('@phtngyn/cms/ApplicationTypes').CmsDocumentQuery<Name>`,
28
+ `export type CmsDocumentQuerySort<Name extends CmsCollectionName> = import('@phtngyn/cms/ApplicationTypes').CmsDocumentQuerySort<Name>`,
29
+ `export type CmsFormDefinition<Name extends CmsFormName = CmsFormName> = import('@phtngyn/cms/ApplicationTypes').CmsFormDefinition<Name>`,
30
+ `export type CmsFormName = import('@phtngyn/cms/ApplicationTypes').CmsFormName`,
31
+ `export type CmsLocale = import('@phtngyn/cms/ApplicationTypes').CmsLocale`,
32
+ `export type CmsMessageKey = import('@phtngyn/cms/ApplicationTypes').CmsMessageKey`,
33
+ `export type CmsMessageParameters<Key extends CmsMessageKey> = import('@phtngyn/cms/ApplicationTypes').CmsMessageParameters<Key>`,
34
+ ""
35
+ ].join("\n");
36
+ }
37
+ function union(values) {
38
+ return [...new Set(values)].sort((left, right) => left.localeCompare(right)).map((value) => JSON.stringify(value)).join(" | ") || "never";
39
+ }
40
+
41
+ //#endregion
42
+ export { generateCmsApplicationTypes };
43
+ //# sourceMappingURL=application-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-types.js","names":[],"sources":["../../../../src/internal/application-types.ts"],"sourcesContent":["import type { CompiledCmsI18n } from './i18n'\n\nexport interface CmsApplicationTypeInput {\n readonly blockNames: ReadonlyArray<string>\n readonly configurationPath: string\n readonly i18n: CompiledCmsI18n\n}\n\nexport function generateCmsApplicationTypes(input: CmsApplicationTypeInput): string {\n const locale = union(Object.keys(input.i18n.locales))\n const messageKey = union(Object.keys(input.i18n.messageParameters))\n const blockName = union(input.blockNames)\n\n const parameters = Object.entries(input.i18n.messageParameters)\n .map(\n ([key, names]) =>\n `${JSON.stringify(key)}: { ${names.map((name) => `readonly ${JSON.stringify(name)}: string | number`).join('; ')} }`,\n )\n .join('; ')\n\n return [\n `import '@phtngyn/cms/ApplicationTypes'`,\n `import '@phtngyn/cms/I18n'`,\n `declare module '@phtngyn/cms/ApplicationTypes' {`,\n ` interface CmsApplicationRegistry {`,\n ` configuration: typeof import(${JSON.stringify(input.configurationPath)}).default`,\n ` blockName: ${blockName}`,\n ` }`,\n `}`,\n `declare module '@phtngyn/cms/I18n' {`,\n ` interface CmsI18nRegistry {`,\n ` locale: ${locale}`,\n ` messageKey: ${messageKey}`,\n ` messageParameters: { ${parameters} }`,\n ` }`,\n `}`,\n `export type CmsBlockName = import('@phtngyn/cms/ApplicationTypes').CmsBlockName`,\n `export type CmsCollectionName = import('@phtngyn/cms/ApplicationTypes').CmsCollectionName`,\n `export type CmsCollection<Name extends CmsCollectionName> = import('@phtngyn/cms/ApplicationTypes').CmsCollection<Name>`,\n `export type CmsDocumentPage<Name extends CmsCollectionName> = import('@phtngyn/cms/ApplicationTypes').CmsDocumentPage<Name>`,\n `export type CmsDocumentQuery<Name extends CmsCollectionName = CmsCollectionName> = import('@phtngyn/cms/ApplicationTypes').CmsDocumentQuery<Name>`,\n `export type CmsDocumentQuerySort<Name extends CmsCollectionName> = import('@phtngyn/cms/ApplicationTypes').CmsDocumentQuerySort<Name>`,\n `export type CmsFormDefinition<Name extends CmsFormName = CmsFormName> = import('@phtngyn/cms/ApplicationTypes').CmsFormDefinition<Name>`,\n `export type CmsFormName = import('@phtngyn/cms/ApplicationTypes').CmsFormName`,\n `export type CmsLocale = import('@phtngyn/cms/ApplicationTypes').CmsLocale`,\n `export type CmsMessageKey = import('@phtngyn/cms/ApplicationTypes').CmsMessageKey`,\n `export type CmsMessageParameters<Key extends CmsMessageKey> = import('@phtngyn/cms/ApplicationTypes').CmsMessageParameters<Key>`,\n '',\n ].join('\\n')\n}\n\nfunction union(values: ReadonlyArray<string>): string {\n return (\n [...new Set(values)]\n .sort((left, right) => left.localeCompare(right))\n .map((value) => JSON.stringify(value))\n .join(' | ') || 'never'\n )\n}\n"],"mappings":";AAQA,SAAgB,4BAA4B,OAAwC;CAClF,MAAM,SAAS,MAAM,OAAO,KAAK,MAAM,KAAK,OAAO,CAAC;CACpD,MAAM,aAAa,MAAM,OAAO,KAAK,MAAM,KAAK,iBAAiB,CAAC;CAClE,MAAM,YAAY,MAAM,MAAM,UAAU;CAExC,MAAM,aAAa,OAAO,QAAQ,MAAM,KAAK,iBAAiB,CAAC,CAC5D,KACE,CAAC,KAAK,WACL,GAAG,KAAK,UAAU,GAAG,EAAE,MAAM,MAAM,KAAK,SAAS,YAAY,KAAK,UAAU,IAAI,EAAE,kBAAkB,CAAC,CAAC,KAAK,IAAI,EAAE,GACrH,CAAC,CACA,KAAK,IAAI;CAEZ,OAAO;EACL;EACA;EACA;EACA;EACA,oCAAoC,KAAK,UAAU,MAAM,iBAAiB,EAAE;EAC5E,kBAAkB;EAClB;EACA;EACA;EACA;EACA,eAAe;EACf,mBAAmB;EACnB,4BAA4B,WAAW;EACvC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,IAAI;AACb;AAEA,SAAS,MAAM,QAAuC;CACpD,OACE,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,CAAC,CACjB,MAAM,MAAM,UAAU,KAAK,cAAc,KAAK,CAAC,CAAC,CAChD,KAAK,UAAU,KAAK,UAAU,KAAK,CAAC,CAAC,CACrC,KAAK,KAAK,KAAK;AAEtB"}
@@ -1,5 +1,5 @@
1
- import { n as formAuthoring } from "../Forms-Dj6NuW66.js";
2
- import { l as validateCollectionBody, n as ComponentDefinition, t as AuthoringCatalog } from "../Configuration-CDMYfTre.js";
1
+ import { n as formAuthoring } from "../Forms-02-p8qEw.js";
2
+ import { l as validateCollectionBody, n as ComponentDefinition, t as AuthoringCatalog } from "../Configuration-CjVUBBwa.js";
3
3
  import { resolveBlockAuthoring } from "./authoring-metadata.js";
4
4
  import { Crypto, Effect, Encoding, FileSystem, Path, Schema } from "effect";
5
5
  import { addTemplate, addVitePlugin, updateTemplates } from "@nuxt/kit";
@@ -7,7 +7,7 @@ import { createCheckerByJson } from "vue-component-meta";
7
7
 
8
8
  //#region src/internal/authoring-catalog.ts
9
9
  /** A complete, validated snapshot shared by Vite and Nitro through ordinary imports. */
10
- const registerAuthoringCatalog = Effect.fn("CmsAuthoring.register")(function* (nuxt, documents, forms = {}) {
10
+ const registerAuthoringCatalog = Effect.fn("CmsAuthoring.register")(function* (nuxt, documents, forms = {}, onBlockNames, additionalTemplatePaths = []) {
11
11
  const fs = yield* FileSystem.FileSystem;
12
12
  const path = yield* Path.Path;
13
13
  const crypto = yield* Crypto.Crypto;
@@ -72,6 +72,7 @@ const registerAuthoringCatalog = Effect.fn("CmsAuthoring.register")(function* (n
72
72
  }
73
73
  for (const name of Object.keys(forms)) if (!definitions.some((definition) => definition.name === name)) throw new Error(`Missing Vue form renderer ${name}.`);
74
74
  const components = definitions.sort((left, right) => left.name.localeCompare(right.name));
75
+ onBlockNames?.(components.filter((component) => forms[component.name] === void 0).map((component) => component.name));
75
76
  for (const collection of documents.types) {
76
77
  const issues = validateCollectionBody(components, collection.body);
77
78
  if (issues.length) throw new Error(`${collection.label}: ${issues.join(" ")}`);
@@ -120,7 +121,11 @@ const registerAuthoringCatalog = Effect.fn("CmsAuthoring.register")(function* (n
120
121
  return run(Effect.logError("Authoring update rejected; keeping the last valid catalog.", error));
121
122
  }
122
123
  function update() {
123
- return rebuild().then((changed) => changed ? updateTemplates({ filter: (candidate) => [template.dst, blocks.dst].includes(candidate.dst) }) : void 0).catch((error) => report(error instanceof Error ? error : new Error(String(error))));
124
+ return rebuild().then((changed) => changed ? updateTemplates({ filter: (candidate) => [
125
+ template.dst,
126
+ blocks.dst,
127
+ ...additionalTemplatePaths
128
+ ].includes(candidate.dst) }) : void 0).catch((error) => report(error instanceof Error ? error : new Error(String(error))));
124
129
  }
125
130
  nuxt.hook("components:extend", (components) => {
126
131
  discovered = components;
@@ -1 +1 @@
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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"}
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 onBlockNames?: (names: ReadonlyArray<string>) => void,\n additionalTemplatePaths: ReadonlyArray<string> = [],\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 onBlockNames?.(\n components.filter((component) => forms[component.name] === undefined).map((component) => component.name),\n )\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({\n filter: (candidate) => [template.dst, blocks.dst, ...additionalTemplatePaths].includes(candidate.dst),\n })\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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"}
@@ -1,4 +1,4 @@
1
- import { a as BlockAuthoring, c as parseAuthoringContent, n as ComponentDefinition, s as createAuthoringSchema } from "../Configuration-CDMYfTre.js";
1
+ import { a as BlockAuthoring, c as parseAuthoringContent, n as ComponentDefinition, s as createAuthoringSchema } from "../Configuration-CjVUBBwa.js";
2
2
  import { compileCmsBlock, readAuthoringDefault } from "./authoring-compiler.js";
3
3
  import { Effect, Result, Schema } from "effect";
4
4
  import ts from "typescript";
@@ -1,8 +1,8 @@
1
+ import { R as SeoConfiguration } from "../models-DgkGTFus.js";
2
+ import { j as StudioBootstrap, t as maxS3SingleCopyBytes, u as makeDefaultSeoOptions } from "../S3MediaObjects-DC0c8sYC.js";
1
3
  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
4
  import { compileCmsI18n } from "./i18n.js";
5
- import { i as PreviewOrigin } from "../models-B4IoTmp7.js";
5
+ import { i as PreviewOrigin } from "../models-k2nXyD6q.js";
6
6
  import { compileCmsDocumentModel } from "./document-model.js";
7
7
  import { Predicate, Result, Schema } from "effect";
8
8
 
@@ -17,7 +17,10 @@ const InstallationConfiguration = Schema.Struct({
17
17
  initialDelayMillis: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),
18
18
  intervalMillis: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThan(0)))
19
19
  })])),
20
- databaseUrl: Schema.NonEmptyString,
20
+ database: Schema.Struct({
21
+ schema: Schema.NonEmptyString.check(Schema.makeFilter((value) => /^[a-z_][a-z0-9_]{0,62}$/u.test(value), { expected: "a lowercase PostgreSQL identifier" })),
22
+ url: Schema.NonEmptyString
23
+ }),
21
24
  initializationToken: Schema.NonEmptyString.check(Schema.isMinLength(32)),
22
25
  media: Schema.optionalKey(Schema.Union([Schema.Literals([false]), Schema.Struct({
23
26
  maxUploadBytes: Schema.optionalKey(Schema.Int.check(Schema.isBetween({
@@ -35,6 +38,7 @@ const InstallationConfiguration = Schema.Struct({
35
38
  endpoint: optionalString,
36
39
  forcePathStyle: Schema.optionalKey(Schema.Boolean),
37
40
  provisionBucket: Schema.optionalKey(Schema.Boolean),
41
+ prefix: Schema.NonEmptyString.check(Schema.makeFilter((value) => !value.startsWith("/") && value.endsWith("/") && !value.includes(".."), { expected: "a relative object prefix ending in /" })),
38
42
  region: Schema.NonEmptyString
39
43
  })
40
44
  })])),
@@ -83,11 +87,11 @@ function resolveCmsInstallation(authored, authoring) {
83
87
  initialDelayMillis: cleanup?.initialDelayMillis ?? DEFAULT_CLEANUP_INITIAL_DELAY_MILLIS,
84
88
  intervalMillis: cleanup?.intervalMillis ?? DEFAULT_CLEANUP_INTERVAL_MILLIS
85
89
  },
86
- databaseUrl: configuration.databaseUrl,
90
+ database: configuration.database,
87
91
  documentModel: compiled.documentModel,
88
92
  initializationToken: configuration.initializationToken,
89
93
  ...media === void 0 ? void 0 : { media: {
90
- publicBaseUrl: media.publicBaseUrl,
94
+ publicBaseUrl: `${media.publicBaseUrl.replace(/\/+$/gu, "")}/${media.storage.prefix.replace(/\/+$/gu, "")}`,
91
95
  ...media.storage,
92
96
  forcePathStyle: media.storage.forcePathStyle ?? false,
93
97
  provisionBucket: media.storage.provisionBucket ?? false
@@ -1 +1 @@
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
+ {"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 database: Schema.Struct({\n schema: Schema.NonEmptyString.check(\n Schema.makeFilter((value) => /^[a-z_][a-z0-9_]{0,62}$/u.test(value), {\n expected: 'a lowercase PostgreSQL identifier',\n }),\n ),\n url: Schema.NonEmptyString,\n }),\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 prefix: Schema.NonEmptyString.check(\n Schema.makeFilter((value) => !value.startsWith('/') && value.endsWith('/') && !value.includes('..'), {\n expected: 'a relative object prefix ending in /',\n }),\n ),\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 database: configuration.database,\n documentModel: compiled.documentModel,\n initializationToken: configuration.initializationToken,\n ...(media === undefined\n ? undefined\n : {\n media: {\n publicBaseUrl: `${media.publicBaseUrl.replace(/\\/+$/gu, '')}/${media.storage.prefix.replace(/\\/+$/gu, '')}`,\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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"}
@@ -0,0 +1,3 @@
1
+ import { n as doctorCmsDevelopment, r as resetCmsDevelopment, t as bootstrapCmsDevelopment } from "../dev-lifecycle-vQLxwCFq.js";
2
+
3
+ export { bootstrapCmsDevelopment, doctorCmsDevelopment, resetCmsDevelopment };
@@ -1,6 +1,6 @@
1
1
  import { FIELD_INPUT_METADATA } from "./field-metadata.js";
2
- import { r as DocumentConfiguration } from "../Configuration-CDMYfTre.js";
3
- import { t as createDocumentEngine } from "../DocumentEngine-J7g-emdf.js";
2
+ import { r as DocumentConfiguration } from "../Configuration-CjVUBBwa.js";
3
+ import { t as createDocumentEngine } from "../DocumentEngine-BbhfnTAc.js";
4
4
  import { Effect, Predicate, Result, Schema } from "effect";
5
5
 
6
6
  //#region src/internal/document-model.ts
@@ -1 +1 @@
1
- {"version":3,"file":"document-model.js","names":[],"sources":["../../../../src/internal/document-model.ts"],"sourcesContent":["import type { CmsI18nOptions } from '../I18n'\nimport type { StandardJSONSchemaV1 } from 'effect/StandardSchema'\nimport type {\n DocumentSchemaProjection,\n ExecutableDocumentModel,\n ExecutableDocumentSchema,\n} from '@internal/document/DocumentEngine'\nimport type {\n DocumentConfiguration as DocumentConfigurationType,\n DocumentField,\n} from '@internal/protocol/Configuration'\nimport type {\n CmsCollectionOptions,\n CmsCollectionSchema,\n CmsDocumentModelOptions,\n CmsFieldInput,\n} from '../DocumentModel'\nimport { createDocumentEngine } from '@internal/document/DocumentEngine'\nimport { DocumentConfiguration } from '@internal/protocol/Configuration'\nimport { Effect, Predicate, Result, Schema } from 'effect'\nimport { FIELD_INPUT_METADATA } from './field-metadata'\n\nconst isJsonObject = Schema.is(Schema.JsonObject)\n\ntype EncodedDocumentConfiguration = Schema.Codec.Encoded<typeof DocumentConfiguration>\n\ninterface CmsDocumentModel {\n readonly authoring: DocumentConfigurationType\n readonly executable: ExecutableDocumentModel\n}\n\ninterface CompiledCollection {\n readonly authoring: EncodedDocumentConfiguration['types'][number]\n readonly executable: ExecutableDocumentSchema\n}\n\nexport class CmsDocumentModelInvalid extends Schema.TaggedError<CmsDocumentModelInvalid>()('Cms.DocumentModelInvalid', {\n message: Schema.NonEmptyString,\n path: Schema.NonEmptyString,\n}) {}\n\nconst isCmsDocumentModelInvalid = Schema.is(CmsDocumentModelInvalid)\n\nexport function compileCmsDocumentModel(documents: CmsDocumentModelOptions, i18n?: CmsI18nOptions): CmsDocumentModel {\n try {\n const compiled = Object.entries(documents.collections).map(([collection, options]) =>\n compileCollection(collection, options),\n )\n\n const decoded = Schema.decodeResult(DocumentConfiguration)({\n ...(i18n === undefined\n ? undefined\n : {\n locales: {\n defaultLocale: i18n.defaultLocale,\n fallbackLocale: i18n.fallbackLocale ?? null,\n locales: Object.keys(i18n.locales),\n prefixDefaultLocale: i18n.prefixDefaultLocale ?? false,\n },\n }),\n types: compiled.map((entry) => entry.authoring),\n })\n\n if (Result.isFailure(decoded)) throw invalid('documents', String(decoded.failure))\n\n const model = {\n authoring: decoded.success,\n executable: {\n types: Object.fromEntries(compiled.map((entry) => [entry.authoring.collection, entry.executable])),\n },\n }\n\n const engine = Effect.runSync(\n Effect.result(createDocumentEngine(model.authoring, { documentModel: model.executable })),\n )\n\n if (Result.isFailure(engine)) throw invalid('documents', engine.failure.message)\n\n return model\n } catch (cause) {\n throw isCmsDocumentModelInvalid(cause)\n ? cause\n : invalid('documents.collections', cause instanceof Error ? cause.message : String(cause))\n }\n}\n\nfunction compileCollection(collection: string, options: CmsCollectionOptions): CompiledCollection {\n const path = `documents.collections.${collection}`\n let generated: ReturnType<StandardJSONSchemaV1.Converter['input']>\n\n try {\n if (isEffectCollectionSchema(options.schema)) {\n const document = Schema.toJsonSchemaDocument(options.schema, {\n includeAnnotationKey: (key) => key === FIELD_INPUT_METADATA,\n referencePolicy: () => undefined,\n })\n\n generated = { ...document.schema, $defs: document.definitions }\n } else {\n if (!Predicate.isFunction(options.schema['~standard']?.jsonSchema?.input)) {\n throw new Error('Studio needs Standard JSON Schema V1 input conversion (or an adapter that supplies it).')\n }\n\n generated = options.schema['~standard'].jsonSchema.input({ target: 'draft-2020-12' })\n }\n } catch (cause) {\n throw invalid(`${path}.schema`, cause instanceof Error ? cause.message : String(cause))\n }\n\n const decoded = Schema.decodeUnknownResult(Schema.JsonObject)(generated)\n\n if (Result.isFailure(decoded)) throw invalid(`${path}.schema`, 'The generated input structure is not serializable.')\n const input = resolveInputStructure(decoded.success, `${path}.schema`)\n\n if (input.type !== 'object') throw invalid(`${path}.schema`, 'A collection schema must describe an object input.')\n const projection = compileProjection(input, `${path}.schema`)\n\n const validator = isEffectCollectionSchema(options.schema)\n ? Schema.toStandardSchemaV1(options.schema)\n : options.schema\n\n return {\n authoring: {\n addressPattern: options.route,\n ...(options.body === undefined ? undefined : { body: options.body }),\n authoringFields: compileAuthoringFields(input, `${path}.schema`),\n canCreate: options.canCreate ?? true,\n collection,\n description: options.description ?? '',\n directory: options.source ?? collection,\n hierarchy: options.hierarchy ?? options.route.includes('*'),\n label: options.label,\n },\n executable: {\n project: projection,\n validate: (value) => Effect.tryPromise(() => Promise.resolve(validator['~standard'].validate(value))),\n },\n }\n}\n\ntype ProjectDocumentProjection = (input: Schema.JsonObject) => DocumentSchemaProjection\n\nfunction compileProjection(schema: Schema.JsonObject, path: string, parent = ''): ProjectDocumentProjection {\n const properties = objectKeyword(schema, 'properties', path, true)\n\n const declarations = new Map(\n Object.entries(properties).map(([name, value]) => {\n const fieldPath = parent ? `${parent}.${name}` : name\n const property = requireObject(value, `${path}.${name}`)\n const nested = property.type === 'object' ? compileProjection(property, `${path}.${name}`, fieldPath) : undefined\n\n return [name, nested] as const\n }),\n )\n\n return (input) => {\n const value: Record<string, Schema.Json> = {}\n const unknownPaths: string[] = []\n\n for (const [name, child] of Object.entries(input)) {\n const nested = declarations.get(name)\n\n if (!declarations.has(name)) {\n unknownPaths.push(parent ? `${parent}.${name}` : name)\n } else if (nested && isJsonObject(child)) {\n const projected = nested(child)\n value[name] = projected.value\n unknownPaths.push(...projected.unknownPaths)\n } else {\n value[name] = child\n }\n }\n\n return { unknownPaths, value }\n }\n}\n\nfunction compileAuthoringFields(\n schema: Schema.JsonObject,\n path: string,\n parent = '',\n parentRequired = true,\n): ReadonlyArray<DocumentField> {\n const properties = objectKeyword(schema, 'properties', path, true)\n const required = stringArrayKeyword(schema, 'required', path)\n\n return Object.entries(properties).flatMap(([name, value]) => {\n if (!name || name.includes('.')) {\n throw invalid(`${path}.${name || '<empty>'}`, 'Field names must be non-empty and cannot contain dots.')\n }\n\n const fieldPath = parent ? `${parent}.${name}` : name\n\n if (fieldPath === 'id') throw invalid(`${path}.id`, 'Field \"id\" is reserved for CMS identity.')\n const property = requireObject(value, `${path}.${name}`)\n const fieldRequired = parentRequired && required.has(name)\n\n if (property.type === 'object') {\n if (property.default !== undefined) {\n throw invalid(\n `${path}.${name}`,\n 'Defaults on object fields are not supported; default their leaf fields instead.',\n )\n }\n\n return compileAuthoringFields(property, `${path}.${name}`, fieldPath, fieldRequired)\n }\n\n return [compileAuthoringField(property, `${path}.${name}`, fieldPath, fieldRequired)]\n })\n}\n\nfunction compileAuthoringField(\n schema: Schema.JsonObject,\n schemaPath: string,\n path: string,\n required: boolean,\n): DocumentField {\n const presentation = fieldPresentation(schema, schemaPath, path, required)\n\n switch (schema.type) {\n case 'boolean':\n return { ...presentation, input: input(schema, schemaPath, 'toggle', ['toggle']), type: 'boolean' }\n case 'integer':\n case 'number': {\n const options = numericOptions(schema.enum, schemaPath)\n\n return {\n ...presentation,\n input: input(schema, schemaPath, options.length > 0 ? 'select' : 'number', ['number', 'select']),\n options,\n type: 'number',\n }\n }\n\n case 'string': {\n if (schema.format === 'date') {\n return { ...presentation, input: input(schema, schemaPath, 'date', ['date']), type: 'date' }\n }\n\n const options = stringOptions(schema.enum, schemaPath)\n\n return {\n ...presentation,\n input: input(schema, schemaPath, options.length > 0 ? 'select' : 'text', ['select', 'text', 'textarea']),\n options,\n type: 'string',\n }\n }\n\n case 'array': {\n const items = requireObject(schema.items, `${schemaPath}[]`)\n\n if (items.type !== 'string') throw invalid(schemaPath, 'Studio currently supports authoring arrays of strings.')\n\n return {\n ...presentation,\n input: input(schema, schemaPath, 'multiselect', ['multiselect']),\n options: stringOptions(items.enum, `${schemaPath}[]`),\n type: 'string[]',\n }\n }\n\n default:\n throw invalid(schemaPath, `Studio cannot generate an input for schema type \"${displayJson(schema.type)}\".`)\n }\n}\n\nfunction fieldPresentation(schema: Schema.JsonObject, schemaPath: string, path: string, required: boolean) {\n const defaultValue = schema.default\n const description = stringKeyword(schema, 'description', schemaPath)\n const title = stringKeyword(schema, 'title', schemaPath)\n\n return {\n ...(defaultValue === undefined ? undefined : { defaultValue }),\n ...(description === undefined ? undefined : { description }),\n label: title?.trim() || humanize(path),\n path,\n required,\n }\n}\n\nfunction input<const Supported extends ReadonlyArray<CmsFieldInput>>(\n schema: Schema.JsonObject,\n path: string,\n fallback: Supported[number],\n supported: Supported,\n): Supported[number] {\n const configured = schema[FIELD_INPUT_METADATA]\n\n if (configured === undefined) return fallback\n const decoded = Schema.decodeUnknownResult(Schema.Literals([...supported]))(configured)\n\n if (Result.isSuccess(decoded)) return decoded.success\n throw invalid(path, `Input \"${displayJson(configured)}\" is not compatible with this field.`)\n}\n\nfunction stringOptions(value: Schema.Json | undefined, path: string): ReadonlyArray<string> {\n if (value === undefined) return []\n const decoded = Schema.decodeUnknownResult(Schema.Array(Schema.String))(value)\n\n if (Result.isFailure(decoded)) throw invalid(path, 'Field options must all be strings.')\n\n return decoded.success\n}\n\nfunction numericOptions(value: Schema.Json | undefined, path: string): ReadonlyArray<number> {\n if (value === undefined) return []\n const decoded = Schema.decodeUnknownResult(Schema.Array(Schema.Finite))(value)\n\n if (Result.isFailure(decoded)) throw invalid(path, 'Field options must all be finite numbers.')\n\n return decoded.success\n}\n\nfunction objectKeyword(schema: Schema.JsonObject, keyword: string, path: string, optional = false): Schema.JsonObject {\n const value = schema[keyword]\n\n if (value === undefined && optional) return {}\n\n return requireObject(value, `${path}.${keyword}`)\n}\n\nfunction stringArrayKeyword(schema: Schema.JsonObject, keyword: string, path: string): ReadonlySet<string> {\n const value = schema[keyword]\n\n if (value === undefined) return new Set()\n const decoded = Schema.decodeUnknownResult(Schema.Array(Schema.String))(value)\n\n if (Result.isFailure(decoded)) throw invalid(`${path}.${keyword}`, `Expected \"${keyword}\" to be an array of strings.`)\n\n return new Set(decoded.success)\n}\n\nfunction stringKeyword(schema: Schema.JsonObject, keyword: string, path: string): string | undefined {\n const value = schema[keyword]\n\n if (value === undefined) return undefined\n const decoded = Schema.decodeUnknownResult(Schema.String)(value)\n\n if (Result.isFailure(decoded)) throw invalid(`${path}.${keyword}`, `Expected \"${keyword}\" to be a string.`)\n\n return decoded.success\n}\n\nfunction requireObject(value: Schema.Json | undefined, path: string): Schema.JsonObject {\n if (!isJsonObject(value)) throw invalid(path, 'Studio requires an object input structure at this location.')\n\n return value\n}\n\nfunction humanize(path: string): string {\n const name = path.split('.').at(-1) ?? path\n\n const words = name\n .replace(/([a-z\\d])([A-Z])/gu, '$1 $2')\n .replace(/[-_]+/gu, ' ')\n .trim()\n\n return words ? `${words.charAt(0).toUpperCase()}${words.slice(1)}` : name\n}\n\nfunction displayJson(value: Schema.Json | undefined): string {\n return value === undefined ? 'undefined' : (JSON.stringify(value) ?? 'undefined')\n}\n\nfunction invalid(path: string, message: string): CmsDocumentModelInvalid {\n return new CmsDocumentModelInvalid({ message, path })\n}\n\n/** Resolve local input references while rejecting recursive or ambiguous editor structures. */\nfunction resolveInputStructure(root: Schema.JsonObject, path: string): Schema.JsonObject {\n function visit(node: Schema.JsonObject, currentPath: string, ancestors: ReadonlySet<string>): Schema.JsonObject {\n if (node.$ref !== undefined) {\n const decodedRef = Schema.decodeUnknownResult(Schema.String)(node.$ref)\n\n if (Result.isFailure(decodedRef)) throw invalid(currentPath, 'Expected a string schema reference.')\n const ref = decodedRef.success\n\n if (!ref.startsWith('#/') || ancestors.has(ref)) {\n throw invalid(currentPath, 'Studio requires non-recursive local schema references.')\n }\n\n let target: Schema.Json | undefined = root\n\n for (const segment of ref.slice(2).split('/')) {\n target = isJsonObject(target) ? target[segment.replace(/~1/gu, '/').replace(/~0/gu, '~')] : undefined\n }\n\n const { $ref: _, ...siblings } = node\n\n return visit(\n Object.assign({}, requireObject(target, currentPath), siblings),\n currentPath,\n new Set([...ancestors, ref]),\n )\n }\n\n if (node.anyOf !== undefined || node.oneOf !== undefined) {\n throw invalid(currentPath, 'Studio requires a single supported input type per field.')\n }\n\n const out = Object.fromEntries(Object.entries(node))\n\n if (node.allOf !== undefined) {\n if (!Array.isArray(node.allOf)) throw invalid(currentPath, 'Expected an array of schema constraints.')\n\n for (const constraint of node.allOf) {\n const part = visit(requireObject(constraint, currentPath), currentPath, ancestors)\n\n if (\n part.properties !== undefined ||\n part.items !== undefined ||\n (part.type !== undefined && part.type !== node.type)\n ) {\n throw invalid(currentPath, 'Studio cannot combine structural schema intersections.')\n }\n\n for (const key of ['title', 'description', 'default', 'format', 'enum', FIELD_INPUT_METADATA]) {\n if (part[key] === undefined) continue\n\n if (out[key] !== undefined && JSON.stringify(out[key]) !== JSON.stringify(part[key])) {\n throw invalid(currentPath, `Conflicting field metadata \"${key}\" in schema intersection.`)\n }\n\n out[key] = part[key]\n }\n }\n }\n\n if (node.properties !== undefined) {\n out.properties = Object.fromEntries(\n Object.entries(requireObject(node.properties, currentPath)).map(([name, value]) => [\n name,\n visit(requireObject(value, `${currentPath}.${name}`), `${currentPath}.${name}`, ancestors),\n ]),\n )\n }\n\n if (node.items !== undefined)\n out.items = visit(requireObject(node.items, `${currentPath}[]`), `${currentPath}[]`, ancestors)\n\n return out\n }\n\n return visit(root, path, new Set())\n}\n\nfunction isEffectCollectionSchema(schema: CmsCollectionSchema): schema is Schema.ConstraintDecoder<unknown> {\n return Schema.isSchema(schema)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"document-model.js","names":[],"sources":["../../../../src/internal/document-model.ts"],"sourcesContent":["import type { CmsI18nOptions } from '../I18n'\nimport type { StandardJSONSchemaV1 } from '@standard-schema/spec'\nimport type {\n DocumentSchemaProjection,\n ExecutableDocumentModel,\n ExecutableDocumentSchema,\n} from '@internal/document/DocumentEngine'\nimport type {\n DocumentConfiguration as DocumentConfigurationType,\n DocumentField,\n} from '@internal/protocol/Configuration'\nimport type {\n CmsCollectionOptions,\n CmsCollectionSchema,\n CmsDocumentModelOptions,\n CmsFieldInput,\n} from '../DocumentModel'\nimport { createDocumentEngine } from '@internal/document/DocumentEngine'\nimport { DocumentConfiguration } from '@internal/protocol/Configuration'\nimport { Effect, Predicate, Result, Schema } from 'effect'\nimport { FIELD_INPUT_METADATA } from './field-metadata'\n\nconst isJsonObject = Schema.is(Schema.JsonObject)\n\ntype EncodedDocumentConfiguration = Schema.Codec.Encoded<typeof DocumentConfiguration>\n\ninterface CmsDocumentModel {\n readonly authoring: DocumentConfigurationType\n readonly executable: ExecutableDocumentModel\n}\n\ninterface CompiledCollection {\n readonly authoring: EncodedDocumentConfiguration['types'][number]\n readonly executable: ExecutableDocumentSchema\n}\n\nexport class CmsDocumentModelInvalid extends Schema.TaggedError<CmsDocumentModelInvalid>()('Cms.DocumentModelInvalid', {\n message: Schema.NonEmptyString,\n path: Schema.NonEmptyString,\n}) {}\n\nconst isCmsDocumentModelInvalid = Schema.is(CmsDocumentModelInvalid)\n\nexport function compileCmsDocumentModel(documents: CmsDocumentModelOptions, i18n?: CmsI18nOptions): CmsDocumentModel {\n try {\n const compiled = Object.entries(documents.collections).map(([collection, options]) =>\n compileCollection(collection, options),\n )\n\n const decoded = Schema.decodeResult(DocumentConfiguration)({\n ...(i18n === undefined\n ? undefined\n : {\n locales: {\n defaultLocale: i18n.defaultLocale,\n fallbackLocale: i18n.fallbackLocale ?? null,\n locales: Object.keys(i18n.locales),\n prefixDefaultLocale: i18n.prefixDefaultLocale ?? false,\n },\n }),\n types: compiled.map((entry) => entry.authoring),\n })\n\n if (Result.isFailure(decoded)) throw invalid('documents', String(decoded.failure))\n\n const model = {\n authoring: decoded.success,\n executable: {\n types: Object.fromEntries(compiled.map((entry) => [entry.authoring.collection, entry.executable])),\n },\n }\n\n const engine = Effect.runSync(\n Effect.result(createDocumentEngine(model.authoring, { documentModel: model.executable })),\n )\n\n if (Result.isFailure(engine)) throw invalid('documents', engine.failure.message)\n\n return model\n } catch (cause) {\n throw isCmsDocumentModelInvalid(cause)\n ? cause\n : invalid('documents.collections', cause instanceof Error ? cause.message : String(cause))\n }\n}\n\nfunction compileCollection(collection: string, options: CmsCollectionOptions): CompiledCollection {\n const path = `documents.collections.${collection}`\n let generated: ReturnType<StandardJSONSchemaV1.Converter['input']>\n\n try {\n if (isEffectCollectionSchema(options.schema)) {\n const document = Schema.toJsonSchemaDocument(options.schema, {\n includeAnnotationKey: (key) => key === FIELD_INPUT_METADATA,\n referencePolicy: () => undefined,\n })\n\n generated = { ...document.schema, $defs: document.definitions }\n } else {\n if (!Predicate.isFunction(options.schema['~standard']?.jsonSchema?.input)) {\n throw new Error('Studio needs Standard JSON Schema V1 input conversion (or an adapter that supplies it).')\n }\n\n generated = options.schema['~standard'].jsonSchema.input({ target: 'draft-2020-12' })\n }\n } catch (cause) {\n throw invalid(`${path}.schema`, cause instanceof Error ? cause.message : String(cause))\n }\n\n const decoded = Schema.decodeUnknownResult(Schema.JsonObject)(generated)\n\n if (Result.isFailure(decoded)) throw invalid(`${path}.schema`, 'The generated input structure is not serializable.')\n const input = resolveInputStructure(decoded.success, `${path}.schema`)\n\n if (input.type !== 'object') throw invalid(`${path}.schema`, 'A collection schema must describe an object input.')\n const projection = compileProjection(input, `${path}.schema`)\n\n const validator = isEffectCollectionSchema(options.schema)\n ? Schema.toStandardSchemaV1(options.schema)\n : options.schema\n\n return {\n authoring: {\n addressPattern: options.route,\n ...(options.body === undefined ? undefined : { body: options.body }),\n authoringFields: compileAuthoringFields(input, `${path}.schema`),\n canCreate: options.canCreate ?? true,\n collection,\n description: options.description ?? '',\n directory: options.source ?? collection,\n hierarchy: options.hierarchy ?? options.route.includes('*'),\n label: options.label,\n },\n executable: {\n project: projection,\n validate: (value) => Effect.tryPromise(() => Promise.resolve(validator['~standard'].validate(value))),\n },\n }\n}\n\ntype ProjectDocumentProjection = (input: Schema.JsonObject) => DocumentSchemaProjection\n\nfunction compileProjection(schema: Schema.JsonObject, path: string, parent = ''): ProjectDocumentProjection {\n const properties = objectKeyword(schema, 'properties', path, true)\n\n const declarations = new Map(\n Object.entries(properties).map(([name, value]) => {\n const fieldPath = parent ? `${parent}.${name}` : name\n const property = requireObject(value, `${path}.${name}`)\n const nested = property.type === 'object' ? compileProjection(property, `${path}.${name}`, fieldPath) : undefined\n\n return [name, nested] as const\n }),\n )\n\n return (input) => {\n const value: Record<string, Schema.Json> = {}\n const unknownPaths: string[] = []\n\n for (const [name, child] of Object.entries(input)) {\n const nested = declarations.get(name)\n\n if (!declarations.has(name)) {\n unknownPaths.push(parent ? `${parent}.${name}` : name)\n } else if (nested && isJsonObject(child)) {\n const projected = nested(child)\n value[name] = projected.value\n unknownPaths.push(...projected.unknownPaths)\n } else {\n value[name] = child\n }\n }\n\n return { unknownPaths, value }\n }\n}\n\nfunction compileAuthoringFields(\n schema: Schema.JsonObject,\n path: string,\n parent = '',\n parentRequired = true,\n): ReadonlyArray<DocumentField> {\n const properties = objectKeyword(schema, 'properties', path, true)\n const required = stringArrayKeyword(schema, 'required', path)\n\n return Object.entries(properties).flatMap(([name, value]) => {\n if (!name || name.includes('.')) {\n throw invalid(`${path}.${name || '<empty>'}`, 'Field names must be non-empty and cannot contain dots.')\n }\n\n const fieldPath = parent ? `${parent}.${name}` : name\n\n if (fieldPath === 'id') throw invalid(`${path}.id`, 'Field \"id\" is reserved for CMS identity.')\n const property = requireObject(value, `${path}.${name}`)\n const fieldRequired = parentRequired && required.has(name)\n\n if (property.type === 'object') {\n if (property.default !== undefined) {\n throw invalid(\n `${path}.${name}`,\n 'Defaults on object fields are not supported; default their leaf fields instead.',\n )\n }\n\n return compileAuthoringFields(property, `${path}.${name}`, fieldPath, fieldRequired)\n }\n\n return [compileAuthoringField(property, `${path}.${name}`, fieldPath, fieldRequired)]\n })\n}\n\nfunction compileAuthoringField(\n schema: Schema.JsonObject,\n schemaPath: string,\n path: string,\n required: boolean,\n): DocumentField {\n const presentation = fieldPresentation(schema, schemaPath, path, required)\n\n switch (schema.type) {\n case 'boolean':\n return { ...presentation, input: input(schema, schemaPath, 'toggle', ['toggle']), type: 'boolean' }\n case 'integer':\n case 'number': {\n const options = numericOptions(schema.enum, schemaPath)\n\n return {\n ...presentation,\n input: input(schema, schemaPath, options.length > 0 ? 'select' : 'number', ['number', 'select']),\n options,\n type: 'number',\n }\n }\n\n case 'string': {\n if (schema.format === 'date') {\n return { ...presentation, input: input(schema, schemaPath, 'date', ['date']), type: 'date' }\n }\n\n const options = stringOptions(schema.enum, schemaPath)\n\n return {\n ...presentation,\n input: input(schema, schemaPath, options.length > 0 ? 'select' : 'text', ['select', 'text', 'textarea']),\n options,\n type: 'string',\n }\n }\n\n case 'array': {\n const items = requireObject(schema.items, `${schemaPath}[]`)\n\n if (items.type !== 'string') throw invalid(schemaPath, 'Studio currently supports authoring arrays of strings.')\n\n return {\n ...presentation,\n input: input(schema, schemaPath, 'multiselect', ['multiselect']),\n options: stringOptions(items.enum, `${schemaPath}[]`),\n type: 'string[]',\n }\n }\n\n default:\n throw invalid(schemaPath, `Studio cannot generate an input for schema type \"${displayJson(schema.type)}\".`)\n }\n}\n\nfunction fieldPresentation(schema: Schema.JsonObject, schemaPath: string, path: string, required: boolean) {\n const defaultValue = schema.default\n const description = stringKeyword(schema, 'description', schemaPath)\n const title = stringKeyword(schema, 'title', schemaPath)\n\n return {\n ...(defaultValue === undefined ? undefined : { defaultValue }),\n ...(description === undefined ? undefined : { description }),\n label: title?.trim() || humanize(path),\n path,\n required,\n }\n}\n\nfunction input<const Supported extends ReadonlyArray<CmsFieldInput>>(\n schema: Schema.JsonObject,\n path: string,\n fallback: Supported[number],\n supported: Supported,\n): Supported[number] {\n const configured = schema[FIELD_INPUT_METADATA]\n\n if (configured === undefined) return fallback\n const decoded = Schema.decodeUnknownResult(Schema.Literals([...supported]))(configured)\n\n if (Result.isSuccess(decoded)) return decoded.success\n throw invalid(path, `Input \"${displayJson(configured)}\" is not compatible with this field.`)\n}\n\nfunction stringOptions(value: Schema.Json | undefined, path: string): ReadonlyArray<string> {\n if (value === undefined) return []\n const decoded = Schema.decodeUnknownResult(Schema.Array(Schema.String))(value)\n\n if (Result.isFailure(decoded)) throw invalid(path, 'Field options must all be strings.')\n\n return decoded.success\n}\n\nfunction numericOptions(value: Schema.Json | undefined, path: string): ReadonlyArray<number> {\n if (value === undefined) return []\n const decoded = Schema.decodeUnknownResult(Schema.Array(Schema.Finite))(value)\n\n if (Result.isFailure(decoded)) throw invalid(path, 'Field options must all be finite numbers.')\n\n return decoded.success\n}\n\nfunction objectKeyword(schema: Schema.JsonObject, keyword: string, path: string, optional = false): Schema.JsonObject {\n const value = schema[keyword]\n\n if (value === undefined && optional) return {}\n\n return requireObject(value, `${path}.${keyword}`)\n}\n\nfunction stringArrayKeyword(schema: Schema.JsonObject, keyword: string, path: string): ReadonlySet<string> {\n const value = schema[keyword]\n\n if (value === undefined) return new Set()\n const decoded = Schema.decodeUnknownResult(Schema.Array(Schema.String))(value)\n\n if (Result.isFailure(decoded)) throw invalid(`${path}.${keyword}`, `Expected \"${keyword}\" to be an array of strings.`)\n\n return new Set(decoded.success)\n}\n\nfunction stringKeyword(schema: Schema.JsonObject, keyword: string, path: string): string | undefined {\n const value = schema[keyword]\n\n if (value === undefined) return undefined\n const decoded = Schema.decodeUnknownResult(Schema.String)(value)\n\n if (Result.isFailure(decoded)) throw invalid(`${path}.${keyword}`, `Expected \"${keyword}\" to be a string.`)\n\n return decoded.success\n}\n\nfunction requireObject(value: Schema.Json | undefined, path: string): Schema.JsonObject {\n if (!isJsonObject(value)) throw invalid(path, 'Studio requires an object input structure at this location.')\n\n return value\n}\n\nfunction humanize(path: string): string {\n const name = path.split('.').at(-1) ?? path\n\n const words = name\n .replace(/([a-z\\d])([A-Z])/gu, '$1 $2')\n .replace(/[-_]+/gu, ' ')\n .trim()\n\n return words ? `${words.charAt(0).toUpperCase()}${words.slice(1)}` : name\n}\n\nfunction displayJson(value: Schema.Json | undefined): string {\n return value === undefined ? 'undefined' : (JSON.stringify(value) ?? 'undefined')\n}\n\nfunction invalid(path: string, message: string): CmsDocumentModelInvalid {\n return new CmsDocumentModelInvalid({ message, path })\n}\n\n/** Resolve local input references while rejecting recursive or ambiguous editor structures. */\nfunction resolveInputStructure(root: Schema.JsonObject, path: string): Schema.JsonObject {\n function visit(node: Schema.JsonObject, currentPath: string, ancestors: ReadonlySet<string>): Schema.JsonObject {\n if (node.$ref !== undefined) {\n const decodedRef = Schema.decodeUnknownResult(Schema.String)(node.$ref)\n\n if (Result.isFailure(decodedRef)) throw invalid(currentPath, 'Expected a string schema reference.')\n const ref = decodedRef.success\n\n if (!ref.startsWith('#/') || ancestors.has(ref)) {\n throw invalid(currentPath, 'Studio requires non-recursive local schema references.')\n }\n\n let target: Schema.Json | undefined = root\n\n for (const segment of ref.slice(2).split('/')) {\n target = isJsonObject(target) ? target[segment.replace(/~1/gu, '/').replace(/~0/gu, '~')] : undefined\n }\n\n const { $ref: _, ...siblings } = node\n\n return visit(\n Object.assign({}, requireObject(target, currentPath), siblings),\n currentPath,\n new Set([...ancestors, ref]),\n )\n }\n\n if (node.anyOf !== undefined || node.oneOf !== undefined) {\n throw invalid(currentPath, 'Studio requires a single supported input type per field.')\n }\n\n const out = Object.fromEntries(Object.entries(node))\n\n if (node.allOf !== undefined) {\n if (!Array.isArray(node.allOf)) throw invalid(currentPath, 'Expected an array of schema constraints.')\n\n for (const constraint of node.allOf) {\n const part = visit(requireObject(constraint, currentPath), currentPath, ancestors)\n\n if (\n part.properties !== undefined ||\n part.items !== undefined ||\n (part.type !== undefined && part.type !== node.type)\n ) {\n throw invalid(currentPath, 'Studio cannot combine structural schema intersections.')\n }\n\n for (const key of ['title', 'description', 'default', 'format', 'enum', FIELD_INPUT_METADATA]) {\n if (part[key] === undefined) continue\n\n if (out[key] !== undefined && JSON.stringify(out[key]) !== JSON.stringify(part[key])) {\n throw invalid(currentPath, `Conflicting field metadata \"${key}\" in schema intersection.`)\n }\n\n out[key] = part[key]\n }\n }\n }\n\n if (node.properties !== undefined) {\n out.properties = Object.fromEntries(\n Object.entries(requireObject(node.properties, currentPath)).map(([name, value]) => [\n name,\n visit(requireObject(value, `${currentPath}.${name}`), `${currentPath}.${name}`, ancestors),\n ]),\n )\n }\n\n if (node.items !== undefined)\n out.items = visit(requireObject(node.items, `${currentPath}[]`), `${currentPath}[]`, ancestors)\n\n return out\n }\n\n return visit(root, path, new Set())\n}\n\nfunction isEffectCollectionSchema(schema: CmsCollectionSchema): schema is Schema.ConstraintDecoder<unknown> {\n return Schema.isSchema(schema)\n}\n"],"mappings":";;;;;;AAsBA,MAAM,eAAe,OAAO,GAAG,OAAO,UAAU;AAchD,IAAa,0BAAb,cAA6C,OAAO,YAAqC,CAAC,CAAC,4BAA4B;CACrH,SAAS,OAAO;CAChB,MAAM,OAAO;AACf,CAAC,CAAC,CAAC,CAAC;AAEJ,MAAM,4BAA4B,OAAO,GAAG,uBAAuB;AAEnE,SAAgB,wBAAwB,WAAoC,MAAyC;CACnH,IAAI;EACF,MAAM,WAAW,OAAO,QAAQ,UAAU,WAAW,CAAC,CAAC,KAAK,CAAC,YAAY,aACvE,kBAAkB,YAAY,OAAO,CACvC;EAEA,MAAM,UAAU,OAAO,aAAa,qBAAqB,CAAC,CAAC;GACzD,GAAI,SAAS,SACT,SACA,EACE,SAAS;IACP,eAAe,KAAK;IACpB,gBAAgB,KAAK,kBAAkB;IACvC,SAAS,OAAO,KAAK,KAAK,OAAO;IACjC,qBAAqB,KAAK,uBAAuB;GACnD,EACF;GACJ,OAAO,SAAS,KAAK,UAAU,MAAM,SAAS;EAChD,CAAC;EAED,IAAI,OAAO,UAAU,OAAO,GAAG,MAAM,QAAQ,aAAa,OAAO,QAAQ,OAAO,CAAC;EAEjF,MAAM,QAAQ;GACZ,WAAW,QAAQ;GACnB,YAAY,EACV,OAAO,OAAO,YAAY,SAAS,KAAK,UAAU,CAAC,MAAM,UAAU,YAAY,MAAM,UAAU,CAAC,CAAC,EACnG;EACF;EAEA,MAAM,SAAS,OAAO,QACpB,OAAO,OAAO,qBAAqB,MAAM,WAAW,EAAE,eAAe,MAAM,WAAW,CAAC,CAAC,CAC1F;EAEA,IAAI,OAAO,UAAU,MAAM,GAAG,MAAM,QAAQ,aAAa,OAAO,QAAQ,OAAO;EAE/E,OAAO;CACT,SAAS,OAAO;EACd,MAAM,0BAA0B,KAAK,IACjC,QACA,QAAQ,yBAAyB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;CAC7F;AACF;AAEA,SAAS,kBAAkB,YAAoB,SAAmD;CAChG,MAAM,OAAO,yBAAyB;CACtC,IAAI;CAEJ,IAAI;EACF,IAAI,yBAAyB,QAAQ,MAAM,GAAG;GAC5C,MAAM,WAAW,OAAO,qBAAqB,QAAQ,QAAQ;IAC3D,uBAAuB,QAAQ,QAAQ;IACvC,uBAAuB;GACzB,CAAC;GAED,YAAY;IAAE,GAAG,SAAS;IAAQ,OAAO,SAAS;GAAY;EAChE,OAAO;GACL,IAAI,CAAC,UAAU,WAAW,QAAQ,OAAO,YAAY,EAAE,YAAY,KAAK,GACtE,MAAM,IAAI,MAAM,yFAAyF;GAG3G,YAAY,QAAQ,OAAO,YAAY,CAAC,WAAW,MAAM,EAAE,QAAQ,gBAAgB,CAAC;EACtF;CACF,SAAS,OAAO;EACd,MAAM,QAAQ,GAAG,KAAK,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;CACxF;CAEA,MAAM,UAAU,OAAO,oBAAoB,OAAO,UAAU,CAAC,CAAC,SAAS;CAEvE,IAAI,OAAO,UAAU,OAAO,GAAG,MAAM,QAAQ,GAAG,KAAK,UAAU,oDAAoD;CACnH,MAAM,QAAQ,sBAAsB,QAAQ,SAAS,GAAG,KAAK,QAAQ;CAErE,IAAI,MAAM,SAAS,UAAU,MAAM,QAAQ,GAAG,KAAK,UAAU,oDAAoD;CACjH,MAAM,aAAa,kBAAkB,OAAO,GAAG,KAAK,QAAQ;CAE5D,MAAM,YAAY,yBAAyB,QAAQ,MAAM,IACrD,OAAO,mBAAmB,QAAQ,MAAM,IACxC,QAAQ;CAEZ,OAAO;EACL,WAAW;GACT,gBAAgB,QAAQ;GACxB,GAAI,QAAQ,SAAS,SAAY,SAAY,EAAE,MAAM,QAAQ,KAAK;GAClE,iBAAiB,uBAAuB,OAAO,GAAG,KAAK,QAAQ;GAC/D,WAAW,QAAQ,aAAa;GAChC;GACA,aAAa,QAAQ,eAAe;GACpC,WAAW,QAAQ,UAAU;GAC7B,WAAW,QAAQ,aAAa,QAAQ,MAAM,SAAS,GAAG;GAC1D,OAAO,QAAQ;EACjB;EACA,YAAY;GACV,SAAS;GACT,WAAW,UAAU,OAAO,iBAAiB,QAAQ,QAAQ,UAAU,YAAY,CAAC,SAAS,KAAK,CAAC,CAAC;EACtG;CACF;AACF;AAIA,SAAS,kBAAkB,QAA2B,MAAc,SAAS,IAA+B;CAC1G,MAAM,aAAa,cAAc,QAAQ,cAAc,MAAM,IAAI;CAEjE,MAAM,eAAe,IAAI,IACvB,OAAO,QAAQ,UAAU,CAAC,CAAC,KAAK,CAAC,MAAM,WAAW;EAChD,MAAM,YAAY,SAAS,GAAG,OAAO,GAAG,SAAS;EACjD,MAAM,WAAW,cAAc,OAAO,GAAG,KAAK,GAAG,MAAM;EAGvD,OAAO,CAAC,MAFO,SAAS,SAAS,WAAW,kBAAkB,UAAU,GAAG,KAAK,GAAG,QAAQ,SAAS,IAAI,MAEpF;CACtB,CAAC,CACH;CAEA,QAAQ,UAAU;EAChB,MAAM,QAAqC,CAAC;EAC5C,MAAM,eAAyB,CAAC;EAEhC,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,KAAK,GAAG;GACjD,MAAM,SAAS,aAAa,IAAI,IAAI;GAEpC,IAAI,CAAC,aAAa,IAAI,IAAI,GACxB,aAAa,KAAK,SAAS,GAAG,OAAO,GAAG,SAAS,IAAI;QAChD,IAAI,UAAU,aAAa,KAAK,GAAG;IACxC,MAAM,YAAY,OAAO,KAAK;IAC9B,MAAM,QAAQ,UAAU;IACxB,aAAa,KAAK,GAAG,UAAU,YAAY;GAC7C,OACE,MAAM,QAAQ;EAElB;EAEA,OAAO;GAAE;GAAc;EAAM;CAC/B;AACF;AAEA,SAAS,uBACP,QACA,MACA,SAAS,IACT,iBAAiB,MACa;CAC9B,MAAM,aAAa,cAAc,QAAQ,cAAc,MAAM,IAAI;CACjE,MAAM,WAAW,mBAAmB,QAAQ,YAAY,IAAI;CAE5D,OAAO,OAAO,QAAQ,UAAU,CAAC,CAAC,SAAS,CAAC,MAAM,WAAW;EAC3D,IAAI,CAAC,QAAQ,KAAK,SAAS,GAAG,GAC5B,MAAM,QAAQ,GAAG,KAAK,GAAG,QAAQ,aAAa,wDAAwD;EAGxG,MAAM,YAAY,SAAS,GAAG,OAAO,GAAG,SAAS;EAEjD,IAAI,cAAc,MAAM,MAAM,QAAQ,GAAG,KAAK,MAAM,4CAA0C;EAC9F,MAAM,WAAW,cAAc,OAAO,GAAG,KAAK,GAAG,MAAM;EACvD,MAAM,gBAAgB,kBAAkB,SAAS,IAAI,IAAI;EAEzD,IAAI,SAAS,SAAS,UAAU;GAC9B,IAAI,SAAS,YAAY,QACvB,MAAM,QACJ,GAAG,KAAK,GAAG,QACX,iFACF;GAGF,OAAO,uBAAuB,UAAU,GAAG,KAAK,GAAG,QAAQ,WAAW,aAAa;EACrF;EAEA,OAAO,CAAC,sBAAsB,UAAU,GAAG,KAAK,GAAG,QAAQ,WAAW,aAAa,CAAC;CACtF,CAAC;AACH;AAEA,SAAS,sBACP,QACA,YACA,MACA,UACe;CACf,MAAM,eAAe,kBAAkB,QAAQ,YAAY,MAAM,QAAQ;CAEzE,QAAQ,OAAO,MAAf;EACE,KAAK,WACH,OAAO;GAAE,GAAG;GAAc,OAAO,MAAM,QAAQ,YAAY,UAAU,CAAC,QAAQ,CAAC;GAAG,MAAM;EAAU;EACpG,KAAK;EACL,KAAK,UAAU;GACb,MAAM,UAAU,eAAe,OAAO,MAAM,UAAU;GAEtD,OAAO;IACL,GAAG;IACH,OAAO,MAAM,QAAQ,YAAY,QAAQ,SAAS,IAAI,WAAW,UAAU,CAAC,UAAU,QAAQ,CAAC;IAC/F;IACA,MAAM;GACR;EACF;EAEA,KAAK,UAAU;GACb,IAAI,OAAO,WAAW,QACpB,OAAO;IAAE,GAAG;IAAc,OAAO,MAAM,QAAQ,YAAY,QAAQ,CAAC,MAAM,CAAC;IAAG,MAAM;GAAO;GAG7F,MAAM,UAAU,cAAc,OAAO,MAAM,UAAU;GAErD,OAAO;IACL,GAAG;IACH,OAAO,MAAM,QAAQ,YAAY,QAAQ,SAAS,IAAI,WAAW,QAAQ;KAAC;KAAU;KAAQ;IAAU,CAAC;IACvG;IACA,MAAM;GACR;EACF;EAEA,KAAK,SAAS;GACZ,MAAM,QAAQ,cAAc,OAAO,OAAO,GAAG,WAAW,GAAG;GAE3D,IAAI,MAAM,SAAS,UAAU,MAAM,QAAQ,YAAY,wDAAwD;GAE/G,OAAO;IACL,GAAG;IACH,OAAO,MAAM,QAAQ,YAAY,eAAe,CAAC,aAAa,CAAC;IAC/D,SAAS,cAAc,MAAM,MAAM,GAAG,WAAW,GAAG;IACpD,MAAM;GACR;EACF;EAEA,SACE,MAAM,QAAQ,YAAY,oDAAoD,YAAY,OAAO,IAAI,EAAE,GAAG;CAC9G;AACF;AAEA,SAAS,kBAAkB,QAA2B,YAAoB,MAAc,UAAmB;CACzG,MAAM,eAAe,OAAO;CAC5B,MAAM,cAAc,cAAc,QAAQ,eAAe,UAAU;CACnE,MAAM,QAAQ,cAAc,QAAQ,SAAS,UAAU;CAEvD,OAAO;EACL,GAAI,iBAAiB,SAAY,SAAY,EAAE,aAAa;EAC5D,GAAI,gBAAgB,SAAY,SAAY,EAAE,YAAY;EAC1D,OAAO,OAAO,KAAK,KAAK,SAAS,IAAI;EACrC;EACA;CACF;AACF;AAEA,SAAS,MACP,QACA,MACA,UACA,WACmB;CACnB,MAAM,aAAa,OAAO;CAE1B,IAAI,eAAe,QAAW,OAAO;CACrC,MAAM,UAAU,OAAO,oBAAoB,OAAO,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU;CAEtF,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO,QAAQ;CAC9C,MAAM,QAAQ,MAAM,UAAU,YAAY,UAAU,EAAE,qCAAqC;AAC7F;AAEA,SAAS,cAAc,OAAgC,MAAqC;CAC1F,IAAI,UAAU,QAAW,OAAO,CAAC;CACjC,MAAM,UAAU,OAAO,oBAAoB,OAAO,MAAM,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK;CAE7E,IAAI,OAAO,UAAU,OAAO,GAAG,MAAM,QAAQ,MAAM,oCAAoC;CAEvF,OAAO,QAAQ;AACjB;AAEA,SAAS,eAAe,OAAgC,MAAqC;CAC3F,IAAI,UAAU,QAAW,OAAO,CAAC;CACjC,MAAM,UAAU,OAAO,oBAAoB,OAAO,MAAM,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK;CAE7E,IAAI,OAAO,UAAU,OAAO,GAAG,MAAM,QAAQ,MAAM,2CAA2C;CAE9F,OAAO,QAAQ;AACjB;AAEA,SAAS,cAAc,QAA2B,SAAiB,MAAc,WAAW,OAA0B;CACpH,MAAM,QAAQ,OAAO;CAErB,IAAI,UAAU,UAAa,UAAU,OAAO,CAAC;CAE7C,OAAO,cAAc,OAAO,GAAG,KAAK,GAAG,SAAS;AAClD;AAEA,SAAS,mBAAmB,QAA2B,SAAiB,MAAmC;CACzG,MAAM,QAAQ,OAAO;CAErB,IAAI,UAAU,QAAW,uBAAO,IAAI,IAAI;CACxC,MAAM,UAAU,OAAO,oBAAoB,OAAO,MAAM,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK;CAE7E,IAAI,OAAO,UAAU,OAAO,GAAG,MAAM,QAAQ,GAAG,KAAK,GAAG,WAAW,aAAa,QAAQ,6BAA6B;CAErH,OAAO,IAAI,IAAI,QAAQ,OAAO;AAChC;AAEA,SAAS,cAAc,QAA2B,SAAiB,MAAkC;CACnG,MAAM,QAAQ,OAAO;CAErB,IAAI,UAAU,QAAW,OAAO;CAChC,MAAM,UAAU,OAAO,oBAAoB,OAAO,MAAM,CAAC,CAAC,KAAK;CAE/D,IAAI,OAAO,UAAU,OAAO,GAAG,MAAM,QAAQ,GAAG,KAAK,GAAG,WAAW,aAAa,QAAQ,kBAAkB;CAE1G,OAAO,QAAQ;AACjB;AAEA,SAAS,cAAc,OAAgC,MAAiC;CACtF,IAAI,CAAC,aAAa,KAAK,GAAG,MAAM,QAAQ,MAAM,6DAA6D;CAE3G,OAAO;AACT;AAEA,SAAS,SAAS,MAAsB;CACtC,MAAM,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK;CAEvC,MAAM,QAAQ,KACX,QAAQ,sBAAsB,OAAO,CAAC,CACtC,QAAQ,WAAW,GAAG,CAAC,CACvB,KAAK;CAER,OAAO,QAAQ,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,MAAM,MAAM,CAAC,MAAM;AACvE;AAEA,SAAS,YAAY,OAAwC;CAC3D,OAAO,UAAU,SAAY,cAAe,KAAK,UAAU,KAAK,KAAK;AACvE;AAEA,SAAS,QAAQ,MAAc,SAA0C;CACvE,OAAO,IAAI,wBAAwB;EAAE;EAAS;CAAK,CAAC;AACtD;;AAGA,SAAS,sBAAsB,MAAyB,MAAiC;CACvF,SAAS,MAAM,MAAyB,aAAqB,WAAmD;EAC9G,IAAI,KAAK,SAAS,QAAW;GAC3B,MAAM,aAAa,OAAO,oBAAoB,OAAO,MAAM,CAAC,CAAC,KAAK,IAAI;GAEtE,IAAI,OAAO,UAAU,UAAU,GAAG,MAAM,QAAQ,aAAa,qCAAqC;GAClG,MAAM,MAAM,WAAW;GAEvB,IAAI,CAAC,IAAI,WAAW,IAAI,KAAK,UAAU,IAAI,GAAG,GAC5C,MAAM,QAAQ,aAAa,wDAAwD;GAGrF,IAAI,SAAkC;GAEtC,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,GAC1C,SAAS,aAAa,MAAM,IAAI,OAAO,QAAQ,QAAQ,QAAQ,GAAG,CAAC,CAAC,QAAQ,QAAQ,GAAG,KAAK;GAG9F,MAAM,EAAE,MAAM,GAAG,GAAG,aAAa;GAEjC,OAAO,MACL,OAAO,OAAO,CAAC,GAAG,cAAc,QAAQ,WAAW,GAAG,QAAQ,GAC9D,6BACA,IAAI,IAAI,CAAC,GAAG,WAAW,GAAG,CAAC,CAC7B;EACF;EAEA,IAAI,KAAK,UAAU,UAAa,KAAK,UAAU,QAC7C,MAAM,QAAQ,aAAa,0DAA0D;EAGvF,MAAM,MAAM,OAAO,YAAY,OAAO,QAAQ,IAAI,CAAC;EAEnD,IAAI,KAAK,UAAU,QAAW;GAC5B,IAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,GAAG,MAAM,QAAQ,aAAa,0CAA0C;GAErG,KAAK,MAAM,cAAc,KAAK,OAAO;IACnC,MAAM,OAAO,MAAM,cAAc,YAAY,WAAW,GAAG,aAAa,SAAS;IAEjF,IACE,KAAK,eAAe,UACpB,KAAK,UAAU,UACd,KAAK,SAAS,UAAa,KAAK,SAAS,KAAK,MAE/C,MAAM,QAAQ,aAAa,wDAAwD;IAGrF,KAAK,MAAM,OAAO;KAAC;KAAS;KAAe;KAAW;KAAU;KAAQ;IAAoB,GAAG;KAC7F,IAAI,KAAK,SAAS,QAAW;KAE7B,IAAI,IAAI,SAAS,UAAa,KAAK,UAAU,IAAI,IAAI,MAAM,KAAK,UAAU,KAAK,IAAI,GACjF,MAAM,QAAQ,aAAa,+BAA+B,IAAI,0BAA0B;KAG1F,IAAI,OAAO,KAAK;IAClB;GACF;EACF;EAEA,IAAI,KAAK,eAAe,QACtB,IAAI,aAAa,OAAO,YACtB,OAAO,QAAQ,cAAc,KAAK,YAAY,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,WAAW,CACjF,MACA,MAAM,cAAc,OAAO,GAAG,YAAY,GAAG,MAAM,GAAG,GAAG,YAAY,GAAG,QAAQ,SAAS,CAC3F,CAAC,CACH;EAGF,IAAI,KAAK,UAAU,QACjB,IAAI,QAAQ,MAAM,cAAc,KAAK,OAAO,GAAG,YAAY,GAAG,GAAG,GAAG,YAAY,KAAK,SAAS;EAEhG,OAAO;CACT;CAEA,OAAO,MAAM,MAAM,sBAAM,IAAI,IAAI,CAAC;AACpC;AAEA,SAAS,yBAAyB,QAA0E;CAC1G,OAAO,OAAO,SAAS,MAAM;AAC/B"}
@@ -7,6 +7,7 @@ function compileCmsI18n(options) {
7
7
  defaultLocale: "",
8
8
  fallbackLocale: null,
9
9
  prefixDefaultLocale: false,
10
+ messageParameters: {},
10
11
  locales: {}
11
12
  };
12
13
  const codes = Object.keys(options.locales);
@@ -34,13 +35,33 @@ function compileCmsI18n(options) {
34
35
  messages: Object.fromEntries(entries)
35
36
  }];
36
37
  }));
38
+ const canonicalLocale = options.fallbackLocale ?? options.defaultLocale;
39
+ const canonicalMessages = locales[canonicalLocale]?.messages ?? {};
40
+ const canonicalKeys = Object.keys(canonicalMessages);
41
+ const messageParameters = Object.fromEntries(canonicalKeys.map((key) => [key, placeholders(canonicalMessages[key] ?? "")]));
42
+ for (const [code, locale] of Object.entries(locales)) {
43
+ for (const key of Object.keys(locale.messages)) {
44
+ if (!Object.hasOwn(canonicalMessages, key)) throw new Error(`Invalid i18n message ${code}.${key}: the canonical locale ${canonicalLocale} has no such key.`);
45
+ const expected = messageParameters[key] ?? [];
46
+ const actual = placeholders(locale.messages[key] ?? "");
47
+ if (expected.join("\0") !== actual.join("\0")) throw new Error(`Invalid i18n message ${code}.${key}: placeholders must match ${canonicalLocale}.${key} (${expected.join(", ")}).`);
48
+ }
49
+ if (options.fallbackLocale == null) {
50
+ const missing = canonicalKeys.find((key) => !Object.hasOwn(locale.messages, key));
51
+ if (missing) throw new Error(`Invalid i18n locale ${code}: missing message ${missing} and no fallback locale is configured.`);
52
+ }
53
+ }
37
54
  return {
38
55
  defaultLocale: options.defaultLocale,
39
56
  fallbackLocale: options.fallbackLocale ?? null,
40
57
  prefixDefaultLocale: options.prefixDefaultLocale ?? false,
58
+ messageParameters,
41
59
  locales
42
60
  };
43
61
  }
62
+ function placeholders(message) {
63
+ return [...message.matchAll(/\{([\w]+)\}/gu)].flatMap((match) => match[1] ? [match[1]] : []).filter((name, index, names) => names.indexOf(name) === index).sort((left, right) => left.localeCompare(right));
64
+ }
44
65
 
45
66
  //#endregion
46
67
  export { compileCmsI18n };
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.js","names":[],"sources":["../../../../src/internal/i18n.ts"],"sourcesContent":["import { Result, Schema } from 'effect'\nimport type { CmsI18nOptions } from '../I18n'\n\nexport interface CompiledCmsI18n {\n readonly defaultLocale: string\n readonly fallbackLocale: string | null\n readonly prefixDefaultLocale: boolean\n readonly locales: Readonly<\n Record<string, { readonly name: string; readonly messages: Readonly<Record<string, string>> }>\n >\n}\n\n/** Copies only public, serializable fields; executable installation configuration stays on the server. */\nexport function compileCmsI18n(options?: CmsI18nOptions): CompiledCmsI18n {\n if (!options) return { defaultLocale: '', fallbackLocale: null, prefixDefaultLocale: false, locales: {} }\n const codes = Object.keys(options.locales)\n\n if (\n !codes.includes(options.defaultLocale) ||\n (options.fallbackLocale != null && !codes.includes(options.fallbackLocale))\n ) {\n throw new Error('i18n defaultLocale and fallbackLocale must be declared in i18n.locales.')\n }\n\n const locales = Object.fromEntries(\n Object.entries(options.locales).map(([code, locale]) => {\n if (\n !/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/u.test(code) ||\n !Schema.is(Schema.String)(locale.name) ||\n !locale.name.trim()\n ) {\n throw new Error(`Invalid i18n locale: ${code}. Supply a locale code and display name.`)\n }\n\n const entries: [string, string][] = []\n const ancestors = new Set<object>()\n\n function visit(value: Schema.Json, path: string): void {\n if (Schema.is(Schema.String)(value)) {\n entries.push([path, value])\n\n return\n }\n\n if (!Schema.is(Schema.JsonObject)(value) || ancestors.has(value)) {\n throw new Error(`Invalid i18n message ${code}.${path}: expected a string or nested dictionary.`)\n }\n\n ancestors.add(value)\n\n for (const [key, child] of Object.entries(value)) {\n if (!key || key.includes('.')) throw new Error(`Invalid i18n message key: ${code}.${path}.${key}`)\n visit(child, path ? `${path}.${key}` : key)\n }\n\n ancestors.delete(value)\n }\n\n visit(Result.getOrThrow(Schema.decodeResult(Schema.JsonObject)(locale.messages ?? {})), '')\n\n return [code, { name: locale.name, messages: Object.fromEntries(entries) }]\n }),\n )\n\n return {\n defaultLocale: options.defaultLocale,\n fallbackLocale: options.fallbackLocale ?? null,\n prefixDefaultLocale: options.prefixDefaultLocale ?? false,\n locales,\n }\n}\n"],"mappings":";;;;AAaA,SAAgB,eAAe,SAA2C;CACxE,IAAI,CAAC,SAAS,OAAO;EAAE,eAAe;EAAI,gBAAgB;EAAM,qBAAqB;EAAO,SAAS,CAAC;CAAE;CACxG,MAAM,QAAQ,OAAO,KAAK,QAAQ,OAAO;CAEzC,IACE,CAAC,MAAM,SAAS,QAAQ,aAAa,KACpC,QAAQ,kBAAkB,QAAQ,CAAC,MAAM,SAAS,QAAQ,cAAc,GAEzE,MAAM,IAAI,MAAM,yEAAyE;CAG3F,MAAM,UAAU,OAAO,YACrB,OAAO,QAAQ,QAAQ,OAAO,CAAC,CAAC,KAAK,CAAC,MAAM,YAAY;EACtD,IACE,CAAC,yCAAyC,KAAK,IAAI,KACnD,CAAC,OAAO,GAAG,OAAO,MAAM,CAAC,CAAC,OAAO,IAAI,KACrC,CAAC,OAAO,KAAK,KAAK,GAElB,MAAM,IAAI,MAAM,wBAAwB,KAAK,yCAAyC;EAGxF,MAAM,UAA8B,CAAC;EACrC,MAAM,4BAAY,IAAI,IAAY;EAElC,SAAS,MAAM,OAAoB,MAAoB;GACrD,IAAI,OAAO,GAAG,OAAO,MAAM,CAAC,CAAC,KAAK,GAAG;IACnC,QAAQ,KAAK,CAAC,MAAM,KAAK,CAAC;IAE1B;GACF;GAEA,IAAI,CAAC,OAAO,GAAG,OAAO,UAAU,CAAC,CAAC,KAAK,KAAK,UAAU,IAAI,KAAK,GAC7D,MAAM,IAAI,MAAM,wBAAwB,KAAK,GAAG,KAAK,0CAA0C;GAGjG,UAAU,IAAI,KAAK;GAEnB,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAAG;IAChD,IAAI,CAAC,OAAO,IAAI,SAAS,GAAG,GAAG,MAAM,IAAI,MAAM,6BAA6B,KAAK,GAAG,KAAK,GAAG,KAAK;IACjG,MAAM,OAAO,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG;GAC5C;GAEA,UAAU,OAAO,KAAK;EACxB;EAEA,MAAM,OAAO,WAAW,OAAO,aAAa,OAAO,UAAU,CAAC,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,GAAG,EAAE;EAE1F,OAAO,CAAC,MAAM;GAAE,MAAM,OAAO;GAAM,UAAU,OAAO,YAAY,OAAO;EAAE,CAAC;CAC5E,CAAC,CACH;CAEA,OAAO;EACL,eAAe,QAAQ;EACvB,gBAAgB,QAAQ,kBAAkB;EAC1C,qBAAqB,QAAQ,uBAAuB;EACpD;CACF;AACF"}
1
+ {"version":3,"file":"i18n.js","names":[],"sources":["../../../../src/internal/i18n.ts"],"sourcesContent":["import { Result, Schema } from 'effect'\nimport type { CmsI18nOptions } from '../I18n'\n\nexport interface CompiledCmsI18n {\n readonly defaultLocale: string\n readonly fallbackLocale: string | null\n readonly prefixDefaultLocale: boolean\n readonly messageParameters: Readonly<Record<string, ReadonlyArray<string>>>\n readonly locales: Readonly<\n Record<string, { readonly name: string; readonly messages: Readonly<Record<string, string>> }>\n >\n}\n\n/** Copies only public, serializable fields; executable installation configuration stays on the server. */\nexport function compileCmsI18n(options?: CmsI18nOptions): CompiledCmsI18n {\n if (!options)\n return { defaultLocale: '', fallbackLocale: null, prefixDefaultLocale: false, messageParameters: {}, locales: {} }\n const codes = Object.keys(options.locales)\n\n if (\n !codes.includes(options.defaultLocale) ||\n (options.fallbackLocale != null && !codes.includes(options.fallbackLocale))\n ) {\n throw new Error('i18n defaultLocale and fallbackLocale must be declared in i18n.locales.')\n }\n\n const locales = Object.fromEntries(\n Object.entries(options.locales).map(([code, locale]) => {\n if (\n !/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/u.test(code) ||\n !Schema.is(Schema.String)(locale.name) ||\n !locale.name.trim()\n ) {\n throw new Error(`Invalid i18n locale: ${code}. Supply a locale code and display name.`)\n }\n\n const entries: [string, string][] = []\n const ancestors = new Set<object>()\n\n function visit(value: Schema.Json, path: string): void {\n if (Schema.is(Schema.String)(value)) {\n entries.push([path, value])\n\n return\n }\n\n if (!Schema.is(Schema.JsonObject)(value) || ancestors.has(value)) {\n throw new Error(`Invalid i18n message ${code}.${path}: expected a string or nested dictionary.`)\n }\n\n ancestors.add(value)\n\n for (const [key, child] of Object.entries(value)) {\n if (!key || key.includes('.')) throw new Error(`Invalid i18n message key: ${code}.${path}.${key}`)\n visit(child, path ? `${path}.${key}` : key)\n }\n\n ancestors.delete(value)\n }\n\n visit(Result.getOrThrow(Schema.decodeResult(Schema.JsonObject)(locale.messages ?? {})), '')\n\n return [code, { name: locale.name, messages: Object.fromEntries(entries) }]\n }),\n )\n\n const canonicalLocale = options.fallbackLocale ?? options.defaultLocale\n const canonicalMessages = locales[canonicalLocale]?.messages ?? {}\n const canonicalKeys = Object.keys(canonicalMessages)\n\n const messageParameters = Object.fromEntries(\n canonicalKeys.map((key) => [key, placeholders(canonicalMessages[key] ?? '')]),\n )\n\n for (const [code, locale] of Object.entries(locales)) {\n for (const key of Object.keys(locale.messages)) {\n if (!Object.hasOwn(canonicalMessages, key))\n throw new Error(`Invalid i18n message ${code}.${key}: the canonical locale ${canonicalLocale} has no such key.`)\n\n const expected = messageParameters[key] ?? []\n const actual = placeholders(locale.messages[key] ?? '')\n\n if (expected.join('\\0') !== actual.join('\\0'))\n throw new Error(\n `Invalid i18n message ${code}.${key}: placeholders must match ${canonicalLocale}.${key} (${expected.join(', ')}).`,\n )\n }\n\n if (options.fallbackLocale == null) {\n const missing = canonicalKeys.find((key) => !Object.hasOwn(locale.messages, key))\n\n if (missing)\n throw new Error(`Invalid i18n locale ${code}: missing message ${missing} and no fallback locale is configured.`)\n }\n }\n\n return {\n defaultLocale: options.defaultLocale,\n fallbackLocale: options.fallbackLocale ?? null,\n prefixDefaultLocale: options.prefixDefaultLocale ?? false,\n messageParameters,\n locales,\n }\n}\n\nfunction placeholders(message: string): ReadonlyArray<string> {\n return [...message.matchAll(/\\{([\\w]+)\\}/gu)]\n .flatMap((match) => (match[1] ? [match[1]] : []))\n .filter((name, index, names) => names.indexOf(name) === index)\n .sort((left, right) => left.localeCompare(right))\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { a as PreviewSessionId, i as PreviewOrigin } from "./models-B4IoTmp7.js";
1
+ import { a as PreviewSessionId, i as PreviewOrigin } from "./models-k2nXyD6q.js";
2
2
  import { Option, Schema } from "effect";
3
3
 
4
4
  //#region ../protocol/src/internal/preview/location.ts
@@ -32,4 +32,4 @@ function previewRedirect(url, parameters) {
32
32
 
33
33
  //#endregion
34
34
  export { readPreviewLocation as n, withPreviewLocation as r, previewRedirect as t };
35
- //# sourceMappingURL=location-BTqdfIzX.js.map
35
+ //# sourceMappingURL=location-BgYhXEZp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"location-BTqdfIzX.js","names":["PreviewOriginSchema","PreviewSessionIdSchema"],"sources":["../../../../protocol/src/internal/preview/location.ts"],"sourcesContent":["import { Option, Schema } from 'effect'\nimport { PreviewOrigin as PreviewOriginSchema, PreviewSessionId as PreviewSessionIdSchema } from './models'\n\nconst ENABLED_PARAMETER = '_cms_preview'\n\nconst EDITOR_ORIGIN_PARAMETER = '_cms_preview_editor_origin'\n\nconst SESSION_PARAMETER = '_cms_preview_session'\n\nconst PreviewLocationParameters = Schema.Struct({\n editorOrigin: PreviewOriginSchema,\n sessionId: PreviewSessionIdSchema,\n})\n\nexport interface PreviewLocationParameters extends Schema.Schema.Type<typeof PreviewLocationParameters> {}\n\nexport function readPreviewLocation(url: URL): PreviewLocationParameters | undefined {\n if (url.searchParams.get(ENABLED_PARAMETER) !== '1' || url.searchParams.get(EDITOR_ORIGIN_PARAMETER) !== url.origin)\n return undefined\n\n return Schema.decodeUnknownOption(PreviewLocationParameters)({\n editorOrigin: url.searchParams.get(EDITOR_ORIGIN_PARAMETER),\n sessionId: url.searchParams.get(SESSION_PARAMETER),\n }).pipe(Option.getOrUndefined)\n}\n\nexport function withPreviewLocation(url: URL, parameters: PreviewLocationParameters): URL {\n const next = new URL(url)\n next.searchParams.set(ENABLED_PARAMETER, '1')\n next.searchParams.set(EDITOR_ORIGIN_PARAMETER, parameters.editorOrigin)\n next.searchParams.set(SESSION_PARAMETER, parameters.sessionId)\n\n return next\n}\n\nexport function withoutPreviewLocation(url: URL): URL {\n const next = new URL(url)\n next.searchParams.delete(ENABLED_PARAMETER)\n next.searchParams.delete(EDITOR_ORIGIN_PARAMETER)\n next.searchParams.delete(SESSION_PARAMETER)\n\n return next\n}\n\nexport function previewRedirect(url: URL, parameters: PreviewLocationParameters): string | undefined {\n const current = readPreviewLocation(url)\n\n if (current?.sessionId === parameters.sessionId && current.editorOrigin === parameters.editorOrigin) return undefined\n const next = withPreviewLocation(url, parameters)\n\n return `${next.pathname}${next.search}${next.hash}`\n}\n"],"mappings":";;;;AAGA,MAAM,oBAAoB;AAE1B,MAAM,0BAA0B;AAEhC,MAAM,oBAAoB;AAE1B,MAAM,4BAA4B,OAAO,OAAO;CAC9C,cAAcA;CACd,WAAWC;AACb,CAAC;AAID,SAAgB,oBAAoB,KAAiD;CACnF,IAAI,IAAI,aAAa,IAAI,iBAAiB,MAAM,OAAO,IAAI,aAAa,IAAI,uBAAuB,MAAM,IAAI,QAC3G,OAAO;CAET,OAAO,OAAO,oBAAoB,yBAAyB,CAAC,CAAC;EAC3D,cAAc,IAAI,aAAa,IAAI,uBAAuB;EAC1D,WAAW,IAAI,aAAa,IAAI,iBAAiB;CACnD,CAAC,CAAC,CAAC,KAAK,OAAO,cAAc;AAC/B;AAEA,SAAgB,oBAAoB,KAAU,YAA4C;CACxF,MAAM,OAAO,IAAI,IAAI,GAAG;CACxB,KAAK,aAAa,IAAI,mBAAmB,GAAG;CAC5C,KAAK,aAAa,IAAI,yBAAyB,WAAW,YAAY;CACtE,KAAK,aAAa,IAAI,mBAAmB,WAAW,SAAS;CAE7D,OAAO;AACT;AAWA,SAAgB,gBAAgB,KAAU,YAA2D;CACnG,MAAM,UAAU,oBAAoB,GAAG;CAEvC,IAAI,SAAS,cAAc,WAAW,aAAa,QAAQ,iBAAiB,WAAW,cAAc,OAAO;CAC5G,MAAM,OAAO,oBAAoB,KAAK,UAAU;CAEhD,OAAO,GAAG,KAAK,WAAW,KAAK,SAAS,KAAK;AAC/C"}
1
+ {"version":3,"file":"location-BgYhXEZp.js","names":["PreviewOriginSchema","PreviewSessionIdSchema"],"sources":["../../../../protocol/src/internal/preview/location.ts"],"sourcesContent":["import { Option, Schema } from 'effect'\nimport { PreviewOrigin as PreviewOriginSchema, PreviewSessionId as PreviewSessionIdSchema } from './models'\n\nconst ENABLED_PARAMETER = '_cms_preview'\n\nconst EDITOR_ORIGIN_PARAMETER = '_cms_preview_editor_origin'\n\nconst SESSION_PARAMETER = '_cms_preview_session'\n\nconst PreviewLocationParameters = Schema.Struct({\n editorOrigin: PreviewOriginSchema,\n sessionId: PreviewSessionIdSchema,\n})\n\nexport interface PreviewLocationParameters extends Schema.Schema.Type<typeof PreviewLocationParameters> {}\n\nexport function readPreviewLocation(url: URL): PreviewLocationParameters | undefined {\n if (url.searchParams.get(ENABLED_PARAMETER) !== '1' || url.searchParams.get(EDITOR_ORIGIN_PARAMETER) !== url.origin)\n return undefined\n\n return Schema.decodeUnknownOption(PreviewLocationParameters)({\n editorOrigin: url.searchParams.get(EDITOR_ORIGIN_PARAMETER),\n sessionId: url.searchParams.get(SESSION_PARAMETER),\n }).pipe(Option.getOrUndefined)\n}\n\nexport function withPreviewLocation(url: URL, parameters: PreviewLocationParameters): URL {\n const next = new URL(url)\n next.searchParams.set(ENABLED_PARAMETER, '1')\n next.searchParams.set(EDITOR_ORIGIN_PARAMETER, parameters.editorOrigin)\n next.searchParams.set(SESSION_PARAMETER, parameters.sessionId)\n\n return next\n}\n\nexport function withoutPreviewLocation(url: URL): URL {\n const next = new URL(url)\n next.searchParams.delete(ENABLED_PARAMETER)\n next.searchParams.delete(EDITOR_ORIGIN_PARAMETER)\n next.searchParams.delete(SESSION_PARAMETER)\n\n return next\n}\n\nexport function previewRedirect(url: URL, parameters: PreviewLocationParameters): string | undefined {\n const current = readPreviewLocation(url)\n\n if (current?.sessionId === parameters.sessionId && current.editorOrigin === parameters.editorOrigin) return undefined\n const next = withPreviewLocation(url, parameters)\n\n return `${next.pathname}${next.search}${next.hash}`\n}\n"],"mappings":";;;;AAGA,MAAM,oBAAoB;AAE1B,MAAM,0BAA0B;AAEhC,MAAM,oBAAoB;AAE1B,MAAM,4BAA4B,OAAO,OAAO;CAC9C,cAAcA;CACd,WAAWC;AACb,CAAC;AAID,SAAgB,oBAAoB,KAAiD;CACnF,IAAI,IAAI,aAAa,IAAI,iBAAiB,MAAM,OAAO,IAAI,aAAa,IAAI,uBAAuB,MAAM,IAAI,QAC3G,OAAO;CAET,OAAO,OAAO,oBAAoB,yBAAyB,CAAC,CAAC;EAC3D,cAAc,IAAI,aAAa,IAAI,uBAAuB;EAC1D,WAAW,IAAI,aAAa,IAAI,iBAAiB;CACnD,CAAC,CAAC,CAAC,KAAK,OAAO,cAAc;AAC/B;AAEA,SAAgB,oBAAoB,KAAU,YAA4C;CACxF,MAAM,OAAO,IAAI,IAAI,GAAG;CACxB,KAAK,aAAa,IAAI,mBAAmB,GAAG;CAC5C,KAAK,aAAa,IAAI,yBAAyB,WAAW,YAAY;CACtE,KAAK,aAAa,IAAI,mBAAmB,WAAW,SAAS;CAE7D,OAAO;AACT;AAWA,SAAgB,gBAAgB,KAAU,YAA2D;CACnG,MAAM,UAAU,oBAAoB,GAAG;CAEvC,IAAI,SAAS,cAAc,WAAW,aAAa,QAAQ,iBAAiB,WAAW,cAAc,OAAO;CAC5G,MAAM,OAAO,oBAAoB,KAAK,UAAU;CAEhD,OAAO,GAAG,KAAK,WAAW,KAAK,SAAS,KAAK;AAC/C"}
@@ -496,6 +496,10 @@ const CompiledDocumentSource = Schema.Struct({
496
496
  mappings: Schema.Array(DocumentSourceMapping),
497
497
  publishedAt: Schema.optionalKey(Schema.DateTimeUtcFromString)
498
498
  });
499
+ const DocumentAlternative = Schema.Struct({
500
+ locale: Locale,
501
+ path: PublicPath
502
+ });
499
503
  const CompiledDocument = Schema.Struct({
500
504
  id: DocumentId,
501
505
  key: PublicPath,
@@ -507,6 +511,7 @@ const CompiledDocument = Schema.Struct({
507
511
  description: Schema.optionalKey(Schema.String),
508
512
  seo: Schema.optionalKey(DocumentSeo),
509
513
  resolvedSeo: Schema.optionalKey(ResolvedSeo),
514
+ alternatives: Schema.optionalKey(Schema.Array(DocumentAlternative)),
510
515
  data: Schema.JsonObject,
511
516
  issues: Schema.Array(DocumentIssue),
512
517
  analysis: CmsDocumentAnalysis,
@@ -706,4 +711,4 @@ const DocumentValidationResult = Schema.Struct({
706
711
 
707
712
  //#endregion
708
713
  export { StudioActor as $, UnpublishDocumentInput as A, SeoMediaUnavailable as B, PublishedDocumentLookup as C, CollectionName as Ct, RemoveDocumentInput as D, PublishedDocumentSurroundQuery as E, RequestId as Et, SaveSeoInput as F, SeoUrl as G, SeoRevision as H, SeoCanonicalOrigin as I, AccessDenied as J, SeoVersionConflict as K, SeoCapabilities as L, DocumentSeo as M, GlobalSeoSettings as N, RestoreDocumentInput as O, PublishSeoInput as P, Role as Q, SeoConfiguration as R, PublishDocumentInput as S, AddressPattern as St, PublishedDocumentQuery as T, SourceDirectory as Tt, SeoSnapshot as U, SeoMutationResult as V, SeoState as W, DOCUMENT_ACTIONS as X, AuthenticationRequired as Y, MEDIA_ACTIONS as Z, DocumentSurround as _, MediaReference as _t, DOCUMENT_REVISION_ACTIONS as a, MediaCleanupReport as at, MarkdownNode as b, MediaTooLarge as bt, DocumentIssue as c, MediaFolder as ct, DocumentNavigationQuery as d, MediaInvalid as dt, StudioEntryDenied as et, DocumentQueryScalar as f, MediaName as ft, DocumentSummary as g, MediaQuery as gt, DocumentSourceMapping as h, MediaPage as ht, CreateDocumentInput as i, MediaByteSize as it, UpdateDocumentInput as j, UndeleteDocumentInput as k, DocumentMutationResult as l, MediaId as lt, DocumentSource as m, MediaObjectKey as mt, CmsMarkdownDocument as n, ImageMimeType as nt, DeletedDocument as o, MediaConflict as ot, DocumentRevisionAction as p, MediaNotFound as pt, SitemapEntry as q, CompiledDocument as r, MediaAsset as rt, DocumentBrowseQuery as s, MediaCursor as st, CmsDocumentAnalysis as t, StudioRequestContext as tt, DocumentNavigationItem as u, MediaIntegrityReport as ut, DocumentValidationResult as v, MediaReferenced as vt, PublishedDocumentPage as w, Locale as wt, MoveDocumentInput as x, MediaUpload as xt, DuplicateDocumentInput as y, MediaStatus as yt, SeoConfirmationRequired as z };
709
- //# sourceMappingURL=models-Bah5B3bT.js.map
714
+ //# sourceMappingURL=models-DgkGTFus.js.map