@phtngyn/cms 0.2.0-beta.1 → 0.2.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +40 -45
- package/package.json +7 -5
- package/src/ApplicationTypes.d.ts +7 -5
- package/src/{Configuration-CjVUBBwa.js → Configuration-BU-UyGoH.js} +4 -4
- package/src/{Configuration-CjVUBBwa.js.map → Configuration-BU-UyGoH.js.map} +1 -1
- package/src/Configuration.d.ts +41 -24
- package/src/Configuration.js.map +1 -1
- package/src/Content.js +42 -19
- package/src/Content.js.map +1 -1
- package/src/{ContentTransfer-CTzGGKFV.js → ContentTransfer-BhF9G56s.js} +2 -2
- package/src/{ContentTransfer-CTzGGKFV.js.map → ContentTransfer-BhF9G56s.js.map} +1 -1
- package/src/{DocumentEngine-BbhfnTAc.js → DocumentEngine-ClhFXW9M.js} +4 -4
- package/src/{DocumentEngine-BbhfnTAc.js.map → DocumentEngine-ClhFXW9M.js.map} +1 -1
- package/src/DocumentModel.d.ts +6 -1
- package/src/DocumentModel.js +4 -3
- package/src/DocumentModel.js.map +1 -1
- package/src/{Forms-CfcI3tPU.js → Forms-BbkE7QfC.js} +47 -16
- package/src/Forms-BbkE7QfC.js.map +1 -0
- package/src/{Forms-02-p8qEw.js → Forms-DoB56hfe.js} +24 -7
- package/src/Forms-DoB56hfe.js.map +1 -0
- package/src/{Forms-BorTcIlp.d.ts → Forms-R0HoTR-o.d.ts} +30 -9
- package/src/Forms.d.ts +16 -15
- package/src/Forms.js.map +1 -1
- package/src/{I18n-BXlVunfa.d.ts → I18n-zbqpWxki.d.ts} +3 -1
- package/src/I18n.d.ts +1 -1
- package/src/Module.js +4 -2
- package/src/Module.js.map +1 -1
- package/src/{S3MediaObjects-DC0c8sYC.js → S3MediaObjects-CR3p1WTg.js} +21 -13
- package/src/S3MediaObjects-CR3p1WTg.js.map +1 -0
- package/src/cli.js +60 -34
- package/src/cli.js.map +1 -1
- package/src/{connection-BPf4BQUZ.js → connection-D5S9Iph-.js} +2 -2
- package/src/{connection-BPf4BQUZ.js.map → connection-D5S9Iph-.js.map} +1 -1
- package/src/{dev-lifecycle-vQLxwCFq.js → dev-lifecycle-D3f9-upa.js} +129 -42
- package/src/dev-lifecycle-D3f9-upa.js.map +1 -0
- package/src/{installation-DsGst1BH.js → installation-fZtNxtoW.js} +68 -41
- package/src/installation-fZtNxtoW.js.map +1 -0
- package/src/internal/authoring-catalog.js +2 -2
- package/src/internal/authoring-metadata.js +1 -1
- package/src/internal/configuration.js +149 -50
- package/src/internal/configuration.js.map +1 -1
- package/src/internal/dev-lifecycle.js +2 -2
- package/src/internal/diagnostics.js +47 -0
- package/src/internal/diagnostics.js.map +1 -0
- package/src/internal/document-model.js +2 -2
- package/src/internal/form-capabilities.js +1 -1
- package/src/internal/i18n.js +6 -1
- package/src/internal/i18n.js.map +1 -1
- package/src/internal/studio-app.js +8 -6
- package/src/internal/studio-app.js.map +1 -1
- package/src/{location-BgYhXEZp.js → location-CPX7oj0o.js} +2 -2
- package/src/{location-BgYhXEZp.js.map → location-CPX7oj0o.js.map} +1 -1
- package/src/{models-k2nXyD6q.js → models-C9kF9JlQ.js} +2 -2
- package/src/{models-k2nXyD6q.js.map → models-C9kF9JlQ.js.map} +1 -1
- package/src/{models-DgkGTFus.js → models-ChRxBChy.js} +4 -2
- package/src/{models-DgkGTFus.js.map → models-ChRxBChy.js.map} +1 -1
- package/src/runtime/delivery/context.js +1 -1
- package/src/runtime/delivery/plugin.js +3 -2
- package/src/runtime/delivery/plugin.js.map +1 -1
- package/src/runtime/forms/document.js +1 -1
- package/src/runtime/forms/useCmsForm.js +73 -46
- package/src/runtime/forms/useCmsForm.js.map +1 -1
- package/src/runtime/i18n/useCmsI18n.d.ts +1 -1
- package/src/runtime/i18n/useCmsI18n.js.map +1 -1
- package/src/runtime/installation.js +1 -1
- package/src/runtime/plugin.js +12 -4
- package/src/runtime/plugin.js.map +1 -1
- package/src/runtime/preview/connection.js +1 -1
- package/src/runtime/preview/controller.js +2 -2
- package/src/runtime/preview/plugin.client.js +3 -3
- package/src/runtime/preview/plugin.client.js.map +1 -1
- package/src/runtime/preview/store.js +1 -1
- package/src/runtime/sitemap.js +1 -1
- package/src/{store-BYgSt7E3.js → store-CCsjHaZm.js} +8 -8
- package/src/store-CCsjHaZm.js.map +1 -0
- package/studio/{CreateDocumentDialog-BdiM77bb.js → CreateDocumentDialog-DJ8c0WZb.js} +3 -3
- package/studio/{documentPlanning-B7fyUj9r.js → documentPlanning-CDb31mnl.js} +6417 -6358
- package/studio/host.css +1 -1
- package/studio/host.js +7612 -7249
- package/src/Forms-02-p8qEw.js.map +0 -1
- package/src/Forms-CfcI3tPU.js.map +0 -1
- package/src/S3MediaObjects-DC0c8sYC.js.map +0 -1
- package/src/dev-lifecycle-vQLxwCFq.js.map +0 -1
- package/src/installation-DsGst1BH.js.map +0 -1
- package/src/store-BYgSt7E3.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as CmsMarkdownDocument } from "./models-
|
|
2
|
-
import { a as FormSteps, t as FORM_REVISION_MAX_BYTES } from "./Forms-
|
|
1
|
+
import { n as CmsMarkdownDocument } from "./models-ChRxBChy.js";
|
|
2
|
+
import { a as FormOption, i as FormFieldType, s as FormSteps, t as FORM_REVISION_MAX_BYTES } from "./Forms-BbkE7QfC.js";
|
|
3
3
|
import { Option, Predicate, Result, Schema } from "effect";
|
|
4
4
|
import { resolveAttributes, textContent } from "comark/utils";
|
|
5
5
|
|
|
@@ -196,7 +196,7 @@ function sameJson(left, right) {
|
|
|
196
196
|
//#endregion
|
|
197
197
|
//#region ../document/src/Forms.ts
|
|
198
198
|
function formStructureIssues(input, capabilities, name) {
|
|
199
|
-
const decoded = Schema.decodeUnknownResult(
|
|
199
|
+
const decoded = Schema.decodeUnknownResult(DraftFormSteps)(input, { onExcessProperty: "error" });
|
|
200
200
|
if (Result.isFailure(decoded)) return ["Each form needs steps with a title and at least one valid question."];
|
|
201
201
|
const issues = [];
|
|
202
202
|
if (new TextEncoder().encode(JSON.stringify(formRevision(name, capabilities, decoded.success))).byteLength > 6e4) issues.push("This form is too large. Reduce the number or size of questions.");
|
|
@@ -252,11 +252,28 @@ function fieldIssue(field, value) {
|
|
|
252
252
|
return;
|
|
253
253
|
}
|
|
254
254
|
if (!Predicate.isString(value)) return "Enter text.";
|
|
255
|
-
if (field.type === "select" && !field.options
|
|
255
|
+
if (field.type === "select" && !field.options.some((option) => option.id === value)) return "Choose an available option.";
|
|
256
256
|
if (field.type === "email" && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/u.test(value)) return "Enter a valid email address.";
|
|
257
|
-
if (field.minLength !== void 0 && value.length < field.minLength) return `Enter at least ${field.minLength} characters.`;
|
|
258
|
-
if (field.maxLength !== void 0 && value.length > field.maxLength) return `Enter at most ${field.maxLength} characters.`;
|
|
257
|
+
if ((field.type === "text" || field.type === "email" || field.type === "textarea") && field.minLength !== void 0 && value.length < field.minLength) return `Enter at least ${field.minLength} characters.`;
|
|
258
|
+
if ((field.type === "text" || field.type === "email" || field.type === "textarea") && field.maxLength !== void 0 && value.length > field.maxLength) return `Enter at most ${field.maxLength} characters.`;
|
|
259
259
|
}
|
|
260
|
+
const DraftFormField = Schema.Struct({
|
|
261
|
+
id: Schema.NonEmptyString,
|
|
262
|
+
label: Schema.NonEmptyString,
|
|
263
|
+
type: FormFieldType,
|
|
264
|
+
help: Schema.optionalKey(Schema.String),
|
|
265
|
+
required: Schema.optionalKey(Schema.Boolean),
|
|
266
|
+
minLength: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),
|
|
267
|
+
maxLength: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),
|
|
268
|
+
min: Schema.optionalKey(Schema.Finite),
|
|
269
|
+
max: Schema.optionalKey(Schema.Finite),
|
|
270
|
+
options: Schema.optionalKey(Schema.Array(FormOption))
|
|
271
|
+
});
|
|
272
|
+
const DraftFormSteps = Schema.Array(Schema.Struct({
|
|
273
|
+
id: Schema.NonEmptyString,
|
|
274
|
+
title: Schema.NonEmptyString,
|
|
275
|
+
fields: Schema.Array(DraftFormField).check(Schema.isMinLength(1), Schema.isMaxLength(100))
|
|
276
|
+
})).check(Schema.isMinLength(1), Schema.isMaxLength(20));
|
|
260
277
|
/** Paths refer to authored nodes, never rendered Vue children. Revision comparison is exact. */
|
|
261
278
|
function documentForms(document, components, preview = false) {
|
|
262
279
|
const forms = [];
|
|
@@ -364,4 +381,4 @@ function formAuthoring(capabilities) {
|
|
|
364
381
|
|
|
365
382
|
//#endregion
|
|
366
383
|
export { encodeCmsEditorComponentAttributes as a, resolveCmsComarkAttributes as c, createCmsComarkRenderData as d, mutableJson as f, validateFormValues as i, withCmsComarkProps as l, toComarkDocument as m, formAuthoring as n, normalizeCmsComponentBindings as o, mutableJsonObject as p, formStructureIssues as r, projectCmsEditorComponentAttributes as s, documentForms as t, cmsComarkTextContent as u };
|
|
367
|
-
//# sourceMappingURL=Forms-
|
|
384
|
+
//# sourceMappingURL=Forms-DoB56hfe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Forms-DoB56hfe.js","names":["isJsonObject","jsonObject","CmsMarkdownDocumentSchema","FormFieldTypeSchema","FormOptionSchema"],"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 {\n FormCapabilities,\n FormDefinition,\n FormField,\n FormFieldType,\n FormOption,\n FormValues,\n} from '@internal/protocol/Forms'\nimport {\n FORM_REVISION_MAX_BYTES,\n FormFieldType as FormFieldTypeSchema,\n FormOption as FormOptionSchema,\n FormSteps,\n} 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(DraftFormSteps)(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 (\n (field.type === 'text' || field.type === 'email' || field.type === 'textarea') &&\n field.minLength !== undefined &&\n value.length < field.minLength\n )\n return `Enter at least ${field.minLength} characters.`\n\n if (\n (field.type === 'text' || field.type === 'email' || field.type === 'textarea') &&\n field.maxLength !== undefined &&\n value.length > field.maxLength\n )\n return `Enter at most ${field.maxLength} characters.`\n\n return undefined\n}\n\ninterface DraftFormField {\n readonly id: string\n readonly label: string\n readonly type: FormFieldType\n readonly help?: string\n readonly required?: boolean\n readonly minLength?: number\n readonly maxLength?: number\n readonly min?: number\n readonly max?: number\n readonly options?: ReadonlyArray<FormOption>\n}\n\nconst DraftFormField: Schema.Codec<DraftFormField> = Schema.Struct({\n id: Schema.NonEmptyString,\n label: Schema.NonEmptyString,\n type: FormFieldTypeSchema,\n help: Schema.optionalKey(Schema.String),\n required: Schema.optionalKey(Schema.Boolean),\n minLength: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),\n maxLength: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),\n min: Schema.optionalKey(Schema.Finite),\n max: Schema.optionalKey(Schema.Finite),\n options: Schema.optionalKey(Schema.Array(FormOptionSchema)),\n})\n\nconst DraftFormSteps = Schema.Array(\n Schema.Struct({\n id: Schema.NonEmptyString,\n title: Schema.NonEmptyString,\n fields: Schema.Array(DraftFormField).check(Schema.isMinLength(1), Schema.isMaxLength(100)),\n }),\n).check(Schema.isMinLength(1), Schema.isMaxLength(20))\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(\n name: string,\n capabilities: FormCapabilities,\n steps: Schema.Schema.Type<typeof DraftFormSteps>,\n): 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":"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"}
|
|
@@ -16,18 +16,30 @@ interface FormOption {
|
|
|
16
16
|
readonly label: string;
|
|
17
17
|
}
|
|
18
18
|
declare const FormOption: Schema.Codec<FormOption>;
|
|
19
|
-
interface
|
|
19
|
+
interface FormFieldBase {
|
|
20
20
|
readonly id: string;
|
|
21
21
|
readonly label: string;
|
|
22
|
-
readonly type: FormFieldType;
|
|
23
22
|
readonly help?: string;
|
|
24
23
|
readonly required?: boolean;
|
|
24
|
+
}
|
|
25
|
+
interface FormTextField<Type extends 'text' | 'email' | 'textarea'> extends FormFieldBase {
|
|
26
|
+
readonly type: Type;
|
|
25
27
|
readonly minLength?: number;
|
|
26
28
|
readonly maxLength?: number;
|
|
29
|
+
}
|
|
30
|
+
interface FormNumberField extends FormFieldBase {
|
|
31
|
+
readonly type: 'number';
|
|
27
32
|
readonly min?: number;
|
|
28
33
|
readonly max?: number;
|
|
29
|
-
readonly options?: ReadonlyArray<FormOption>;
|
|
30
34
|
}
|
|
35
|
+
interface FormCheckboxField extends FormFieldBase {
|
|
36
|
+
readonly type: 'checkbox';
|
|
37
|
+
}
|
|
38
|
+
interface FormSelectField extends FormFieldBase {
|
|
39
|
+
readonly type: 'select';
|
|
40
|
+
readonly options: readonly [FormOption, ...FormOption[]];
|
|
41
|
+
}
|
|
42
|
+
type FormField = FormTextField<'text'> | FormTextField<'email'> | FormTextField<'textarea'> | FormNumberField | FormCheckboxField | FormSelectField;
|
|
31
43
|
declare const FormField: Schema.Codec<FormField>;
|
|
32
44
|
interface FormStep {
|
|
33
45
|
readonly id: string;
|
|
@@ -61,11 +73,20 @@ declare const FormSubmission: Schema.Codec<FormSubmission, {
|
|
|
61
73
|
readonly revision: string;
|
|
62
74
|
readonly values: FormValues;
|
|
63
75
|
}>;
|
|
64
|
-
|
|
65
|
-
readonly status:
|
|
66
|
-
readonly
|
|
67
|
-
}
|
|
68
|
-
|
|
76
|
+
declare const FormResult: Schema.Union<readonly [Schema.Struct<{
|
|
77
|
+
readonly status: Schema.Literals<readonly ["accepted"]>;
|
|
78
|
+
readonly reference: Schema.optionalKey<Schema.NonEmptyString>;
|
|
79
|
+
}>, Schema.Struct<{
|
|
80
|
+
readonly status: Schema.Literals<readonly ["invalid"]>;
|
|
81
|
+
readonly errors: Schema.$Record<Schema.String, Schema.String>;
|
|
82
|
+
}>, Schema.Struct<{
|
|
83
|
+
readonly status: Schema.Literals<readonly ["stale"]>;
|
|
84
|
+
}>, Schema.Struct<{
|
|
85
|
+
readonly status: Schema.Literals<readonly ["unavailable"]>;
|
|
86
|
+
}>, Schema.Struct<{
|
|
87
|
+
readonly status: Schema.Literals<readonly ["failed"]>;
|
|
88
|
+
}>]>;
|
|
89
|
+
type FormResult = typeof FormResult.Type;
|
|
69
90
|
//#endregion
|
|
70
91
|
export { FormStep as a, FormResult as i, FormDefinition as n, FormSubmission as o, FormField as r, FormValues as s, FormCapabilities as t };
|
|
71
|
-
//# sourceMappingURL=Forms-
|
|
92
|
+
//# sourceMappingURL=Forms-R0HoTR-o.d.ts.map
|
package/src/Forms.d.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
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-
|
|
2
|
-
import { ComputedRef, MaybeRefOrGetter, Ref
|
|
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-R0HoTR-o.js";
|
|
2
|
+
import { ComputedRef, MaybeRefOrGetter, Ref } 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
|
|
9
|
-
readonly field:
|
|
10
|
-
|
|
11
|
-
readonly dirty:
|
|
12
|
-
readonly touched:
|
|
13
|
-
readonly valid:
|
|
14
|
-
readonly
|
|
15
|
-
readonly
|
|
8
|
+
interface CmsFormControl {
|
|
9
|
+
readonly field: FormField;
|
|
10
|
+
value: FormValues[string];
|
|
11
|
+
readonly dirty: boolean;
|
|
12
|
+
readonly touched: boolean;
|
|
13
|
+
readonly valid: boolean;
|
|
14
|
+
readonly error: string | undefined;
|
|
15
|
+
readonly attrs: {
|
|
16
16
|
readonly id: string;
|
|
17
17
|
readonly name: string;
|
|
18
18
|
readonly required: boolean;
|
|
19
19
|
readonly 'aria-invalid': 'true' | undefined;
|
|
20
20
|
readonly 'aria-describedby': string | undefined;
|
|
21
|
-
}
|
|
21
|
+
};
|
|
22
22
|
readonly helpAttrs: {
|
|
23
23
|
readonly id: string;
|
|
24
24
|
};
|
|
@@ -42,9 +42,10 @@ interface UseCmsFormReturn {
|
|
|
42
42
|
readonly isPreview: ComputedRef<boolean>;
|
|
43
43
|
readonly submitError: Readonly<Ref<string | undefined>>;
|
|
44
44
|
readonly canSubmit: ComputedRef<boolean>;
|
|
45
|
-
readonly
|
|
46
|
-
readonly
|
|
47
|
-
readonly
|
|
45
|
+
readonly visibleControls: ComputedRef<ReadonlyArray<CmsFormControl>>;
|
|
46
|
+
readonly invalidControls: ComputedRef<ReadonlyArray<CmsFormControl>>;
|
|
47
|
+
readonly firstInvalidControlId: ComputedRef<string | undefined>;
|
|
48
|
+
readonly control: (field: string | FormField) => CmsFormControl;
|
|
48
49
|
readonly next: () => boolean;
|
|
49
50
|
readonly previous: () => void;
|
|
50
51
|
readonly validate: () => boolean;
|
|
@@ -58,5 +59,5 @@ export declare function useCmsForm(input: MaybeRefOrGetter<FormDefinition>, opti
|
|
|
58
59
|
/** Register this definition under the kebab-case name of your Vue form renderer. */
|
|
59
60
|
export declare function defineCmsForm<const Definition extends FormCapabilities>(definition: Definition): Definition;
|
|
60
61
|
//#endregion
|
|
61
|
-
export type { FormDefinition as CmsFormDefinition, FormField as CmsFormField,
|
|
62
|
+
export type { CmsFormControl, FormDefinition as CmsFormDefinition, FormField as CmsFormField, FormResult as CmsFormResult, FormStep as CmsFormStep, FormValues as CmsFormValues, UseCmsFormOptions, UseCmsFormReturn };
|
|
62
63
|
//# 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 {
|
|
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 { CmsFormControl, 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"}
|
|
@@ -6,6 +6,8 @@ interface CmsI18nOptions {
|
|
|
6
6
|
readonly defaultLocale: string;
|
|
7
7
|
readonly fallbackLocale?: string | null;
|
|
8
8
|
readonly prefixDefaultLocale?: boolean;
|
|
9
|
+
/** Select where CMS-derived locale metadata owns Nuxt Site Config. */
|
|
10
|
+
readonly siteConfig?: 'documents' | 'localized-routes';
|
|
9
11
|
readonly locales: Readonly<Record<string, {
|
|
10
12
|
readonly name: string;
|
|
11
13
|
readonly messages?: CmsMessages;
|
|
@@ -24,4 +26,4 @@ type CmsMessageParameters<Key extends CmsMessageKey> = CmsI18nRegistry extends {
|
|
|
24
26
|
} ? Key extends keyof Parameters ? Parameters[Key] : never : Readonly<Record<string, string | number>>;
|
|
25
27
|
//#endregion
|
|
26
28
|
export { CmsMessageParameters as a, CmsMessageKey as i, CmsI18nRegistry as n, CmsMessages as o, CmsLocale as r, CmsI18nOptions as t };
|
|
27
|
-
//# sourceMappingURL=I18n-
|
|
29
|
+
//# sourceMappingURL=I18n-zbqpWxki.d.ts.map
|
package/src/I18n.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as CmsMessageParameters, i as CmsMessageKey, n as CmsI18nRegistry, o as CmsMessages, r as CmsLocale, t as CmsI18nOptions } from "./I18n-
|
|
1
|
+
import { a as CmsMessageParameters, i as CmsMessageKey, n as CmsI18nRegistry, o as CmsMessages, r as CmsLocale, t as CmsI18nOptions } from "./I18n-zbqpWxki.js";
|
|
2
2
|
export { CmsI18nOptions, CmsI18nRegistry, CmsLocale, CmsMessageKey, CmsMessageParameters, CmsMessages };
|
package/src/Module.js
CHANGED
|
@@ -3,7 +3,7 @@ import { registerStudioApp } from "./internal/studio-app.js";
|
|
|
3
3
|
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
|
-
import { compileCmsConfiguration } from "./internal/configuration.js";
|
|
6
|
+
import { cmsRuntimeConfigurationDefaults, compileCmsConfiguration } from "./internal/configuration.js";
|
|
7
7
|
import { generateCmsApplicationTypes } from "./internal/application-types.js";
|
|
8
8
|
import { Effect, Layer } from "effect";
|
|
9
9
|
import { addComponent, addImports, addPlugin, addServerHandler, addServerPlugin, addServerTemplate, addTemplate, addTypeTemplate, addVitePlugin, createResolver, defineNuxtModule, extendPages } from "@nuxt/kit";
|
|
@@ -35,6 +35,7 @@ const setupModule = Effect.fn("CmsNuxtModule.setup")(function* (nuxt) {
|
|
|
35
35
|
const authored = yield* loadCmsConfiguration(nuxt.options.rootDir);
|
|
36
36
|
const compiled = compileCmsConfiguration(authored.configuration);
|
|
37
37
|
const i18n = compiled.i18n;
|
|
38
|
+
Object.assign(nuxt.options.runtimeConfig, { cms: cmsRuntimeConfigurationDefaults(authored.configuration, nuxt.options.runtimeConfig.cms) });
|
|
38
39
|
configureSitemap(nuxt.options);
|
|
39
40
|
const i18nTemplate = addTemplate({
|
|
40
41
|
filename: "cms/i18n.mjs",
|
|
@@ -145,7 +146,8 @@ function registerDeliveryUi(nuxt) {
|
|
|
145
146
|
pages.push({
|
|
146
147
|
file: resolver.resolve("./runtime/delivery/document"),
|
|
147
148
|
name: "cms-document-page",
|
|
148
|
-
path: "/:contentPath(.*)*"
|
|
149
|
+
path: "/:contentPath(.*)*",
|
|
150
|
+
meta: { cmsDocument: true }
|
|
149
151
|
});
|
|
150
152
|
});
|
|
151
153
|
}
|
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'\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
|
+
{"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 { cmsRuntimeConfigurationDefaults, 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 Object.assign(nuxt.options.runtimeConfig, {\n cms: cmsRuntimeConfigurationDefaults(authored.configuration, nuxt.options.runtimeConfig.cms),\n })\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 meta: { cmsDocument: true },\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 { $ 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-
|
|
3
|
-
import { i as ContentSnapshot, n as ContentApplyResult, o as ContentTransferConflict, r as ContentPlan, s as ContentTransferInput, t as ContentApplyInput } from "./ContentTransfer-
|
|
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-ChRxBChy.js";
|
|
3
|
+
import { i as ContentSnapshot, n as ContentApplyResult, o as ContentTransferConflict, r as ContentPlan, s as ContentTransferInput, t as ContentApplyInput } from "./ContentTransfer-BhF9G56s.js";
|
|
4
4
|
import { u as STUDIO_API_PATH } from "./HttpPaths-c9nLZ9H2.js";
|
|
5
|
-
import {
|
|
6
|
-
import { a as encodeCmsEditorComponentAttributes, d as createCmsComarkRenderData, m as toComarkDocument, p as mutableJsonObject, s as projectCmsEditorComponentAttributes } from "./Forms-
|
|
5
|
+
import { c as FormSubmission, o as FormResult } from "./Forms-BbkE7QfC.js";
|
|
6
|
+
import { a as encodeCmsEditorComponentAttributes, d as createCmsComarkRenderData, m as toComarkDocument, p as mutableJsonObject, s as projectCmsEditorComponentAttributes } from "./Forms-DoB56hfe.js";
|
|
7
7
|
import { i as withoutEditorMetadata } from "./metadata-BEZPWh-3.js";
|
|
8
|
-
import { d as EditorRenderFailed, i as MediaConfiguration, r as DocumentConfiguration } from "./Configuration-
|
|
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-
|
|
8
|
+
import { d as EditorRenderFailed, i as MediaConfiguration, r as DocumentConfiguration } from "./Configuration-BU-UyGoH.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-ClhFXW9M.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";
|
|
@@ -559,7 +559,8 @@ const StudioDocumentsApi = HttpApiGroup.make("documents").add(HttpApiEndpoint.ge
|
|
|
559
559
|
params: { documentId: DocumentId },
|
|
560
560
|
payload: Schema.Struct({
|
|
561
561
|
...MoveDocumentPayload.fields,
|
|
562
|
-
includeChildren: DuplicateDocumentInput.fields.includeChildren
|
|
562
|
+
includeChildren: DuplicateDocumentInput.fields.includeChildren,
|
|
563
|
+
locale: DuplicateDocumentInput.fields.locale
|
|
563
564
|
}),
|
|
564
565
|
success: DocumentMutationResult,
|
|
565
566
|
error: MutationErrors
|
|
@@ -1067,11 +1068,17 @@ function makeDocumentState(authored, published, snapshot) {
|
|
|
1067
1068
|
authoredById.set(document.id, document);
|
|
1068
1069
|
}
|
|
1069
1070
|
for (const documentId of activeById.keys()) if (!authoredById.has(documentId)) throw new Error(`Compiled document "${documentId}" is missing from the repository snapshot.`);
|
|
1071
|
+
const publishedById = /* @__PURE__ */ new Map();
|
|
1072
|
+
for (const document of published.documents) {
|
|
1073
|
+
if (publishedById.has(document.id)) throw new Error(`Compiled document "${document.id}" appears more than once in the published catalog.`);
|
|
1074
|
+
publishedById.set(document.id, document);
|
|
1075
|
+
}
|
|
1070
1076
|
return {
|
|
1071
1077
|
activeById,
|
|
1072
1078
|
authored,
|
|
1073
1079
|
authoredById,
|
|
1074
1080
|
published,
|
|
1081
|
+
publishedById,
|
|
1075
1082
|
snapshot
|
|
1076
1083
|
};
|
|
1077
1084
|
}
|
|
@@ -1177,7 +1184,7 @@ function errorMessage(cause) {
|
|
|
1177
1184
|
return cause instanceof Error && cause.message ? cause.message : "Markdown could not be parsed.";
|
|
1178
1185
|
}
|
|
1179
1186
|
function browseMetadata(state, source) {
|
|
1180
|
-
const live = state.
|
|
1187
|
+
const live = state.publishedById.get(source.documentId);
|
|
1181
1188
|
const metadata = {};
|
|
1182
1189
|
if (source.createdBy) metadata.createdBy = source.createdBy;
|
|
1183
1190
|
if (source.editedBy) metadata.editedBy = source.editedBy;
|
|
@@ -1244,7 +1251,7 @@ const prepareTreeMutation = Effect.fn("Documents.prepareTreeMutation")(function*
|
|
|
1244
1251
|
sourcePath: root.sourcePath
|
|
1245
1252
|
}) ?? "";
|
|
1246
1253
|
const nextRelative = destination.kind === "home" ? "" : [destination.parent, destination.slug].filter(Boolean).join("/");
|
|
1247
|
-
if (rootRelative && (nextRelative === rootRelative || nextRelative.startsWith(`${rootRelative}/`))) return yield* invalid("Choose a destination outside this page and its subpages.");
|
|
1254
|
+
if (!(command.action === "document.duplicate" && command.input.locale !== void 0 && command.input.locale !== parent.locale) && rootRelative && (nextRelative === rootRelative || nextRelative.startsWith(`${rootRelative}/`))) return yield* invalid("Choose a destination outside this page and its subpages.");
|
|
1248
1255
|
const relative = documentRelativePath(collection, {
|
|
1249
1256
|
document: page,
|
|
1250
1257
|
sourcePath: source.sourcePath
|
|
@@ -1255,8 +1262,9 @@ const prepareTreeMutation = Effect.fn("Documents.prepareTreeMutation")(function*
|
|
|
1255
1262
|
kind: "entry",
|
|
1256
1263
|
slug: yield* decodeSlug(slug)
|
|
1257
1264
|
}, segments.length ? { parent: yield* decodeParent(segments.join("/")) } : void 0) : { kind: "home" };
|
|
1258
|
-
const
|
|
1259
|
-
const
|
|
1265
|
+
const destinationPage = command.action === "document.duplicate" && command.input.locale ? Object.assign({}, page, { locale: command.input.locale }) : page;
|
|
1266
|
+
const sourcePath = yield* Effect.fromResult(planDocumentMove(configuration, destinationPage, location));
|
|
1267
|
+
const markdown = yield* relocateDocumentMarkdown(configuration, destinationPage, location, source.markdown).pipe(Effect.mapError(() => invalid("The page could not be copied to its new URL.")));
|
|
1260
1268
|
if (command.action === "document.duplicate") {
|
|
1261
1269
|
const documentId = yield* command.nextDocumentId;
|
|
1262
1270
|
plans.push({
|
|
@@ -1694,7 +1702,7 @@ const commitDocumentMutation = Effect.fn("Documents.commitMutation")(function* (
|
|
|
1694
1702
|
resource: {
|
|
1695
1703
|
kind: "collection",
|
|
1696
1704
|
collection: source.collection,
|
|
1697
|
-
locale: source.locale
|
|
1705
|
+
locale: command.input.locale ?? source.locale
|
|
1698
1706
|
}
|
|
1699
1707
|
});
|
|
1700
1708
|
}
|
|
@@ -2793,4 +2801,4 @@ const maxS3SingleCopyBytes = 5e9;
|
|
|
2793
2801
|
|
|
2794
2802
|
//#endregion
|
|
2795
2803
|
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 };
|
|
2796
|
-
//# sourceMappingURL=S3MediaObjects-
|
|
2804
|
+
//# sourceMappingURL=S3MediaObjects-CR3p1WTg.js.map
|