@phtngyn/cms 0.1.0-beta.5 → 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 +11 -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
@@ -1 +1 @@
1
- {"version":3,"file":"Forms-Dj6NuW66.js","names":["isJsonObject","jsonObject","CmsMarkdownDocumentSchema"],"sources":["../../../../document/src/internal/comark/document-adapter.ts","../../../../document/src/internal/comark/bindings.ts","../../../../document/src/Forms.ts"],"sourcesContent":["import type { CmsMarkdownDocument, MarkdownNode } from '@internal/protocol/Documents'\nimport type {\n ElementNodeAttributes,\n MarkdownDocument as ComarkMarkdownDocument,\n Node as ComarkNode,\n NodeRenderData,\n} from 'comark'\nimport { textContent } from 'comark/utils'\nimport { Predicate, Schema } from 'effect'\n\nconst isJsonObject = Schema.is(Schema.JsonObject)\n\nexport function toComarkDocument(document: CmsMarkdownDocument): ComarkMarkdownDocument {\n return {\n frontmatter: mutableJsonObject(document.frontmatter),\n meta: mutableJsonObject(document.meta),\n nodes: document.nodes.map(toComarkNode),\n }\n}\n\nexport function createCmsComarkRenderData(document: CmsMarkdownDocument): NodeRenderData {\n return {\n data: {},\n frontmatter: mutableJsonObject(document.frontmatter),\n meta: mutableJsonObject(document.meta),\n props: {},\n }\n}\n\n/** Extracts inline text with Comark semantics, preserving punctuation between nested inline nodes. */\nexport function cmsComarkTextContent(node: MarkdownNode): string {\n return textContent(toComarkNode(node), { decodeUnicodeEntities: true })\n}\n\nexport function toMutableComarkAttributes(attributes: Schema.JsonObject): ElementNodeAttributes {\n const result: ElementNodeAttributes = {}\n\n for (const [name, value] of Object.entries(attributes)) {\n if (name !== '$') result[name] = mutableJson(value)\n }\n\n const internal = jsonObject(attributes.$)\n const line = internal.line\n const html = binaryFlag(internal.html)\n const block = binaryFlag(internal.block)\n\n if (Predicate.isNumber(line) || html !== undefined || block !== undefined) {\n const metadata: Record<string, number> = {}\n\n if (Predicate.isNumber(line)) metadata.line = line\n\n if (html !== undefined) metadata.html = html\n\n if (block !== undefined) metadata.block = block\n result.$ = metadata\n }\n\n return result\n}\n\nexport function mutableJson(value: Schema.Json): Schema.Json {\n if (Array.isArray(value)) return value.map(mutableJson)\n\n if (isJsonObject(value)) return mutableJsonObject(value)\n\n return value\n}\n\nfunction toComarkNode(node: MarkdownNode): ComarkNode {\n if (Predicate.isString(node)) return node\n\n if (node[0] === null) return [null, toMutableComarkAttributes(node[1]), node[2]]\n const [tag, attributes, ...children] = node\n\n return [tag, toMutableComarkAttributes(attributes), ...children.map(toComarkNode)]\n}\n\nexport function mutableJsonObject(value: Schema.JsonObject): Record<string, Schema.Json> {\n return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, mutableJson(child)]))\n}\n\nfunction binaryFlag(value: Schema.Json | undefined): 0 | 1 | undefined {\n return value === 0 || value === 1 ? value : undefined\n}\n\nfunction jsonObject(value: Schema.Json | undefined): Schema.JsonObject {\n return isJsonObject(value) ? value : {}\n}\n","import type { ComponentDefinition } from '@internal/protocol/Configuration'\nimport type { CmsMarkdownDocument, MarkdownNode } from '@internal/protocol/Documents'\nimport type { NodeRenderData } from 'comark'\nimport { CmsMarkdownDocument as CmsMarkdownDocumentSchema } from '@internal/protocol/Documents'\nimport { resolveAttributes } from 'comark/utils'\nimport { Option, Predicate, Schema } from 'effect'\nimport { mutableJson, mutableJsonObject, toMutableComarkAttributes } from './document-adapter'\n\nconst isJsonObject = Schema.is(Schema.JsonObject)\n\nconst decodeJson = Schema.decodeUnknownOption(Schema.Json)\n\nexport type CmsComarkAttributeValue = Schema.Json | undefined\n\nexport type CmsComarkAttributes = ReadonlyMap<string, CmsComarkAttributeValue>\n\ninterface CmsEditorComponentProjection {\n readonly bindings: Schema.JsonObject\n readonly props: Schema.JsonObject\n readonly renderData: NodeRenderData\n}\n\n/** Normalizes bindings exactly as Comark's framework renderers do before passing props to a component. */\nexport function resolveCmsComarkAttributes(\n attributes: Schema.JsonObject,\n renderData: NodeRenderData,\n): CmsComarkAttributes {\n const resolved = new Map<string, CmsComarkAttributeValue>()\n\n for (const [name, value] of Object.entries(\n resolveAttributes(toMutableComarkAttributes(attributes), renderData, { parseJson: true }),\n )) {\n if (Predicate.isUndefined(value)) {\n resolved.set(name, undefined)\n continue\n }\n\n const decoded = decodeJson(value)\n\n if (Option.isNone(decoded)) throw new Error(`Comark resolved non-JSON attribute \"${name}\".`)\n resolved.set(name, decoded.value)\n }\n\n return resolved\n}\n\n/** Projects bindings to editable values while retaining enough metadata to reconstruct their authored form. */\nexport function projectCmsEditorComponentAttributes(\n attributes: Schema.JsonObject,\n renderData: NodeRenderData,\n): CmsEditorComponentProjection {\n const resolved = resolveCmsComarkAttributes(attributes, renderData)\n const props: Record<string, Schema.Json> = {}\n\n for (const [name, value] of resolved) {\n if (!Predicate.isUndefined(value)) props[name] = mutableJson(value)\n }\n\n const bindings: Record<string, Schema.Json> = {}\n\n for (const [authoredName, authoredValue] of Object.entries(attributes)) {\n if (!authoredName.startsWith(':') || authoredName.length === 1) continue\n const name = authoredName.slice(1)\n\n if (!resolved.has(name)) continue\n const literal = jsonLiteral(authoredValue)\n\n if (!Predicate.isString(authoredValue) || literal !== authoredValue) {\n bindings[name] = { kind: 'literal' }\n continue\n }\n\n const resolvedValue = resolved.get(name)\n bindings[name] = Object.assign(\n { expression: authoredValue, kind: 'expression' },\n Predicate.isUndefined(resolvedValue) ? undefined : { resolved: mutableJson(resolvedValue) },\n )\n }\n\n return { bindings, props, renderData: withCmsComarkProps(renderData, resolved) }\n}\n\n/** Reconstructs authored bindings, keeping expressions until a user replaces their resolved value. */\nexport function encodeCmsEditorComponentAttributes(\n props: Schema.JsonObject,\n bindings: Schema.JsonObject,\n): Schema.JsonObject {\n const attributes = mutableJsonObject(props)\n\n for (const [name, encodedBinding] of Object.entries(bindings)) {\n const binding = jsonObject(encodedBinding)\n const kind = binding.kind\n\n if (kind !== 'literal' && kind !== 'expression') continue\n const current = props[name]\n\n if (Predicate.isUndefined(current)) {\n const expression = binding.expression\n\n if (kind === 'expression' && Predicate.isString(expression)) attributes[`:${name}`] = expression\n continue\n }\n\n delete attributes[name]\n const expression = binding.expression\n const resolved = binding.resolved\n attributes[`:${name}`] =\n kind === 'expression' &&\n Predicate.isString(expression) &&\n Object.hasOwn(binding, 'resolved') &&\n sameJson(current, resolved)\n ? expression\n : mutableJson(current)\n }\n\n return attributes\n}\n\nexport function withCmsComarkProps(renderData: NodeRenderData, attributes: CmsComarkAttributes): NodeRenderData {\n return attributes.size > 0 ? { ...renderData, props: Object.fromEntries(attributes) } : renderData\n}\n\n/** Restores typed component bindings that Comark's block-YAML roundtrip can emit as plain attributes. */\nexport function normalizeCmsComponentBindings(\n document: CmsMarkdownDocument,\n components: ReadonlyMap<string, ComponentDefinition> | undefined,\n): CmsMarkdownDocument {\n if (!components) return document\n\n return CmsMarkdownDocumentSchema.make({\n frontmatter: document.frontmatter,\n meta: document.meta,\n nodes: document.nodes.map((node) => normalizeComponentNode(node, components)),\n })\n}\n\nexport function matchesCmsComponentPropType(\n value: CmsComarkAttributeValue,\n type: ComponentDefinition['authoring']['props'][number]['type'],\n): boolean {\n switch (type) {\n case 'object':\n return isJsonObject(value)\n case 'array':\n return Array.isArray(value)\n case 'boolean':\n return Predicate.isBoolean(value)\n case 'number':\n return Predicate.isNumber(value)\n case 'string':\n return Predicate.isString(value)\n }\n}\n\nfunction normalizeComponentNode(\n node: MarkdownNode,\n components: ReadonlyMap<string, ComponentDefinition>,\n): MarkdownNode {\n if (Predicate.isString(node) || node[0] === null) return node\n const [tag, originalAttributes, ...originalChildren] = node\n const attributes = mutableJsonObject(originalAttributes)\n const definition = components.get(tag.toLocaleLowerCase())\n\n if (definition) {\n for (const prop of definition.authoring.props) {\n if (prop.type === 'string' || `:${prop.name}` in attributes || !(prop.name in attributes)) continue\n const value = attributes[prop.name]\n\n if (Predicate.isUndefined(value)) continue\n const resolved = jsonLiteral(value)\n\n if (!matchesCmsComponentPropType(resolved, prop.type)) continue\n delete attributes[prop.name]\n attributes[`:${prop.name}`] = value\n }\n }\n\n return [tag, attributes, ...originalChildren.map((child) => normalizeComponentNode(child, components))]\n}\n\nfunction jsonLiteral(value: Schema.Json | undefined): CmsComarkAttributeValue {\n if (!Predicate.isString(value)) return value\n\n try {\n const decoded = decodeJson(JSON.parse(value))\n\n return Option.isSome(decoded) ? decoded.value : value\n } catch {\n return value\n }\n}\n\nfunction jsonObject(value: Schema.Json | undefined): Schema.JsonObject {\n return isJsonObject(value) ? value : {}\n}\n\nfunction sameJson(left: Schema.Json, right: Schema.Json | undefined): boolean {\n return !Predicate.isUndefined(right) && JSON.stringify(left) === JSON.stringify(right)\n}\n","import { createCmsComarkRenderData } from './internal/comark/document-adapter'\nimport { projectCmsEditorComponentAttributes } from './internal/comark/bindings'\nimport type { NodeRenderData } from 'comark'\nimport type { BlockAuthoring, BlockProp } from '@internal/protocol/Authoring'\nimport type { ComponentDefinition } from '@internal/protocol/Configuration'\nimport type { CmsMarkdownDocument } from '@internal/protocol/Documents'\nimport type { FormCapabilities, FormDefinition, FormField, FormStep, FormValues } from '@internal/protocol/Forms'\nimport { FORM_REVISION_MAX_BYTES, FormSteps } from '@internal/protocol/Forms'\nimport { Predicate, Result, Schema } from 'effect'\n\nexport function formStructureIssues(\n input: Schema.Json | undefined,\n capabilities: FormCapabilities,\n name: string,\n): string[] {\n const decoded = Schema.decodeUnknownResult(FormSteps)(input, { onExcessProperty: 'error' })\n\n if (Result.isFailure(decoded)) return ['Each form needs steps with a title and at least one valid question.']\n const issues: string[] = []\n const revisionBytes = new TextEncoder().encode(JSON.stringify(formRevision(name, capabilities, decoded.success)))\n\n if (revisionBytes.byteLength > FORM_REVISION_MAX_BYTES)\n issues.push('This form is too large. Reduce the number or size of questions.')\n const ids = new Set<string>()\n\n for (const step of decoded.success) {\n if (ids.has(step.id)) issues.push('Steps and questions must have unique identities.')\n ids.add(step.id)\n\n for (const field of step.fields) {\n if (ids.has(field.id)) issues.push('Steps and questions must have unique identities.')\n ids.add(field.id)\n\n if (['_form', '__proto__', 'constructor', 'prototype'].includes(field.id))\n issues.push('This question identity is reserved.')\n\n if (!capabilities.fieldTypes.includes(field.type))\n issues.push(`${field.label}: this question type is unavailable.`)\n\n for (const rule of ['required', 'minLength', 'maxLength', 'min', 'max'] as const) {\n if (field[rule] !== undefined && !capabilities.rules.includes(rule))\n issues.push(`${field.label}: ${rule} is unavailable.`)\n }\n\n const text = ['text', 'email', 'textarea'].includes(field.type)\n\n if (!text && (field.minLength !== undefined || field.maxLength !== undefined))\n issues.push(`${field.label}: length limits require a text question.`)\n\n if (field.type !== 'number' && (field.min !== undefined || field.max !== undefined))\n issues.push(`${field.label}: numeric limits require a number question.`)\n\n if (field.min !== undefined && field.max !== undefined && field.min > field.max)\n issues.push(`${field.label}: minimum exceeds maximum.`)\n\n if (field.minLength !== undefined && field.maxLength !== undefined && field.minLength > field.maxLength)\n issues.push(`${field.label}: minimum length exceeds maximum length.`)\n const options = field.options ?? []\n\n if (\n field.type === 'select' &&\n (!options.length || new Set(options.map((option) => option.id)).size !== options.length)\n )\n issues.push(`${field.label}: choices need unique identities and at least one option.`)\n\n if (field.type !== 'select' && options.length) issues.push(`${field.label}: choices require a select question.`)\n }\n }\n\n return issues\n}\n\nexport function validateFormValues(fields: ReadonlyArray<FormField>, values: FormValues): Record<string, string> {\n return Object.fromEntries(\n fields.flatMap((field) => {\n const issue = fieldIssue(field, Object.hasOwn(values, field.id) ? values[field.id] : undefined)\n\n return issue ? [[field.id, issue]] : []\n }),\n )\n}\n\nfunction fieldIssue(field: FormField, value: FormValues[string] | undefined): string | undefined {\n const empty = value === undefined || value === null || value === '' || (Predicate.isString(value) && !value.trim())\n\n if (empty) return field.required ? `${field.label} is required.` : undefined\n\n if (field.type === 'checkbox')\n return !Predicate.isBoolean(value)\n ? 'Choose yes or no.'\n : field.required && !value\n ? `${field.label} must be checked.`\n : undefined\n\n if (field.type === 'number') {\n if (!Predicate.isNumber(value) || !Number.isFinite(value)) return 'Enter a number.'\n\n if (field.min !== undefined && value < field.min) return `Enter at least ${field.min}.`\n\n if (field.max !== undefined && value > field.max) return `Enter at most ${field.max}.`\n\n return undefined\n }\n\n if (!Predicate.isString(value)) return 'Enter text.'\n\n if (field.type === 'select' && !field.options?.some((option) => option.id === value))\n return 'Choose an available option.'\n\n if (field.type === 'email' && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/u.test(value)) return 'Enter a valid email address.'\n\n if (field.minLength !== undefined && value.length < field.minLength)\n return `Enter at least ${field.minLength} characters.`\n\n if (field.maxLength !== undefined && value.length > field.maxLength)\n return `Enter at most ${field.maxLength} characters.`\n\n return undefined\n}\n\n/** Paths refer to authored nodes, never rendered Vue children. Revision comparison is exact. */\nexport function documentForms(\n document: { readonly id: FormDefinition['documentId']; readonly body: CmsMarkdownDocument },\n components: ReadonlyArray<ComponentDefinition>,\n preview = false,\n): FormDefinition[] {\n const forms: FormDefinition[] = []\n\n const visit = (nodes: CmsMarkdownDocument['nodes'], parent: number[], renderData: NodeRenderData) => {\n nodes.forEach((node, index) => {\n if (Predicate.isString(node) || node[0] === null) return\n const nodePath = [...parent, index]\n const projection = projectCmsEditorComponentAttributes(node[1], renderData)\n const capabilities = components.find((component) => component.name === node[0])?.authoring.form\n\n if (capabilities && !formStructureIssues(projection.props.steps, capabilities, node[0]).length) {\n const steps = Result.getOrThrow(Schema.decodeUnknownResult(FormSteps)(projection.props.steps))\n forms.push({\n name: node[0],\n documentId: document.id,\n nodePath,\n steps,\n preview,\n revision: formRevision(node[0], capabilities, steps),\n })\n }\n\n visit(node.slice(2).filter(isNode), nodePath, projection.renderData)\n })\n }\n\n visit(document.body.nodes, [], createCmsComarkRenderData(document.body))\n\n return forms\n}\n\nfunction formRevision(name: string, capabilities: FormCapabilities, steps: ReadonlyArray<FormStep>): string {\n return JSON.stringify([name, capabilities, steps])\n}\n\nfunction isNode(value: Schema.Json | undefined): value is CmsMarkdownDocument['nodes'][number] {\n return Predicate.isString(value) || Array.isArray(value)\n}\n\nexport function formAuthoring(capabilities: FormCapabilities): BlockAuthoring {\n const prop = (\n name: string,\n label: string,\n type: BlockProp['type'],\n input: BlockProp['input'],\n extra: Partial<BlockProp> = {},\n ): BlockProp => ({ name, label, type, input, required: false, nullable: false, options: [], ...extra })\n\n const question = [\n prop('label', 'Question', 'string', 'text', { required: true, defaultValue: 'New question' }),\n prop('type', 'Answer type', 'string', 'select', {\n required: true,\n defaultValue: capabilities.fieldTypes[0],\n options: capabilities.fieldTypes.map((value) => ({ value, label: value })),\n }),\n prop('help', 'Help text', 'string', 'textarea'),\n ...capabilities.rules.map((rule) =>\n prop(\n rule,\n {\n required: 'Required',\n minLength: 'Minimum characters',\n maxLength: 'Maximum characters',\n min: 'Minimum value',\n max: 'Maximum value',\n }[rule],\n rule === 'required' ? 'boolean' : 'number',\n rule === 'required' ? 'toggle' : 'number',\n ),\n ),\n prop('options', 'Choices', 'array', 'list', {\n fields: [prop('label', 'Choice', 'string', 'text', { required: true, defaultValue: 'New choice' })],\n }),\n ]\n\n return {\n version: 1,\n label: capabilities.label,\n group: 'Forms',\n form: capabilities,\n props: [\n prop('steps', 'Steps', 'array', 'list', {\n required: true,\n fields: [\n prop('title', 'Step title', 'string', 'text', { required: true, defaultValue: 'New step' }),\n prop('fields', 'Questions', 'array', 'list', { required: true, fields: question }),\n ],\n }),\n ],\n slots: [],\n initialProps: {\n steps: [\n {\n id: 'first-step',\n title: 'Your details',\n fields: [\n {\n id: 'first-question',\n label: 'Your answer',\n type: capabilities.fieldTypes[0] ?? 'text',\n ...(capabilities.fieldTypes[0] === 'select'\n ? { options: [{ id: 'first-choice', label: 'First choice' }] }\n : undefined),\n },\n ],\n },\n ],\n },\n }\n}\n"],"mappings":";;;;;;AAUA,MAAMA,iBAAe,OAAO,GAAG,OAAO,UAAU;AAEhD,SAAgB,iBAAiB,UAAuD;CACtF,OAAO;EACL,aAAa,kBAAkB,SAAS,WAAW;EACnD,MAAM,kBAAkB,SAAS,IAAI;EACrC,OAAO,SAAS,MAAM,IAAI,YAAY;CACxC;AACF;AAEA,SAAgB,0BAA0B,UAA+C;CACvF,OAAO;EACL,MAAM,CAAC;EACP,aAAa,kBAAkB,SAAS,WAAW;EACnD,MAAM,kBAAkB,SAAS,IAAI;EACrC,OAAO,CAAC;CACV;AACF;;AAGA,SAAgB,qBAAqB,MAA4B;CAC/D,OAAO,YAAY,aAAa,IAAI,GAAG,EAAE,uBAAuB,KAAK,CAAC;AACxE;AAEA,SAAgB,0BAA0B,YAAsD;CAC9F,MAAM,SAAgC,CAAC;CAEvC,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,UAAU,GACnD,IAAI,SAAS,KAAK,OAAO,QAAQ,YAAY,KAAK;CAGpD,MAAM,WAAWC,aAAW,WAAW,CAAC;CACxC,MAAM,OAAO,SAAS;CACtB,MAAM,OAAO,WAAW,SAAS,IAAI;CACrC,MAAM,QAAQ,WAAW,SAAS,KAAK;CAEvC,IAAI,UAAU,SAAS,IAAI,KAAK,SAAS,UAAa,UAAU,QAAW;EACzE,MAAM,WAAmC,CAAC;EAE1C,IAAI,UAAU,SAAS,IAAI,GAAG,SAAS,OAAO;EAE9C,IAAI,SAAS,QAAW,SAAS,OAAO;EAExC,IAAI,UAAU,QAAW,SAAS,QAAQ;EAC1C,OAAO,IAAI;CACb;CAEA,OAAO;AACT;AAEA,SAAgB,YAAY,OAAiC;CAC3D,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,IAAI,WAAW;CAEtD,IAAID,eAAa,KAAK,GAAG,OAAO,kBAAkB,KAAK;CAEvD,OAAO;AACT;AAEA,SAAS,aAAa,MAAgC;CACpD,IAAI,UAAU,SAAS,IAAI,GAAG,OAAO;CAErC,IAAI,KAAK,OAAO,MAAM,OAAO;EAAC;EAAM,0BAA0B,KAAK,EAAE;EAAG,KAAK;CAAE;CAC/E,MAAM,CAAC,KAAK,YAAY,GAAG,YAAY;CAEvC,OAAO;EAAC;EAAK,0BAA0B,UAAU;EAAG,GAAG,SAAS,IAAI,YAAY;CAAC;AACnF;AAEA,SAAgB,kBAAkB,OAAuD;CACvF,OAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,WAAW,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC;AAClG;AAEA,SAAS,WAAW,OAAmD;CACrE,OAAO,UAAU,KAAK,UAAU,IAAI,QAAQ;AAC9C;AAEA,SAASC,aAAW,OAAmD;CACrE,OAAOD,eAAa,KAAK,IAAI,QAAQ,CAAC;AACxC;;;;AC/EA,MAAM,eAAe,OAAO,GAAG,OAAO,UAAU;AAEhD,MAAM,aAAa,OAAO,oBAAoB,OAAO,IAAI;;AAazD,SAAgB,2BACd,YACA,YACqB;CACrB,MAAM,2BAAW,IAAI,IAAqC;CAE1D,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QACjC,kBAAkB,0BAA0B,UAAU,GAAG,YAAY,EAAE,WAAW,KAAK,CAAC,CAC1F,GAAG;EACD,IAAI,UAAU,YAAY,KAAK,GAAG;GAChC,SAAS,IAAI,MAAM,MAAS;GAC5B;EACF;EAEA,MAAM,UAAU,WAAW,KAAK;EAEhC,IAAI,OAAO,OAAO,OAAO,GAAG,MAAM,IAAI,MAAM,uCAAuC,KAAK,GAAG;EAC3F,SAAS,IAAI,MAAM,QAAQ,KAAK;CAClC;CAEA,OAAO;AACT;;AAGA,SAAgB,oCACd,YACA,YAC8B;CAC9B,MAAM,WAAW,2BAA2B,YAAY,UAAU;CAClE,MAAM,QAAqC,CAAC;CAE5C,KAAK,MAAM,CAAC,MAAM,UAAU,UAC1B,IAAI,CAAC,UAAU,YAAY,KAAK,GAAG,MAAM,QAAQ,YAAY,KAAK;CAGpE,MAAM,WAAwC,CAAC;CAE/C,KAAK,MAAM,CAAC,cAAc,kBAAkB,OAAO,QAAQ,UAAU,GAAG;EACtE,IAAI,CAAC,aAAa,WAAW,GAAG,KAAK,aAAa,WAAW,GAAG;EAChE,MAAM,OAAO,aAAa,MAAM,CAAC;EAEjC,IAAI,CAAC,SAAS,IAAI,IAAI,GAAG;EACzB,MAAM,UAAU,YAAY,aAAa;EAEzC,IAAI,CAAC,UAAU,SAAS,aAAa,KAAK,YAAY,eAAe;GACnE,SAAS,QAAQ,EAAE,MAAM,UAAU;GACnC;EACF;EAEA,MAAM,gBAAgB,SAAS,IAAI,IAAI;EACvC,SAAS,QAAQ,OAAO,OACtB;GAAE,YAAY;GAAe,MAAM;EAAa,GAChD,UAAU,YAAY,aAAa,IAAI,SAAY,EAAE,UAAU,YAAY,aAAa,EAAE,CAC5F;CACF;CAEA,OAAO;EAAE;EAAU;EAAO,YAAY,mBAAmB,YAAY,QAAQ;CAAE;AACjF;;AAGA,SAAgB,mCACd,OACA,UACmB;CACnB,MAAM,aAAa,kBAAkB,KAAK;CAE1C,KAAK,MAAM,CAAC,MAAM,mBAAmB,OAAO,QAAQ,QAAQ,GAAG;EAC7D,MAAM,UAAU,WAAW,cAAc;EACzC,MAAM,OAAO,QAAQ;EAErB,IAAI,SAAS,aAAa,SAAS,cAAc;EACjD,MAAM,UAAU,MAAM;EAEtB,IAAI,UAAU,YAAY,OAAO,GAAG;GAClC,MAAM,aAAa,QAAQ;GAE3B,IAAI,SAAS,gBAAgB,UAAU,SAAS,UAAU,GAAG,WAAW,IAAI,UAAU;GACtF;EACF;EAEA,OAAO,WAAW;EAClB,MAAM,aAAa,QAAQ;EAC3B,MAAM,WAAW,QAAQ;EACzB,WAAW,IAAI,UACb,SAAS,gBACT,UAAU,SAAS,UAAU,KAC7B,OAAO,OAAO,SAAS,UAAU,KACjC,SAAS,SAAS,QAAQ,IACtB,aACA,YAAY,OAAO;CAC3B;CAEA,OAAO;AACT;AAEA,SAAgB,mBAAmB,YAA4B,YAAiD;CAC9G,OAAO,WAAW,OAAO,IAAI;EAAE,GAAG;EAAY,OAAO,OAAO,YAAY,UAAU;CAAE,IAAI;AAC1F;;AAGA,SAAgB,8BACd,UACA,YACqB;CACrB,IAAI,CAAC,YAAY,OAAO;CAExB,OAAOE,oBAA0B,KAAK;EACpC,aAAa,SAAS;EACtB,MAAM,SAAS;EACf,OAAO,SAAS,MAAM,KAAK,SAAS,uBAAuB,MAAM,UAAU,CAAC;CAC9E,CAAC;AACH;AAEA,SAAgB,4BACd,OACA,MACS;CACT,QAAQ,MAAR;EACE,KAAK,UACH,OAAO,aAAa,KAAK;EAC3B,KAAK,SACH,OAAO,MAAM,QAAQ,KAAK;EAC5B,KAAK,WACH,OAAO,UAAU,UAAU,KAAK;EAClC,KAAK,UACH,OAAO,UAAU,SAAS,KAAK;EACjC,KAAK,UACH,OAAO,UAAU,SAAS,KAAK;CACnC;AACF;AAEA,SAAS,uBACP,MACA,YACc;CACd,IAAI,UAAU,SAAS,IAAI,KAAK,KAAK,OAAO,MAAM,OAAO;CACzD,MAAM,CAAC,KAAK,oBAAoB,GAAG,oBAAoB;CACvD,MAAM,aAAa,kBAAkB,kBAAkB;CACvD,MAAM,aAAa,WAAW,IAAI,IAAI,kBAAkB,CAAC;CAEzD,IAAI,YACF,KAAK,MAAM,QAAQ,WAAW,UAAU,OAAO;EAC7C,IAAI,KAAK,SAAS,YAAY,IAAI,KAAK,UAAU,cAAc,EAAE,KAAK,QAAQ,aAAa;EAC3F,MAAM,QAAQ,WAAW,KAAK;EAE9B,IAAI,UAAU,YAAY,KAAK,GAAG;EAGlC,IAAI,CAAC,4BAFY,YAAY,KAEW,GAAG,KAAK,IAAI,GAAG;EACvD,OAAO,WAAW,KAAK;EACvB,WAAW,IAAI,KAAK,UAAU;CAChC;CAGF,OAAO;EAAC;EAAK;EAAY,GAAG,iBAAiB,KAAK,UAAU,uBAAuB,OAAO,UAAU,CAAC;CAAC;AACxG;AAEA,SAAS,YAAY,OAAyD;CAC5E,IAAI,CAAC,UAAU,SAAS,KAAK,GAAG,OAAO;CAEvC,IAAI;EACF,MAAM,UAAU,WAAW,KAAK,MAAM,KAAK,CAAC;EAE5C,OAAO,OAAO,OAAO,OAAO,IAAI,QAAQ,QAAQ;CAClD,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,WAAW,OAAmD;CACrE,OAAO,aAAa,KAAK,IAAI,QAAQ,CAAC;AACxC;AAEA,SAAS,SAAS,MAAmB,OAAyC;CAC5E,OAAO,CAAC,UAAU,YAAY,KAAK,KAAK,KAAK,UAAU,IAAI,MAAM,KAAK,UAAU,KAAK;AACvF;;;;AC5LA,SAAgB,oBACd,OACA,cACA,MACU;CACV,MAAM,UAAU,OAAO,oBAAoB,SAAS,CAAC,CAAC,OAAO,EAAE,kBAAkB,QAAQ,CAAC;CAE1F,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO,CAAC,qEAAqE;CAC5G,MAAM,SAAmB,CAAC;CAG1B,IAFsB,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,UAAU,aAAa,MAAM,cAAc,QAAQ,OAAO,CAAC,CAE/F,CAAC,CAAC,kBAChB,OAAO,KAAK,iEAAiE;CAC/E,MAAM,sBAAM,IAAI,IAAY;CAE5B,KAAK,MAAM,QAAQ,QAAQ,SAAS;EAClC,IAAI,IAAI,IAAI,KAAK,EAAE,GAAG,OAAO,KAAK,kDAAkD;EACpF,IAAI,IAAI,KAAK,EAAE;EAEf,KAAK,MAAM,SAAS,KAAK,QAAQ;GAC/B,IAAI,IAAI,IAAI,MAAM,EAAE,GAAG,OAAO,KAAK,kDAAkD;GACrF,IAAI,IAAI,MAAM,EAAE;GAEhB,IAAI;IAAC;IAAS;IAAa;IAAe;GAAW,CAAC,CAAC,SAAS,MAAM,EAAE,GACtE,OAAO,KAAK,qCAAqC;GAEnD,IAAI,CAAC,aAAa,WAAW,SAAS,MAAM,IAAI,GAC9C,OAAO,KAAK,GAAG,MAAM,MAAM,qCAAqC;GAElE,KAAK,MAAM,QAAQ;IAAC;IAAY;IAAa;IAAa;IAAO;GAAK,GACpE,IAAI,MAAM,UAAU,UAAa,CAAC,aAAa,MAAM,SAAS,IAAI,GAChE,OAAO,KAAK,GAAG,MAAM,MAAM,IAAI,KAAK,iBAAiB;GAKzD,IAAI,CAFS;IAAC;IAAQ;IAAS;GAAU,CAAC,CAAC,SAAS,MAAM,IAElD,MAAM,MAAM,cAAc,UAAa,MAAM,cAAc,SACjE,OAAO,KAAK,GAAG,MAAM,MAAM,yCAAyC;GAEtE,IAAI,MAAM,SAAS,aAAa,MAAM,QAAQ,UAAa,MAAM,QAAQ,SACvE,OAAO,KAAK,GAAG,MAAM,MAAM,4CAA4C;GAEzE,IAAI,MAAM,QAAQ,UAAa,MAAM,QAAQ,UAAa,MAAM,MAAM,MAAM,KAC1E,OAAO,KAAK,GAAG,MAAM,MAAM,2BAA2B;GAExD,IAAI,MAAM,cAAc,UAAa,MAAM,cAAc,UAAa,MAAM,YAAY,MAAM,WAC5F,OAAO,KAAK,GAAG,MAAM,MAAM,yCAAyC;GACtE,MAAM,UAAU,MAAM,WAAW,CAAC;GAElC,IACE,MAAM,SAAS,aACd,CAAC,QAAQ,UAAU,IAAI,IAAI,QAAQ,KAAK,WAAW,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,QAAQ,SAEjF,OAAO,KAAK,GAAG,MAAM,MAAM,0DAA0D;GAEvF,IAAI,MAAM,SAAS,YAAY,QAAQ,QAAQ,OAAO,KAAK,GAAG,MAAM,MAAM,qCAAqC;EACjH;CACF;CAEA,OAAO;AACT;AAEA,SAAgB,mBAAmB,QAAkC,QAA4C;CAC/G,OAAO,OAAO,YACZ,OAAO,SAAS,UAAU;EACxB,MAAM,QAAQ,WAAW,OAAO,OAAO,OAAO,QAAQ,MAAM,EAAE,IAAI,OAAO,MAAM,MAAM,MAAS;EAE9F,OAAO,QAAQ,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC;CACxC,CAAC,CACH;AACF;AAEA,SAAS,WAAW,OAAkB,OAA2D;CAG/F,IAFc,UAAU,UAAa,UAAU,QAAQ,UAAU,MAAO,UAAU,SAAS,KAAK,KAAK,CAAC,MAAM,KAAK,GAEtG,OAAO,MAAM,WAAW,GAAG,MAAM,MAAM,iBAAiB;CAEnE,IAAI,MAAM,SAAS,YACjB,OAAO,CAAC,UAAU,UAAU,KAAK,IAC7B,sBACA,MAAM,YAAY,CAAC,QACjB,GAAG,MAAM,MAAM,qBACf;CAER,IAAI,MAAM,SAAS,UAAU;EAC3B,IAAI,CAAC,UAAU,SAAS,KAAK,KAAK,CAAC,OAAO,SAAS,KAAK,GAAG,OAAO;EAElE,IAAI,MAAM,QAAQ,UAAa,QAAQ,MAAM,KAAK,OAAO,kBAAkB,MAAM,IAAI;EAErF,IAAI,MAAM,QAAQ,UAAa,QAAQ,MAAM,KAAK,OAAO,iBAAiB,MAAM,IAAI;EAEpF;CACF;CAEA,IAAI,CAAC,UAAU,SAAS,KAAK,GAAG,OAAO;CAEvC,IAAI,MAAM,SAAS,YAAY,CAAC,MAAM,SAAS,MAAM,WAAW,OAAO,OAAO,KAAK,GACjF,OAAO;CAET,IAAI,MAAM,SAAS,WAAW,CAAC,8BAA8B,KAAK,KAAK,GAAG,OAAO;CAEjF,IAAI,MAAM,cAAc,UAAa,MAAM,SAAS,MAAM,WACxD,OAAO,kBAAkB,MAAM,UAAU;CAE3C,IAAI,MAAM,cAAc,UAAa,MAAM,SAAS,MAAM,WACxD,OAAO,iBAAiB,MAAM,UAAU;AAG5C;;AAGA,SAAgB,cACd,UACA,YACA,UAAU,OACQ;CAClB,MAAM,QAA0B,CAAC;CAEjC,MAAM,SAAS,OAAqC,QAAkB,eAA+B;EACnG,MAAM,SAAS,MAAM,UAAU;GAC7B,IAAI,UAAU,SAAS,IAAI,KAAK,KAAK,OAAO,MAAM;GAClD,MAAM,WAAW,CAAC,GAAG,QAAQ,KAAK;GAClC,MAAM,aAAa,oCAAoC,KAAK,IAAI,UAAU;GAC1E,MAAM,eAAe,WAAW,MAAM,cAAc,UAAU,SAAS,KAAK,EAAE,CAAC,EAAE,UAAU;GAE3F,IAAI,gBAAgB,CAAC,oBAAoB,WAAW,MAAM,OAAO,cAAc,KAAK,EAAE,CAAC,CAAC,QAAQ;IAC9F,MAAM,QAAQ,OAAO,WAAW,OAAO,oBAAoB,SAAS,CAAC,CAAC,WAAW,MAAM,KAAK,CAAC;IAC7F,MAAM,KAAK;KACT,MAAM,KAAK;KACX,YAAY,SAAS;KACrB;KACA;KACA;KACA,UAAU,aAAa,KAAK,IAAI,cAAc,KAAK;IACrD,CAAC;GACH;GAEA,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,GAAG,UAAU,WAAW,UAAU;EACrE,CAAC;CACH;CAEA,MAAM,SAAS,KAAK,OAAO,CAAC,GAAG,0BAA0B,SAAS,IAAI,CAAC;CAEvE,OAAO;AACT;AAEA,SAAS,aAAa,MAAc,cAAgC,OAAwC;CAC1G,OAAO,KAAK,UAAU;EAAC;EAAM;EAAc;CAAK,CAAC;AACnD;AAEA,SAAS,OAAO,OAA+E;CAC7F,OAAO,UAAU,SAAS,KAAK,KAAK,MAAM,QAAQ,KAAK;AACzD;AAEA,SAAgB,cAAc,cAAgD;CAC5E,MAAM,QACJ,MACA,OACA,MACA,OACA,QAA4B,CAAC,OACd;EAAE;EAAM;EAAO;EAAM;EAAO,UAAU;EAAO,UAAU;EAAO,SAAS,CAAC;EAAG,GAAG;CAAM;CAErG,MAAM,WAAW;EACf,KAAK,SAAS,YAAY,UAAU,QAAQ;GAAE,UAAU;GAAM,cAAc;EAAe,CAAC;EAC5F,KAAK,QAAQ,eAAe,UAAU,UAAU;GAC9C,UAAU;GACV,cAAc,aAAa,WAAW;GACtC,SAAS,aAAa,WAAW,KAAK,WAAW;IAAE;IAAO,OAAO;GAAM,EAAE;EAC3E,CAAC;EACD,KAAK,QAAQ,aAAa,UAAU,UAAU;EAC9C,GAAG,aAAa,MAAM,KAAK,SACzB,KACE,MACA;GACE,UAAU;GACV,WAAW;GACX,WAAW;GACX,KAAK;GACL,KAAK;EACP,EAAE,OACF,SAAS,aAAa,YAAY,UAClC,SAAS,aAAa,WAAW,QACnC,CACF;EACA,KAAK,WAAW,WAAW,SAAS,QAAQ,EAC1C,QAAQ,CAAC,KAAK,SAAS,UAAU,UAAU,QAAQ;GAAE,UAAU;GAAM,cAAc;EAAa,CAAC,CAAC,EACpG,CAAC;CACH;CAEA,OAAO;EACL,SAAS;EACT,OAAO,aAAa;EACpB,OAAO;EACP,MAAM;EACN,OAAO,CACL,KAAK,SAAS,SAAS,SAAS,QAAQ;GACtC,UAAU;GACV,QAAQ,CACN,KAAK,SAAS,cAAc,UAAU,QAAQ;IAAE,UAAU;IAAM,cAAc;GAAW,CAAC,GAC1F,KAAK,UAAU,aAAa,SAAS,QAAQ;IAAE,UAAU;IAAM,QAAQ;GAAS,CAAC,CACnF;EACF,CAAC,CACH;EACA,OAAO,CAAC;EACR,cAAc,EACZ,OAAO,CACL;GACE,IAAI;GACJ,OAAO;GACP,QAAQ,CACN;IACE,IAAI;IACJ,OAAO;IACP,MAAM,aAAa,WAAW,MAAM;IACpC,GAAI,aAAa,WAAW,OAAO,WAC/B,EAAE,SAAS,CAAC;KAAE,IAAI;KAAgB,OAAO;IAAe,CAAC,EAAE,IAC3D;GACN,CACF;EACF,CACF,EACF;CACF;AACF"}
1
+ {"version":3,"file":"Forms-02-p8qEw.js","names":["isJsonObject","jsonObject","CmsMarkdownDocumentSchema"],"sources":["../../../../document/src/internal/comark/document-adapter.ts","../../../../document/src/internal/comark/bindings.ts","../../../../document/src/Forms.ts"],"sourcesContent":["import type { CmsMarkdownDocument, MarkdownNode } from '@internal/protocol/Documents'\nimport type {\n ElementNodeAttributes,\n MarkdownDocument as ComarkMarkdownDocument,\n Node as ComarkNode,\n NodeRenderData,\n} from 'comark'\nimport { textContent } from 'comark/utils'\nimport { Predicate, Schema } from 'effect'\n\nconst isJsonObject = Schema.is(Schema.JsonObject)\n\nexport function toComarkDocument(document: CmsMarkdownDocument): ComarkMarkdownDocument {\n return {\n frontmatter: mutableJsonObject(document.frontmatter),\n meta: mutableJsonObject(document.meta),\n nodes: document.nodes.map(toComarkNode),\n }\n}\n\nexport function createCmsComarkRenderData(document: CmsMarkdownDocument): NodeRenderData {\n return {\n data: {},\n frontmatter: mutableJsonObject(document.frontmatter),\n meta: mutableJsonObject(document.meta),\n props: {},\n }\n}\n\n/** Extracts inline text with Comark semantics, preserving punctuation between nested inline nodes. */\nexport function cmsComarkTextContent(node: MarkdownNode): string {\n return textContent(toComarkNode(node), { decodeUnicodeEntities: true })\n}\n\nexport function toMutableComarkAttributes(attributes: Schema.JsonObject): ElementNodeAttributes {\n const result: ElementNodeAttributes = {}\n\n for (const [name, value] of Object.entries(attributes)) {\n if (name !== '$') result[name] = mutableJson(value)\n }\n\n const internal = jsonObject(attributes.$)\n const line = internal.line\n const html = binaryFlag(internal.html)\n const block = binaryFlag(internal.block)\n\n if (Predicate.isNumber(line) || html !== undefined || block !== undefined) {\n const metadata: Record<string, number> = {}\n\n if (Predicate.isNumber(line)) metadata.line = line\n\n if (html !== undefined) metadata.html = html\n\n if (block !== undefined) metadata.block = block\n result.$ = metadata\n }\n\n return result\n}\n\nexport function mutableJson(value: Schema.Json): Schema.Json {\n if (Array.isArray(value)) return value.map(mutableJson)\n\n if (isJsonObject(value)) return mutableJsonObject(value)\n\n return value\n}\n\nfunction toComarkNode(node: MarkdownNode): ComarkNode {\n if (Predicate.isString(node)) return node\n\n if (node[0] === null) return [null, toMutableComarkAttributes(node[1]), node[2]]\n const [tag, attributes, ...children] = node\n\n return [tag, toMutableComarkAttributes(attributes), ...children.map(toComarkNode)]\n}\n\nexport function mutableJsonObject(value: Schema.JsonObject): Record<string, Schema.Json> {\n return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, mutableJson(child)]))\n}\n\nfunction binaryFlag(value: Schema.Json | undefined): 0 | 1 | undefined {\n return value === 0 || value === 1 ? value : undefined\n}\n\nfunction jsonObject(value: Schema.Json | undefined): Schema.JsonObject {\n return isJsonObject(value) ? value : {}\n}\n","import type { ComponentDefinition } from '@internal/protocol/Configuration'\nimport type { CmsMarkdownDocument, MarkdownNode } from '@internal/protocol/Documents'\nimport type { NodeRenderData } from 'comark'\nimport { CmsMarkdownDocument as CmsMarkdownDocumentSchema } from '@internal/protocol/Documents'\nimport { resolveAttributes } from 'comark/utils'\nimport { Option, Predicate, Schema } from 'effect'\nimport { mutableJson, mutableJsonObject, toMutableComarkAttributes } from './document-adapter'\n\nconst isJsonObject = Schema.is(Schema.JsonObject)\n\nconst decodeJson = Schema.decodeUnknownOption(Schema.Json)\n\nexport type CmsComarkAttributeValue = Schema.Json | undefined\n\nexport type CmsComarkAttributes = ReadonlyMap<string, CmsComarkAttributeValue>\n\ninterface CmsEditorComponentProjection {\n readonly bindings: Schema.JsonObject\n readonly props: Schema.JsonObject\n readonly renderData: NodeRenderData\n}\n\n/** Normalizes bindings exactly as Comark's framework renderers do before passing props to a component. */\nexport function resolveCmsComarkAttributes(\n attributes: Schema.JsonObject,\n renderData: NodeRenderData,\n): CmsComarkAttributes {\n const resolved = new Map<string, CmsComarkAttributeValue>()\n\n for (const [name, value] of Object.entries(\n resolveAttributes(toMutableComarkAttributes(attributes), renderData, { parseJson: true }),\n )) {\n if (Predicate.isUndefined(value)) {\n resolved.set(name, undefined)\n continue\n }\n\n const decoded = decodeJson(value)\n\n if (Option.isNone(decoded)) throw new Error(`Comark resolved non-JSON attribute \"${name}\".`)\n resolved.set(name, decoded.value)\n }\n\n return resolved\n}\n\n/** Projects bindings to editable values while retaining enough metadata to reconstruct their authored form. */\nexport function projectCmsEditorComponentAttributes(\n attributes: Schema.JsonObject,\n renderData: NodeRenderData,\n): CmsEditorComponentProjection {\n const resolved = resolveCmsComarkAttributes(attributes, renderData)\n const props: Record<string, Schema.Json> = {}\n\n for (const [name, value] of resolved) {\n if (!Predicate.isUndefined(value)) props[name] = mutableJson(value)\n }\n\n const bindings: Record<string, Schema.Json> = {}\n\n for (const [authoredName, authoredValue] of Object.entries(attributes)) {\n if (!authoredName.startsWith(':') || authoredName.length === 1) continue\n const name = authoredName.slice(1)\n\n if (!resolved.has(name)) continue\n const literal = jsonLiteral(authoredValue)\n\n if (!Predicate.isString(authoredValue) || literal !== authoredValue) {\n bindings[name] = { kind: 'literal' }\n continue\n }\n\n const resolvedValue = resolved.get(name)\n bindings[name] = Object.assign(\n { expression: authoredValue, kind: 'expression' },\n Predicate.isUndefined(resolvedValue) ? undefined : { resolved: mutableJson(resolvedValue) },\n )\n }\n\n return { bindings, props, renderData: withCmsComarkProps(renderData, resolved) }\n}\n\n/** Reconstructs authored bindings, keeping expressions until a user replaces their resolved value. */\nexport function encodeCmsEditorComponentAttributes(\n props: Schema.JsonObject,\n bindings: Schema.JsonObject,\n): Schema.JsonObject {\n const attributes = mutableJsonObject(props)\n\n for (const [name, encodedBinding] of Object.entries(bindings)) {\n const binding = jsonObject(encodedBinding)\n const kind = binding.kind\n\n if (kind !== 'literal' && kind !== 'expression') continue\n const current = props[name]\n\n if (Predicate.isUndefined(current)) {\n const expression = binding.expression\n\n if (kind === 'expression' && Predicate.isString(expression)) attributes[`:${name}`] = expression\n continue\n }\n\n delete attributes[name]\n const expression = binding.expression\n const resolved = binding.resolved\n attributes[`:${name}`] =\n kind === 'expression' &&\n Predicate.isString(expression) &&\n Object.hasOwn(binding, 'resolved') &&\n sameJson(current, resolved)\n ? expression\n : mutableJson(current)\n }\n\n return attributes\n}\n\nexport function withCmsComarkProps(renderData: NodeRenderData, attributes: CmsComarkAttributes): NodeRenderData {\n return attributes.size > 0 ? { ...renderData, props: Object.fromEntries(attributes) } : renderData\n}\n\n/** Restores typed component bindings that Comark's block-YAML roundtrip can emit as plain attributes. */\nexport function normalizeCmsComponentBindings(\n document: CmsMarkdownDocument,\n components: ReadonlyMap<string, ComponentDefinition> | undefined,\n): CmsMarkdownDocument {\n if (!components) return document\n\n return CmsMarkdownDocumentSchema.make({\n frontmatter: document.frontmatter,\n meta: document.meta,\n nodes: document.nodes.map((node) => normalizeComponentNode(node, components)),\n })\n}\n\nexport function matchesCmsComponentPropType(\n value: CmsComarkAttributeValue,\n type: ComponentDefinition['authoring']['props'][number]['type'],\n): boolean {\n switch (type) {\n case 'object':\n return isJsonObject(value)\n case 'array':\n return Array.isArray(value)\n case 'boolean':\n return Predicate.isBoolean(value)\n case 'number':\n return Predicate.isNumber(value)\n case 'string':\n return Predicate.isString(value)\n }\n}\n\nfunction normalizeComponentNode(\n node: MarkdownNode,\n components: ReadonlyMap<string, ComponentDefinition>,\n): MarkdownNode {\n if (Predicate.isString(node) || node[0] === null) return node\n const [tag, originalAttributes, ...originalChildren] = node\n const attributes = mutableJsonObject(originalAttributes)\n const definition = components.get(tag.toLocaleLowerCase())\n\n if (definition) {\n for (const prop of definition.authoring.props) {\n if (prop.type === 'string' || `:${prop.name}` in attributes || !(prop.name in attributes)) continue\n const value = attributes[prop.name]\n\n if (Predicate.isUndefined(value)) continue\n const resolved = jsonLiteral(value)\n\n if (!matchesCmsComponentPropType(resolved, prop.type)) continue\n delete attributes[prop.name]\n attributes[`:${prop.name}`] = value\n }\n }\n\n return [tag, attributes, ...originalChildren.map((child) => normalizeComponentNode(child, components))]\n}\n\nfunction jsonLiteral(value: Schema.Json | undefined): CmsComarkAttributeValue {\n if (!Predicate.isString(value)) return value\n\n try {\n const decoded = decodeJson(JSON.parse(value))\n\n return Option.isSome(decoded) ? decoded.value : value\n } catch {\n return value\n }\n}\n\nfunction jsonObject(value: Schema.Json | undefined): Schema.JsonObject {\n return isJsonObject(value) ? value : {}\n}\n\nfunction sameJson(left: Schema.Json, right: Schema.Json | undefined): boolean {\n return !Predicate.isUndefined(right) && JSON.stringify(left) === JSON.stringify(right)\n}\n","import { createCmsComarkRenderData } from './internal/comark/document-adapter'\nimport { projectCmsEditorComponentAttributes } from './internal/comark/bindings'\nimport type { NodeRenderData } from 'comark'\nimport type { BlockAuthoring, BlockProp } from '@internal/protocol/Authoring'\nimport type { ComponentDefinition } from '@internal/protocol/Configuration'\nimport type { CmsMarkdownDocument } from '@internal/protocol/Documents'\nimport type { FormCapabilities, FormDefinition, FormField, FormStep, FormValues } from '@internal/protocol/Forms'\nimport { FORM_REVISION_MAX_BYTES, FormSteps } from '@internal/protocol/Forms'\nimport { Predicate, Result, Schema } from 'effect'\n\nexport function formStructureIssues(\n input: Schema.Json | undefined,\n capabilities: FormCapabilities,\n name: string,\n): string[] {\n const decoded = Schema.decodeUnknownResult(FormSteps)(input, { onExcessProperty: 'error' })\n\n if (Result.isFailure(decoded)) return ['Each form needs steps with a title and at least one valid question.']\n const issues: string[] = []\n const revisionBytes = new TextEncoder().encode(JSON.stringify(formRevision(name, capabilities, decoded.success)))\n\n if (revisionBytes.byteLength > FORM_REVISION_MAX_BYTES)\n issues.push('This form is too large. Reduce the number or size of questions.')\n const ids = new Set<string>()\n\n for (const step of decoded.success) {\n if (ids.has(step.id)) issues.push('Steps and questions must have unique identities.')\n ids.add(step.id)\n\n for (const field of step.fields) {\n if (ids.has(field.id)) issues.push('Steps and questions must have unique identities.')\n ids.add(field.id)\n\n if (['_form', '__proto__', 'constructor', 'prototype'].includes(field.id))\n issues.push('This question identity is reserved.')\n\n if (!capabilities.fieldTypes.includes(field.type))\n issues.push(`${field.label}: this question type is unavailable.`)\n\n for (const rule of ['required', 'minLength', 'maxLength', 'min', 'max'] as const) {\n if (field[rule] !== undefined && !capabilities.rules.includes(rule))\n issues.push(`${field.label}: ${rule} is unavailable.`)\n }\n\n const text = ['text', 'email', 'textarea'].includes(field.type)\n\n if (!text && (field.minLength !== undefined || field.maxLength !== undefined))\n issues.push(`${field.label}: length limits require a text question.`)\n\n if (field.type !== 'number' && (field.min !== undefined || field.max !== undefined))\n issues.push(`${field.label}: numeric limits require a number question.`)\n\n if (field.min !== undefined && field.max !== undefined && field.min > field.max)\n issues.push(`${field.label}: minimum exceeds maximum.`)\n\n if (field.minLength !== undefined && field.maxLength !== undefined && field.minLength > field.maxLength)\n issues.push(`${field.label}: minimum length exceeds maximum length.`)\n const options = field.options ?? []\n\n if (\n field.type === 'select' &&\n (!options.length || new Set(options.map((option) => option.id)).size !== options.length)\n )\n issues.push(`${field.label}: choices need unique identities and at least one option.`)\n\n if (field.type !== 'select' && options.length) issues.push(`${field.label}: choices require a select question.`)\n }\n }\n\n return issues\n}\n\nexport function validateFormValues(fields: ReadonlyArray<FormField>, values: FormValues): Record<string, string> {\n return Object.fromEntries(\n fields.flatMap((field) => {\n const issue = fieldIssue(field, Object.hasOwn(values, field.id) ? values[field.id] : undefined)\n\n return issue ? [[field.id, issue]] : []\n }),\n )\n}\n\nfunction fieldIssue(field: FormField, value: FormValues[string] | undefined): string | undefined {\n const empty = value === undefined || value === null || value === '' || (Predicate.isString(value) && !value.trim())\n\n if (empty) return field.required ? `${field.label} is required.` : undefined\n\n if (field.type === 'checkbox')\n return !Predicate.isBoolean(value)\n ? 'Choose yes or no.'\n : field.required && !value\n ? `${field.label} must be checked.`\n : undefined\n\n if (field.type === 'number') {\n if (!Predicate.isNumber(value) || !Number.isFinite(value)) return 'Enter a number.'\n\n if (field.min !== undefined && value < field.min) return `Enter at least ${field.min}.`\n\n if (field.max !== undefined && value > field.max) return `Enter at most ${field.max}.`\n\n return undefined\n }\n\n if (!Predicate.isString(value)) return 'Enter text.'\n\n if (field.type === 'select' && !field.options?.some((option) => option.id === value))\n return 'Choose an available option.'\n\n if (field.type === 'email' && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/u.test(value)) return 'Enter a valid email address.'\n\n if (field.minLength !== undefined && value.length < field.minLength)\n return `Enter at least ${field.minLength} characters.`\n\n if (field.maxLength !== undefined && value.length > field.maxLength)\n return `Enter at most ${field.maxLength} characters.`\n\n return undefined\n}\n\n/** Paths refer to authored nodes, never rendered Vue children. Revision comparison is exact. */\nexport function documentForms(\n document: { readonly id: FormDefinition['documentId']; readonly body: CmsMarkdownDocument },\n components: ReadonlyArray<ComponentDefinition>,\n preview = false,\n): FormDefinition[] {\n const forms: FormDefinition[] = []\n\n const visit = (nodes: CmsMarkdownDocument['nodes'], parent: number[], renderData: NodeRenderData) => {\n nodes.forEach((node, index) => {\n if (Predicate.isString(node) || node[0] === null) return\n const nodePath = [...parent, index]\n const projection = projectCmsEditorComponentAttributes(node[1], renderData)\n const capabilities = components.find((component) => component.name === node[0])?.authoring.form\n\n if (capabilities && !formStructureIssues(projection.props.steps, capabilities, node[0]).length) {\n const steps = Result.getOrThrow(Schema.decodeUnknownResult(FormSteps)(projection.props.steps))\n forms.push({\n name: node[0],\n documentId: document.id,\n nodePath,\n steps,\n preview,\n revision: formRevision(node[0], capabilities, steps),\n })\n }\n\n visit(node.slice(2).filter(isNode), nodePath, projection.renderData)\n })\n }\n\n visit(document.body.nodes, [], createCmsComarkRenderData(document.body))\n\n return forms\n}\n\nfunction formRevision(name: string, capabilities: FormCapabilities, steps: ReadonlyArray<FormStep>): string {\n return JSON.stringify([name, capabilities, steps])\n}\n\nfunction isNode(value: Schema.Json | undefined): value is CmsMarkdownDocument['nodes'][number] {\n return Predicate.isString(value) || Array.isArray(value)\n}\n\nexport function formAuthoring(capabilities: FormCapabilities): BlockAuthoring {\n const prop = (\n name: string,\n label: string,\n type: BlockProp['type'],\n input: BlockProp['input'],\n extra: Partial<BlockProp> = {},\n ): BlockProp => ({ name, label, type, input, required: false, nullable: false, options: [], ...extra })\n\n const question = [\n prop('label', 'Question', 'string', 'text', { required: true, defaultValue: 'New question' }),\n prop('type', 'Answer type', 'string', 'select', {\n required: true,\n defaultValue: capabilities.fieldTypes[0],\n options: capabilities.fieldTypes.map((value) => ({ value, label: value })),\n }),\n prop('help', 'Help text', 'string', 'textarea'),\n ...capabilities.rules.map((rule) =>\n prop(\n rule,\n {\n required: 'Required',\n minLength: 'Minimum characters',\n maxLength: 'Maximum characters',\n min: 'Minimum value',\n max: 'Maximum value',\n }[rule],\n rule === 'required' ? 'boolean' : 'number',\n rule === 'required' ? 'toggle' : 'number',\n ),\n ),\n prop('options', 'Choices', 'array', 'list', {\n fields: [prop('label', 'Choice', 'string', 'text', { required: true, defaultValue: 'New choice' })],\n }),\n ]\n\n return {\n version: 1,\n label: capabilities.label,\n group: 'Forms',\n form: capabilities,\n props: [\n prop('steps', 'Steps', 'array', 'list', {\n required: true,\n fields: [\n prop('title', 'Step title', 'string', 'text', { required: true, defaultValue: 'New step' }),\n prop('fields', 'Questions', 'array', 'list', { required: true, fields: question }),\n ],\n }),\n ],\n slots: [],\n initialProps: {\n steps: [\n {\n id: 'first-step',\n title: 'Your details',\n fields: [\n {\n id: 'first-question',\n label: 'Your answer',\n type: capabilities.fieldTypes[0] ?? 'text',\n ...(capabilities.fieldTypes[0] === 'select'\n ? { options: [{ id: 'first-choice', label: 'First choice' }] }\n : undefined),\n },\n ],\n },\n ],\n },\n }\n}\n"],"mappings":";;;;;;AAUA,MAAMA,iBAAe,OAAO,GAAG,OAAO,UAAU;AAEhD,SAAgB,iBAAiB,UAAuD;CACtF,OAAO;EACL,aAAa,kBAAkB,SAAS,WAAW;EACnD,MAAM,kBAAkB,SAAS,IAAI;EACrC,OAAO,SAAS,MAAM,IAAI,YAAY;CACxC;AACF;AAEA,SAAgB,0BAA0B,UAA+C;CACvF,OAAO;EACL,MAAM,CAAC;EACP,aAAa,kBAAkB,SAAS,WAAW;EACnD,MAAM,kBAAkB,SAAS,IAAI;EACrC,OAAO,CAAC;CACV;AACF;;AAGA,SAAgB,qBAAqB,MAA4B;CAC/D,OAAO,YAAY,aAAa,IAAI,GAAG,EAAE,uBAAuB,KAAK,CAAC;AACxE;AAEA,SAAgB,0BAA0B,YAAsD;CAC9F,MAAM,SAAgC,CAAC;CAEvC,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,UAAU,GACnD,IAAI,SAAS,KAAK,OAAO,QAAQ,YAAY,KAAK;CAGpD,MAAM,WAAWC,aAAW,WAAW,CAAC;CACxC,MAAM,OAAO,SAAS;CACtB,MAAM,OAAO,WAAW,SAAS,IAAI;CACrC,MAAM,QAAQ,WAAW,SAAS,KAAK;CAEvC,IAAI,UAAU,SAAS,IAAI,KAAK,SAAS,UAAa,UAAU,QAAW;EACzE,MAAM,WAAmC,CAAC;EAE1C,IAAI,UAAU,SAAS,IAAI,GAAG,SAAS,OAAO;EAE9C,IAAI,SAAS,QAAW,SAAS,OAAO;EAExC,IAAI,UAAU,QAAW,SAAS,QAAQ;EAC1C,OAAO,IAAI;CACb;CAEA,OAAO;AACT;AAEA,SAAgB,YAAY,OAAiC;CAC3D,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,IAAI,WAAW;CAEtD,IAAID,eAAa,KAAK,GAAG,OAAO,kBAAkB,KAAK;CAEvD,OAAO;AACT;AAEA,SAAS,aAAa,MAAgC;CACpD,IAAI,UAAU,SAAS,IAAI,GAAG,OAAO;CAErC,IAAI,KAAK,OAAO,MAAM,OAAO;EAAC;EAAM,0BAA0B,KAAK,EAAE;EAAG,KAAK;CAAE;CAC/E,MAAM,CAAC,KAAK,YAAY,GAAG,YAAY;CAEvC,OAAO;EAAC;EAAK,0BAA0B,UAAU;EAAG,GAAG,SAAS,IAAI,YAAY;CAAC;AACnF;AAEA,SAAgB,kBAAkB,OAAuD;CACvF,OAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,WAAW,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC;AAClG;AAEA,SAAS,WAAW,OAAmD;CACrE,OAAO,UAAU,KAAK,UAAU,IAAI,QAAQ;AAC9C;AAEA,SAASC,aAAW,OAAmD;CACrE,OAAOD,eAAa,KAAK,IAAI,QAAQ,CAAC;AACxC;;;;AC/EA,MAAM,eAAe,OAAO,GAAG,OAAO,UAAU;AAEhD,MAAM,aAAa,OAAO,oBAAoB,OAAO,IAAI;;AAazD,SAAgB,2BACd,YACA,YACqB;CACrB,MAAM,2BAAW,IAAI,IAAqC;CAE1D,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QACjC,kBAAkB,0BAA0B,UAAU,GAAG,YAAY,EAAE,WAAW,KAAK,CAAC,CAC1F,GAAG;EACD,IAAI,UAAU,YAAY,KAAK,GAAG;GAChC,SAAS,IAAI,MAAM,MAAS;GAC5B;EACF;EAEA,MAAM,UAAU,WAAW,KAAK;EAEhC,IAAI,OAAO,OAAO,OAAO,GAAG,MAAM,IAAI,MAAM,uCAAuC,KAAK,GAAG;EAC3F,SAAS,IAAI,MAAM,QAAQ,KAAK;CAClC;CAEA,OAAO;AACT;;AAGA,SAAgB,oCACd,YACA,YAC8B;CAC9B,MAAM,WAAW,2BAA2B,YAAY,UAAU;CAClE,MAAM,QAAqC,CAAC;CAE5C,KAAK,MAAM,CAAC,MAAM,UAAU,UAC1B,IAAI,CAAC,UAAU,YAAY,KAAK,GAAG,MAAM,QAAQ,YAAY,KAAK;CAGpE,MAAM,WAAwC,CAAC;CAE/C,KAAK,MAAM,CAAC,cAAc,kBAAkB,OAAO,QAAQ,UAAU,GAAG;EACtE,IAAI,CAAC,aAAa,WAAW,GAAG,KAAK,aAAa,WAAW,GAAG;EAChE,MAAM,OAAO,aAAa,MAAM,CAAC;EAEjC,IAAI,CAAC,SAAS,IAAI,IAAI,GAAG;EACzB,MAAM,UAAU,YAAY,aAAa;EAEzC,IAAI,CAAC,UAAU,SAAS,aAAa,KAAK,YAAY,eAAe;GACnE,SAAS,QAAQ,EAAE,MAAM,UAAU;GACnC;EACF;EAEA,MAAM,gBAAgB,SAAS,IAAI,IAAI;EACvC,SAAS,QAAQ,OAAO,OACtB;GAAE,YAAY;GAAe,MAAM;EAAa,GAChD,UAAU,YAAY,aAAa,IAAI,SAAY,EAAE,UAAU,YAAY,aAAa,EAAE,CAC5F;CACF;CAEA,OAAO;EAAE;EAAU;EAAO,YAAY,mBAAmB,YAAY,QAAQ;CAAE;AACjF;;AAGA,SAAgB,mCACd,OACA,UACmB;CACnB,MAAM,aAAa,kBAAkB,KAAK;CAE1C,KAAK,MAAM,CAAC,MAAM,mBAAmB,OAAO,QAAQ,QAAQ,GAAG;EAC7D,MAAM,UAAU,WAAW,cAAc;EACzC,MAAM,OAAO,QAAQ;EAErB,IAAI,SAAS,aAAa,SAAS,cAAc;EACjD,MAAM,UAAU,MAAM;EAEtB,IAAI,UAAU,YAAY,OAAO,GAAG;GAClC,MAAM,aAAa,QAAQ;GAE3B,IAAI,SAAS,gBAAgB,UAAU,SAAS,UAAU,GAAG,WAAW,IAAI,UAAU;GACtF;EACF;EAEA,OAAO,WAAW;EAClB,MAAM,aAAa,QAAQ;EAC3B,MAAM,WAAW,QAAQ;EACzB,WAAW,IAAI,UACb,SAAS,gBACT,UAAU,SAAS,UAAU,KAC7B,OAAO,OAAO,SAAS,UAAU,KACjC,SAAS,SAAS,QAAQ,IACtB,aACA,YAAY,OAAO;CAC3B;CAEA,OAAO;AACT;AAEA,SAAgB,mBAAmB,YAA4B,YAAiD;CAC9G,OAAO,WAAW,OAAO,IAAI;EAAE,GAAG;EAAY,OAAO,OAAO,YAAY,UAAU;CAAE,IAAI;AAC1F;;AAGA,SAAgB,8BACd,UACA,YACqB;CACrB,IAAI,CAAC,YAAY,OAAO;CAExB,OAAOE,oBAA0B,KAAK;EACpC,aAAa,SAAS;EACtB,MAAM,SAAS;EACf,OAAO,SAAS,MAAM,KAAK,SAAS,uBAAuB,MAAM,UAAU,CAAC;CAC9E,CAAC;AACH;AAEA,SAAgB,4BACd,OACA,MACS;CACT,QAAQ,MAAR;EACE,KAAK,UACH,OAAO,aAAa,KAAK;EAC3B,KAAK,SACH,OAAO,MAAM,QAAQ,KAAK;EAC5B,KAAK,WACH,OAAO,UAAU,UAAU,KAAK;EAClC,KAAK,UACH,OAAO,UAAU,SAAS,KAAK;EACjC,KAAK,UACH,OAAO,UAAU,SAAS,KAAK;CACnC;AACF;AAEA,SAAS,uBACP,MACA,YACc;CACd,IAAI,UAAU,SAAS,IAAI,KAAK,KAAK,OAAO,MAAM,OAAO;CACzD,MAAM,CAAC,KAAK,oBAAoB,GAAG,oBAAoB;CACvD,MAAM,aAAa,kBAAkB,kBAAkB;CACvD,MAAM,aAAa,WAAW,IAAI,IAAI,kBAAkB,CAAC;CAEzD,IAAI,YACF,KAAK,MAAM,QAAQ,WAAW,UAAU,OAAO;EAC7C,IAAI,KAAK,SAAS,YAAY,IAAI,KAAK,UAAU,cAAc,EAAE,KAAK,QAAQ,aAAa;EAC3F,MAAM,QAAQ,WAAW,KAAK;EAE9B,IAAI,UAAU,YAAY,KAAK,GAAG;EAGlC,IAAI,CAAC,4BAFY,YAAY,KAEW,GAAG,KAAK,IAAI,GAAG;EACvD,OAAO,WAAW,KAAK;EACvB,WAAW,IAAI,KAAK,UAAU;CAChC;CAGF,OAAO;EAAC;EAAK;EAAY,GAAG,iBAAiB,KAAK,UAAU,uBAAuB,OAAO,UAAU,CAAC;CAAC;AACxG;AAEA,SAAS,YAAY,OAAyD;CAC5E,IAAI,CAAC,UAAU,SAAS,KAAK,GAAG,OAAO;CAEvC,IAAI;EACF,MAAM,UAAU,WAAW,KAAK,MAAM,KAAK,CAAC;EAE5C,OAAO,OAAO,OAAO,OAAO,IAAI,QAAQ,QAAQ;CAClD,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,WAAW,OAAmD;CACrE,OAAO,aAAa,KAAK,IAAI,QAAQ,CAAC;AACxC;AAEA,SAAS,SAAS,MAAmB,OAAyC;CAC5E,OAAO,CAAC,UAAU,YAAY,KAAK,KAAK,KAAK,UAAU,IAAI,MAAM,KAAK,UAAU,KAAK;AACvF;;;;AC5LA,SAAgB,oBACd,OACA,cACA,MACU;CACV,MAAM,UAAU,OAAO,oBAAoB,SAAS,CAAC,CAAC,OAAO,EAAE,kBAAkB,QAAQ,CAAC;CAE1F,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO,CAAC,qEAAqE;CAC5G,MAAM,SAAmB,CAAC;CAG1B,IAFsB,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,UAAU,aAAa,MAAM,cAAc,QAAQ,OAAO,CAAC,CAE/F,CAAC,CAAC,kBAChB,OAAO,KAAK,iEAAiE;CAC/E,MAAM,sBAAM,IAAI,IAAY;CAE5B,KAAK,MAAM,QAAQ,QAAQ,SAAS;EAClC,IAAI,IAAI,IAAI,KAAK,EAAE,GAAG,OAAO,KAAK,kDAAkD;EACpF,IAAI,IAAI,KAAK,EAAE;EAEf,KAAK,MAAM,SAAS,KAAK,QAAQ;GAC/B,IAAI,IAAI,IAAI,MAAM,EAAE,GAAG,OAAO,KAAK,kDAAkD;GACrF,IAAI,IAAI,MAAM,EAAE;GAEhB,IAAI;IAAC;IAAS;IAAa;IAAe;GAAW,CAAC,CAAC,SAAS,MAAM,EAAE,GACtE,OAAO,KAAK,qCAAqC;GAEnD,IAAI,CAAC,aAAa,WAAW,SAAS,MAAM,IAAI,GAC9C,OAAO,KAAK,GAAG,MAAM,MAAM,qCAAqC;GAElE,KAAK,MAAM,QAAQ;IAAC;IAAY;IAAa;IAAa;IAAO;GAAK,GACpE,IAAI,MAAM,UAAU,UAAa,CAAC,aAAa,MAAM,SAAS,IAAI,GAChE,OAAO,KAAK,GAAG,MAAM,MAAM,IAAI,KAAK,iBAAiB;GAKzD,IAAI,CAFS;IAAC;IAAQ;IAAS;GAAU,CAAC,CAAC,SAAS,MAAM,IAElD,MAAM,MAAM,cAAc,UAAa,MAAM,cAAc,SACjE,OAAO,KAAK,GAAG,MAAM,MAAM,yCAAyC;GAEtE,IAAI,MAAM,SAAS,aAAa,MAAM,QAAQ,UAAa,MAAM,QAAQ,SACvE,OAAO,KAAK,GAAG,MAAM,MAAM,4CAA4C;GAEzE,IAAI,MAAM,QAAQ,UAAa,MAAM,QAAQ,UAAa,MAAM,MAAM,MAAM,KAC1E,OAAO,KAAK,GAAG,MAAM,MAAM,2BAA2B;GAExD,IAAI,MAAM,cAAc,UAAa,MAAM,cAAc,UAAa,MAAM,YAAY,MAAM,WAC5F,OAAO,KAAK,GAAG,MAAM,MAAM,yCAAyC;GACtE,MAAM,UAAU,MAAM,WAAW,CAAC;GAElC,IACE,MAAM,SAAS,aACd,CAAC,QAAQ,UAAU,IAAI,IAAI,QAAQ,KAAK,WAAW,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,QAAQ,SAEjF,OAAO,KAAK,GAAG,MAAM,MAAM,0DAA0D;GAEvF,IAAI,MAAM,SAAS,YAAY,QAAQ,QAAQ,OAAO,KAAK,GAAG,MAAM,MAAM,qCAAqC;EACjH;CACF;CAEA,OAAO;AACT;AAEA,SAAgB,mBAAmB,QAAkC,QAA4C;CAC/G,OAAO,OAAO,YACZ,OAAO,SAAS,UAAU;EACxB,MAAM,QAAQ,WAAW,OAAO,OAAO,OAAO,QAAQ,MAAM,EAAE,IAAI,OAAO,MAAM,MAAM,MAAS;EAE9F,OAAO,QAAQ,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC;CACxC,CAAC,CACH;AACF;AAEA,SAAS,WAAW,OAAkB,OAA2D;CAG/F,IAFc,UAAU,UAAa,UAAU,QAAQ,UAAU,MAAO,UAAU,SAAS,KAAK,KAAK,CAAC,MAAM,KAAK,GAEtG,OAAO,MAAM,WAAW,GAAG,MAAM,MAAM,iBAAiB;CAEnE,IAAI,MAAM,SAAS,YACjB,OAAO,CAAC,UAAU,UAAU,KAAK,IAC7B,sBACA,MAAM,YAAY,CAAC,QACjB,GAAG,MAAM,MAAM,qBACf;CAER,IAAI,MAAM,SAAS,UAAU;EAC3B,IAAI,CAAC,UAAU,SAAS,KAAK,KAAK,CAAC,OAAO,SAAS,KAAK,GAAG,OAAO;EAElE,IAAI,MAAM,QAAQ,UAAa,QAAQ,MAAM,KAAK,OAAO,kBAAkB,MAAM,IAAI;EAErF,IAAI,MAAM,QAAQ,UAAa,QAAQ,MAAM,KAAK,OAAO,iBAAiB,MAAM,IAAI;EAEpF;CACF;CAEA,IAAI,CAAC,UAAU,SAAS,KAAK,GAAG,OAAO;CAEvC,IAAI,MAAM,SAAS,YAAY,CAAC,MAAM,SAAS,MAAM,WAAW,OAAO,OAAO,KAAK,GACjF,OAAO;CAET,IAAI,MAAM,SAAS,WAAW,CAAC,8BAA8B,KAAK,KAAK,GAAG,OAAO;CAEjF,IAAI,MAAM,cAAc,UAAa,MAAM,SAAS,MAAM,WACxD,OAAO,kBAAkB,MAAM,UAAU;CAE3C,IAAI,MAAM,cAAc,UAAa,MAAM,SAAS,MAAM,WACxD,OAAO,iBAAiB,MAAM,UAAU;AAG5C;;AAGA,SAAgB,cACd,UACA,YACA,UAAU,OACQ;CAClB,MAAM,QAA0B,CAAC;CAEjC,MAAM,SAAS,OAAqC,QAAkB,eAA+B;EACnG,MAAM,SAAS,MAAM,UAAU;GAC7B,IAAI,UAAU,SAAS,IAAI,KAAK,KAAK,OAAO,MAAM;GAClD,MAAM,WAAW,CAAC,GAAG,QAAQ,KAAK;GAClC,MAAM,aAAa,oCAAoC,KAAK,IAAI,UAAU;GAC1E,MAAM,eAAe,WAAW,MAAM,cAAc,UAAU,SAAS,KAAK,EAAE,CAAC,EAAE,UAAU;GAE3F,IAAI,gBAAgB,CAAC,oBAAoB,WAAW,MAAM,OAAO,cAAc,KAAK,EAAE,CAAC,CAAC,QAAQ;IAC9F,MAAM,QAAQ,OAAO,WAAW,OAAO,oBAAoB,SAAS,CAAC,CAAC,WAAW,MAAM,KAAK,CAAC;IAC7F,MAAM,KAAK;KACT,MAAM,KAAK;KACX,YAAY,SAAS;KACrB;KACA;KACA;KACA,UAAU,aAAa,KAAK,IAAI,cAAc,KAAK;IACrD,CAAC;GACH;GAEA,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,GAAG,UAAU,WAAW,UAAU;EACrE,CAAC;CACH;CAEA,MAAM,SAAS,KAAK,OAAO,CAAC,GAAG,0BAA0B,SAAS,IAAI,CAAC;CAEvE,OAAO;AACT;AAEA,SAAS,aAAa,MAAc,cAAgC,OAAwC;CAC1G,OAAO,KAAK,UAAU;EAAC;EAAM;EAAc;CAAK,CAAC;AACnD;AAEA,SAAS,OAAO,OAA+E;CAC7F,OAAO,UAAU,SAAS,KAAK,KAAK,MAAM,QAAQ,KAAK;AACzD;AAEA,SAAgB,cAAc,cAAgD;CAC5E,MAAM,QACJ,MACA,OACA,MACA,OACA,QAA4B,CAAC,OACd;EAAE;EAAM;EAAO;EAAM;EAAO,UAAU;EAAO,UAAU;EAAO,SAAS,CAAC;EAAG,GAAG;CAAM;CAErG,MAAM,WAAW;EACf,KAAK,SAAS,YAAY,UAAU,QAAQ;GAAE,UAAU;GAAM,cAAc;EAAe,CAAC;EAC5F,KAAK,QAAQ,eAAe,UAAU,UAAU;GAC9C,UAAU;GACV,cAAc,aAAa,WAAW;GACtC,SAAS,aAAa,WAAW,KAAK,WAAW;IAAE;IAAO,OAAO;GAAM,EAAE;EAC3E,CAAC;EACD,KAAK,QAAQ,aAAa,UAAU,UAAU;EAC9C,GAAG,aAAa,MAAM,KAAK,SACzB,KACE,MACA;GACE,UAAU;GACV,WAAW;GACX,WAAW;GACX,KAAK;GACL,KAAK;EACP,EAAE,OACF,SAAS,aAAa,YAAY,UAClC,SAAS,aAAa,WAAW,QACnC,CACF;EACA,KAAK,WAAW,WAAW,SAAS,QAAQ,EAC1C,QAAQ,CAAC,KAAK,SAAS,UAAU,UAAU,QAAQ;GAAE,UAAU;GAAM,cAAc;EAAa,CAAC,CAAC,EACpG,CAAC;CACH;CAEA,OAAO;EACL,SAAS;EACT,OAAO,aAAa;EACpB,OAAO;EACP,MAAM;EACN,OAAO,CACL,KAAK,SAAS,SAAS,SAAS,QAAQ;GACtC,UAAU;GACV,QAAQ,CACN,KAAK,SAAS,cAAc,UAAU,QAAQ;IAAE,UAAU;IAAM,cAAc;GAAW,CAAC,GAC1F,KAAK,UAAU,aAAa,SAAS,QAAQ;IAAE,UAAU;IAAM,QAAQ;GAAS,CAAC,CACnF;EACF,CAAC,CACH;EACA,OAAO,CAAC;EACR,cAAc,EACZ,OAAO,CACL;GACE,IAAI;GACJ,OAAO;GACP,QAAQ,CACN;IACE,IAAI;IACJ,OAAO;IACP,MAAM,aAAa,WAAW,MAAM;IACpC,GAAI,aAAa,WAAW,OAAO,WAC/B,EAAE,SAAS,CAAC;KAAE,IAAI;KAAgB,OAAO;IAAe,CAAC,EAAE,IAC3D;GACN,CACF;EACF,CACF,EACF;CACF;AACF"}
@@ -1,8 +1,5 @@
1
+ import { t as DocumentId } from "./scalars-CA6kyipS.js";
1
2
  import { Schema } from "effect";
