@lucidcms/core
Version:
The core of the Lucid CMS. It's responsible for spinning up the API and serving the CMS.
1 lines • 8.44 kB
Source Map (JSON)
{"version":3,"file":"custom-field.mjs","names":["constants"],"sources":["../../../../../../src/libs/collection/custom-fields/fields/code/custom-field.ts"],"sourcesContent":["import z from \"zod\";\nimport constants from \"../../../../../constants/constants.js\";\nimport type { ServiceResponse } from \"../../../../../types.js\";\nimport { copy } from \"../../../../i18n/index.js\";\nimport CustomField from \"../../custom-field.js\";\nimport type {\n\tCFConfig,\n\tCFProps,\n\tCFResponse,\n\tCustomFieldAiFormatResponse,\n\tGetSchemaDefinitionProps,\n\tSchemaDefinition,\n} from \"../../types.js\";\nimport { zodToJsonSchema } from \"../../utils/helpers.js\";\nimport keyToTitle from \"../../utils/key-to-title.js\";\nimport zodSafeParse from \"../../utils/zod-safe-parse.js\";\nimport { codeFieldConfig } from \"./config.js\";\nimport type { CodeValue } from \"./types.js\";\n\nclass CodeCustomField extends CustomField<\"code\"> {\n\ttype = codeFieldConfig.type;\n\tconfig;\n\tkey;\n\tprops;\n\tconstructor(key: string, props?: CFProps<\"code\">) {\n\t\tsuper();\n\t\tthis.key = key;\n\t\tthis.props = props;\n\t\tthis.config = {\n\t\t\tkey: this.key,\n\t\t\ttype: this.type,\n\t\t\tdetails: {\n\t\t\t\tlabel:\n\t\t\t\t\tthis.props?.details?.label ??\n\t\t\t\t\tcopy(`admin:fields.${this.type}.${this.key}.label`, {\n\t\t\t\t\t\tdefaultMessage: keyToTitle(this.key),\n\t\t\t\t\t}),\n\t\t\t\tsummary: this.props?.details?.summary,\n\t\t\t\tplaceholder: this.props?.details?.placeholder,\n\t\t\t},\n\t\t\tai: this.props?.ai,\n\t\t\tlocalized: this.props?.localized ?? false,\n\t\t\tdefault: this.props?.default ?? null,\n\t\t\tlanguages: this.props?.languages ?? [\n\t\t\t\t...constants.customFields.code.languages,\n\t\t\t],\n\t\t\tindex: this.props?.index,\n\t\t\tui: {\n\t\t\t\thidden: this.props?.ui?.hidden,\n\t\t\t\tdisabled: this.props?.ui?.disabled,\n\t\t\t\tcondition: this.props?.ui?.condition,\n\t\t\t\twidth: this.props?.ui?.width,\n\t\t\t},\n\t\t\tvalidation: this.props?.validation,\n\t\t} satisfies CFConfig<\"code\">;\n\t}\n\toverride get supportsAi() {\n\t\treturn true;\n\t}\n\toverride get jsonSchema() {\n\t\treturn zodToJsonSchema(this.config.validation?.zod, {\n\t\t\ttype: \"object\",\n\t\t\tdescription: \"A code snippet with its language.\",\n\t\t\tproperties: {\n\t\t\t\tlanguage: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tenum: this.config.languages,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"The language of the code snippet. Infer it from the existing value or the instruction, and keep the existing language unless asked to change it.\",\n\t\t\t\t},\n\t\t\t\tvalue: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"The raw code snippet content. Do not wrap it in markdown code fences.\",\n\t\t\t\t},\n\t\t\t},\n\t\t\trequired: [\"language\", \"value\"],\n\t\t\tadditionalProperties: false,\n\t\t});\n\t}\n\tgetSchemaDefinition(\n\t\tprops: GetSchemaDefinitionProps,\n\t): Awaited<ServiceResponse<SchemaDefinition>> {\n\t\treturn {\n\t\t\tdata: {\n\t\t\t\tcolumns: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: this.key,\n\t\t\t\t\t\ttype: props.db.getDataType(\"json\"),\n\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\tdefault: this.config.default,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\terror: undefined,\n\t\t};\n\t}\n\tformatResponseValue(value?: CodeValue | null) {\n\t\treturn (value ??\n\t\t\tthis.config.default ??\n\t\t\tnull) satisfies CFResponse<\"code\">[\"value\"];\n\t}\n\toverride formatAiGeneratedValue(value: unknown): CustomFieldAiFormatResponse {\n\t\tif (typeof value === \"string\") {\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(value) as unknown;\n\t\t\t\tconst coerced = this.coerceAiCodeValue(parsed);\n\t\t\t\tif (coerced) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\tvalue: coerced,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// not serialized JSON - treat the string as raw code content\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tvalue: {\n\t\t\t\t\tlanguage: this.fallbackAiLanguage(),\n\t\t\t\t\tvalue: value,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst coerced = this.coerceAiCodeValue(value);\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tvalue: coerced ?? {\n\t\t\t\tlanguage: this.fallbackAiLanguage(),\n\t\t\t\tvalue: String(value ?? \"\"),\n\t\t\t},\n\t\t};\n\t}\n\t/** Coerces AI output into a `{ language, value }` shape with a configured language. */\n\tprivate coerceAiCodeValue(value: unknown): CodeValue | null {\n\t\tif (!value || typeof value !== \"object\" || Array.isArray(value))\n\t\t\treturn null;\n\n\t\tconst code = value as Partial<CodeValue>;\n\t\tif (typeof code.value !== \"string\") return null;\n\n\t\treturn {\n\t\t\tlanguage:\n\t\t\t\ttypeof code.language === \"string\" &&\n\t\t\t\tthis.config.languages.includes(code.language)\n\t\t\t\t\t? code.language\n\t\t\t\t\t: this.fallbackAiLanguage(),\n\t\t\tvalue: code.value,\n\t\t};\n\t}\n\tprivate fallbackAiLanguage() {\n\t\treturn this.config.languages[0] ?? \"text\";\n\t}\n\toverride normalizeInputValue(value: unknown) {\n\t\tif (typeof value === \"string\" && value.trim() === \"\") return null;\n\t\tif (value && typeof value === \"object\" && !Array.isArray(value)) {\n\t\t\tconst code = value as Partial<CodeValue>;\n\t\t\tif (typeof code.value === \"string\" && code.value.trim() === \"\")\n\t\t\t\treturn null;\n\t\t}\n\t\treturn value;\n\t}\n\tuniqueValidation(value: unknown) {\n\t\tconst valueSchema = z.object({\n\t\t\tlanguage: z.string(),\n\t\t\tvalue: z.string(),\n\t\t});\n\n\t\tconst valueValidate = zodSafeParse(value, valueSchema);\n\t\tif (!valueValidate.valid) return valueValidate;\n\n\t\tconst val = value as CodeValue;\n\n\t\tif (!this.config.languages.includes(val.language)) {\n\t\t\treturn {\n\t\t\t\tvalid: false,\n\t\t\t\tmessage: copy(\n\t\t\t\t\t\"server:core.fields.code.validation.language.error.message\",\n\t\t\t\t\t{\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tvalid: this.config.languages.join(\", \"),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tvalid: true,\n\t\t};\n\t}\n}\n\nexport default CodeCustomField;\n"],"mappings":"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"}