2
- //#region ../protocol/src/internal/documents/scalars.d.ts
3
- declare const DocumentId: Schema.brand<Schema.String, "DocumentId">;
4
- type DocumentId = typeof DocumentId.Type;
5
- //#endregion
6
3
  //#region ../protocol/src/Forms.d.ts
7
4
  type FormFieldType = 'text' | 'email' | 'textarea' | 'number' | 'checkbox' | 'select';
8
5
  declare const FormFieldType: Schema.Codec<FormFieldType>;
@@ -71,4 +68,4 @@ interface FormResult {
71
68
  declare const FormResult: Schema.Codec<FormResult>;
72
69
  //#endregion
73
70
  export { FormStep as a, FormResult as i, FormDefinition as n, FormSubmission as o, FormField as r, FormValues as s, FormCapabilities as t };
74
- //# sourceMappingURL=Forms-BsJMev5_.d.ts.map
71
+ //# sourceMappingURL=Forms-BorTcIlp.d.ts.map
package/src/Forms.d.ts CHANGED
@@ -1,24 +1,32 @@
1
- import { a as FormStep, i as FormResult, n as FormDefinition, o as FormSubmission, r as FormField, s as FormValues, t as FormCapabilities } from "./Forms-BsJMev5_.js";
2
- import { ComputedRef, MaybeRefOrGetter, Ref } from "vue";
1
+ import { a as FormStep, i as FormResult, n as FormDefinition, o as FormSubmission, r as FormField, s as FormValues, t as FormCapabilities } from "./Forms-BorTcIlp.js";
2
+ import { ComputedRef, MaybeRefOrGetter, Ref, WritableComputedRef } from "vue";
3
3
  //#region src/runtime/forms/useCmsForm.d.ts
4
4
  interface UseCmsFormOptions {
5
5
  /** Replace the HTTP transport, retaining validation and submission state. */
6
6
  readonly submit?: (submission: FormSubmission, signal: AbortSignal) => Promise<FormResult>;
7
7
  }
8
- interface CmsFormFieldState {
9
- readonly field: FormField;
10
- readonly value: FormValues[string];
11
- readonly error: string | undefined;
12
- readonly helpId: string;
13
- readonly errorId: string;
14
- readonly inputAttrs: {
8
+ interface CmsFormFieldController {
9
+ readonly field: ComputedRef<FormField>;
10
+ readonly value: WritableComputedRef<FormValues[string]>;
11
+ readonly dirty: ComputedRef<boolean>;
12
+ readonly touched: ComputedRef<boolean>;
13
+ readonly valid: ComputedRef<boolean>;
14
+ readonly errors: ComputedRef<ReadonlyArray<string>>;
15
+ readonly controlAttrs: ComputedRef<{
15
16
  readonly id: string;
16
17
  readonly name: string;
17
18
  readonly required: boolean;
18
19
  readonly 'aria-invalid': 'true' | undefined;
19
20
  readonly 'aria-describedby': string | undefined;
21
+ }>;
22
+ readonly helpAttrs: {
23
+ readonly id: string;
24
+ };
25
+ readonly errorAttrs: {
26
+ readonly id: string;
27
+ readonly role: 'alert';
20
28
  };
21
- readonly setValue: (value: FormValues[string] | undefined) => void;
29
+ readonly touch: () => void;
22
30
  }
23
31
  interface UseCmsFormReturn {
24
32
  readonly fields: ComputedRef<ReadonlyArray<FormField>>;
@@ -29,11 +37,14 @@ interface UseCmsFormReturn {
29
37
  readonly stepIndex: Readonly<Ref<number>>;
30
38
  readonly isFirstStep: ComputedRef<boolean>;
31
39
  readonly isLastStep: ComputedRef<boolean>;
32
- readonly isSubmitting: Readonly<Ref<boolean>>;
40
+ readonly submitting: Readonly<Ref<boolean>>;
33
41
  readonly isSuccess: Readonly<Ref<boolean>>;
34
42
  readonly isPreview: ComputedRef<boolean>;
35
- readonly error: Readonly<Ref<string | undefined>>;
36
- readonly fieldState: (field: FormField) => CmsFormFieldState;
43
+ readonly submitError: Readonly<Ref<string | undefined>>;
44
+ readonly canSubmit: ComputedRef<boolean>;
45
+ readonly invalidFields: ComputedRef<ReadonlyArray<CmsFormFieldController>>;
46
+ readonly firstInvalidFieldId: ComputedRef<string | undefined>;
47
+ readonly field: (field: string | FormField) => CmsFormFieldController;
37
48
  readonly next: () => boolean;
38
49
  readonly previous: () => void;
39
50
  readonly validate: () => boolean;
@@ -47,5 +58,5 @@ export declare function useCmsForm(input: MaybeRefOrGetter<FormDefinition>, opti
47
58
  /** Register this definition under the kebab-case name of your Vue form renderer. */
48
59
  export declare function defineCmsForm<const Definition extends FormCapabilities>(definition: Definition): Definition;
49
60
  //#endregion
50
- export type { FormDefinition as CmsFormDefinition, FormField as CmsFormField, CmsFormFieldState, FormResult as CmsFormResult, FormStep as CmsFormStep, FormValues as CmsFormValues, UseCmsFormOptions, UseCmsFormReturn };
61
+ export type { FormDefinition as CmsFormDefinition, FormField as CmsFormField, CmsFormFieldController, FormResult as CmsFormResult, FormStep as CmsFormStep, FormValues as CmsFormValues, UseCmsFormOptions, UseCmsFormReturn };
51
62
  //# sourceMappingURL=Forms.d.ts.map
package/src/Forms.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Forms.js","names":[],"sources":["../../../src/Forms.ts"],"sourcesContent":["import type { FormCapabilities } from '@internal/protocol/Forms'\nimport { validateFormCapabilities } from './internal/form-capabilities'\n\nexport type {\n FormDefinition as CmsFormDefinition,\n FormField as CmsFormField,\n FormStep as CmsFormStep,\n FormValues as CmsFormValues,\n FormResult as CmsFormResult,\n} from '@internal/protocol/Forms'\n\nexport type { CmsFormFieldState, UseCmsFormOptions, UseCmsFormReturn } from './runtime/forms/useCmsForm'\n\nexport { useCmsForm } from './runtime/forms/useCmsForm'\n\n/** Register this definition under the kebab-case name of your Vue form renderer. */\nexport function defineCmsForm<const Definition extends FormCapabilities>(definition: Definition): Definition {\n validateFormCapabilities(definition)\n\n return definition\n}\n"],"mappings":";;;;;AAgBA,SAAgB,cAAyD,YAAoC;CAC3G,yBAAyB,UAAU;CAEnC,OAAO;AACT"}
1
+ {"version":3,"file":"Forms.js","names":[],"sources":["../../../src/Forms.ts"],"sourcesContent":["import type { FormCapabilities } from '@internal/protocol/Forms'\nimport { validateFormCapabilities } from './internal/form-capabilities'\n\nexport type {\n FormDefinition as CmsFormDefinition,\n FormField as CmsFormField,\n FormStep as CmsFormStep,\n FormValues as CmsFormValues,\n FormResult as CmsFormResult,\n} from '@internal/protocol/Forms'\n\nexport type { CmsFormFieldController, UseCmsFormOptions, UseCmsFormReturn } from './runtime/forms/useCmsForm'\n\nexport { useCmsForm } from './runtime/forms/useCmsForm'\n\n/** Register this definition under the kebab-case name of your Vue form renderer. */\nexport function defineCmsForm<const Definition extends FormCapabilities>(definition: Definition): Definition {\n validateFormCapabilities(definition)\n\n return definition\n}\n"],"mappings":";;;;;AAgBA,SAAgB,cAAyD,YAAoC;CAC3G,yBAAyB,UAAU;CAEnC,OAAO;AACT"}
@@ -0,0 +1,27 @@
1
+ //#region src/I18n.d.ts
2
+ interface CmsMessages {
3
+ readonly [key: string]: string | CmsMessages;
4
+ }
5
+ interface CmsI18nOptions {
6
+ readonly defaultLocale: string;
7
+ readonly fallbackLocale?: string | null;
8
+ readonly prefixDefaultLocale?: boolean;
9
+ readonly locales: Readonly<Record<string, {
10
+ readonly name: string;
11
+ readonly messages?: CmsMessages;
12
+ }>>;
13
+ }
14
+ /** Nuxt augments this registry with the message keys from cms.config.ts. */
15
+ interface CmsI18nRegistry {}
16
+ type CmsMessageKey = CmsI18nRegistry extends {
17
+ messageKey: infer Key extends string;
18
+ } ? Key : string;
19
+ type CmsLocale = CmsI18nRegistry extends {
20
+ locale: infer Locale extends string;
21
+ } ? Locale : string;
22
+ type CmsMessageParameters<Key extends CmsMessageKey> = CmsI18nRegistry extends {
23
+ messageParameters: infer Parameters;
24
+ } ? Key extends keyof Parameters ? Parameters[Key] : never : Readonly<Record<string, string | number>>;
25
+ //#endregion
26
+ export { CmsMessageParameters as a, CmsMessageKey as i, CmsI18nRegistry as n, CmsMessages as o, CmsLocale as r, CmsI18nOptions as t };
27
+ //# sourceMappingURL=I18n-BXlVunfa.d.ts.map
package/src/I18n.d.ts CHANGED
@@ -1,20 +1,2 @@
1
- //#region src/I18n.d.ts
2
- export interface CmsMessages {
3
- readonly [key: string]: string | CmsMessages;
4
- }
5
- export interface CmsI18nOptions {
6
- readonly defaultLocale: string;
7
- readonly fallbackLocale?: string | null;
8
- readonly prefixDefaultLocale?: boolean;
9
- readonly locales: Readonly<Record<string, {
10
- readonly name: string;
11
- readonly messages?: CmsMessages;
12
- }>>;
13
- }
14
- /** Nuxt augments this registry with the message keys from cms.config.ts. */
15
- export interface CmsI18nRegistry {}
16
- export type CmsMessageKey = CmsI18nRegistry extends {
17
- messageKey: infer Key extends string;
18
- } ? Key : string;
19
- //#endregion
20
- //# sourceMappingURL=I18n.d.ts.map
1
+ import { a as CmsMessageParameters, i as CmsMessageKey, n as CmsI18nRegistry, o as CmsMessages, r as CmsLocale, t as CmsI18nOptions } from "./I18n-BXlVunfa.js";
2
+ export { CmsI18nOptions, CmsI18nRegistry, CmsLocale, CmsMessageKey, CmsMessageParameters, CmsMessages };
package/src/Module.js CHANGED
@@ -4,6 +4,7 @@ import { cmsAuthoringPlugin } from "./internal/authoring-compiler.js";
4
4
  import { registerAuthoringCatalog } from "./internal/authoring-catalog.js";
5
5
  import { loadCmsConfiguration } from "./internal/cms-config.js";
6
6
  import { compileCmsConfiguration } from "./internal/configuration.js";
7
+ import { generateCmsApplicationTypes } from "./internal/application-types.js";
7
8
  import { Effect, Layer } from "effect";
8
9
  import { addComponent, addImports, addPlugin, addServerHandler, addServerPlugin, addServerTemplate, addTemplate, addTypeTemplate, addVitePlugin, createResolver, defineNuxtModule, extendPages } from "@nuxt/kit";
9
10
  import { NodeCrypto, NodeFileSystem, NodePath } from "@effect/platform-node-shared";
@@ -18,6 +19,7 @@ const cmsNuxtModule = defineNuxtModule({
18
19
  "@nuxtjs/sitemap": {},
19
20
  "@comark/nuxt": {},
20
21
  "nuxt-schema-org": {},
22
+ "nuxt-site-config": {},
21
23
  "nuxt-seo-utils": {}
22
24
  },
23
25
  meta: {
@@ -40,13 +42,20 @@ const setupModule = Effect.fn("CmsNuxtModule.setup")(function* (nuxt) {
40
42
  getContents: () => `export default JSON.parse(${JSON.stringify(JSON.stringify(i18n))})`
41
43
  });
42
44
  nuxt.options.alias["#cms/i18n"] = i18nTemplate.dst;
43
- const messageKeys = [...new Set(Object.values(i18n.locales).flatMap((locale) => Object.keys(locale.messages)))];
44
- addTypeTemplate({
45
- filename: "types/cms-i18n.d.ts",
46
- getContents: () => `import '@phtngyn/cms/I18n'\ndeclare module '@phtngyn/cms/I18n' { interface CmsI18nRegistry { messageKey: ${messageKeys.map((key) => JSON.stringify(key)).join(" | ") || "string"} } }`
45
+ let blockNames = [];
46
+ const applicationTypes = addTypeTemplate({
47
+ filename: "types/cms-application.d.ts",
48
+ getContents: () => generateCmsApplicationTypes({
49
+ blockNames,
50
+ configurationPath: authored.path,
51
+ i18n
52
+ })
47
53
  });
54
+ nuxt.options.alias["#cms/types"] = applicationTypes.dst;
48
55
  nuxt.options.watch.push(authored.path);
49
- const authoring = yield* registerAuthoringCatalog(nuxt, compiled.documents, Object.fromEntries(Object.entries(authored.configuration.forms ?? {}).map(([name, form]) => [name, form.definition])));
56
+ const authoring = yield* registerAuthoringCatalog(nuxt, compiled.documents, Object.fromEntries(Object.entries(authored.configuration.forms ?? {}).map(([name, form]) => [name, form.definition])), (names) => {
57
+ blockNames = names;
58
+ }, [applicationTypes.dst]);
50
59
  const installationPluginId = resolver.resolve("./runtime/plugin.virtual.mjs");
51
60
  const installationPluginTemplate = addServerTemplate({
52
61
  filename: installationPluginId,
package/src/Module.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Module.js","names":[],"sources":["../../../src/Module.ts"],"sourcesContent":["import type { HookResult, Nuxt } from '@nuxt/schema'\nimport type { NitroConfig } from 'nitropack/types'\nimport { registerStudioApp } from './internal/studio-app'\nimport { registerAuthoringCatalog } from './internal/authoring-catalog'\nimport { NodeCrypto, NodeFileSystem, NodePath } from '@effect/platform-node-shared'\nimport {\n CMS_AUTHENTICATION_PATH,\n STUDIO_APP_PATH,\n STUDIO_BASE_PATH,\n STUDIO_API_PATH,\n STUDIO_HEALTH_PATH,\n STUDIO_COLLABORATION_PATH,\n} from '@internal/protocol/HttpPaths'\nimport {\n addTemplate,\n addTypeTemplate,\n addComponent,\n addImports,\n addPlugin,\n addServerHandler,\n addServerPlugin,\n addServerTemplate,\n addVitePlugin,\n createResolver,\n defineNuxtModule,\n extendPages,\n} from '@nuxt/kit'\nimport { Effect, Layer } from 'effect'\nimport { loadCmsConfiguration } from './internal/cms-config'\nimport { compileCmsConfiguration } from './internal/configuration'\nimport { cmsAuthoringPlugin } from './internal/authoring-compiler'\n\nconst CMS_SITEMAP_SOURCE_PATH = `${STUDIO_BASE_PATH}/sitemap`\n\ndeclare module '@nuxt/schema' {\n interface NuxtHooks {\n 'nitro:config': (nitroConfig: NitroConfig) => HookResult\n }\n}\n\nconst resolver = createResolver(import.meta.url)\n\nconst nodeLayer = Layer.merge(NodeCrypto.layer, Layer.merge(NodeFileSystem.layer, NodePath.layer))\n\nconst cmsNuxtModule = defineNuxtModule({\n moduleDependencies: {\n '@nuxtjs/robots': {},\n '@nuxtjs/sitemap': {},\n '@comark/nuxt': {},\n 'nuxt-schema-org': {},\n 'nuxt-seo-utils': {},\n },\n meta: {\n compatibility: { nuxt: '>=4.5.0 <5.0.0' },\n name: '@phtngyn/cms',\n },\n setup(_options, nuxt) {\n return Effect.runPromise(setupModule(nuxt).pipe(Effect.provide(nodeLayer)))\n },\n})\n\nexport default cmsNuxtModule\n\nconst setupModule = Effect.fn('CmsNuxtModule.setup')(function* (nuxt: Nuxt) {\n addVitePlugin(cmsAuthoringPlugin())\n const authored = yield* loadCmsConfiguration(nuxt.options.rootDir)\n const compiled = compileCmsConfiguration(authored.configuration)\n const i18n = compiled.i18n\n\n configureSitemap(nuxt.options)\n\n const i18nTemplate = addTemplate({\n filename: 'cms/i18n.mjs',\n write: true,\n getContents: () => `export default JSON.parse(${JSON.stringify(JSON.stringify(i18n))})`,\n })\n\n nuxt.options.alias['#cms/i18n'] = i18nTemplate.dst\n const messageKeys = [...new Set(Object.values(i18n.locales).flatMap((locale) => Object.keys(locale.messages)))]\n addTypeTemplate({\n filename: 'types/cms-i18n.d.ts',\n getContents: () =>\n `import '@phtngyn/cms/I18n'\\ndeclare module '@phtngyn/cms/I18n' { interface CmsI18nRegistry { messageKey: ${messageKeys.map((key) => JSON.stringify(key)).join(' | ') || 'string'} } }`,\n })\n nuxt.options.watch.push(authored.path)\n\n const authoring = yield* registerAuthoringCatalog(\n nuxt,\n compiled.documents,\n Object.fromEntries(\n Object.entries(authored.configuration.forms ?? {}).map(([name, form]) => [name, form.definition]),\n ),\n )\n\n const installationPluginId = resolver.resolve('./runtime/plugin.virtual.mjs')\n\n const installationPluginTemplate = addServerTemplate({\n filename: installationPluginId,\n getContents: () =>\n [\n `import { createInstallationPlugin } from ${JSON.stringify(resolver.resolve('./runtime/plugin'))}`,\n `import cmsConfiguration from ${JSON.stringify(authored.path)}`,\n `import authoring from ${JSON.stringify(authoring.dst)}`,\n `export default createInstallationPlugin(cmsConfiguration, authoring)`,\n ].join('\\n'),\n })\n\n addServerHandler({ handler: resolver.resolve('./runtime/api'), route: `${STUDIO_HEALTH_PATH}/**:path` })\n addServerHandler({ handler: resolver.resolve('./runtime/sitemap'), route: CMS_SITEMAP_SOURCE_PATH })\n registerDeliveryUi(nuxt)\n yield* registerStudioApp(nuxt, resolver)\n configureNitro(nuxt)\n addServerPlugin(installationPluginTemplate.filename)\n addServerHandler({\n handler: resolver.resolve('./runtime/api'),\n route: `${CMS_AUTHENTICATION_PATH}/**:path`,\n })\n addServerHandler({\n handler: resolver.resolve('./runtime/collaboration'),\n route: STUDIO_COLLABORATION_PATH,\n })\n addServerHandler({\n handler: resolver.resolve('./runtime/api'),\n route: `${STUDIO_API_PATH}/**:path`,\n })\n})\n\ninterface CmsSitemapConfiguration {\n sources?: Array<unknown>\n}\n\ninterface CmsNuxtSitemapOptions {\n readonly modules?: unknown\n sitemap?: false | CmsSitemapConfiguration\n}\n\nfunction configureSitemap(options: CmsNuxtSitemapOptions): void {\n if (options.sitemap === false) return\n\n const sitemap = options.sitemap ?? {}\n const sources = sitemap.sources ?? []\n\n if (!sources.includes(CMS_SITEMAP_SOURCE_PATH)) sitemap.sources = [...sources, CMS_SITEMAP_SOURCE_PATH]\n\n options.sitemap = sitemap\n}\n\nfunction registerDeliveryUi(nuxt: Nuxt): void {\n addPlugin(resolver.resolve('./runtime/blocks'))\n nuxt.options.css.push(resolver.resolve('./runtime/preview/preview.css'))\n addComponent({ name: 'DocumentField', filePath: resolver.resolve('./runtime/delivery/DocumentField') })\n addComponent({ name: 'DocumentRenderer', filePath: resolver.resolve('./runtime/delivery/DocumentRenderer') })\n addComponent({ name: 'DocumentScope', filePath: resolver.resolve('./runtime/delivery/DocumentScope') })\n addComponent({\n name: 'CmsStudioPreviewMarker',\n filePath: resolver.resolve('./runtime/preview/CmsStudioPreviewMarker'),\n })\n addPlugin(resolver.resolve('./runtime/delivery/plugin'))\n addPlugin(resolver.resolve('./runtime/preview/plugin.client'))\n addImports([\n { name: 'useCmsI18n', from: resolver.resolve('./runtime/i18n/useCmsI18n') },\n { name: 'useCmsForm', from: resolver.resolve('./runtime/forms/useCmsForm') },\n { name: 'useCmsDocumentSeo', from: resolver.resolve('./runtime/delivery/useCmsDocumentSeo') },\n { name: 'useDocument', from: resolver.resolve('./runtime/delivery/useDocument') },\n { name: 'useDocumentQuery', from: resolver.resolve('./runtime/delivery/useDocumentQuery') },\n ])\n extendPages((pages) => {\n pages.push({\n file: resolver.resolve('./runtime/delivery/document'),\n name: 'cms-document-page',\n path: '/:contentPath(.*)*',\n })\n })\n}\n\nfunction configureNitro(nuxt: Nuxt): void {\n nuxt.hook('nitro:config', (config: NitroConfig) => {\n config.experimental ||= {}\n config.experimental.websocket = true\n config.routeRules ||= {}\n const studioRules = { ssr: false, headers: { 'cache-control': 'no-store' } }\n config.routeRules[`${STUDIO_APP_PATH}/**`] = studioRules\n config.routeRules[STUDIO_APP_PATH] = studioRules\n\n config.routeRules[STUDIO_BASE_PATH] = { redirect: { statusCode: 302, to: STUDIO_APP_PATH } }\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Module.js","names":[],"sources":["../../../src/Module.ts"],"sourcesContent":["import type { HookResult, Nuxt } from '@nuxt/schema'\nimport type { NitroConfig } from 'nitropack/types'\nimport { registerStudioApp } from './internal/studio-app'\nimport { registerAuthoringCatalog } from './internal/authoring-catalog'\nimport { NodeCrypto, NodeFileSystem, NodePath } from '@effect/platform-node-shared'\nimport {\n CMS_AUTHENTICATION_PATH,\n STUDIO_APP_PATH,\n STUDIO_BASE_PATH,\n STUDIO_API_PATH,\n STUDIO_HEALTH_PATH,\n STUDIO_COLLABORATION_PATH,\n} from '@internal/protocol/HttpPaths'\nimport {\n addTemplate,\n addTypeTemplate,\n addComponent,\n addImports,\n addPlugin,\n addServerHandler,\n addServerPlugin,\n addServerTemplate,\n addVitePlugin,\n createResolver,\n defineNuxtModule,\n extendPages,\n} from '@nuxt/kit'\nimport { Effect, Layer } from 'effect'\nimport { loadCmsConfiguration } from './internal/cms-config'\nimport { compileCmsConfiguration } from './internal/configuration'\nimport { cmsAuthoringPlugin } from './internal/authoring-compiler'\nimport { generateCmsApplicationTypes } from './internal/application-types'\n\nconst CMS_SITEMAP_SOURCE_PATH = `${STUDIO_BASE_PATH}/sitemap`\n\ndeclare module '@nuxt/schema' {\n interface NuxtHooks {\n 'nitro:config': (nitroConfig: NitroConfig) => HookResult\n }\n}\n\nconst resolver = createResolver(import.meta.url)\n\nconst nodeLayer = Layer.merge(NodeCrypto.layer, Layer.merge(NodeFileSystem.layer, NodePath.layer))\n\nconst cmsNuxtModule = defineNuxtModule({\n moduleDependencies: {\n '@nuxtjs/robots': {},\n '@nuxtjs/sitemap': {},\n '@comark/nuxt': {},\n 'nuxt-schema-org': {},\n 'nuxt-site-config': {},\n 'nuxt-seo-utils': {},\n },\n meta: {\n compatibility: { nuxt: '>=4.5.0 <5.0.0' },\n name: '@phtngyn/cms',\n },\n setup(_options, nuxt) {\n return Effect.runPromise(setupModule(nuxt).pipe(Effect.provide(nodeLayer)))\n },\n})\n\nexport default cmsNuxtModule\n\nconst setupModule = Effect.fn('CmsNuxtModule.setup')(function* (nuxt: Nuxt) {\n addVitePlugin(cmsAuthoringPlugin())\n const authored = yield* loadCmsConfiguration(nuxt.options.rootDir)\n const compiled = compileCmsConfiguration(authored.configuration)\n const i18n = compiled.i18n\n\n configureSitemap(nuxt.options)\n\n const i18nTemplate = addTemplate({\n filename: 'cms/i18n.mjs',\n write: true,\n getContents: () => `export default JSON.parse(${JSON.stringify(JSON.stringify(i18n))})`,\n })\n\n nuxt.options.alias['#cms/i18n'] = i18nTemplate.dst\n let blockNames: ReadonlyArray<string> = []\n\n const applicationTypes = addTypeTemplate({\n filename: 'types/cms-application.d.ts',\n getContents: () => generateCmsApplicationTypes({ blockNames, configurationPath: authored.path, i18n }),\n })\n\n nuxt.options.alias['#cms/types'] = applicationTypes.dst\n nuxt.options.watch.push(authored.path)\n\n const authoring = yield* registerAuthoringCatalog(\n nuxt,\n compiled.documents,\n Object.fromEntries(\n Object.entries(authored.configuration.forms ?? {}).map(([name, form]) => [name, form.definition]),\n ),\n (names) => {\n blockNames = names\n },\n [applicationTypes.dst],\n )\n\n const installationPluginId = resolver.resolve('./runtime/plugin.virtual.mjs')\n\n const installationPluginTemplate = addServerTemplate({\n filename: installationPluginId,\n getContents: () =>\n [\n `import { createInstallationPlugin } from ${JSON.stringify(resolver.resolve('./runtime/plugin'))}`,\n `import cmsConfiguration from ${JSON.stringify(authored.path)}`,\n `import authoring from ${JSON.stringify(authoring.dst)}`,\n `export default createInstallationPlugin(cmsConfiguration, authoring)`,\n ].join('\\n'),\n })\n\n addServerHandler({ handler: resolver.resolve('./runtime/api'), route: `${STUDIO_HEALTH_PATH}/**:path` })\n addServerHandler({ handler: resolver.resolve('./runtime/sitemap'), route: CMS_SITEMAP_SOURCE_PATH })\n registerDeliveryUi(nuxt)\n yield* registerStudioApp(nuxt, resolver)\n configureNitro(nuxt)\n addServerPlugin(installationPluginTemplate.filename)\n addServerHandler({\n handler: resolver.resolve('./runtime/api'),\n route: `${CMS_AUTHENTICATION_PATH}/**:path`,\n })\n addServerHandler({\n handler: resolver.resolve('./runtime/collaboration'),\n route: STUDIO_COLLABORATION_PATH,\n })\n addServerHandler({\n handler: resolver.resolve('./runtime/api'),\n route: `${STUDIO_API_PATH}/**:path`,\n })\n})\n\ninterface CmsSitemapConfiguration {\n sources?: Array<unknown>\n}\n\ninterface CmsNuxtSitemapOptions {\n readonly modules?: unknown\n sitemap?: false | CmsSitemapConfiguration\n}\n\nfunction configureSitemap(options: CmsNuxtSitemapOptions): void {\n if (options.sitemap === false) return\n\n const sitemap = options.sitemap ?? {}\n const sources = sitemap.sources ?? []\n\n if (!sources.includes(CMS_SITEMAP_SOURCE_PATH)) sitemap.sources = [...sources, CMS_SITEMAP_SOURCE_PATH]\n\n options.sitemap = sitemap\n}\n\nfunction registerDeliveryUi(nuxt: Nuxt): void {\n addPlugin(resolver.resolve('./runtime/blocks'))\n nuxt.options.css.push(resolver.resolve('./runtime/preview/preview.css'))\n addComponent({ name: 'DocumentField', filePath: resolver.resolve('./runtime/delivery/DocumentField') })\n addComponent({ name: 'DocumentRenderer', filePath: resolver.resolve('./runtime/delivery/DocumentRenderer') })\n addComponent({ name: 'DocumentScope', filePath: resolver.resolve('./runtime/delivery/DocumentScope') })\n addComponent({\n name: 'CmsStudioPreviewMarker',\n filePath: resolver.resolve('./runtime/preview/CmsStudioPreviewMarker'),\n })\n addPlugin(resolver.resolve('./runtime/delivery/plugin'))\n addPlugin(resolver.resolve('./runtime/preview/plugin.client'))\n addImports([\n { name: 'useCmsI18n', from: resolver.resolve('./runtime/i18n/useCmsI18n') },\n { name: 'useCmsForm', from: resolver.resolve('./runtime/forms/useCmsForm') },\n { name: 'useCmsDocumentSeo', from: resolver.resolve('./runtime/delivery/useCmsDocumentSeo') },\n { name: 'useDocument', from: resolver.resolve('./runtime/delivery/useDocument') },\n { name: 'useDocumentQuery', from: resolver.resolve('./runtime/delivery/useDocumentQuery') },\n ])\n extendPages((pages) => {\n pages.push({\n file: resolver.resolve('./runtime/delivery/document'),\n name: 'cms-document-page',\n path: '/:contentPath(.*)*',\n })\n })\n}\n\nfunction configureNitro(nuxt: Nuxt): void {\n nuxt.hook('nitro:config', (config: NitroConfig) => {\n config.experimental ||= {}\n config.experimental.websocket = true\n config.routeRules ||= {}\n const studioRules = { ssr: false, headers: { 'cache-control': 'no-store' } }\n config.routeRules[`${STUDIO_APP_PATH}/**`] = studioRules\n config.routeRules[STUDIO_APP_PATH] = studioRules\n\n config.routeRules[STUDIO_BASE_PATH] = { redirect: { statusCode: 302, to: STUDIO_APP_PATH } }\n })\n}\n"],"mappings":"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"}
@@ -1,12 +1,12 @@
1
1
  import { c as RevisionId, d as SourcePath, f as nonNegativeInt, i as DocumentVersion, n as DocumentHistoryCursor, o as PublicPath, r as DocumentId, s as RelativeDocumentPath, t as DocumentGeneration, u as Slug } from "./scalars-B2lgGUnj.js";
2
- import { i as FormResult, o as FormSubmission } from "./Forms-CfcI3tPU.js";
3
- import { a as encodeCmsEditorComponentAttributes, d as createCmsComarkRenderData, m as toComarkDocument, p as mutableJsonObject, s as projectCmsEditorComponentAttributes } from "./Forms-Dj6NuW66.js";
4
- import { $ as StudioActor, B as SeoMediaUnavailable, C as PublishedDocumentLookup, D as RemoveDocumentInput, E as PublishedDocumentSurroundQuery, Et as RequestId, F as SaveSeoInput, G as SeoUrl, I as SeoCanonicalOrigin, J as AccessDenied, K as SeoVersionConflict, L as SeoCapabilities, N as GlobalSeoSettings, O as RestoreDocumentInput, P as PublishSeoInput, Q as Role, R as SeoConfiguration, S as PublishDocumentInput, T as PublishedDocumentQuery, U as SeoSnapshot, V as SeoMutationResult, W as SeoState, X as DOCUMENT_ACTIONS, Y as AuthenticationRequired, Z as MEDIA_ACTIONS, _ as DocumentSurround, _t as MediaReference, at as MediaCleanupReport, bt as MediaTooLarge, c as DocumentIssue, ct as MediaFolder, d as DocumentNavigationQuery, dt as MediaInvalid, et as StudioEntryDenied, f as DocumentQueryScalar, g as DocumentSummary, gt as MediaQuery, ht as MediaPage, i as CreateDocumentInput, it as MediaByteSize, j as UpdateDocumentInput, k as UndeleteDocumentInput, l as DocumentMutationResult, lt as MediaId, m as DocumentSource, mt as MediaObjectKey, n as CmsMarkdownDocument, nt as ImageMimeType, o as DeletedDocument, ot as MediaConflict, p as DocumentRevisionAction, pt as MediaNotFound, q as SitemapEntry, r as CompiledDocument, rt as MediaAsset, s as DocumentBrowseQuery, u as DocumentNavigationItem, ut as MediaIntegrityReport, v as DocumentValidationResult, vt as MediaReferenced, w as PublishedDocumentPage, x as MoveDocumentInput, xt as MediaUpload, y as DuplicateDocumentInput, z as SeoConfirmationRequired } from "./models-Bah5B3bT.js";
2
+ import { $ as StudioActor, B as SeoMediaUnavailable, C as PublishedDocumentLookup, D as RemoveDocumentInput, E as PublishedDocumentSurroundQuery, Et as RequestId, F as SaveSeoInput, G as SeoUrl, I as SeoCanonicalOrigin, J as AccessDenied, K as SeoVersionConflict, L as SeoCapabilities, N as GlobalSeoSettings, O as RestoreDocumentInput, P as PublishSeoInput, Q as Role, R as SeoConfiguration, S as PublishDocumentInput, T as PublishedDocumentQuery, U as SeoSnapshot, V as SeoMutationResult, W as SeoState, X as DOCUMENT_ACTIONS, Y as AuthenticationRequired, Z as MEDIA_ACTIONS, _ as DocumentSurround, _t as MediaReference, at as MediaCleanupReport, bt as MediaTooLarge, c as DocumentIssue, ct as MediaFolder, d as DocumentNavigationQuery, dt as MediaInvalid, et as StudioEntryDenied, f as DocumentQueryScalar, g as DocumentSummary, gt as MediaQuery, ht as MediaPage, i as CreateDocumentInput, it as MediaByteSize, j as UpdateDocumentInput, k as UndeleteDocumentInput, l as DocumentMutationResult, lt as MediaId, m as DocumentSource, mt as MediaObjectKey, n as CmsMarkdownDocument, nt as ImageMimeType, o as DeletedDocument, ot as MediaConflict, p as DocumentRevisionAction, pt as MediaNotFound, q as SitemapEntry, r as CompiledDocument, rt as MediaAsset, s as DocumentBrowseQuery, u as DocumentNavigationItem, ut as MediaIntegrityReport, v as DocumentValidationResult, vt as MediaReferenced, w as PublishedDocumentPage, x as MoveDocumentInput, xt as MediaUpload, y as DuplicateDocumentInput, z as SeoConfirmationRequired } from "./models-DgkGTFus.js";
3
+ import { i as ContentSnapshot, n as ContentApplyResult, o as ContentTransferConflict, r as ContentPlan, s as ContentTransferInput, t as ContentApplyInput } from "./ContentTransfer-CTzGGKFV.js";
5
4
  import { u as STUDIO_API_PATH } from "./HttpPaths-c9nLZ9H2.js";
5
+ import { i as FormResult, o as FormSubmission } from "./Forms-CfcI3tPU.js";
6
+ import { a as encodeCmsEditorComponentAttributes, d as createCmsComarkRenderData, m as toComarkDocument, p as mutableJsonObject, s as projectCmsEditorComponentAttributes } from "./Forms-02-p8qEw.js";
6
7
  import { i as withoutEditorMetadata } from "./metadata-BEZPWh-3.js";
7
- import { d as EditorRenderFailed, i as MediaConfiguration, r as DocumentConfiguration } from "./Configuration-CDMYfTre.js";
8
- import { i as ContentSnapshot, n as ContentApplyResult, o as ContentTransferConflict, r as ContentPlan, s as ContentTransferInput, t as ContentApplyInput } from "./ContentTransfer-C3Av9sWz.js";
9
- import { a as normalizeDocumentRelativePath, c as resolveDocumentAddress, i as localizeDocumentPath, n as referenceTarget, o as normalizePublicPath, r as DocumentCompilationFailed, s as parseDocumentAddress, t as createDocumentEngine } from "./DocumentEngine-J7g-emdf.js";
8
+ import { d as EditorRenderFailed, i as MediaConfiguration, r as DocumentConfiguration } from "./Configuration-CjVUBBwa.js";
9
+ import { a as normalizeDocumentRelativePath, c as resolveDocumentAddress, i as localizeDocumentPath, n as referenceTarget, o as normalizePublicPath, r as DocumentCompilationFailed, s as parseDocumentAddress, t as createDocumentEngine } from "./DocumentEngine-BbhfnTAc.js";
10
10
  import { Context, Crypto, Data, DateTime, Effect, Encoding, Layer, Option, Predicate, PubSub, Redacted, Ref, Result, Schedule, Schema, Semaphore, Stream, flow } from "effect";
11
11
  import { NodeStream } from "@effect/platform-node-shared";
12
12
  import { Multipart } from "effect/unstable/http";
@@ -2191,6 +2191,7 @@ const makeDocuments = Effect.fn("Documents.make")(function* (configuration, opti
2191
2191
  return ContentSnapshot.make({
2192
2192
  version: 1,
2193
2193
  sources: current.snapshot.active.map((source) => ({
2194
+ documentId: source.documentId,
2194
2195
  sourcePath: source.sourcePath,
2195
2196
  markdown: source.markdown,
2196
2197
  published: source.publishedVersion === source.version
@@ -2431,17 +2432,30 @@ const seoDeliveryLayer = Layer.effect(SeoDelivery, Effect.gen(function* () {
2431
2432
  const previews = yield* PreviewSeo;
2432
2433
  const published = yield* PublishedSeo;
2433
2434
  const documents = yield* PublishedDocuments;
2434
- const resolveWith = (document, snapshot) => CompiledDocument.make(Object.assign({}, document, { resolvedSeo: resolveDocumentSeo({
2435
- capabilities: snapshot.capabilities,
2436
- document,
2437
- global: snapshot.revision.settings
2438
- }) }));
2439
- const publishedDocument = Effect.fn("SeoDelivery.publishedDocument")((document) => published.read.pipe(Effect.map((snapshot) => resolveWith(document, snapshot))));
2440
- const previewDocument = Effect.fn("SeoDelivery.previewDocument")((document) => previews.read.pipe(Effect.map((snapshot) => resolveWith(document, snapshot))));
2435
+ const alternatives = (document) => documents.snapshot.pipe(Effect.map((snapshot) => snapshot.flatMap((candidate) => candidate.key === document.key && candidate.locale !== void 0 ? [{
2436
+ locale: candidate.locale,
2437
+ path: candidate.path
2438
+ }] : [])));
2439
+ const resolveWith = (document, snapshot, localized) => CompiledDocument.make(Object.assign({}, document, {
2440
+ alternatives: localized,
2441
+ resolvedSeo: resolveDocumentSeo({
2442
+ capabilities: snapshot.capabilities,
2443
+ document,
2444
+ global: snapshot.revision.settings
2445
+ })
2446
+ }));
2447
+ const publishedDocument = Effect.fn("SeoDelivery.publishedDocument")((document) => Effect.all({
2448
+ snapshot: published.read,
2449
+ alternatives: alternatives(document)
2450
+ }).pipe(Effect.map(({ alternatives, snapshot }) => resolveWith(document, snapshot, alternatives))));
2451
+ const previewDocument = Effect.fn("SeoDelivery.previewDocument")((document) => Effect.all({
2452
+ snapshot: previews.read,
2453
+ alternatives: alternatives(document)
2454
+ }).pipe(Effect.map(({ alternatives, snapshot }) => resolveWith(document, snapshot, alternatives))));
2441
2455
  const sitemap = Effect.gen(function* () {
2442
2456
  const snapshot = yield* published.read;
2443
2457
  const resolved = (yield* documents.snapshot).flatMap((document) => {
2444
- const resolvedDocument = resolveWith(document, snapshot);
2458
+ const resolvedDocument = resolveWith(document, snapshot, []);
2445
2459
  return resolvedDocument.resolvedSeo?.index === true && resolvedDocument.source.publishedAt !== void 0 ? [resolvedDocument] : [];
2446
2460
  });
2447
2461
  const localesByKey = /* @__PURE__ */ new Map();
@@ -2600,30 +2614,30 @@ function s3MediaObjectStoreLayer(options) {
2600
2614
  }
2601
2615
  function makeStore(options, client) {
2602
2616
  return {
2603
- list: listObjects(options.bucket, client),
2604
- promote: (input) => promoteObject(options.bucket, input, client),
2605
- put: (input) => putObject(options.bucket, input, client),
2617
+ list: listObjects(options.bucket, options.prefix, client),
2618
+ promote: (input) => promoteObject(options.bucket, options.prefix, input, client),
2619
+ put: (input) => putObject(options.bucket, options.prefix, input, client),
2606
2620
  remove: (objectKey) => providerRequest("MediaObjectStore.S3.remove", client.deleteObject({
2607
2621
  bucket: options.bucket,
2608
- key: objectKey
2622
+ key: physicalKey(options.prefix, objectKey)
2609
2623
  })),
2610
- stat: (objectKey) => statObject(options.bucket, objectKey, client)
2624
+ stat: (objectKey) => statObject(options.bucket, options.prefix, objectKey, client)
2611
2625
  };
2612
2626
  }
2613
- function promoteObject(bucket, input, client) {
2627
+ function promoteObject(bucket, prefix, input, client) {
2614
2628
  if (input.byteSize > 5e9) return Effect.fail(storageError("MediaObjectStore.S3.promote", "The object exceeds the S3 single-copy size limit."));
2615
- return statObject(bucket, input.sourceObjectKey, client).pipe(Effect.flatMap((source) => Option.isSome(source) && source.value.byteSize === input.byteSize && source.value.mimeType === input.mimeType ? Effect.void : Effect.fail(storageError("MediaObjectStore.S3.promote.source", "The staged object metadata does not match its intent."))), Effect.flatMap(() => providerRequest("MediaObjectStore.S3.promote.copy", client.copyObject({
2629
+ return statObject(bucket, prefix, input.sourceObjectKey, client).pipe(Effect.flatMap((source) => Option.isSome(source) && source.value.byteSize === input.byteSize && source.value.mimeType === input.mimeType ? Effect.void : Effect.fail(storageError("MediaObjectStore.S3.promote.source", "The staged object metadata does not match its intent."))), Effect.flatMap(() => providerRequest("MediaObjectStore.S3.promote.copy", client.copyObject({
2616
2630
  bucket,
2617
2631
  cacheControl: replaceableMediaCacheControl,
2618
2632
  contentType: input.mimeType,
2619
- copySource: copySource(bucket, input.sourceObjectKey),
2620
- key: input.destinationObjectKey
2621
- }))), Effect.flatMap(() => statObject(bucket, input.destinationObjectKey, client)), Effect.flatMap((destination) => Option.isSome(destination) && destination.value.byteSize === input.byteSize && destination.value.mimeType === input.mimeType ? Effect.succeed(destination.value) : Effect.fail(storageError("MediaObjectStore.S3.promote.verify", "The promoted object metadata does not match its intent."))));
2633
+ copySource: copySource(bucket, physicalKey(prefix, input.sourceObjectKey)),
2634
+ key: physicalKey(prefix, input.destinationObjectKey)
2635
+ }))), Effect.flatMap(() => statObject(bucket, prefix, input.destinationObjectKey, client)), Effect.flatMap((destination) => Option.isSome(destination) && destination.value.byteSize === input.byteSize && destination.value.mimeType === input.mimeType ? Effect.succeed(destination.value) : Effect.fail(storageError("MediaObjectStore.S3.promote.verify", "The promoted object metadata does not match its intent."))));
2622
2636
  }
2623
2637
  function copySource(bucket, objectKey) {
2624
2638
  return `/${encodeURIComponent(bucket)}/${objectKey.split("/").map(encodeURIComponent).join("/")}`;
2625
2639
  }
2626
- function putObject(bucket, input, client) {
2640
+ function putObject(bucket, prefix, input, client) {
2627
2641
  return Effect.gen(function* () {
2628
2642
  const body = yield* validatedWriteBody(input);
2629
2643
  yield* client.putObject({
@@ -2632,7 +2646,7 @@ function putObject(bucket, input, client) {
2632
2646
  cacheControl: replaceableMediaCacheControl,
2633
2647
  contentLength: input.byteSize,
2634
2648
  contentType: input.mimeType,
2635
- key: input.objectKey
2649
+ key: physicalKey(prefix, input.objectKey)
2636
2650
  }).pipe(Effect.catch((failure) => isWriteBodyError(failure.cause) ? Effect.fail(failure.cause) : Effect.fail(providerError("MediaObjectStore.S3.put", failure))));
2637
2651
  return {
2638
2652
  byteSize: input.byteSize,
@@ -2648,27 +2662,27 @@ const validatedWriteBody = Effect.fn("MediaObjectStore.S3.validateWriteBody")(fu
2648
2662
  return chunk;
2649
2663
  })), Stream.concat(Stream.fromEffect(Ref.get(byteLength).pipe(Effect.flatMap((actual) => actual === input.byteSize ? Effect.void : Effect.fail(storageError("MediaObjectStore.S3.put.body", "The object body does not match its declared byte size."))))).pipe(Stream.drain)));
2650
2664
  });
2651
- function statObject(bucket, objectKey, client) {
2665
+ function statObject(bucket, prefix, objectKey, client) {
2652
2666
  return client.headObject({
2653
2667
  bucket,
2654
- key: objectKey
2668
+ key: physicalKey(prefix, objectKey)
2655
2669
  }).pipe(Effect.matchEffect({
2656
2670
  onFailure: (failure) => isMissingObject(failure.cause) ? Effect.succeed(Option.none()) : Effect.fail(providerError("MediaObjectStore.S3.stat", failure)),
2657
2671
  onSuccess: (output) => decodeStoredObject("MediaObjectStore.S3.stat", objectKey, output.contentLength, output.contentType).pipe(Effect.asSome)
2658
2672
  }));
2659
2673
  }
2660
- function listObjects(bucket, client) {
2674
+ function listObjects(bucket, prefix, client) {
2661
2675
  return Stream.paginate({ seenTokens: /* @__PURE__ */ new Set() }, (state) => providerRequest("MediaObjectStore.S3.list", client.listObjects({
2662
2676
  bucket,
2663
2677
  continuationToken: state.continuationToken,
2664
- prefix: mediaObjectPrefix
2678
+ prefix: `${prefix}${mediaObjectPrefix}`
2665
2679
  })).pipe(Effect.flatMap((page) => Effect.gen(function* () {
2666
- return [yield* Effect.forEach(page.objects, decodeListedObject), yield* nextListState(state, page)];
2680
+ return [yield* Effect.forEach(page.objects, (object) => decodeListedObject(object, prefix)), yield* nextListState(state, page)];
2667
2681
  }))));
2668
2682
  }
2669
- function decodeListedObject(object) {
2683
+ function decodeListedObject(object, prefix) {
2670
2684
  if (object.key === void 0) return Effect.fail(storageError("MediaObjectStore.S3.list", "The provider returned object metadata without a key."));
2671
- return decodeStoredObject("MediaObjectStore.S3.list", object.key, object.size);
2685
+ return decodeStoredObject("MediaObjectStore.S3.list", object.key.slice(prefix.length), object.size);
2672
2686
  }
2673
2687
  function nextListState(state, page) {
2674
2688
  if (!page.isTruncated) return Effect.succeedNone;
@@ -2742,7 +2756,8 @@ function resolveOptions(options) {
2742
2756
  const bucket = options.bucket.trim();
2743
2757
  const region = options.region.trim();
2744
2758
  const endpoint = options.endpoint?.trim();
2745
- if (!bucket || !region || options.endpoint !== void 0 && !endpoint) return Effect.fail(storageError("MediaObjectStore.S3.configure", "The bucket, region, and configured endpoint must be non-empty."));
2759
+ const prefix = options.prefix.trim();
2760
+ if (!bucket || !region || options.endpoint !== void 0 && !endpoint || !prefix || prefix.startsWith("/") || !prefix.endsWith("/") || prefix.includes("..")) return Effect.fail(storageError("MediaObjectStore.S3.configure", "The bucket, region, configured endpoint, and relative object prefix must be valid."));
2746
2761
  if (options.credentials) {
2747
2762
  const secretAccessKey = Redacted.value(options.credentials.secretAccessKey);
2748
2763
  const sessionToken = options.credentials.sessionToken && Redacted.value(options.credentials.sessionToken);
@@ -2757,10 +2772,14 @@ function resolveOptions(options) {
2757
2772
  } : void 0,
2758
2773
  endpoint,
2759
2774
  forcePathStyle: options.forcePathStyle ?? false,
2775
+ prefix,
2760
2776
  provisionBucket: options.provisionBucket ?? false,
2761
2777
  region
2762
2778
  });
2763
2779
  }
2780
+ function physicalKey(prefix, objectKey) {
2781
+ return `${prefix}${objectKey}`;
2782
+ }
2764
2783
  function storageError(operation, message) {
2765
2784
  return new MediaStorageError({
2766
2785
  cause: new Error(message),
@@ -2774,4 +2793,4 @@ const maxS3SingleCopyBytes = 5e9;
2774
2793
 
2775
2794
  //#endregion
2776
2795
  export { DocumentRevision as $, StudioBadRequest as A, User as B, DocumentStore as C, CurrentStudioRequest as D, defaultAccessControlLayer as E, studioInternalError as F, UserSelfRemovalDenied as G, UserAlreadyExists as H, InitializationAlreadyCompleted as I, CollaborationServerMessage as J, UserSelfRoleChangeDenied as K, InitializationProofInvalid as L, StudioRequestConflict as M, StudioSchemaError as N, StudioApi as O, StudioInternalError as P, DocumentHistoryInvalidCursor as Q, InitializationState as R, DocumentPersistenceError as S, AccessControl as T, UserNotFound as U, UserAdministrationDenied as V, UserPage as W, StateVector as X, CollaborationTicket as Y, DocumentHistoryComparisonTooLarge as Z, Documents as _, mediaObjectPrefix as a, ActivityEntry as at, cursorCodec as b, Seo as c, ActivityPage as ct, seoDeliveryLayer as d, DocumentMediaUnavailable as dt, ACTIVITY_ACTIONS as et, seoLayer as f, DocumentNotFound as ft, DocumentPreviews as g, PublishedDocumentNotFound as gt, DocumentMaintenance as h, DocumentVersionConflict as ht, MediaObjectStore as i, ActivityCursorInvalid as it, StudioBootstrap as j, StudioAuthentication as k, SeoDelivery as l, ActivityTarget as lt, SeoStore as m, DocumentValidationFailed as mt, s3MediaObjectStoreLayer as n, ActivityContext as nt, PreviewSeo as o, ActivityEntryDraft as ot, SeoPersistenceError as p, DocumentPathConflict as pt, CollaborationClientMessage as q, MediaPersistenceError as r, ActivityCursor as rt, PublishedSeo as s, ActivityId as st, maxS3SingleCopyBytes as t, ActivityAction as tt, makeDefaultSeoOptions as u, ActivityTargetKind as ut, PublishedDocuments as v, renderEditorMarkdown as w, DocumentGenerationConflict as x, documentsLayer as y, CreateUserInput as z };
2777
- //# sourceMappingURL=S3MediaObjects-CpPSzJto.js.map
2796
+ //# sourceMappingURL=S3MediaObjects-DC0c8sYC.js.map