@shapio/schema 0.3.1 → 0.4.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.
- package/dist/index.d.ts +36 -9
- package/dist/index.js +181 -73
- package/dist/index.js.map +1 -1
- package/dist/resolve-7-z9VQqw.d.ts +91 -0
- package/dist/resolve-viddCEYd.js +91 -0
- package/dist/resolve-viddCEYd.js.map +1 -0
- package/dist/seoResolve.d.ts +2 -0
- package/dist/seoResolve.js +2 -0
- package/package.json +6 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["closed","closed"],"sources":["../src/types/dataTypes.ts","../src/types/definitions.ts","../src/types/locales.ts","../src/types/settings.ts","../src/editors/catalogue.ts","../src/display/titleField.ts","../src/display/layout.ts","../src/validators/apiKey.ts","../src/naming/plural.ts","../src/normalize.ts","../src/validators/defaultValue.ts","../src/validators/issues.ts","../src/validators/naming.ts","../src/validators/typeboxIssues.ts","../src/validators/definition.ts","../src/validators/parse.ts","../src/validators/schema.ts","../src/diff/types.ts","../src/fileFormat/canonical.ts","../src/diff/diffDefinitions.ts","../src/diff/classify.ts","../src/fileFormat/hash.ts","../src/fileFormat/layout.ts","../src/fileFormat/lockFile.ts","../src/sync/threeWay.ts","../src/richtext/render.ts","../src/themes/tokens.ts","../src/themes/contrast.ts"],"sourcesContent":["/** Every stored data type. A field's data type is separate from the editor that renders it (brief §2.5). */\nexport const DATA_TYPES = [\n 'string',\n 'text',\n 'richtext',\n 'number',\n 'integer',\n 'decimal',\n 'biginteger',\n 'boolean',\n 'date',\n 'datetime',\n 'time',\n 'enum',\n 'json',\n 'slug',\n 'email',\n 'url',\n 'uid',\n 'media',\n 'relation',\n 'component',\n 'dynamiczone',\n] as const;\n\nexport type DataType = (typeof DATA_TYPES)[number];\n\nexport const isDataType = (value: unknown): value is DataType =>\n typeof value === 'string' && (DATA_TYPES as readonly string[]).includes(value);\n\n/**\n * Scalar types stored as one JSON value per field (string, number or boolean). Only these can be unique,\n * filterable or sortable: their index expression is a single cast of `data ->> fieldId` (ADR 0001).\n */\nexport const SCALAR_DATA_TYPES: ReadonlySet<DataType> = new Set<DataType>([\n 'string',\n 'text',\n 'number',\n 'integer',\n 'decimal',\n 'biginteger',\n 'boolean',\n 'date',\n 'datetime',\n 'time',\n 'enum',\n 'slug',\n 'email',\n 'url',\n 'uid',\n]);\n\n/** Types that may carry `unique: true` (boolean and long text make no sense as unique keys). */\nexport const UNIQUE_CAPABLE_DATA_TYPES: ReadonlySet<DataType> = new Set<DataType>([\n 'string',\n 'number',\n 'integer',\n 'decimal',\n 'biginteger',\n 'date',\n 'datetime',\n 'time',\n 'slug',\n 'email',\n 'url',\n 'uid',\n]);\n\n/** Types whose values point at other definitions; the reference checks look at these. */\nexport const REFERENCE_DATA_TYPES: ReadonlySet<DataType> = new Set<DataType>([\n 'relation',\n 'component',\n 'dynamiczone',\n]);\n\n/**\n * How a value is physically represented in the content JSON. Changing a field's type within a storage\n * family never needs a data conversion, only a validity check; across families it is a conversion.\n */\nexport type StorageFamily =\n | 'jsonString'\n | 'jsonNumber'\n | 'numericString'\n | 'boolean'\n | 'json'\n | 'richtext'\n | 'media'\n | 'relation'\n | 'component'\n | 'dynamiczone';\n\nexport const STORAGE_FAMILY: Readonly<Record<DataType, StorageFamily>> = {\n string: 'jsonString',\n text: 'jsonString',\n slug: 'jsonString',\n email: 'jsonString',\n url: 'jsonString',\n uid: 'jsonString',\n enum: 'jsonString',\n date: 'jsonString',\n datetime: 'jsonString',\n time: 'jsonString',\n number: 'jsonNumber',\n integer: 'jsonNumber',\n decimal: 'numericString',\n biginteger: 'numericString',\n boolean: 'boolean',\n json: 'json',\n richtext: 'richtext',\n media: 'media',\n relation: 'relation',\n component: 'component',\n dynamiczone: 'dynamiczone',\n};\n","import { Type, type Static } from 'typebox';\nimport { DATA_TYPES, type DataType } from './dataTypes.js';\nimport type { JsonValue } from './json.js';\nimport type { DataTypeSettings } from './settings.js';\n\n/**\n * Model and component definitions. Both kinds share one table (`models`, with a `kind` discriminator) but\n * have distinct TypeScript types: a component cannot be published, localised or addressed by a route.\n *\n * The `*InputSchema` TypeBox schemas describe what callers send and what schema files contain: IDs and\n * defaulted properties may be omitted. `normalizeDefinition` turns input into the normalized types below,\n * which are what Shapio stores, hashes and diffs.\n */\nconst closed = { additionalProperties: false } as const;\n\nexport const MODEL_KINDS = ['collection', 'singleton'] as const;\nexport type ModelKind = (typeof MODEL_KINDS)[number];\nexport const DEFINITION_KINDS = [...MODEL_KINDS, 'component'] as const;\nexport type DefinitionKind = (typeof DEFINITION_KINDS)[number];\n\nexport const SORT_DIRECTIONS = ['asc', 'desc'] as const;\nexport type SortDirection = (typeof SORT_DIRECTIONS)[number];\n\nexport const MAX_FIELDS_PER_DEFINITION = 500;\nexport const MAX_LABEL_LENGTH = 200;\nexport const MAX_DESCRIPTION_LENGTH = 2000;\n\nconst Label = Type.String({ minLength: 1, maxLength: MAX_LABEL_LENGTH });\nconst Description = Type.Optional(Type.String({ maxLength: MAX_DESCRIPTION_LENGTH }));\n\nexport const EditorChoiceInputSchema = Type.Object(\n {\n id: Type.String({ minLength: 1, maxLength: 128 }),\n options: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n },\n closed,\n);\n\nexport const FieldInputSchema = Type.Object(\n {\n id: Type.Optional(Type.String()),\n apiKey: Type.String(),\n label: Label,\n /** Help text shown under the control. */\n description: Description,\n type: Type.Enum(DATA_TYPES),\n required: Type.Optional(Type.Boolean()),\n /** Per-locale value. Ignored (must be false) when the model is not localized. */\n localized: Type.Optional(Type.Boolean()),\n /** Readable by delivery principals wherever the model is readable (ADR 0005). Default true. */\n public: Type.Optional(Type.Boolean()),\n unique: Type.Optional(Type.Boolean()),\n filterable: Type.Optional(Type.Boolean()),\n sortable: Type.Optional(Type.Boolean()),\n /** Hidden from editors and the API; stored values are preserved until an explicit cleanup. */\n deprecated: Type.Optional(Type.Boolean()),\n /** Used for new entries and to backfill existing ones when the field becomes required. */\n defaultValue: Type.Optional(Type.Unknown()),\n /** Type-specific settings, validated against SETTINGS_SCHEMAS[type]. */\n settings: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n editor: Type.Optional(EditorChoiceInputSchema),\n },\n closed,\n);\n\nconst FieldGroupSchema = Type.Object(\n { id: Type.String({ minLength: 1, maxLength: 64 }), label: Label, fieldIds: Type.Array(Type.String()) },\n closed,\n);\n\nexport const ModelDisplayInputSchema = Type.Object(\n {\n /** Field whose value labels an entry in lists, pickers and relation summaries. */\n titleFieldId: Type.Optional(Type.String()),\n /** Columns of the content list, in order. */\n listFieldIds: Type.Optional(Type.Array(Type.String())),\n defaultSort: Type.Optional(\n Type.Object({ fieldId: Type.String(), direction: Type.Enum(SORT_DIRECTIONS) }, closed),\n ),\n /** Editor layout: named sections of the entry form. */\n groups: Type.Optional(Type.Array(FieldGroupSchema)),\n /** Fields rendered as blocks in the entry document's canvas, in order. Default: see `effectiveLayout`. */\n canvasFieldIds: Type.Optional(Type.Array(Type.String())),\n /** A single image `media` field shown as the cover above the title. Default: see `effectiveLayout`. */\n coverFieldId: Type.Optional(Type.String()),\n /** Properties shown as chips in the document's strip. Default: the first non-empty ones. */\n stripFieldIds: Type.Optional(Type.Array(Type.String())),\n },\n closed,\n);\n\nexport const ComponentDisplayInputSchema = Type.Object(\n {\n titleFieldId: Type.Optional(Type.String()),\n groups: Type.Optional(Type.Array(FieldGroupSchema)),\n },\n closed,\n);\n\nconst definitionBase = {\n id: Type.Optional(Type.String()),\n apiKey: Type.String(),\n label: Label,\n description: Description,\n fields: Type.Array(FieldInputSchema, { maxItems: MAX_FIELDS_PER_DEFINITION }),\n};\n\nexport const ModelDefinitionInputSchema = Type.Object(\n {\n ...definitionBase,\n kind: Type.Enum(MODEL_KINDS),\n /**\n * Collections only: names the list route and query (`/api/content/articles`, `articles(…)`). Optional\n * here so files written before plural API IDs still parse; normalizing fills it on a collection.\n */\n pluralApiKey: Type.Optional(Type.String()),\n localized: Type.Optional(Type.Boolean()),\n /** Entries have separate draft and published states. Default true. */\n draftAndPublish: Type.Optional(Type.Boolean()),\n display: Type.Optional(ModelDisplayInputSchema),\n },\n closed,\n);\n\nexport const ComponentDefinitionInputSchema = Type.Object(\n {\n ...definitionBase,\n kind: Type.Literal('component'),\n category: Type.Optional(Type.String({ minLength: 1, maxLength: 100 })),\n icon: Type.Optional(Type.String({ minLength: 1, maxLength: 64 })),\n display: Type.Optional(ComponentDisplayInputSchema),\n },\n closed,\n);\n\nexport const DefinitionInputSchema = Type.Union([ModelDefinitionInputSchema, ComponentDefinitionInputSchema]);\n\nexport type FieldInput = Static<typeof FieldInputSchema>;\nexport type ModelDefinitionInput = Static<typeof ModelDefinitionInputSchema>;\nexport type ComponentDefinitionInput = Static<typeof ComponentDefinitionInputSchema>;\nexport type DefinitionInput = ModelDefinitionInput | ComponentDefinitionInput;\n\nexport type EditorChoice = { id: string; options: Record<string, JsonValue> };\n\ntype FieldBase = {\n id: string;\n apiKey: string;\n label: string;\n description?: string;\n required: boolean;\n localized: boolean;\n public: boolean;\n unique: boolean;\n filterable: boolean;\n sortable: boolean;\n deprecated: boolean;\n defaultValue?: JsonValue;\n editor: EditorChoice;\n};\n\n/** A normalized field. Narrow on `type` to get typed `settings`. */\nexport type FieldDefinition<T extends DataType = DataType> = {\n [K in T]: FieldBase & { type: K; settings: DataTypeSettings[K] };\n}[T];\n\nexport type FieldGroup = { id: string; label: string; fieldIds: string[] };\n\nexport type ModelDisplay = {\n titleFieldId?: string;\n listFieldIds?: string[];\n defaultSort?: { fieldId: string; direction: SortDirection };\n groups?: FieldGroup[];\n canvasFieldIds?: string[];\n coverFieldId?: string;\n stripFieldIds?: string[];\n};\n\nexport type ComponentDisplay = { titleFieldId?: string; groups?: FieldGroup[] };\n\nexport type ModelDefinition = {\n id: string;\n kind: ModelKind;\n apiKey: string;\n /**\n * Present on collections (filled by normalizing), absent on singletons. Read it through `routeKeyOf`,\n * which also covers a stored definition that predates plural API IDs.\n */\n pluralApiKey?: string;\n label: string;\n description?: string;\n localized: boolean;\n draftAndPublish: boolean;\n fields: FieldDefinition[];\n display: ModelDisplay;\n};\n\nexport type ComponentDefinition = {\n id: string;\n kind: 'component';\n apiKey: string;\n label: string;\n description?: string;\n category?: string;\n icon?: string;\n fields: FieldDefinition[];\n display: ComponentDisplay;\n};\n\n/** Either kind. Most schema machinery (diff, file format, registry) works on both. */\nexport type SchemaDefinition = ModelDefinition | ComponentDefinition;\n\nexport const isComponentDefinition = (definition: SchemaDefinition): definition is ComponentDefinition =>\n definition.kind === 'component';\n\nexport const isModelDefinition = (definition: SchemaDefinition): definition is ModelDefinition =>\n definition.kind !== 'component';\n","import { Type, type Static } from 'typebox';\n\n/** BCP 47 subset: language (2–3 letters) plus optional subtags, e.g. `en`, `fr-CA`, `zh-Hant-TW`. */\nexport const LOCALE_CODE_PATTERN = /^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/;\nexport const MAX_FALLBACK_CHAIN = 10;\n\nexport const LocaleInputSchema = Type.Object(\n {\n code: Type.String({ pattern: LOCALE_CODE_PATTERN.source, maxLength: 35 }),\n label: Type.String({ minLength: 1, maxLength: 100 }),\n /** Locales tried in order when content is missing in this one; the default locale is always last. */\n fallbacks: Type.Optional(Type.Array(Type.String(), { maxItems: MAX_FALLBACK_CHAIN })),\n },\n { additionalProperties: false },\n);\n\nexport type LocaleInput = Static<typeof LocaleInputSchema>;\n\nexport type LocaleDefinition = {\n code: string;\n label: string;\n isDefault: boolean;\n fallbacks: string[];\n};\n","import { Type, type Static, type TSchema } from 'typebox';\nimport type { DataType } from './dataTypes.js';\nimport {\n BIGINTEGER_PATTERN,\n DATE_PATTERN,\n DATETIME_PATTERN,\n DECIMAL_PATTERN,\n TIME_PATTERN,\n} from './valueFormats.js';\n\n/**\n * Per-data-type settings: validation rules and type configuration (relation target, component reference,\n * enum values...). Each schema is closed (`additionalProperties: false`) so a typo in a hand-edited schema\n * file is reported instead of ignored. Defaults are applied by `normalizeDefinition`.\n */\nconst closed = { additionalProperties: false } as const;\nconst NonNegativeInt = Type.Integer({ minimum: 0 });\nconst pattern = (regex: RegExp) => Type.String({ pattern: regex.source });\n\nconst lengthRules = {\n minLength: Type.Optional(NonNegativeInt),\n maxLength: Type.Optional(Type.Integer({ minimum: 1 })),\n};\nconst countRules = {\n min: Type.Optional(NonNegativeInt),\n max: Type.Optional(Type.Integer({ minimum: 1 })),\n};\n\nexport const MEDIA_KINDS = ['image', 'video', 'audio', 'document', 'other'] as const;\nexport const RELATION_CARDINALITIES = ['one', 'many'] as const;\n\nexport const EnumValueSchema = Type.Object(\n {\n value: Type.String({ minLength: 1, maxLength: 64 }),\n label: Type.String({ minLength: 1, maxLength: 200 }),\n },\n closed,\n);\n\nexport const SETTINGS_SCHEMAS = {\n string: Type.Object(\n { ...lengthRules, pattern: Type.Optional(Type.String({ minLength: 1, maxLength: 500 })) },\n closed,\n ),\n text: Type.Object(lengthRules, closed),\n richtext: Type.Object(\n {\n formatVersion: Type.Optional(Type.Integer({ minimum: 1 })),\n maxLength: Type.Optional(Type.Integer({ minimum: 1 })),\n },\n closed,\n ),\n number: Type.Object({ min: Type.Optional(Type.Number()), max: Type.Optional(Type.Number()) }, closed),\n integer: Type.Object({ min: Type.Optional(Type.Integer()), max: Type.Optional(Type.Integer()) }, closed),\n decimal: Type.Object(\n {\n precision: Type.Optional(Type.Integer({ minimum: 1, maximum: 1000 })),\n scale: Type.Optional(Type.Integer({ minimum: 0, maximum: 1000 })),\n min: Type.Optional(pattern(DECIMAL_PATTERN)),\n max: Type.Optional(pattern(DECIMAL_PATTERN)),\n },\n closed,\n ),\n biginteger: Type.Object(\n { min: Type.Optional(pattern(BIGINTEGER_PATTERN)), max: Type.Optional(pattern(BIGINTEGER_PATTERN)) },\n closed,\n ),\n boolean: Type.Object({}, closed),\n date: Type.Object(\n { min: Type.Optional(pattern(DATE_PATTERN)), max: Type.Optional(pattern(DATE_PATTERN)) },\n closed,\n ),\n datetime: Type.Object(\n { min: Type.Optional(pattern(DATETIME_PATTERN)), max: Type.Optional(pattern(DATETIME_PATTERN)) },\n closed,\n ),\n time: Type.Object(\n { min: Type.Optional(pattern(TIME_PATTERN)), max: Type.Optional(pattern(TIME_PATTERN)) },\n closed,\n ),\n enum: Type.Object(\n {\n values: Type.Array(EnumValueSchema, { minItems: 1, maxItems: 500 }),\n multiple: Type.Optional(Type.Boolean()),\n },\n closed,\n ),\n json: Type.Object({}, closed),\n slug: Type.Object({ ...lengthRules, sourceFieldId: Type.Optional(Type.String()) }, closed),\n email: Type.Object({}, closed),\n url: Type.Object(\n { protocols: Type.Optional(Type.Array(Type.Enum(['http', 'https', 'mailto', 'tel']), { minItems: 1 })) },\n closed,\n ),\n uid: Type.Object(lengthRules, closed),\n media: Type.Object(\n {\n multiple: Type.Optional(Type.Boolean()),\n allowedKinds: Type.Optional(Type.Array(Type.Enum(MEDIA_KINDS), { minItems: 1 })),\n ...countRules,\n },\n closed,\n ),\n relation: Type.Object(\n { target: Type.String(), cardinality: Type.Enum(RELATION_CARDINALITIES), ...countRules },\n closed,\n ),\n component: Type.Object(\n { component: Type.String(), repeatable: Type.Optional(Type.Boolean()), ...countRules },\n closed,\n ),\n dynamiczone: Type.Object(\n { components: Type.Array(Type.String(), { minItems: 1, maxItems: 100 }), ...countRules },\n closed,\n ),\n} satisfies Record<DataType, TSchema>;\n\ntype SettingsSchemas = typeof SETTINGS_SCHEMAS;\n\n/** Settings as authored (defaults may be missing). */\nexport type DataTypeSettingsInput = { [T in DataType]: Static<SettingsSchemas[T]> };\n\n/** Settings after normalization: the defaulted keys are always present. */\nexport type DataTypeSettings = Omit<DataTypeSettingsInput, 'richtext' | 'enum' | 'media' | 'component'> & {\n richtext: DataTypeSettingsInput['richtext'] & { formatVersion: number };\n enum: DataTypeSettingsInput['enum'] & { multiple: boolean };\n media: DataTypeSettingsInput['media'] & { multiple: boolean };\n component: DataTypeSettingsInput['component'] & { repeatable: boolean };\n};\n","import { Type, type TSchema } from 'typebox';\nimport type { DataType } from '../types/dataTypes.js';\nimport type { FieldDefinition } from '../types/definitions.js';\n\n/**\n * Built-in editors (ADR 0009): which data types each can edit and the schema of its options. The server\n * validates every field's editor choice against this catalogue, so selecting and configuring an editor is\n * runtime metadata. Custom editors (loaded at runtime from the project) use namespaced IDs containing a dot,\n * e.g. `acme.colorWheel`; their options are free-form JSON here because their schema lives in the project.\n */\nexport type EditorCatalogueEntry = {\n id: string;\n dataTypes: readonly DataType[];\n optionsSchema: TSchema;\n /** Extra compatibility rule beyond the data type (e.g. radio buttons only for single-value enums). */\n supports?: (field: FieldDefinition) => boolean;\n};\n\nconst closed = { additionalProperties: false } as const;\nconst Placeholder = Type.Optional(Type.String({ maxLength: 200 }));\nconst isMultipleEnum = (field: FieldDefinition) => field.type === 'enum' && field.settings.multiple;\n\nconst entries: EditorCatalogueEntry[] = [\n {\n id: 'textInput',\n dataTypes: ['string', 'email', 'url', 'uid'],\n optionsSchema: Type.Object({ placeholder: Placeholder }, closed),\n },\n {\n id: 'textarea',\n dataTypes: ['text', 'string'],\n optionsSchema: Type.Object(\n { placeholder: Placeholder, rows: Type.Optional(Type.Integer({ minimum: 2, maximum: 40 })) },\n closed,\n ),\n },\n {\n id: 'color',\n dataTypes: ['string'],\n optionsSchema: Type.Object(\n {\n format: Type.Optional(Type.Enum(['hex', 'rgb'])),\n presets: Type.Optional(Type.Array(Type.String({ maxLength: 32 }), { maxItems: 50 })),\n },\n closed,\n ),\n },\n {\n id: 'richText',\n dataTypes: ['richtext'],\n optionsSchema: Type.Object({ toolbar: Type.Optional(Type.Enum(['full', 'minimal'])) }, closed),\n },\n {\n id: 'numberInput',\n dataTypes: ['number', 'integer', 'decimal', 'biginteger'],\n optionsSchema: Type.Object(\n { placeholder: Placeholder, step: Type.Optional(Type.Number({ exclusiveMinimum: 0 })) },\n closed,\n ),\n },\n {\n id: 'toggle',\n dataTypes: ['boolean'],\n optionsSchema: Type.Object({}, closed),\n },\n {\n id: 'checkbox',\n dataTypes: ['boolean'],\n optionsSchema: Type.Object({}, closed),\n },\n {\n id: 'segmented',\n dataTypes: ['boolean', 'enum'],\n optionsSchema: Type.Object(\n {\n trueLabel: Type.Optional(Type.String({ maxLength: 50 })),\n falseLabel: Type.Optional(Type.String({ maxLength: 50 })),\n },\n closed,\n ),\n supports: (field) => !isMultipleEnum(field),\n },\n {\n id: 'select',\n dataTypes: ['enum'],\n optionsSchema: Type.Object({ placeholder: Placeholder }, closed),\n },\n {\n id: 'radio',\n dataTypes: ['enum'],\n optionsSchema: Type.Object({ layout: Type.Optional(Type.Enum(['vertical', 'horizontal'])) }, closed),\n supports: (field) => !isMultipleEnum(field),\n },\n {\n id: 'checkboxGroup',\n dataTypes: ['enum'],\n optionsSchema: Type.Object({ layout: Type.Optional(Type.Enum(['vertical', 'horizontal'])) }, closed),\n supports: isMultipleEnum,\n },\n {\n id: 'datePicker',\n dataTypes: ['date'],\n optionsSchema: Type.Object({}, closed),\n },\n {\n id: 'dateTimePicker',\n dataTypes: ['datetime'],\n optionsSchema: Type.Object({ display: Type.Optional(Type.Enum(['local', 'utc'])) }, closed),\n },\n {\n id: 'timePicker',\n dataTypes: ['time'],\n optionsSchema: Type.Object(\n { stepMinutes: Type.Optional(Type.Integer({ minimum: 1, maximum: 60 })) },\n closed,\n ),\n },\n {\n id: 'slugInput',\n dataTypes: ['slug'],\n optionsSchema: Type.Object({ placeholder: Placeholder }, closed),\n },\n {\n id: 'jsonEditor',\n dataTypes: ['json'],\n optionsSchema: Type.Object({ rows: Type.Optional(Type.Integer({ minimum: 3, maximum: 80 })) }, closed),\n },\n {\n id: 'mediaPicker',\n dataTypes: ['media'],\n optionsSchema: Type.Object({}, closed),\n },\n {\n id: 'relationPicker',\n dataTypes: ['relation'],\n optionsSchema: Type.Object({ allowInlineCreate: Type.Optional(Type.Boolean()) }, closed),\n },\n {\n id: 'componentEditor',\n dataTypes: ['component'],\n optionsSchema: Type.Object({ collapsed: Type.Optional(Type.Boolean()) }, closed),\n },\n {\n id: 'dynamicZoneEditor',\n dataTypes: ['dynamiczone'],\n optionsSchema: Type.Object({ collapsed: Type.Optional(Type.Boolean()) }, closed),\n },\n];\n\nexport const EDITOR_CATALOGUE: ReadonlyMap<string, EditorCatalogueEntry> = new Map(\n entries.map((entry) => [entry.id, entry]),\n);\n\n/** The editor a field gets when its definition names none. */\nexport const DEFAULT_EDITORS: Readonly<Record<DataType, string>> = {\n string: 'textInput',\n text: 'textarea',\n richtext: 'richText',\n number: 'numberInput',\n integer: 'numberInput',\n decimal: 'numberInput',\n biginteger: 'numberInput',\n boolean: 'toggle',\n date: 'datePicker',\n datetime: 'dateTimePicker',\n time: 'timePicker',\n enum: 'select',\n json: 'jsonEditor',\n slug: 'slugInput',\n email: 'textInput',\n url: 'textInput',\n uid: 'textInput',\n media: 'mediaPicker',\n relation: 'relationPicker',\n component: 'componentEditor',\n dynamiczone: 'dynamicZoneEditor',\n};\n\n/** `vendor.name` (letters, digits, `_`, `-`), e.g. `acme.colorWheel`. Built-in IDs never contain a dot. */\nexport const CUSTOM_EDITOR_ID_PATTERN = /^[A-Za-z][A-Za-z0-9_-]*(\\.[A-Za-z][A-Za-z0-9_-]*)+$/;\n\nexport const isCustomEditorId = (id: string): boolean => CUSTOM_EDITOR_ID_PATTERN.test(id);\n\n/** Built-in editors that can edit this field (for the admin's editor picker). */\nexport const listCompatibleEditors = (field: FieldDefinition): EditorCatalogueEntry[] =>\n entries.filter((entry) => entry.dataTypes.includes(field.type) && (entry.supports?.(field) ?? true));\n","import type { FieldDefinition, SchemaDefinition } from '../types/definitions.js';\n\n/** Field types that may label entries: the only types `display.titleFieldId` accepts, and the fallback's. */\nexport const TITLE_FIELD_TYPES: ReadonlySet<string> = new Set([\n 'string',\n 'text',\n 'slug',\n 'email',\n 'uid',\n 'enum',\n]);\n\n/**\n * Field types the list API's `q` search runs on, checked on top of the title field: an enum title is not\n * searchable. `url` is listed for search only; it is never a title.\n */\nexport const TEXT_TITLE_FIELD_TYPES: ReadonlySet<string> = new Set([\n 'string',\n 'text',\n 'slug',\n 'email',\n 'url',\n 'uid',\n]);\n\n/**\n * The field that labels a definition's entries in lists, pickers, relation summaries and search: the\n * configured `display.titleFieldId` when it points at a live (non-deprecated) field, otherwise the first\n * live field of a title type (TITLE_FIELD_TYPES) in field order, otherwise undefined. `titleFieldId` is\n * optional, so a model built without one still gets a readable title.\n */\nexport const effectiveTitleField = (definition: SchemaDefinition): FieldDefinition | undefined => {\n const live = definition.fields.filter((field) => !field.deprecated);\n const configured = definition.display.titleFieldId;\n return (\n (configured === undefined ? undefined : live.find((field) => field.id === configured)) ??\n live.find((field) => TITLE_FIELD_TYPES.has(field.type))\n );\n};\n","import type { DataType } from '../types/dataTypes.js';\nimport type { FieldDefinition, ModelDefinition } from '../types/definitions.js';\nimport { effectiveTitleField } from './titleField.js';\n\n/**\n * Data types that can be blocks in the entry document's canvas. Components must also be repeatable and\n * media must hold several files (`isCanvasEligible`); a single component or file is a property.\n */\nexport const CANVAS_ELIGIBLE: ReadonlySet<DataType> = new Set<DataType>([\n 'richtext',\n 'dynamiczone',\n 'component',\n 'media',\n]);\n\n/** Title types that the document edits inline as its H1; any other title type stays a property. */\nexport const INLINE_TITLE_TYPES: ReadonlySet<DataType> = new Set<DataType>(['string', 'text']);\n\n/** How many properties the strip shows when `display.stripFieldIds` is not set. */\nexport const STRIP_DEFAULT_COUNT = 5;\n\nexport const isCanvasEligible = (field: FieldDefinition): boolean => {\n switch (field.type) {\n case 'richtext':\n case 'dynamiczone':\n return true;\n case 'component':\n return field.settings.repeatable;\n case 'media':\n return field.settings.multiple;\n default:\n return false;\n }\n};\n\n/** A single `media` field that may hold an image. */\nexport const isCoverEligible = (field: FieldDefinition): boolean =>\n field.type === 'media' &&\n !field.settings.multiple &&\n (field.settings.allowedKinds === undefined || field.settings.allowedKinds.includes('image'));\n\n/** Properties under one of the model's `display.groups` (`label` undefined for ungrouped fields). */\nexport type PropertyGroup = { id: string; label: string | undefined; fields: FieldDefinition[] };\n\nexport type DocumentLayout = {\n /** The field that labels the entry (`effectiveTitleField`), if any. */\n title: FieldDefinition | undefined;\n /** The title is edited inline as the H1 (string/text); otherwise it is shown read-only and is a property. */\n titleInline: boolean;\n cover: FieldDefinition | undefined;\n /** Canvas blocks, in order. */\n canvas: FieldDefinition[];\n /** Every other live field, ordered by `display.groups`, then field order. */\n properties: FieldDefinition[];\n /** `properties` split by group, for the settings drawer and the property grid. */\n propertyGroups: PropertyGroup[];\n /**\n * The strip's configured properties, or null when it is not configured: then it shows the first\n * STRIP_DEFAULT_COUNT non-empty properties (`stripFieldsOf`), which depends on the entry's values.\n */\n strip: FieldDefinition[] | null;\n};\n\nconst byIds = (live: readonly FieldDefinition[], ids: readonly string[] | undefined) =>\n (ids ?? [])\n .map((id) => live.find((field) => field.id === id))\n .filter((field): field is FieldDefinition => field !== undefined);\n\nconst unique = (fields: readonly FieldDefinition[]) => [...new Map(fields.map((f) => [f.id, f])).values()];\n\nconst groupProperties = (model: ModelDefinition, properties: readonly FieldDefinition[]): PropertyGroup[] => {\n const groups = (model.display.groups ?? [])\n .map((group) => ({ id: group.id, label: group.label, fields: byIds(properties, group.fieldIds) }))\n .filter((group) => group.fields.length > 0);\n const grouped = new Set(groups.flatMap((group) => group.fields.map((field) => field.id)));\n const rest = properties.filter((field) => !grouped.has(field.id));\n return rest.length > 0 ? [...groups, { id: 'other', label: undefined, fields: rest }] : groups;\n};\n\nconst coverOf = (model: ModelDefinition, live: readonly FieldDefinition[], canvas: ReadonlySet<string>) => {\n const configured = byIds(live, model.display.coverFieldId ? [model.display.coverFieldId] : [])[0];\n if (configured && isCoverEligible(configured) && !canvas.has(configured.id)) {\n return configured;\n }\n return live.find((field) => isCoverEligible(field) && !canvas.has(field.id));\n};\n\n/**\n * The entry document's layout: title, cover, canvas blocks and properties. Configured `display` ids win\n * when they point at live, eligible fields; anything else falls back to the defaults (canvas: every\n * eligible field in field order; cover: the first single image field). Deprecated and ineligible ids are\n * skipped, so a stale definition never breaks the editor. Pure: no values, no I/O.\n */\nexport const effectiveLayout = (model: ModelDefinition): DocumentLayout => {\n const live = model.fields.filter((field) => !field.deprecated);\n const title = effectiveTitleField(model);\n const titleInline = title !== undefined && INLINE_TITLE_TYPES.has(title.type);\n const configuredCanvas = unique(byIds(live, model.display.canvasFieldIds).filter(isCanvasEligible));\n const canvasCandidates =\n model.display.canvasFieldIds === undefined ? live.filter(isCanvasEligible) : configuredCanvas;\n const cover = coverOf(model, live, new Set(configuredCanvas.map((field) => field.id)));\n const canvas = canvasCandidates.filter((field) => field.id !== cover?.id);\n const placed = new Set([\n ...canvas.map((field) => field.id),\n ...(cover ? [cover.id] : []),\n ...(titleInline && title ? [title.id] : []),\n ]);\n const propertyGroups = groupProperties(\n model,\n live.filter((field) => !placed.has(field.id)),\n );\n const properties = propertyGroups.flatMap((group) => group.fields);\n const strip =\n model.display.stripFieldIds === undefined ? null : unique(byIds(properties, model.display.stripFieldIds));\n return { title, titleInline, cover, canvas, properties, propertyGroups, strip };\n};\n\n/** The strip's properties: the configured ones, or the first `limit` that `hasValue` says are non-empty. */\nexport const stripFieldsOf = (\n layout: DocumentLayout,\n hasValue: (field: FieldDefinition) => boolean,\n limit = STRIP_DEFAULT_COUNT,\n): FieldDefinition[] => layout.strip ?? layout.properties.filter(hasValue).slice(0, limit);\n","import type { IssueCode } from './issues.js';\n\n/**\n * API keys (models, components, fields) must be valid GraphQL names from day one (CONTRIBUTING.md rule 4),\n * so GraphQL can expose them without renames.\n */\nexport const API_KEY_PATTERN = /^[_A-Za-z][_0-9A-Za-z]*$/;\nexport const MAX_API_KEY_LENGTH = 64;\n\nexport const isApiKeySyntaxValid = (key: string): boolean => API_KEY_PATTERN.test(key);\n\n/**\n * Syntax checks shared by every kind of API key (`noun` names it in messages, e.g. \"plural API ID\").\n * Returns the first problem, or null.\n */\nexport const checkApiKeySyntax = (\n key: string,\n noun = 'API ID',\n): { code: IssueCode; message: string } | null => {\n if (!isApiKeySyntaxValid(key)) {\n return {\n code: 'API_KEY_INVALID',\n message: `\"${key}\" is not a valid ${noun}: use letters, digits and _, not starting with a digit`,\n };\n }\n if (key.length > MAX_API_KEY_LENGTH) {\n return { code: 'API_KEY_TOO_LONG', message: `${noun}s are at most ${MAX_API_KEY_LENGTH} characters` };\n }\n // GraphQL reserves the `__` prefix for introspection.\n if (key.startsWith('__')) {\n return {\n code: 'API_KEY_RESERVED_PREFIX',\n message: `${noun}s must not start with \"__\" (reserved by GraphQL)`,\n };\n }\n return null;\n};\n\n/** Case-folded form used for every collision check: `Title` and `title` collide. */\nexport const foldApiKey = (key: string): string => key.toLowerCase();\n","import pluralize from 'pluralize';\nimport { foldApiKey, MAX_API_KEY_LENGTH } from '../validators/apiKey.js';\n\n/** Appended when English has no distinct plural (`news` → `newsItems`, `series` → `seriesItems`). */\nexport const PLURAL_FALLBACK_SUFFIX = 'Items';\n\n/**\n * Suggests the plural API ID of a collection from its singular one (`article` → `articles`,\n * `category` → `categories`). Only a suggestion for the admin and the value filled into definitions that\n * predate plural API IDs: the plural is stored on the definition and nothing pluralises at request time.\n * Deterministic for a given `pluralize` version, which is pinned exactly for that reason.\n */\nexport const suggestPlural = (apiKey: string): string => {\n if (apiKey === '') {\n return '';\n }\n const plural = pluralize(apiKey);\n if (plural.length <= MAX_API_KEY_LENGTH && foldApiKey(plural) !== foldApiKey(apiKey)) {\n return plural;\n }\n return `${apiKey.slice(0, MAX_API_KEY_LENGTH - PLURAL_FALLBACK_SUFFIX.length)}${PLURAL_FALLBACK_SUFFIX}`;\n};\n","import { DEFAULT_EDITORS } from './editors/catalogue.js';\nimport { suggestPlural } from './naming/plural.js';\nimport type {\n ComponentDefinition,\n ComponentDefinitionInput,\n ComponentDisplay,\n FieldDefinition,\n FieldInput,\n ModelDefinition,\n ModelDefinitionInput,\n ModelDisplay,\n SchemaDefinition,\n} from './types/definitions.js';\nimport type { JsonValue } from './types/json.js';\nimport { RICHTEXT_FORMAT_VERSION } from './types/valueFormats.js';\n\n/** Input whose IDs have been assigned (see `assignIds`). */\ntype WithIds<T extends { id?: string }> = T & { id: string };\nexport type FieldInputWithId = WithIds<FieldInput>;\nexport type DefinitionInputWithIds =\n | (WithIds<ModelDefinitionInput> & { fields: FieldInputWithId[] })\n | (WithIds<ComponentDefinitionInput> & { fields: FieldInputWithId[] });\n\nconst SETTINGS_DEFAULTS: Partial<Record<FieldDefinition['type'], Record<string, unknown>>> = {\n richtext: { formatVersion: RICHTEXT_FORMAT_VERSION },\n enum: { multiple: false },\n media: { multiple: false },\n component: { repeatable: false },\n};\n\n/** Optional text properties where an empty string means \"not set\". */\nconst OPTIONAL_TEXT_KEYS: ReadonlySet<string> = new Set([\n 'description',\n 'category',\n 'icon',\n 'titleFieldId',\n 'coverFieldId',\n 'pluralApiKey',\n]);\n/** Optional list properties where an empty list means \"not set\". `fields` is never optional. */\nconst OPTIONAL_LIST_KEYS: ReadonlySet<string> = new Set([\n 'listFieldIds',\n 'groups',\n 'canvasFieldIds',\n 'stripFieldIds',\n]);\n\nconst withoutEmpty = <T extends Record<string, unknown>>(value: T): T => {\n const result: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value)) {\n const isEmptyText = OPTIONAL_TEXT_KEYS.has(key) && entry === '';\n const isEmptyList = OPTIONAL_LIST_KEYS.has(key) && Array.isArray(entry) && entry.length === 0;\n if (entry === undefined || isEmptyText || isEmptyList) {\n continue;\n }\n result[key] = entry;\n }\n return result as T;\n};\n\nconst normalizeField = (field: FieldInputWithId): FieldDefinition => {\n const normalized = {\n id: field.id,\n apiKey: field.apiKey,\n label: field.label,\n description: field.description,\n type: field.type,\n required: field.required ?? false,\n localized: field.localized ?? false,\n public: field.public ?? true,\n unique: field.unique ?? false,\n filterable: field.filterable ?? false,\n sortable: field.sortable ?? false,\n deprecated: field.deprecated ?? false,\n defaultValue: field.defaultValue as JsonValue | undefined,\n settings: { ...SETTINGS_DEFAULTS[field.type], ...field.settings },\n editor: {\n id: field.editor?.id ?? DEFAULT_EDITORS[field.type],\n options: (field.editor?.options ?? {}) as Record<string, JsonValue>,\n },\n };\n return withoutEmpty(normalized) as FieldDefinition;\n};\n\nconst normalizeModelDisplay = (display: ModelDefinitionInput['display']): ModelDisplay =>\n withoutEmpty({ ...display });\n\nconst normalizeComponentDisplay = (display: ComponentDefinitionInput['display']): ComponentDisplay =>\n withoutEmpty({ ...display });\n\n/**\n * Applies defaults so that two definitions meaning the same thing are byte-identical once serialized\n * canonically: a hand-written file that omits `public` hashes the same as one that says `public: true`.\n * Empty optional strings and arrays are dropped. A collection without a plural API ID gets the suggested\n * one (`suggestPlural`), so files and definitions from before plural API IDs keep working.\n */\nexport const normalizeDefinition = (input: DefinitionInputWithIds): SchemaDefinition => {\n const fields = input.fields.map(normalizeField);\n if (input.kind === 'component') {\n const component: ComponentDefinition = withoutEmpty({\n id: input.id,\n kind: 'component',\n apiKey: input.apiKey,\n label: input.label,\n description: input.description,\n category: input.category,\n icon: input.icon,\n fields,\n display: normalizeComponentDisplay(input.display),\n });\n return component;\n }\n const model: ModelDefinition = withoutEmpty({\n id: input.id,\n kind: input.kind,\n apiKey: input.apiKey,\n // Collections always carry a plural API ID (filled from the singular when missing or empty);\n // singletons never do, so switching a collection to a singleton drops it.\n pluralApiKey: input.kind === 'collection' ? input.pluralApiKey || suggestPlural(input.apiKey) : undefined,\n label: input.label,\n description: input.description,\n localized: input.localized ?? false,\n draftAndPublish: input.draftAndPublish ?? true,\n fields,\n display: normalizeModelDisplay(input.display),\n });\n return model;\n};\n\n/** Normalizes a definition that is already normalized-shaped (e.g. read back from the database). */\nexport const renormalizeDefinition = (definition: SchemaDefinition): SchemaDefinition =>\n normalizeDefinition(definition as unknown as DefinitionInputWithIds);\n","import type { FieldDefinition } from '../types/definitions.js';\nimport {\n BIGINTEGER_PATTERN,\n DATE_PATTERN,\n DATETIME_PATTERN,\n DECIMAL_PATTERN,\n SLUG_PATTERN,\n TIME_PATTERN,\n UID_PATTERN,\n} from '../types/valueFormats.js';\n\n/**\n * Checks that a field's `defaultValue` has the right JSON shape for its type. Full content rules\n * (lengths, ranges) are applied by the content validator when the default is used.\n * Returns a message, or null when the default is acceptable.\n */\nexport const checkDefaultValue = (field: FieldDefinition): string | null => {\n const value = field.defaultValue;\n if (value === undefined) {\n return null;\n }\n const isString = typeof value === 'string';\n const matches = (pattern: RegExp) => isString && pattern.test(value);\n switch (field.type) {\n case 'string':\n case 'text':\n case 'email':\n case 'url':\n return isString ? null : 'must be a string';\n case 'slug':\n return matches(SLUG_PATTERN) ? null : 'must be a lower-case slug';\n case 'uid':\n return matches(UID_PATTERN) ? null : 'must contain only URL-safe characters';\n case 'number':\n return typeof value === 'number' && Number.isFinite(value) ? null : 'must be a number';\n case 'integer':\n return Number.isSafeInteger(value) ? null : 'must be an integer';\n case 'decimal':\n return matches(DECIMAL_PATTERN) ? null : 'must be a decimal string, e.g. \"12.50\"';\n case 'biginteger':\n return matches(BIGINTEGER_PATTERN) ? null : 'must be an integer string, e.g. \"9007199254740993\"';\n case 'boolean':\n return typeof value === 'boolean' ? null : 'must be true or false';\n case 'date':\n return matches(DATE_PATTERN) ? null : 'must be a date, YYYY-MM-DD';\n case 'datetime':\n return matches(DATETIME_PATTERN) ? null : 'must be a UTC date-time, YYYY-MM-DDTHH:mm:ssZ';\n case 'time':\n return matches(TIME_PATTERN) ? null : 'must be a time, HH:mm[:ss]';\n case 'enum': {\n const allowed = new Set(field.settings.values.map((entry) => entry.value));\n if (field.settings.multiple) {\n return Array.isArray(value) && value.every((item) => typeof item === 'string' && allowed.has(item))\n ? null\n : 'must be a list of the enum values';\n }\n return isString && allowed.has(value) ? null : 'must be one of the enum values';\n }\n case 'json':\n return null;\n default:\n return `${field.type} fields cannot have a default value`;\n }\n};\n","/**\n * A problem found in a definition. `path` is a JSON pointer into the definition (`/fields/2/apiKey`), so\n * the admin can put the message next to the control and the CLI can point at the file location.\n */\nexport type ValidationIssue = {\n path: string;\n code: IssueCode;\n message: string;\n /** Set by cross-definition checks so a multi-definition apply can say which file is wrong. */\n definitionId?: string;\n};\n\nexport type IssueCode =\n | 'INVALID_STRUCTURE'\n | 'INVALID_ID'\n | 'DUPLICATE_ID'\n | 'API_KEY_INVALID'\n | 'API_KEY_TOO_LONG'\n | 'API_KEY_RESERVED_PREFIX'\n | 'API_KEY_RESERVED'\n | 'API_KEY_COLLISION'\n | 'PLURAL_API_KEY_SAME_AS_SINGULAR'\n | 'GENERATED_NAME_COLLISION'\n | 'INVALID_SETTINGS'\n | 'INVALID_RANGE'\n | 'INVALID_PATTERN'\n | 'DUPLICATE_ENUM_VALUE'\n | 'INVALID_ENUM_VALUE'\n | 'UNSUPPORTED_FLAG'\n | 'INVALID_DEFAULT_VALUE'\n | 'UNKNOWN_EDITOR'\n | 'INCOMPATIBLE_EDITOR'\n | 'INVALID_EDITOR_OPTIONS'\n | 'UNKNOWN_FIELD_REFERENCE'\n | 'INVALID_FIELD_REFERENCE'\n | 'DUPLICATE_GROUP'\n | 'UNKNOWN_REFERENCE'\n | 'INVALID_REFERENCE_TARGET'\n | 'COMPONENT_CYCLE'\n | 'COMPONENT_TOO_DEEP'\n | 'REFERENCED_DEFINITION';\n\nexport class SchemaValidationError extends Error {\n readonly issues: readonly ValidationIssue[];\n\n constructor(issues: readonly ValidationIssue[]) {\n super(\n `Schema definition is invalid: ${issues.map((issue) => `${issue.path} ${issue.message}`).join('; ')}`,\n );\n this.name = 'SchemaValidationError';\n this.issues = issues;\n }\n}\n\nexport const issue = (path: string, code: IssueCode, message: string): ValidationIssue => ({\n path,\n code,\n message,\n});\n","import { suggestPlural } from '../naming/plural.js';\nimport type { ModelDefinition, SchemaDefinition } from '../types/definitions.js';\n\n/**\n * The names GraphQL (package J) and other generated contracts derive from API keys. Defined here, with the\n * validator, so a name that would collide in GraphQL is rejected when the model is saved, never later.\n * Package J must generate exactly these names.\n */\nexport const toTypeName = (apiKey: string): string => apiKey.charAt(0).toUpperCase() + apiKey.slice(1);\n\n/** Suffixes of the types generated for each model (`Page`, `PageFilter`, `PageInput`...). */\nexport const MODEL_TYPE_SUFFIXES = [\n '',\n 'Filter',\n 'Input',\n 'Connection',\n 'Edge',\n 'Localizations',\n 'Sort',\n] as const;\nexport const COMPONENT_TYPE_SUFFIXES = ['', 'Input'] as const;\nexport const MUTATION_PREFIXES = ['create', 'update', 'delete', 'publish', 'unpublish'] as const;\n\n/**\n * The key a model is addressed by in the delivery API (`/api/content/:routeKey`, preview routes): the\n * plural API ID of a collection, the API ID of a singleton. A collection stored before plural API IDs\n * existed gets the same derived value normalizing would fill, so this never returns undefined.\n */\nexport const routeKeyOf = (definition: ModelDefinition): string =>\n definition.kind === 'collection'\n ? definition.pluralApiKey || suggestPlural(definition.apiKey)\n : definition.apiKey;\n\n/** GraphQL list query of a collection (`articles(…)`): its plural API ID. */\nexport const collectionQueryName = (definition: ModelDefinition): string => routeKeyOf(definition);\n\n/**\n * A stored definition with the plural API ID a collection gets when it predates them (the value\n * normalizing fills), and whether anything was filled. Callers that hash definitions re-hash when `filled`.\n */\nexport const withDerivedPlural = <T extends SchemaDefinition>(\n definition: T,\n): { definition: T; filled: boolean } => {\n if (definition.kind !== 'collection' || definition.pluralApiKey) {\n return { definition, filled: false };\n }\n const { id, kind, apiKey, ...rest } = definition;\n const filled = { id, kind, apiKey, pluralApiKey: suggestPlural(apiKey), ...rest } as T;\n return { definition: filled, filled: true };\n};\n\n/**\n * GraphQL built-ins and the fixed types Shapio's schema always defines. Compared case-folded, so a model\n * called `string` (type `String`) or `pageInfo` is rejected.\n */\nexport const RESERVED_TYPE_NAMES: readonly string[] = [\n 'Query',\n 'Mutation',\n 'Subscription',\n 'String',\n 'Int',\n 'Float',\n 'Boolean',\n 'ID',\n 'JSON',\n 'Date',\n 'DateTime',\n 'Time',\n 'Decimal',\n 'BigInt',\n 'RichText',\n 'Media',\n 'MediaAsset',\n 'MediaVariant',\n 'FocalPoint',\n 'MediaKind',\n 'Int53',\n 'PageInfo',\n 'Locale',\n 'PublicationState',\n 'SortDirection',\n 'Node',\n 'Entry',\n 'Upload',\n 'StringFilter',\n 'IntFilter',\n 'FloatFilter',\n 'BooleanFilter',\n 'IDFilter',\n 'DateFilter',\n 'DateTimeFilter',\n 'TimeFilter',\n 'DecimalFilter',\n 'BigIntFilter',\n 'JSONFilter',\n // The snapshot diff (`_changes`, `_snapshot`).\n 'SnapshotChange',\n 'SnapshotChangeKind',\n 'SnapshotChangeLocale',\n 'SnapshotChangePage',\n 'SnapshotInfo',\n];\n\n/**\n * Model and component API keys the admin uses as static URL segments (`/content/new`,\n * `/develop/components`), so a type with one of these keys could not be opened. Compared case-folded.\n */\nexport const RESERVED_DEFINITION_API_KEYS: readonly string[] = ['new', 'components'];\n\n/**\n * Field API keys that collide with the system fields every entry exposes in REST and GraphQL.\n * Compared case-folded.\n */\nexport const RESERVED_FIELD_API_KEYS: readonly string[] = [\n 'id',\n 'locale',\n 'localizations',\n 'status',\n 'version',\n 'createdAt',\n 'updatedAt',\n 'publishedAt',\n 'createdBy',\n 'updatedBy',\n 'publicationState',\n // Logical operators of every model's GraphQL filter input (`XFilter`), next to the field keys.\n 'and',\n 'or',\n 'not',\n];\n\n/**\n * Root query fields every GraphQL schema has, whatever models exist. Compared case-folded. The first is the\n * schema version field (schemaBuilder.ts reads it by position).\n */\nexport const RESERVED_QUERY_NAMES: readonly string[] = ['_schemaVersion', '_changes', '_snapshot'];\n\nexport type NameNamespace = 'type' | 'query' | 'mutation';\n\nexport type GeneratedName = {\n namespace: NameNamespace;\n name: string;\n /** Which definition (and field, for per-field types) produced the name, for error messages. */\n definitionId: string;\n fieldId?: string;\n /** The definition property the name comes from, when not `apiKey` (for the issue path). */\n property?: 'pluralApiKey';\n};\n\n/** Every name a definition contributes to the GraphQL schema. */\nexport const generatedNames = (definition: SchemaDefinition): GeneratedName[] => {\n const typeName = toTypeName(definition.apiKey);\n const definitionId = definition.id;\n const suffixes = definition.kind === 'component' ? COMPONENT_TYPE_SUFFIXES : MODEL_TYPE_SUFFIXES;\n const names: GeneratedName[] = suffixes.map((suffix) => ({\n namespace: 'type',\n name: `${typeName}${suffix}`,\n definitionId,\n }));\n for (const field of definition.fields) {\n const fieldType = `${typeName}${toTypeName(field.apiKey)}`;\n if (field.type === 'enum') {\n names.push({ namespace: 'type', name: `${fieldType}Enum`, definitionId, fieldId: field.id });\n }\n if (field.type === 'dynamiczone') {\n names.push({ namespace: 'type', name: `${fieldType}Zone`, definitionId, fieldId: field.id });\n names.push({ namespace: 'type', name: `${fieldType}ZoneInput`, definitionId, fieldId: field.id });\n }\n }\n if (definition.kind !== 'component') {\n names.push({ namespace: 'query', name: definition.apiKey, definitionId });\n // Only collections have a list query, so switching a singleton to a collection adds a name; the\n // switch is validated against the whole schema like any other change.\n if (definition.kind === 'collection') {\n names.push({\n namespace: 'query',\n name: collectionQueryName(definition),\n definitionId,\n property: 'pluralApiKey',\n });\n }\n for (const prefix of MUTATION_PREFIXES) {\n names.push({ namespace: 'mutation', name: `${prefix}${typeName}`, definitionId });\n }\n }\n return names;\n};\n","import type { TSchema } from 'typebox';\nimport { Value } from 'typebox/value';\n\nexport type SchemaError = { path: string; message: string };\n\n/**\n * TypeBox errors as (JSON pointer, message) pairs. The `schema is false` echo that accompanies every\n * `additionalProperties` error is dropped, and unknown properties are named in the message.\n */\nexport const collectSchemaErrors = (schema: TSchema, value: unknown, basePath = ''): SchemaError[] =>\n [...Value.Errors(schema, value)]\n .filter((error) => error.keyword !== 'boolean')\n .map((error) => {\n const extra = (error.params as { additionalProperties?: unknown }).additionalProperties;\n const message =\n error.keyword === 'additionalProperties' && Array.isArray(extra)\n ? `unknown propert${extra.length === 1 ? 'y' : 'ies'}: ${extra.join(', ')}`\n : error.message;\n return { path: `${basePath}${error.instancePath}`, message };\n });\n","import { isCanvasEligible, isCoverEligible } from '../display/layout.js';\nimport { TITLE_FIELD_TYPES } from '../display/titleField.js';\nimport { EDITOR_CATALOGUE, isCustomEditorId } from '../editors/catalogue.js';\nimport { isStableId } from '../ids.js';\nimport { SCALAR_DATA_TYPES, UNIQUE_CAPABLE_DATA_TYPES } from '../types/dataTypes.js';\nimport type { FieldDefinition, FieldGroup, ModelDefinition, SchemaDefinition } from '../types/definitions.js';\nimport { checkApiKeySyntax, foldApiKey, isApiKeySyntaxValid } from './apiKey.js';\nimport { checkDefaultValue } from './defaultValue.js';\nimport { issue, type ValidationIssue } from './issues.js';\nimport { RESERVED_DEFINITION_API_KEYS, RESERVED_FIELD_API_KEYS } from './naming.js';\nimport { collectSchemaErrors } from './typeboxIssues.js';\n\n/**\n * Checks one normalized definition on its own: IDs, API keys, per-type settings, flags, editor choice and\n * display references. References to other definitions are checked by `validateSchema`.\n */\nconst RESERVED_FIELD_KEYS: ReadonlySet<string> = new Set(RESERVED_FIELD_API_KEYS.map(foldApiKey));\nconst RESERVED_DEFINITION_KEYS: ReadonlySet<string> = new Set(RESERVED_DEFINITION_API_KEYS.map(foldApiKey));\n/** GraphQL enum values must be names and cannot be `true`, `false` or `null`. */\nconst RESERVED_ENUM_VALUES: ReadonlySet<string> = new Set(['true', 'false', 'null']);\n\ntype RangeCheck = { min: unknown; max: unknown; compare: (a: never, b: never) => number; path: string };\n\nconst compareNumbers = (a: number, b: number) => a - b;\nconst compareBigInts = (a: string, b: string) => {\n const diff = BigInt(a) - BigInt(b);\n return diff === 0n ? 0 : diff > 0n ? 1 : -1;\n};\nconst compareDecimals = (a: string, b: string) => Number(a) - Number(b);\nconst compareText = (a: string, b: string) => (a === b ? 0 : a > b ? 1 : -1);\n\nconst checkRange = ({ min, max, compare, path }: RangeCheck): ValidationIssue[] =>\n min !== undefined && max !== undefined && compare(min as never, max as never) > 0\n ? [issue(path, 'INVALID_RANGE', 'minimum is greater than maximum')]\n : [];\n\nconst settingsRanges = (field: FieldDefinition, path: string): ValidationIssue[] => {\n const s = field.settings as Record<string, unknown>;\n const issues: ValidationIssue[] = [];\n issues.push(\n ...checkRange({ min: s.minLength, max: s.maxLength, compare: compareNumbers, path: `${path}/minLength` }),\n );\n switch (field.type) {\n case 'number':\n case 'integer':\n case 'media':\n case 'relation':\n case 'component':\n case 'dynamiczone':\n issues.push(...checkRange({ min: s.min, max: s.max, compare: compareNumbers, path: `${path}/min` }));\n break;\n case 'biginteger':\n issues.push(...checkRange({ min: s.min, max: s.max, compare: compareBigInts, path: `${path}/min` }));\n break;\n case 'decimal':\n issues.push(...checkRange({ min: s.min, max: s.max, compare: compareDecimals, path: `${path}/min` }));\n if (field.settings.scale !== undefined && field.settings.precision !== undefined) {\n issues.push(\n ...checkRange({\n min: field.settings.scale,\n max: field.settings.precision,\n compare: compareNumbers,\n path: `${path}/scale`,\n }),\n );\n }\n break;\n case 'date':\n case 'datetime':\n case 'time':\n issues.push(...checkRange({ min: s.min, max: s.max, compare: compareText, path: `${path}/min` }));\n break;\n default:\n break;\n }\n return issues;\n};\n\nconst checkSettings = (\n field: FieldDefinition,\n path: string,\n definition: SchemaDefinition,\n): ValidationIssue[] => {\n const issues = settingsRanges(field, `${path}/settings`);\n if (field.type === 'string' && field.settings.pattern !== undefined) {\n try {\n new RegExp(field.settings.pattern, 'u');\n } catch {\n issues.push(issue(`${path}/settings/pattern`, 'INVALID_PATTERN', 'is not a valid regular expression'));\n }\n }\n if (field.type === 'enum') {\n const seen = new Set<string>();\n field.settings.values.forEach((entry, index) => {\n const entryPath = `${path}/settings/values/${index}/value`;\n if (\n !isApiKeySyntaxValid(entry.value) ||\n entry.value.startsWith('__') ||\n RESERVED_ENUM_VALUES.has(entry.value)\n ) {\n issues.push(\n issue(\n entryPath,\n 'INVALID_ENUM_VALUE',\n 'enum values must be GraphQL names (letters, digits, _), not true/false/null',\n ),\n );\n }\n if (seen.has(entry.value)) {\n issues.push(issue(entryPath, 'DUPLICATE_ENUM_VALUE', `\"${entry.value}\" is listed twice`));\n }\n seen.add(entry.value);\n });\n }\n if (field.type === 'slug' && field.settings.sourceFieldId !== undefined) {\n const source = definition.fields.find((candidate) => candidate.id === field.settings.sourceFieldId);\n if (!source) {\n issues.push(\n issue(\n `${path}/settings/sourceFieldId`,\n 'UNKNOWN_FIELD_REFERENCE',\n 'refers to no field of this definition',\n ),\n );\n } else if (source.type !== 'string' && source.type !== 'text') {\n issues.push(\n issue(\n `${path}/settings/sourceFieldId`,\n 'INVALID_FIELD_REFERENCE',\n 'must refer to a string or text field',\n ),\n );\n }\n }\n if (field.type === 'richtext' && field.settings.formatVersion !== 1) {\n issues.push(\n issue(`${path}/settings/formatVersion`, 'INVALID_SETTINGS', 'unsupported rich-text format version'),\n );\n }\n if (field.type === 'relation' && !isStableId(field.settings.target)) {\n issues.push(issue(`${path}/settings/target`, 'INVALID_ID', 'must be the ID of a model'));\n }\n if (field.type === 'component' && !isStableId(field.settings.component)) {\n issues.push(issue(`${path}/settings/component`, 'INVALID_ID', 'must be the ID of a component'));\n }\n if (field.type === 'dynamiczone') {\n field.settings.components.forEach((id, index) => {\n if (!isStableId(id)) {\n issues.push(\n issue(`${path}/settings/components/${index}`, 'INVALID_ID', 'must be the ID of a component'),\n );\n }\n });\n }\n return issues;\n};\n\nconst checkFlags = (field: FieldDefinition, path: string, isComponent: boolean): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n const reject = (flag: string, why: string) =>\n issues.push(issue(`${path}/${flag}`, 'UNSUPPORTED_FLAG', why));\n if (field.unique && !UNIQUE_CAPABLE_DATA_TYPES.has(field.type)) {\n reject('unique', `${field.type} fields cannot be unique`);\n }\n for (const flag of ['filterable', 'sortable'] as const) {\n if (field[flag] && !SCALAR_DATA_TYPES.has(field.type)) {\n reject(flag, `${field.type} fields cannot be ${flag}`);\n }\n if (field[flag] && field.type === 'enum' && field.settings.multiple) {\n reject(flag, `multi-value enum fields cannot be ${flag}`);\n }\n }\n if (isComponent) {\n // Component values live inside a parent entry field; uniqueness and indexes apply to entry fields only.\n for (const flag of ['unique', 'filterable', 'sortable'] as const) {\n if (field[flag]) {\n reject(flag, `fields of a component cannot be ${flag}`);\n }\n }\n }\n if (field.deprecated && field.required) {\n reject('required', 'a deprecated field cannot be required');\n }\n return issues;\n};\n\nconst checkEditor = (field: FieldDefinition, path: string): ValidationIssue[] => {\n const { id, options } = field.editor;\n if (isCustomEditorId(id)) {\n return [];\n }\n const entry = EDITOR_CATALOGUE.get(id);\n if (!entry) {\n return [\n issue(\n `${path}/editor/id`,\n 'UNKNOWN_EDITOR',\n `\"${id}\" is not a built-in editor (custom editors use a vendor.name ID)`,\n ),\n ];\n }\n if (!entry.dataTypes.includes(field.type) || !(entry.supports?.(field) ?? true)) {\n return [\n issue(\n `${path}/editor/id`,\n 'INCOMPATIBLE_EDITOR',\n `the ${id} editor cannot edit this ${field.type} field`,\n ),\n ];\n }\n return collectSchemaErrors(entry.optionsSchema, options, `${path}/editor/options`).map((error) =>\n issue(error.path, 'INVALID_EDITOR_OPTIONS', error.message),\n );\n};\n\nconst checkField = (\n field: FieldDefinition,\n index: number,\n definition: SchemaDefinition,\n): ValidationIssue[] => {\n const path = `/fields/${index}`;\n const issues: ValidationIssue[] = [];\n if (!isStableId(field.id)) {\n issues.push(issue(`${path}/id`, 'INVALID_ID', 'must be a lower-case UUID'));\n }\n const syntax = checkApiKeySyntax(field.apiKey);\n if (syntax) {\n issues.push(issue(`${path}/apiKey`, syntax.code, syntax.message));\n } else if (RESERVED_FIELD_KEYS.has(foldApiKey(field.apiKey))) {\n issues.push(issue(`${path}/apiKey`, 'API_KEY_RESERVED', `\"${field.apiKey}\" is a system field name`));\n }\n issues.push(...checkSettings(field, path, definition));\n issues.push(...checkFlags(field, path, definition.kind === 'component'));\n const defaultProblem = checkDefaultValue(field);\n if (defaultProblem) {\n issues.push(issue(`${path}/defaultValue`, 'INVALID_DEFAULT_VALUE', defaultProblem));\n }\n issues.push(...checkEditor(field, path));\n return issues;\n};\n\nconst checkFieldUniqueness = (definition: SchemaDefinition): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n const ids = new Set<string>();\n const keys = new Map<string, string>();\n definition.fields.forEach((field, index) => {\n if (ids.has(field.id)) {\n issues.push(issue(`/fields/${index}/id`, 'DUPLICATE_ID', 'another field has the same ID'));\n }\n ids.add(field.id);\n const folded = foldApiKey(field.apiKey);\n const clash = keys.get(folded);\n if (clash !== undefined) {\n issues.push(\n issue(\n `/fields/${index}/apiKey`,\n 'API_KEY_COLLISION',\n `\"${field.apiKey}\" collides with field \"${clash}\" (keys are case-insensitive)`,\n ),\n );\n }\n keys.set(folded, field.apiKey);\n });\n return issues;\n};\n\nconst checkGroups = (\n groups: readonly FieldGroup[] | undefined,\n fieldIds: ReadonlySet<string>,\n): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n const groupIds = new Set<string>();\n const placed = new Set<string>();\n (groups ?? []).forEach((group, groupIndex) => {\n if (groupIds.has(group.id)) {\n issues.push(\n issue(`/display/groups/${groupIndex}/id`, 'DUPLICATE_GROUP', 'another group has the same ID'),\n );\n }\n groupIds.add(group.id);\n group.fieldIds.forEach((fieldId, index) => {\n const path = `/display/groups/${groupIndex}/fieldIds/${index}`;\n if (!fieldIds.has(fieldId)) {\n issues.push(issue(path, 'UNKNOWN_FIELD_REFERENCE', 'refers to no field of this definition'));\n } else if (placed.has(fieldId)) {\n issues.push(issue(path, 'INVALID_FIELD_REFERENCE', 'a field can be in one group only'));\n }\n placed.add(fieldId);\n });\n });\n return issues;\n};\n\ntype FieldReferenceCheck = {\n path: string;\n fields: ReadonlyMap<string, FieldDefinition>;\n /** Returns why the field can't be used here, or undefined when it can. */\n reject: (field: FieldDefinition) => string | undefined;\n};\n\n/** A list of field IDs: each must exist, appear once and pass `reject`. */\nconst checkFieldList = (\n ids: readonly string[] | undefined,\n check: FieldReferenceCheck,\n): ValidationIssue[] => {\n const seen = new Set<string>();\n return (ids ?? []).flatMap((fieldId, index) => {\n const path = `${check.path}/${index}`;\n const field = check.fields.get(fieldId);\n if (!field) {\n return [issue(path, 'UNKNOWN_FIELD_REFERENCE', 'refers to no field of this definition')];\n }\n if (seen.has(fieldId)) {\n return [issue(path, 'INVALID_FIELD_REFERENCE', 'the field is listed more than once')];\n }\n seen.add(fieldId);\n const reason = check.reject(field);\n return reason ? [issue(path, 'INVALID_FIELD_REFERENCE', reason)] : [];\n });\n};\n\n/**\n * The entry document's layout (`effectiveLayout`): canvas blocks, cover and strip. Title, cover and canvas\n * are disjoint (title types are never canvas or cover types, so eligibility covers the title); strip\n * entries are properties, so never the cover or a canvas block.\n */\nconst checkDocumentLayout = (\n model: ModelDefinition,\n fields: ReadonlyMap<string, FieldDefinition>,\n): ValidationIssue[] => {\n const { canvasFieldIds, coverFieldId, stripFieldIds } = model.display;\n const canvas = new Set(canvasFieldIds ?? []);\n const issues = checkFieldList(canvasFieldIds, {\n path: '/display/canvasFieldIds',\n fields,\n reject: (field) => (isCanvasEligible(field) ? undefined : canvasRejection(field)),\n });\n if (coverFieldId !== undefined) {\n issues.push(\n ...checkFieldList([coverFieldId], {\n path: '/display/coverFieldId',\n fields,\n reject: (field) =>\n !isCoverEligible(field)\n ? 'the cover must be a single media field that allows images'\n : canvas.has(field.id)\n ? 'the cover cannot also be in the canvas'\n : undefined,\n }).map((found) => ({ ...found, path: '/display/coverFieldId' })),\n );\n }\n issues.push(\n ...checkFieldList(stripFieldIds, {\n path: '/display/stripFieldIds',\n fields,\n reject: (field) =>\n canvas.has(field.id) || field.id === coverFieldId\n ? 'the strip shows properties, not the cover or canvas blocks'\n : undefined,\n }),\n );\n return issues;\n};\n\nconst canvasRejection = (field: FieldDefinition): string => {\n if (field.type === 'component') {\n return 'only a repeatable component can be in the canvas';\n }\n if (field.type === 'media') {\n return 'only a media field with several files can be in the canvas';\n }\n return `a ${field.type} field cannot be in the canvas`;\n};\n\nconst checkDisplay = (definition: SchemaDefinition): ValidationIssue[] => {\n const fields = new Map(definition.fields.map((field) => [field.id, field]));\n const fieldIds = new Set(fields.keys());\n const issues: ValidationIssue[] = [];\n const { titleFieldId } = definition.display;\n if (titleFieldId !== undefined) {\n const title = fields.get(titleFieldId);\n if (!title) {\n issues.push(\n issue('/display/titleFieldId', 'UNKNOWN_FIELD_REFERENCE', 'refers to no field of this definition'),\n );\n } else if (!TITLE_FIELD_TYPES.has(title.type)) {\n issues.push(\n issue(\n '/display/titleFieldId',\n 'INVALID_FIELD_REFERENCE',\n `a ${title.type} field cannot be the title`,\n ),\n );\n }\n }\n if (definition.kind !== 'component') {\n definition.display.listFieldIds?.forEach((fieldId, index) => {\n if (!fieldIds.has(fieldId)) {\n issues.push(\n issue(\n `/display/listFieldIds/${index}`,\n 'UNKNOWN_FIELD_REFERENCE',\n 'refers to no field of this definition',\n ),\n );\n }\n });\n const sort = definition.display.defaultSort;\n if (sort) {\n const field = fields.get(sort.fieldId);\n if (!field) {\n issues.push(\n issue(\n '/display/defaultSort/fieldId',\n 'UNKNOWN_FIELD_REFERENCE',\n 'refers to no field of this definition',\n ),\n );\n } else if (!field.sortable) {\n issues.push(\n issue(\n '/display/defaultSort/fieldId',\n 'INVALID_FIELD_REFERENCE',\n 'the default sort field must be sortable',\n ),\n );\n }\n }\n issues.push(...checkDocumentLayout(definition, fields));\n }\n issues.push(...checkGroups(definition.display.groups, fieldIds));\n return issues;\n};\n\n/**\n * A collection's plural API ID follows the API ID rules and must differ from its singular. Singletons and\n * components have none (normalizing drops it).\n */\nconst checkPluralApiKey = (definition: SchemaDefinition): ValidationIssue[] => {\n if (definition.kind !== 'collection' || definition.pluralApiKey === undefined) {\n return [];\n }\n const syntax = checkApiKeySyntax(definition.pluralApiKey, 'plural API ID');\n if (syntax) {\n return [issue('/pluralApiKey', syntax.code, syntax.message)];\n }\n if (foldApiKey(definition.pluralApiKey) === foldApiKey(definition.apiKey)) {\n return [\n issue(\n '/pluralApiKey',\n 'PLURAL_API_KEY_SAME_AS_SINGULAR',\n 'the plural API ID must differ from the API ID (case-insensitively)',\n ),\n ];\n }\n return [];\n};\n\n/** All problems with one definition, in document order. Empty means valid on its own. */\nexport const validateDefinition = (definition: SchemaDefinition): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n if (!isStableId(definition.id)) {\n issues.push(issue('/id', 'INVALID_ID', 'must be a lower-case UUID'));\n }\n const syntax = checkApiKeySyntax(definition.apiKey);\n if (syntax) {\n issues.push(issue('/apiKey', syntax.code, syntax.message));\n } else if (RESERVED_DEFINITION_KEYS.has(foldApiKey(definition.apiKey))) {\n issues.push(issue('/apiKey', 'API_KEY_RESERVED', `\"${definition.apiKey}\" is reserved by the admin`));\n }\n // A plural derived from an invalid API ID is invalid too; report the API ID once.\n if (!syntax) {\n issues.push(...checkPluralApiKey(definition));\n }\n definition.fields.forEach((field, index) => issues.push(...checkField(field, index, definition)));\n issues.push(...checkFieldUniqueness(definition));\n issues.push(...checkDisplay(definition));\n return issues;\n};\n","import { createStableId } from '../ids.js';\nimport { normalizeDefinition, type DefinitionInputWithIds, type FieldInputWithId } from '../normalize.js';\nimport {\n ComponentDefinitionInputSchema,\n ModelDefinitionInputSchema,\n type DefinitionInput,\n type FieldInput,\n type SchemaDefinition,\n} from '../types/definitions.js';\nimport { SETTINGS_SCHEMAS } from '../types/settings.js';\nimport { foldApiKey } from './apiKey.js';\nimport { validateDefinition } from './definition.js';\nimport { issue, type ValidationIssue } from './issues.js';\nimport { collectSchemaErrors } from './typeboxIssues.js';\n\nexport type ParseDefinitionResult =\n { ok: true; definition: SchemaDefinition } | { ok: false; issues: ValidationIssue[] };\n\nexport type ParseDefinitionOptions = {\n /**\n * The current definition, if this is an edit. Fields sent without an `id` are matched to the current\n * field with the same API key (case-insensitive) and keep its ID; unmatched fields get a new ID.\n */\n previous?: SchemaDefinition;\n createId?: () => string;\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst structuralIssues = (raw: Record<string, unknown>): ValidationIssue[] => {\n const schema = raw.kind === 'component' ? ComponentDefinitionInputSchema : ModelDefinitionInputSchema;\n const issues = collectSchemaErrors(schema, raw).map((error) =>\n issue(error.path, 'INVALID_STRUCTURE', error.message),\n );\n if (issues.length > 0) {\n return issues;\n }\n const fields = raw.fields as FieldInput[];\n fields.forEach((field, index) => {\n const settingsSchema = SETTINGS_SCHEMAS[field.type];\n for (const error of collectSchemaErrors(\n settingsSchema,\n field.settings ?? {},\n `/fields/${index}/settings`,\n )) {\n issues.push(issue(error.path, 'INVALID_SETTINGS', error.message));\n }\n });\n return issues;\n};\n\n/** Fills in missing definition and field IDs (see ParseDefinitionOptions.previous). */\nexport const assignIds = (\n input: DefinitionInput,\n { previous, createId = createStableId }: ParseDefinitionOptions = {},\n): DefinitionInputWithIds => {\n const explicitIds = new Set(input.fields.flatMap((field) => (field.id ? [field.id] : [])));\n const previousByKey = new Map(\n (previous?.fields ?? [])\n .filter((field) => !explicitIds.has(field.id))\n .map((field) => [foldApiKey(field.apiKey), field.id]),\n );\n const fields: FieldInputWithId[] = input.fields.map((field) => {\n if (field.id) {\n return { ...field, id: field.id };\n }\n const matched = previousByKey.get(foldApiKey(field.apiKey));\n previousByKey.delete(foldApiKey(field.apiKey));\n return { ...field, id: matched ?? createId() };\n });\n return { ...input, id: input.id ?? previous?.id ?? createId(), fields };\n};\n\n/**\n * The single entry point from untrusted input (request bodies, schema files) to a normalized definition:\n * structure, settings per data type, ID assignment, defaults, then the per-definition semantic checks.\n * Cross-definition rules (references, cycles, GraphQL name collisions) are `validateSchema`'s job.\n */\nexport const parseDefinition = (\n raw: unknown,\n options: ParseDefinitionOptions = {},\n): ParseDefinitionResult => {\n if (!isObject(raw)) {\n return { ok: false, issues: [issue('', 'INVALID_STRUCTURE', 'a definition must be a JSON object')] };\n }\n const structural = structuralIssues(raw);\n if (structural.length > 0) {\n return { ok: false, issues: structural };\n }\n const definition = normalizeDefinition(assignIds(raw as DefinitionInput, options));\n const issues = validateDefinition(definition);\n return issues.length > 0 ? { ok: false, issues } : { ok: true, definition };\n};\n","import type { SchemaDefinition } from '../types/definitions.js';\nimport { foldApiKey } from './apiKey.js';\nimport { issue, type ValidationIssue } from './issues.js';\nimport {\n generatedNames,\n RESERVED_QUERY_NAMES,\n RESERVED_TYPE_NAMES,\n routeKeyOf,\n type GeneratedName,\n} from './naming.js';\n\n/** Deepest allowed nesting of components (a component inside a component inside ... ) below an entry. */\nexport const MAX_COMPONENT_DEPTH = 5;\n\nconst RESERVED_TYPES: ReadonlySet<string> = new Set(RESERVED_TYPE_NAMES.map(foldApiKey));\nconst RESERVED_QUERIES: ReadonlySet<string> = new Set(RESERVED_QUERY_NAMES.map(foldApiKey));\n\nconst withDefinition = (definition: SchemaDefinition, found: ValidationIssue): ValidationIssue => ({\n ...found,\n definitionId: definition.id,\n});\n\nconst describeOrigin = (name: GeneratedName, byId: ReadonlyMap<string, SchemaDefinition>) => {\n const definition = byId.get(name.definitionId);\n const field = name.fieldId\n ? definition?.fields.find((candidate) => candidate.id === name.fieldId)\n : undefined;\n return field ? `${definition?.apiKey ?? '?'}.${field.apiKey}` : (definition?.apiKey ?? '?');\n};\n\n/** The API IDs a definition claims in the shared case-insensitive namespace, with their issue paths. */\nconst claimedKeys = (definition: SchemaDefinition): Array<{ key: string; path: string; plural: boolean }> => {\n const keys = [{ key: definition.apiKey, path: '/apiKey', plural: false }];\n const plural = definition.kind === 'collection' ? routeKeyOf(definition) : '';\n if (plural) {\n keys.push({ key: plural, path: '/pluralApiKey', plural: true });\n }\n return keys;\n};\n\nconst describeKey = ({ definition, key }: { definition: SchemaDefinition; key: string }) =>\n key === definition.apiKey ? `\"${key}\"` : `the plural API ID \"${key}\" of \"${definition.apiKey}\"`;\n\nconst checkIdentity = (definitions: readonly SchemaDefinition[]): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n const ids = new Set<string>();\n const keys = new Map<string, { definition: SchemaDefinition; key: string }>();\n const fieldOwners = new Map<string, SchemaDefinition>();\n for (const definition of definitions) {\n if (ids.has(definition.id)) {\n issues.push(\n withDefinition(definition, issue('/id', 'DUPLICATE_ID', 'another definition has the same ID')),\n );\n }\n ids.add(definition.id);\n // Plural API IDs share the namespace: `/api/content/posts` and the `posts` query must be unambiguous.\n for (const { key, path, plural } of claimedKeys(definition)) {\n const folded = foldApiKey(key);\n const clash = keys.get(folded);\n if (clash && clash.definition.id !== definition.id) {\n issues.push(\n withDefinition(\n definition,\n issue(\n path,\n 'API_KEY_COLLISION',\n `${plural ? 'the plural API ID ' : ''}\"${key}\" collides with ${describeKey(clash)} (models and components share one case-insensitive namespace)`,\n ),\n ),\n );\n }\n if (!clash) {\n keys.set(folded, { definition, key });\n }\n }\n definition.fields.forEach((field, index) => {\n const owner = fieldOwners.get(field.id);\n if (owner && owner.id !== definition.id) {\n issues.push(\n withDefinition(\n definition,\n issue(\n `/fields/${index}/id`,\n 'DUPLICATE_ID',\n `field ID is already used by \"${owner.apiKey}\"; field IDs are global`,\n ),\n ),\n );\n }\n fieldOwners.set(field.id, definition);\n });\n }\n return issues;\n};\n\nconst checkGeneratedNames = (definitions: readonly SchemaDefinition[]): ValidationIssue[] => {\n const byId = new Map(definitions.map((definition) => [definition.id, definition]));\n const issues: ValidationIssue[] = [];\n const seen = new Map<string, GeneratedName>();\n for (const definition of definitions) {\n for (const name of generatedNames(definition)) {\n const folded = `${name.namespace}:${foldApiKey(name.name)}`;\n const path = name.fieldId\n ? `/fields/${definition.fields.findIndex((field) => field.id === name.fieldId)}/apiKey`\n : `/${name.property ?? 'apiKey'}`;\n if (name.namespace === 'type' && RESERVED_TYPES.has(foldApiKey(name.name))) {\n issues.push(\n withDefinition(\n definition,\n issue(path, 'API_KEY_RESERVED', `generates the GraphQL type \"${name.name}\", which is reserved`),\n ),\n );\n continue;\n }\n if (name.namespace === 'query' && RESERVED_QUERIES.has(foldApiKey(name.name))) {\n issues.push(\n withDefinition(\n definition,\n issue(path, 'API_KEY_RESERVED', `generates the GraphQL query \"${name.name}\", which is reserved`),\n ),\n );\n continue;\n }\n const clash = seen.get(folded);\n if (clash && (clash.definitionId !== name.definitionId || clash.fieldId !== name.fieldId)) {\n issues.push(\n withDefinition(\n definition,\n issue(\n path,\n 'GENERATED_NAME_COLLISION',\n `generates the GraphQL ${name.namespace} name \"${name.name}\", which \"${describeOrigin(clash, byId)}\" already generates`,\n ),\n ),\n );\n continue;\n }\n seen.set(folded, name);\n }\n }\n return issues;\n};\n\n/** Component IDs a definition embeds directly (component and dynamic-zone fields). */\nexport const embeddedComponentIds = (definition: SchemaDefinition): string[] =>\n definition.fields.flatMap((field) => {\n if (field.type === 'component') {\n return [field.settings.component];\n }\n if (field.type === 'dynamiczone') {\n return field.settings.components;\n }\n return [];\n });\n\nconst checkReferences = (definitions: readonly SchemaDefinition[]): ValidationIssue[] => {\n const byId = new Map(definitions.map((definition) => [definition.id, definition]));\n const issues: ValidationIssue[] = [];\n for (const definition of definitions) {\n definition.fields.forEach((field, index) => {\n const path = `/fields/${index}/settings`;\n const expectComponent = (id: string, at: string) => {\n const target = byId.get(id);\n if (!target) {\n issues.push(withDefinition(definition, issue(at, 'UNKNOWN_REFERENCE', 'refers to no component')));\n } else if (target.kind !== 'component') {\n issues.push(\n withDefinition(\n definition,\n issue(at, 'INVALID_REFERENCE_TARGET', `\"${target.apiKey}\" is a model, not a component`),\n ),\n );\n }\n };\n if (field.type === 'relation') {\n const target = byId.get(field.settings.target);\n if (!target) {\n issues.push(\n withDefinition(definition, issue(`${path}/target`, 'UNKNOWN_REFERENCE', 'refers to no model')),\n );\n } else if (target.kind !== 'collection') {\n issues.push(\n withDefinition(\n definition,\n issue(\n `${path}/target`,\n 'INVALID_REFERENCE_TARGET',\n `relations must target a collection model; \"${target.apiKey}\" is a ${target.kind}`,\n ),\n ),\n );\n }\n }\n if (field.type === 'component') {\n expectComponent(field.settings.component, `${path}/component`);\n }\n if (field.type === 'dynamiczone') {\n const seen = new Set<string>();\n field.settings.components.forEach((id, componentIndex) => {\n const at = `${path}/components/${componentIndex}`;\n if (seen.has(id)) {\n issues.push(withDefinition(definition, issue(at, 'DUPLICATE_ID', 'component listed twice')));\n }\n seen.add(id);\n expectComponent(id, at);\n });\n }\n });\n }\n return issues;\n};\n\n/**\n * Longest chain of nested components below each definition, or a cycle. Depth 1 means the definition\n * embeds components that embed nothing.\n */\nconst checkNesting = (definitions: readonly SchemaDefinition[]): ValidationIssue[] => {\n const byId = new Map(definitions.map((definition) => [definition.id, definition]));\n const depthOf = new Map<string, number>();\n const issues: ValidationIssue[] = [];\n const reported = new Set<string>();\n\n const visit = (id: string, stack: string[]): number => {\n const known = depthOf.get(id);\n if (known !== undefined) {\n return known;\n }\n if (stack.includes(id)) {\n const cycle = [...stack.slice(stack.indexOf(id)), id].map(\n (member) => byId.get(member)?.apiKey ?? member,\n );\n const definition = byId.get(id);\n if (definition && !reported.has(id)) {\n reported.add(id);\n issues.push(\n withDefinition(\n definition,\n issue('/fields', 'COMPONENT_CYCLE', `components nest in a cycle: ${cycle.join(' → ')}`),\n ),\n );\n }\n return Number.POSITIVE_INFINITY;\n }\n const definition = byId.get(id);\n if (!definition) {\n return 0;\n }\n const children = embeddedComponentIds(definition).filter(\n (child) => byId.get(child)?.kind === 'component',\n );\n const depth =\n children.length === 0 ? 0 : 1 + Math.max(...children.map((child) => visit(child, [...stack, id])));\n depthOf.set(id, depth);\n return depth;\n };\n\n for (const definition of definitions) {\n const depth = visit(definition.id, []);\n if (Number.isFinite(depth) && depth > MAX_COMPONENT_DEPTH && definition.kind !== 'component') {\n issues.push(\n withDefinition(\n definition,\n issue(\n '/fields',\n 'COMPONENT_TOO_DEEP',\n `components nest ${depth} levels deep; the limit is ${MAX_COMPONENT_DEPTH}`,\n ),\n ),\n );\n }\n }\n return issues;\n};\n\n/**\n * Cross-definition checks over a whole schema (every active definition with the proposed change applied):\n * unique IDs and API keys, GraphQL name collisions, relation and component targets, component cycles and\n * nesting depth. Each definition must already pass `validateDefinition`.\n */\nexport const validateSchema = (definitions: readonly SchemaDefinition[]): ValidationIssue[] => [\n ...checkIdentity(definitions),\n ...checkGeneratedNames(definitions),\n ...checkReferences(definitions),\n ...checkNesting(definitions),\n];\n\n/** Definitions that reference `id` (relations, components, dynamic zones). Used to block deletions. */\nexport const findReferencingDefinitions = (\n definitions: readonly SchemaDefinition[],\n id: string,\n): SchemaDefinition[] =>\n definitions.filter(\n (definition) =>\n definition.id !== id &&\n definition.fields.some(\n (field) =>\n (field.type === 'relation' && field.settings.target === id) ||\n (field.type === 'component' && field.settings.component === id) ||\n (field.type === 'dynamiczone' && field.settings.components.includes(id)),\n ),\n );\n\n/**\n * Models that embed a component directly or through other components, i.e. whose entries change shape\n * when the component does (brief §5: \"editing a shared component must account for all dependent models\").\n */\nexport const findDependentModels = (\n definitions: readonly SchemaDefinition[],\n componentId: string,\n): SchemaDefinition[] => {\n const embeddedBy = new Map<string, SchemaDefinition[]>();\n for (const definition of definitions) {\n for (const child of embeddedComponentIds(definition)) {\n embeddedBy.set(child, [...(embeddedBy.get(child) ?? []), definition]);\n }\n }\n const models = new Map<string, SchemaDefinition>();\n const visited = new Set<string>();\n const queue = [componentId];\n while (queue.length > 0) {\n const current = queue.shift() as string;\n if (visited.has(current)) {\n continue;\n }\n visited.add(current);\n for (const parent of embeddedBy.get(current) ?? []) {\n if (parent.kind === 'component') {\n queue.push(parent.id);\n } else {\n models.set(parent.id, parent);\n }\n }\n }\n return [...models.values()];\n};\n","import type { JsonValue } from '../types/json.js';\n\nexport const CHANGE_KINDS = [\n 'definition.added',\n 'definition.removed',\n 'definition.apiKey',\n 'definition.pluralApiKey',\n 'definition.metadata',\n 'model.kind',\n 'model.localized',\n 'model.draftAndPublish',\n 'field.added',\n 'field.removed',\n 'field.order',\n 'field.apiKey',\n 'field.metadata',\n 'field.editor',\n 'field.type',\n 'field.required',\n 'field.localized',\n 'field.public',\n 'field.deprecated',\n 'field.unique',\n 'field.filterable',\n 'field.sortable',\n 'field.settings',\n] as const;\n\nexport type ChangeKind = (typeof CHANGE_KINDS)[number];\n\n/**\n * One difference between two versions of a definition. `property` names the changed property for\n * `*.metadata` (`label`, `description`, ...) and `field.settings` (the settings key); `from`/`to` hold the\n * old and new values (absent when the side does not exist).\n */\nexport type SchemaChange = {\n kind: ChangeKind;\n definitionId: string;\n fieldId?: string;\n property?: string;\n from?: JsonValue;\n to?: JsonValue;\n};\n","import type { SchemaDefinition } from '../types/definitions.js';\n\n/**\n * Canonical JSON: object keys sorted by code point at every level, arrays in their given order (field\n * order is meaningful: it is the form order), two-space indentation and a trailing newline. Two equal\n * definitions always serialize to the same bytes, so files diff cleanly in git and hashes are stable.\n */\nconst sortKeys = (value: unknown): unknown => {\n if (Array.isArray(value)) {\n return value.map(sortKeys);\n }\n if (typeof value === 'object' && value !== null) {\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(value).sort()) {\n const entry = (value as Record<string, unknown>)[key];\n if (entry !== undefined) {\n sorted[key] = sortKeys(entry);\n }\n }\n return sorted;\n }\n return value;\n};\n\nexport const canonicalJson = (value: unknown): string => `${JSON.stringify(sortKeys(value), null, 2)}\\n`;\n\n/**\n * The bytes Shapio hashes and writes for a definition. The definition must be normalized\n * (`normalizeDefinition`), so defaults are explicit and the same meaning has one spelling.\n */\nexport const serializeDefinition = (definition: SchemaDefinition): string => canonicalJson(definition);\n","import { canonicalJson } from '../fileFormat/canonical.js';\nimport type { FieldDefinition, SchemaDefinition } from '../types/definitions.js';\nimport type { JsonValue } from '../types/json.js';\nimport { routeKeyOf } from '../validators/naming.js';\nimport type { SchemaChange } from './types.js';\n\nconst same = (a: unknown, b: unknown): boolean => canonicalJson(a ?? null) === canonicalJson(b ?? null);\nconst asJson = (value: unknown): JsonValue | undefined => value as JsonValue | undefined;\n\nconst DEFINITION_METADATA = ['label', 'description', 'category', 'icon', 'display'] as const;\nconst FIELD_METADATA = ['label', 'description', 'defaultValue'] as const;\nconst FIELD_FLAGS = [\n ['required', 'field.required'],\n ['localized', 'field.localized'],\n ['public', 'field.public'],\n ['deprecated', 'field.deprecated'],\n ['unique', 'field.unique'],\n ['filterable', 'field.filterable'],\n ['sortable', 'field.sortable'],\n] as const;\n\nconst diffFieldSettings = (\n definitionId: string,\n before: FieldDefinition,\n after: FieldDefinition,\n): SchemaChange[] => {\n const from = before.settings as Record<string, unknown>;\n const to = after.settings as Record<string, unknown>;\n const keys = [...new Set([...Object.keys(from), ...Object.keys(to)])].sort();\n return keys\n .filter((key) => !same(from[key], to[key]))\n .map((key) => ({\n kind: 'field.settings',\n definitionId,\n fieldId: after.id,\n property: key,\n from: asJson(from[key]),\n to: asJson(to[key]),\n }));\n};\n\nconst diffField = (definitionId: string, before: FieldDefinition, after: FieldDefinition): SchemaChange[] => {\n const changes: SchemaChange[] = [];\n const base = { definitionId, fieldId: after.id };\n if (before.apiKey !== after.apiKey) {\n changes.push({ ...base, kind: 'field.apiKey', from: before.apiKey, to: after.apiKey });\n }\n for (const property of FIELD_METADATA) {\n if (!same(before[property], after[property])) {\n changes.push({\n ...base,\n kind: 'field.metadata',\n property,\n from: asJson(before[property]),\n to: asJson(after[property]),\n });\n }\n }\n if (!same(before.editor, after.editor)) {\n changes.push({ ...base, kind: 'field.editor', from: before.editor, to: after.editor });\n }\n if (before.type !== after.type) {\n // Settings are type-specific; a type change is planned as one conversion including its new settings.\n changes.push({ ...base, kind: 'field.type', from: before.type, to: after.type });\n } else {\n changes.push(...diffFieldSettings(definitionId, before, after));\n }\n for (const [flag, kind] of FIELD_FLAGS) {\n if (before[flag] !== after[flag]) {\n changes.push({ ...base, kind, from: before[flag], to: after[flag] });\n }\n }\n return changes;\n};\n\n/**\n * Every difference between two versions of a definition, matched by stable IDs (so a renamed field is a\n * rename, not a removal plus an addition). Pass `null` for a side that does not exist. The order is\n * deterministic: definition-level changes, then fields in the new order, then removed fields.\n */\nexport const diffDefinitions = (\n before: SchemaDefinition | null,\n after: SchemaDefinition | null,\n): SchemaChange[] => {\n if (!before && !after) {\n return [];\n }\n if (!before) {\n return [\n {\n kind: 'definition.added',\n definitionId: (after as SchemaDefinition).id,\n to: (after as SchemaDefinition).apiKey,\n },\n ];\n }\n if (!after) {\n return [{ kind: 'definition.removed', definitionId: before.id, from: before.apiKey }];\n }\n const definitionId = after.id;\n const changes: SchemaChange[] = [];\n if (before.apiKey !== after.apiKey) {\n changes.push({ kind: 'definition.apiKey', definitionId, from: before.apiKey, to: after.apiKey });\n }\n const beforeRecord = before as unknown as Record<string, unknown>;\n const afterRecord = after as unknown as Record<string, unknown>;\n for (const property of DEFINITION_METADATA) {\n if (!same(beforeRecord[property], afterRecord[property])) {\n changes.push({\n kind: 'definition.metadata',\n definitionId,\n property,\n from: asJson(beforeRecord[property]),\n to: asJson(afterRecord[property]),\n });\n }\n }\n if (before.kind !== after.kind) {\n changes.push({ kind: 'model.kind', definitionId, from: before.kind, to: after.kind });\n }\n // Only between two collections: a kind switch is its own (breaking) change and adds or drops the plural.\n if (before.kind === 'collection' && after.kind === 'collection') {\n const [from, to] = [routeKeyOf(before), routeKeyOf(after)];\n if (from !== to) {\n changes.push({ kind: 'definition.pluralApiKey', definitionId, from, to });\n }\n }\n if (before.kind !== 'component' && after.kind !== 'component') {\n if (before.localized !== after.localized) {\n changes.push({ kind: 'model.localized', definitionId, from: before.localized, to: after.localized });\n }\n if (before.draftAndPublish !== after.draftAndPublish) {\n changes.push({\n kind: 'model.draftAndPublish',\n definitionId,\n from: before.draftAndPublish,\n to: after.draftAndPublish,\n });\n }\n }\n\n const beforeFields = new Map(before.fields.map((field) => [field.id, field]));\n const afterIds = new Set(after.fields.map((field) => field.id));\n for (const field of after.fields) {\n const previous = beforeFields.get(field.id);\n if (!previous) {\n changes.push({\n kind: 'field.added',\n definitionId,\n fieldId: field.id,\n to: field as unknown as JsonValue,\n });\n } else {\n changes.push(...diffField(definitionId, previous, field));\n }\n }\n for (const field of before.fields) {\n if (!afterIds.has(field.id)) {\n changes.push({\n kind: 'field.removed',\n definitionId,\n fieldId: field.id,\n from: field as unknown as JsonValue,\n });\n }\n }\n const keptBefore = before.fields.filter((field) => afterIds.has(field.id)).map((field) => field.id);\n const keptAfter = after.fields.filter((field) => beforeFields.has(field.id)).map((field) => field.id);\n if (!same(keptBefore, keptAfter)) {\n changes.push({ kind: 'field.order', definitionId, from: keptBefore, to: keptAfter });\n }\n return changes;\n};\n","import { STORAGE_FAMILY, type DataType } from '../types/dataTypes.js';\nimport type { FieldDefinition, SchemaDefinition } from '../types/definitions.js';\nimport type { SchemaChange } from './types.js';\n\n/**\n * Change classification (brief §5, ADR 0002). Each change gets a category, whether it needs prerequisite\n * work before the new revision can be activated, and flags for breaking API contracts and destroying data.\n *\n * | Brief §5 row | category | activation |\n * | ------------------------------------ | -------------------------------- | ----------------------------- |\n * | Label, help text, editor layout | metadata | immediate |\n * | Compatible editor swap | editorSwap | immediate |\n * | Optional field or new model | additive | immediate (live) |\n * | Required field | requiredField | validateRequired / backfill |\n * | Type or rich-text format conversion | conversion | convert (+ validate) |\n * | API key rename | contract (breaking) | immediate, needs ack |\n * | Field removal | removal (breaking, data kept) | immediate, needs ack |\n * | Unique/index constraint | constraint / index | checkUnique / buildIndex |\n * | (plus) type change of a unique field | as its type change | + checkUnique |\n * | (plus) tightened validation rules | validation | validateValues |\n * | (plus) localized true→false | conversion (destructive) | convert |\n */\nexport type ChangeCategory =\n | 'metadata'\n | 'editorSwap'\n | 'additive'\n | 'requiredField'\n | 'validation'\n | 'conversion'\n | 'contract'\n | 'removal'\n | 'constraint'\n | 'index';\n\n/** Work that must succeed before activation. Content-touching kinds run through the content ports. */\nexport type PrerequisiteKind =\n 'validateRequired' | 'backfill' | 'validateValues' | 'checkUnique' | 'buildIndex' | 'convert';\n\n/** Work done after activation, once nothing reads the old structure. */\nexport type CleanupKind = 'dropIndex' | 'releaseUnique';\n\nexport type ClassifiedChange = SchemaChange & {\n category: ChangeCategory;\n /** Changes the public API contract (REST/GraphQL shape or visibility); needs explicit acknowledgement. */\n breaking: boolean;\n /** Loses stored information that a schema rollback cannot restore. */\n destructive: boolean;\n /** False for conversions Shapio cannot perform; the planner refuses them. */\n supported: boolean;\n prerequisites: PrerequisiteKind[];\n cleanup: CleanupKind[];\n};\n\nexport type ClassifyContext = { before: SchemaDefinition | null; after: SchemaDefinition | null };\n\ntype Classification = Omit<ClassifiedChange, keyof SchemaChange>;\n\nconst result = (category: ChangeCategory, extra: Partial<Classification> = {}): Classification => ({\n category,\n breaking: false,\n destructive: false,\n supported: true,\n prerequisites: [],\n cleanup: [],\n ...extra,\n});\n\nconst findField = (\n definition: SchemaDefinition | null,\n fieldId: string | undefined,\n): FieldDefinition | undefined => definition?.fields.find((field) => field.id === fieldId);\n\nconst hasIndex = (field: FieldDefinition | undefined): boolean =>\n Boolean(field && (field.filterable || field.sortable));\n\n/** Names delivery APIs use for a type; a change of name is a contract change. */\nconst API_SCALAR: Readonly<Record<DataType, string>> = {\n string: 'String',\n text: 'String',\n slug: 'String',\n email: 'String',\n url: 'String',\n uid: 'String',\n enum: 'Enum',\n date: 'Date',\n datetime: 'DateTime',\n time: 'Time',\n number: 'Float',\n integer: 'Int',\n decimal: 'Decimal',\n biginteger: 'BigInt',\n boolean: 'Boolean',\n json: 'JSON',\n richtext: 'RichText',\n media: 'Media',\n relation: 'Relation',\n component: 'Component',\n dynamiczone: 'DynamicZone',\n};\n\nconst PLAIN_TEXT_TYPES: ReadonlySet<DataType> = new Set(['string', 'text']);\nconst SCALAR_FAMILIES = new Set(['jsonString', 'jsonNumber', 'numericString', 'boolean']);\n\nconst hasTextConstraints = (field: FieldDefinition | undefined) => {\n const settings = (field?.settings ?? {}) as Record<string, unknown>;\n return (\n settings.minLength !== undefined || settings.maxLength !== undefined || settings.pattern !== undefined\n );\n};\n\n/**\n * A type change. Within one storage family the stored JSON stays as it is: widening is live, anything else\n * re-validates existing values. Across families Shapio converts values with a job, for the pairs it knows.\n */\nconst classifyTypeChange = (\n from: DataType,\n to: DataType,\n after: FieldDefinition | undefined,\n): Classification => {\n const breaking = API_SCALAR[from] !== API_SCALAR[to];\n const fromFamily = STORAGE_FAMILY[from];\n const toFamily = STORAGE_FAMILY[to];\n if (fromFamily === toFamily) {\n const widening =\n (fromFamily === 'jsonString' && PLAIN_TEXT_TYPES.has(to) && !hasTextConstraints(after)) ||\n (from === 'integer' && to === 'number') ||\n (from === 'biginteger' &&\n to === 'decimal' &&\n after?.type === 'decimal' &&\n after.settings.precision === undefined);\n return widening\n ? result('additive', { breaking })\n : result('validation', { breaking, prerequisites: ['validateValues'] });\n }\n const numericPair =\n (fromFamily === 'jsonNumber' && toFamily === 'numericString') ||\n (fromFamily === 'numericString' && toFamily === 'jsonNumber');\n const toText = SCALAR_FAMILIES.has(fromFamily) && PLAIN_TEXT_TYPES.has(to);\n const textToRichtext = fromFamily === 'jsonString' && to === 'richtext';\n const richtextToText = from === 'richtext' && PLAIN_TEXT_TYPES.has(to);\n const supported = numericPair || toText || textToRichtext || richtextToText;\n return result('conversion', {\n breaking,\n supported,\n destructive: richtextToText,\n prerequisites: supported ? ['convert', 'validateValues'] : [],\n });\n};\n\ntype Comparable = number | string;\nconst compareValues = (a: Comparable, b: Comparable): number => {\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b;\n }\n try {\n const diff = BigInt(String(a)) - BigInt(String(b));\n return diff === 0n ? 0 : diff > 0n ? 1 : -1;\n } catch {\n const numeric = Number(a) - Number(b);\n return Number.isNaN(numeric) ? String(a).localeCompare(String(b)) : numeric;\n }\n};\n\n/** A lower bound (min, minLength) that appears or rises, or an upper bound that appears or falls. */\nconst isTightened = (bound: 'lower' | 'upper', from: unknown, to: unknown): boolean => {\n if (to === undefined || to === null) {\n return false;\n }\n if (from === undefined || from === null) {\n return true;\n }\n const order = compareValues(from as Comparable, to as Comparable);\n return bound === 'lower' ? order < 0 : order > 0;\n};\n\nconst asStrings = (value: unknown): string[] =>\n Array.isArray(value)\n ? value.map((entry) =>\n typeof entry === 'object' && entry !== null\n ? String((entry as { value?: unknown }).value)\n : String(entry),\n )\n : [];\n\nconst removesAny = (from: unknown, to: unknown): boolean => {\n const kept = new Set(asStrings(to));\n return asStrings(from).some((entry) => !kept.has(entry));\n};\n\nconst validation = (tightened: boolean) =>\n tightened ? result('validation', { prerequisites: ['validateValues'] }) : result('additive');\n\nconst classifySettingsChange = (change: SchemaChange): Classification => {\n const { property, from, to } = change;\n switch (property) {\n case 'minLength':\n case 'min':\n return validation(isTightened('lower', from, to));\n case 'maxLength':\n case 'max':\n case 'precision':\n case 'scale':\n return validation(isTightened('upper', from, to));\n case 'pattern':\n return validation(to !== undefined);\n case 'values':\n // Removing an enum value invalidates entries using it; adding values or relabelling does not.\n return validation(removesAny(from, to));\n case 'components':\n case 'allowedKinds':\n case 'protocols':\n // Narrowing the allowed set re-validates; an absent allowedKinds/protocols list means \"any\".\n return validation(to !== undefined && (from === undefined || removesAny(from, to)));\n case 'sourceFieldId':\n return result('metadata');\n case 'multiple':\n case 'repeatable':\n case 'cardinality': {\n const becomesSingle = to === false || to === 'one';\n return result('conversion', {\n breaking: true,\n destructive: becomesSingle,\n prerequisites: ['convert', 'validateValues'],\n });\n }\n case 'formatVersion':\n return result('conversion', { prerequisites: ['convert', 'validateValues'] });\n case 'target':\n case 'component':\n // Existing values point at entries of the old target; they are cleared by the conversion.\n return result('conversion', { breaking: true, destructive: true, prerequisites: ['convert'] });\n default:\n // An unknown setting: be safe and re-validate existing values.\n return result('validation', { prerequisites: ['validateValues'] });\n }\n};\n\nconst classifyFieldChange = (change: SchemaChange, { before, after }: ClassifyContext): Classification => {\n const previous = findField(before, change.fieldId);\n const field = findField(after, change.fieldId);\n switch (change.kind) {\n case 'field.added': {\n const prerequisites: Classification['prerequisites'] = [];\n if (field?.required) {\n prerequisites.push(field.defaultValue !== undefined ? 'backfill' : 'validateRequired');\n }\n if (field?.unique) {\n prerequisites.push('checkUnique');\n }\n if (hasIndex(field)) {\n prerequisites.push('buildIndex');\n }\n return result(field?.required ? 'requiredField' : 'additive', { prerequisites });\n }\n case 'field.removed':\n // Values stay in stored revisions; removing them is a separate, explicit cleanup.\n return result('removal', {\n breaking: true,\n cleanup: [\n ...(hasIndex(previous) ? (['dropIndex'] as const) : []),\n ...(previous?.unique ? (['releaseUnique'] as const) : []),\n ],\n });\n case 'field.order':\n case 'field.metadata':\n return result('metadata');\n case 'field.editor':\n return result('editorSwap');\n case 'field.apiKey':\n return result('contract', { breaking: true });\n case 'field.type': {\n const classification = classifyTypeChange(change.from as DataType, change.to as DataType, field);\n // A unique field's values may normalize differently under the new type (e.g. string → email ignores\n // case): check them for duplicates before activation.\n return field?.unique && previous?.unique && !classification.prerequisites.includes('checkUnique')\n ? { ...classification, prerequisites: [...classification.prerequisites, 'checkUnique'] }\n : classification;\n }\n case 'field.required':\n if (change.to !== true) {\n return result('additive');\n }\n return result('requiredField', {\n prerequisites: [field?.defaultValue !== undefined ? 'backfill' : 'validateRequired'],\n });\n case 'field.localized': {\n const modelLocalized = after?.kind !== 'component' && after?.localized === true;\n if (!modelLocalized) {\n return result('metadata');\n }\n // false→true: every locale's head already holds the shared value (ADR 0004), so nothing to copy.\n return change.to === true\n ? result('additive')\n : result('conversion', { destructive: true, prerequisites: ['convert'] });\n }\n case 'field.public':\n case 'field.deprecated': {\n const hides = change.kind === 'field.public' ? change.to === false : change.to === true;\n return result('metadata', { breaking: hides });\n }\n case 'field.unique':\n return change.to === true\n ? result('constraint', { prerequisites: ['checkUnique'] })\n : result('additive', { cleanup: ['releaseUnique'] });\n case 'field.filterable':\n case 'field.sortable': {\n // Filtering and sorting share one expression index per field.\n if (hasIndex(field) && !hasIndex(previous)) {\n return result('index', { prerequisites: ['buildIndex'] });\n }\n if (!hasIndex(field) && hasIndex(previous)) {\n return result('index', { cleanup: ['dropIndex'] });\n }\n return result('metadata');\n }\n case 'field.settings':\n return classifySettingsChange(change);\n default:\n return result('metadata');\n }\n};\n\n/** Classifies one change in the context of the definitions it was diffed from. */\nexport const classifyChange = (change: SchemaChange, context: ClassifyContext): ClassifiedChange => {\n let classification: Classification;\n switch (change.kind) {\n case 'definition.added':\n classification = result('additive');\n break;\n case 'definition.removed':\n // Soft delete: entries are kept and reappear if the definition is restored.\n classification = result('removal', { breaking: true });\n break;\n case 'definition.apiKey':\n case 'definition.pluralApiKey':\n classification = result('contract', { breaking: true });\n break;\n case 'definition.metadata':\n classification = result('metadata');\n break;\n case 'model.kind':\n classification =\n change.to === 'singleton'\n ? result('validation', { breaking: true, prerequisites: ['validateValues'] })\n : result('contract', { breaking: true });\n break;\n case 'model.localized':\n classification =\n change.to === true\n ? result('additive')\n : result('conversion', { destructive: true, prerequisites: ['convert'] });\n break;\n case 'model.draftAndPublish':\n classification =\n change.to === true\n ? result('additive')\n : result('conversion', { destructive: true, prerequisites: ['convert'] });\n break;\n default:\n classification = classifyFieldChange(change, context);\n }\n return { ...change, ...classification };\n};\n\nexport const classifyChanges = (\n changes: readonly SchemaChange[],\n context: ClassifyContext,\n): ClassifiedChange[] => changes.map((change) => classifyChange(change, context));\n\nexport type ChangeSummary = {\n breaking: boolean;\n destructive: boolean;\n supported: boolean;\n prerequisites: PrerequisiteKind[];\n cleanup: CleanupKind[];\n /** True when nothing but metadata/editor changes are involved. */\n metadataOnly: boolean;\n};\n\nconst PREREQUISITE_ORDER: readonly PrerequisiteKind[] = [\n 'convert',\n 'backfill',\n 'validateRequired',\n 'validateValues',\n 'checkUnique',\n 'buildIndex',\n];\n\nexport const summarizeChanges = (changes: readonly ClassifiedChange[]): ChangeSummary => {\n const prerequisites = new Set(changes.flatMap((change) => change.prerequisites));\n return {\n breaking: changes.some((change) => change.breaking),\n destructive: changes.some((change) => change.destructive),\n supported: changes.every((change) => change.supported),\n prerequisites: PREREQUISITE_ORDER.filter((kind) => prerequisites.has(kind)),\n cleanup: [...new Set(changes.flatMap((change) => change.cleanup))],\n metadataOnly: changes.every(\n (change) => change.category === 'metadata' || change.category === 'editorSwap',\n ),\n };\n};\n\n/** Locale configuration changes (ADR 0002/0004). Locales are global, so they are planned on their own. */\nexport type LocaleChangeKind =\n 'locale.added' | 'locale.removed' | 'locale.defaultChanged' | 'locale.metadata';\n\nexport type ClassifiedLocaleChange = {\n kind: LocaleChangeKind;\n code: string;\n category: ChangeCategory;\n breaking: boolean;\n destructive: boolean;\n};\n\n/**\n * - added: live (entries gain the locale as editors fill it in);\n * - removed: destroys that locale's content (purged by a follow-up job), so it needs explicit consent;\n * - default changed: delivery falls back to a different locale, a contract change for API consumers;\n * - label or fallback chain: metadata.\n */\nexport const classifyLocaleChange = (kind: LocaleChangeKind, code: string): ClassifiedLocaleChange => {\n switch (kind) {\n case 'locale.added':\n return { kind, code, category: 'additive', breaking: false, destructive: false };\n case 'locale.removed':\n return { kind, code, category: 'removal', breaking: true, destructive: true };\n case 'locale.defaultChanged':\n return { kind, code, category: 'contract', breaking: true, destructive: false };\n default:\n return { kind, code, category: 'metadata', breaking: false, destructive: false };\n }\n};\n","import type { SchemaDefinition } from '../types/definitions.js';\nimport { serializeDefinition } from './canonical.js';\n\nconst toHex = (buffer: ArrayBuffer) =>\n Array.from(new Uint8Array(buffer), (byte) => byte.toString(16).padStart(2, '0')).join('');\n\n/** `sha256:<hex>` of a UTF-8 string, via Web Crypto (Node and browsers alike). */\nexport const sha256 = async (text: string): Promise<string> =>\n `sha256:${toHex(await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(text)))}`;\n\n/** Hash of a normalized definition's canonical serialization; recorded per model in the lock file. */\nexport const hashDefinition = (definition: SchemaDefinition): Promise<string> =>\n sha256(serializeDefinition(definition));\n","import type { SchemaDefinition } from '../types/definitions.js';\n\n/**\n * Where schema files live in a repository (plan site-schema): shared definitions in `models/` and\n * `components/`, a site's own in `sites/<siteKey>/models/` and `sites/<siteKey>/components/`. Paths are\n * relative to the schema directory and always use `/` (git paths); callers join them for their file system.\n */\nexport const SCHEMA_KIND_DIRECTORIES = ['models', 'components'] as const;\nexport type SchemaKindDirectory = (typeof SCHEMA_KIND_DIRECTORIES)[number];\n\n/** The folder that holds one directory per site key. */\nexport const SITES_DIRECTORY = 'sites';\n\nconst kindDirectoryOf = (definition: Pick<SchemaDefinition, 'kind'>): SchemaKindDirectory =>\n definition.kind === 'component' ? 'components' : 'models';\n\n/** The directory of a scope's files: `''` (shared) or `sites/<siteKey>`. */\nexport const scopeDirectory = (siteKey: string | null): string =>\n siteKey === null ? '' : `${SITES_DIRECTORY}/${siteKey}`;\n\n/** A definition's file path: `models/post.json`, or `sites/blog/models/post.json` for site `blog`. */\nexport const schemaFilePath = (\n definition: Pick<SchemaDefinition, 'kind' | 'apiKey'>,\n siteKey: string | null,\n): string => {\n const file = `${kindDirectoryOf(definition)}/${definition.apiKey}.json`;\n return siteKey === null ? file : `${scopeDirectory(siteKey)}/${file}`;\n};\n\n/**\n * The scope a schema file path is in: `{ site: null }` for `models/x.json` or `components/x.json`,\n * `{ site: key }` under `sites/<key>/`, undefined for anything else (not a schema file).\n */\nexport const scopeOfSchemaFilePath = (path: string): { site: string | null } | undefined => {\n const parts = path.split('/').filter((part) => part.length > 0);\n const isFile = (kind: string | undefined, name: string | undefined) =>\n (SCHEMA_KIND_DIRECTORIES as readonly string[]).includes(kind ?? '') && (name ?? '').endsWith('.json');\n if (parts.length === 2 && isFile(parts[0], parts[1])) {\n return { site: null };\n }\n if (parts.length === 4 && parts[0] === SITES_DIRECTORY && parts[1] && isFile(parts[2], parts[3])) {\n return { site: parts[1] };\n }\n return undefined;\n};\n","import { Type, type Static } from 'typebox';\nimport { DEFINITION_KINDS, type SchemaDefinition } from '../types/definitions.js';\nimport { collectSchemaErrors } from '../validators/typeboxIssues.js';\nimport { canonicalJson } from './canonical.js';\n\n/** Where `shapio schema pull` keeps its record of what it pulled, relative to the project root. */\nexport const LOCK_FILE_PATH = '.shapio/schema-lock.json';\n/**\n * Format 2 (per-site schemas): each entry records its scope (`site`: a site key, or null when shared) and\n * the lock lists the sites the tree covers. Format 1 (every definition shared) still reads: its entries\n * have no `site`, which means shared, and it covers no site. `upgradeLockFile` spells both the same way.\n */\nexport const LOCK_FILE_FORMAT_VERSION = 2;\n\nexport const LockEntrySchema = Type.Object(\n {\n kind: Type.Enum(DEFINITION_KINDS),\n apiKey: Type.String(),\n /** The definition's per-model version on the instance when it was pulled. */\n version: Type.Integer({ minimum: 1 }),\n /** `hashDefinition` of the pulled definition; a local file with another hash has been edited. */\n hash: Type.String(),\n /**\n * The key of the site the definition belongs to; null (or absent, format 1) when shared. Null comes first:\n * Fastify's Ajv coerces types, and a string branch tried first would turn null into \"\" (no site at all).\n */\n site: Type.Optional(Type.Union([Type.Null(), Type.String()])),\n },\n { additionalProperties: false },\n);\n\nexport const LockFileSchema = Type.Object(\n {\n formatVersion: Type.Union([Type.Literal(1), Type.Literal(LOCK_FILE_FORMAT_VERSION)]),\n /** The instance's global schema version at pull time (informational; the guard is per model). */\n schemaVersion: Type.Integer({ minimum: 0 }),\n /** Keys of the sites whose definitions this tree holds (format 2; absent: none, shared only). */\n sites: Type.Optional(Type.Array(Type.String())),\n /** Keyed by definition ID. */\n definitions: Type.Record(Type.String(), LockEntrySchema),\n },\n { additionalProperties: false },\n);\n\nexport type LockEntry = Static<typeof LockEntrySchema>;\nexport type LockFile = Static<typeof LockFileSchema>;\n\n/** A lock in format 2 with every scope spelled out. */\nexport type ScopedLockEntry = LockEntry & { site: string | null };\nexport type ScopedLockFile = Omit<LockFile, 'formatVersion' | 'sites' | 'definitions'> & {\n formatVersion: typeof LOCK_FILE_FORMAT_VERSION;\n sites: string[];\n definitions: Record<string, ScopedLockEntry>;\n};\n\n/** Format 1 or 2 → format 2: absent scopes are shared, absent sites none. */\nexport const upgradeLockFile = (lock: LockFile): ScopedLockFile => ({\n formatVersion: LOCK_FILE_FORMAT_VERSION,\n schemaVersion: lock.schemaVersion,\n sites: [...(lock.sites ?? [])],\n definitions: Object.fromEntries(\n Object.entries(lock.definitions).map(([id, entry]) => [id, { ...entry, site: entry.site ?? null }]),\n ),\n});\n\n/** The lock entries one site's tree is about: the shared definitions and that site's (`siteKey`). */\nexport const lockEntriesForSite = (lock: LockFile, siteKey: string | null): LockFile['definitions'] =>\n Object.fromEntries(\n Object.entries(lock.definitions).filter(\n ([, entry]) => (entry.site ?? null) === null || entry.site === siteKey,\n ),\n );\n\n/** A tree applies to a site when it covers no site yet (shared only, or format 1) or lists that site. */\nexport const lockCoversSite = (lock: LockFile, siteKey: string): boolean => {\n const sites = lock.sites ?? [];\n return sites.length === 0 || sites.includes(siteKey);\n};\n\n/** `sites` plus `siteKey`, sorted and without duplicates (stable diffs in git). */\nexport const withSiteCovered = (sites: readonly string[], siteKey: string): string[] =>\n [...new Set([...sites, siteKey])].sort();\n\n/**\n * The lock after pulling one site's view (`shapio schema pull --site <siteKey>`): the shared entries and that\n * site's are replaced by what was pulled, another site's entries are kept as they are (one tree can hold\n * several sites), and the tree now covers `siteKey`. A format 1 lock upgrades first (every entry shared).\n */\nexport const mergePulledLock = (\n lock: LockFile | undefined,\n pulled: { schemaVersion: number; siteKey: string; definitions: readonly ExportedDefinition[] },\n): ScopedLockFile => {\n const current = lock ? upgradeLockFile(lock) : undefined;\n const pulledIds = new Set(pulled.definitions.map(({ definition }) => definition.id));\n const kept = Object.entries(current?.definitions ?? {}).filter(\n ([id, entry]) => entry.site !== null && entry.site !== pulled.siteKey && !pulledIds.has(id),\n );\n return {\n formatVersion: LOCK_FILE_FORMAT_VERSION,\n schemaVersion: pulled.schemaVersion,\n sites: withSiteCovered(current?.sites ?? [], pulled.siteKey),\n definitions: Object.fromEntries([\n ...kept,\n ...pulled.definitions.map(({ definition, version, hash, site }): [string, ScopedLockEntry] => [\n definition.id,\n { kind: definition.kind, apiKey: definition.apiKey, version, hash, site },\n ]),\n ]),\n };\n};\n\n/** One definition as `schema export` returns it, with its scope (a site key, or null when shared). */\nexport type ExportedDefinition = {\n definition: SchemaDefinition;\n version: number;\n hash: string;\n site: string | null;\n};\n\nexport class LockFileError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LockFileError';\n }\n}\n\nexport const parseLockFile = (text: string): LockFile => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n throw new LockFileError(`${LOCK_FILE_PATH} is not valid JSON`);\n }\n const errors = collectSchemaErrors(LockFileSchema, parsed);\n if (errors.length > 0) {\n throw new LockFileError(\n `${LOCK_FILE_PATH} is invalid: ${errors.map((error) => `${error.path || '/'} ${error.message}`).join('; ')}`,\n );\n }\n return parsed as LockFile;\n};\n\nexport const serializeLockFile = (lock: LockFile): string => canonicalJson(lock);\n","import type { SchemaDefinition } from '../types/definitions.js';\n\n/**\n * Per-definition three-way decision for `shapio schema apply` (ADR 0002). The base is what the lock file\n * recorded at pull time; local is the file in the repository; remote is the target instance now.\n *\n * - unchanged locally → skip, even if the target changed it since (no silent revert of production edits);\n * - changed locally and unchanged on the target → apply, guarded by the target's current version;\n * - changed on both → refuse and show the diff, like a rejected non-fast-forward push.\n *\n * Deletions need `prune`. Identical content on both sides is never a conflict.\n */\nexport type SyncSide = { version: number; hash: string };\nexport type SyncLocal = { definition: SchemaDefinition; hash: string };\nexport type SyncRemote = SyncSide & { definition: SchemaDefinition };\n\nexport type SyncInput = {\n local?: SyncLocal;\n base?: SyncSide;\n remote?: SyncRemote;\n prune: boolean;\n};\n\nexport type SyncSkipReason =\n 'unchangedLocally' | 'alreadyApplied' | 'remoteOnly' | 'deletedLocallyWithoutPrune' | 'alreadyDeleted';\n\nexport type SyncConflictReason =\n 'changedOnBoth' | 'deletedOnTarget' | 'existsOnTarget' | 'changedOnTargetBeforeDelete';\n\nexport type SyncDecision =\n | { action: 'skip'; reason: SyncSkipReason }\n | { action: 'create' }\n | { action: 'update'; expectedVersion: number }\n | { action: 'delete'; expectedVersion: number }\n | { action: 'conflict'; reason: SyncConflictReason };\n\nconst unchangedSinceBase = (remote: SyncSide, base: SyncSide) =>\n remote.version === base.version || remote.hash === base.hash;\n\nconst decideForLocal = (\n local: SyncLocal,\n base: SyncSide | undefined,\n remote: SyncRemote | undefined,\n): SyncDecision => {\n if (base && local.hash === base.hash) {\n return { action: 'skip', reason: 'unchangedLocally' };\n }\n if (!remote) {\n return base ? { action: 'conflict', reason: 'deletedOnTarget' } : { action: 'create' };\n }\n if (remote.hash === local.hash) {\n return { action: 'skip', reason: 'alreadyApplied' };\n }\n if (!base) {\n return { action: 'conflict', reason: 'existsOnTarget' };\n }\n return unchangedSinceBase(remote, base)\n ? { action: 'update', expectedVersion: remote.version }\n : { action: 'conflict', reason: 'changedOnBoth' };\n};\n\nexport const decideSync = ({ local, base, remote, prune }: SyncInput): SyncDecision => {\n if (local) {\n return decideForLocal(local, base, remote);\n }\n if (!base) {\n return { action: 'skip', reason: 'remoteOnly' };\n }\n if (!remote) {\n return { action: 'skip', reason: 'alreadyDeleted' };\n }\n if (!prune) {\n return { action: 'skip', reason: 'deletedLocallyWithoutPrune' };\n }\n return unchangedSinceBase(remote, base)\n ? { action: 'delete', expectedVersion: remote.version }\n : { action: 'conflict', reason: 'changedOnTargetBeforeDelete' };\n};\n","import { RICHTEXT_FORMAT, RICHTEXT_FORMAT_VERSION } from '../types/valueFormats.js';\nimport { SAFE_LINK_PATTERN } from './spec.js';\nimport type { RichTextDocument, RichTextNode } from './validate.js';\n\n/**\n * HTML rendering of stored rich text for delivery (ADR 0003). Rendered from JSON only, never from stored\n * HTML: every tag comes from this allow-list and every text and attribute value is escaped, so the output\n * is safe whatever the document held. Deterministic, so a site built at a pinned snapshot gets the same HTML.\n */\n\n/** Resolves an image's media ID to a deliverable URL; undefined when the asset is missing or not visible. */\nexport type MediaUrlResolver = (mediaId: string) => string | undefined;\n\nconst ESCAPES: Readonly<Record<string, string>> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n};\n\nexport const escapeHtml = (value: string): string =>\n value.replace(/[&<>\"']/g, (char) => ESCAPES[char] ?? char);\n\n/** Attribute values come from validated documents: strings and numbers only. */\nconst textOf = (value: unknown): string =>\n typeof value === 'string' || typeof value === 'number' ? String(value) : '';\n\nconst attribute = (name: string, value: unknown) =>\n value === null || value === undefined ? '' : ` ${name}=\"${escapeHtml(textOf(value))}\"`;\n\nconst BLOCK_TAGS: Readonly<Record<string, string>> = {\n paragraph: 'p',\n blockquote: 'blockquote',\n bulletList: 'ul',\n listItem: 'li',\n table: 'table',\n tableRow: 'tr',\n tableHeader: 'th',\n tableCell: 'td',\n};\n\nconst renderMarks = (text: string, marks: RichTextNode['marks']): string =>\n (marks ?? []).reduceRight((inner, mark) => {\n switch (mark.type) {\n case 'bold':\n return `<strong>${inner}</strong>`;\n case 'italic':\n return `<em>${inner}</em>`;\n case 'code':\n return `<code>${inner}</code>`;\n case 'link': {\n const href = textOf(mark.attrs?.href).trim();\n if (!SAFE_LINK_PATTERN.test(href)) {\n return inner;\n }\n const blank = mark.attrs?.target === '_blank';\n return `<a${attribute('href', href)}${blank ? ' target=\"_blank\" rel=\"noopener noreferrer nofollow\"' : ''}>${inner}</a>`;\n }\n default:\n return inner;\n }\n }, escapeHtml(text));\n\nconst cellAttributes = (node: RichTextNode) => {\n const colspan = Number(node.attrs?.colspan ?? 1);\n const rowspan = Number(node.attrs?.rowspan ?? 1);\n return `${colspan > 1 ? attribute('colspan', colspan) : ''}${rowspan > 1 ? attribute('rowspan', rowspan) : ''}`;\n};\n\nconst renderNode = (node: RichTextNode, resolveMedia: MediaUrlResolver | undefined): string => {\n const children = () => (node.content ?? []).map((child) => renderNode(child, resolveMedia)).join('');\n switch (node.type) {\n case 'doc':\n return children();\n case 'text':\n return renderMarks(node.text ?? '', node.marks);\n case 'hardBreak':\n return '<br>';\n case 'horizontalRule':\n return '<hr>';\n case 'heading': {\n const level = Math.min(6, Math.max(1, Number(node.attrs?.level ?? 1)));\n return `<h${level}>${children()}</h${level}>`;\n }\n case 'orderedList': {\n const start = Number(node.attrs?.start ?? 1);\n return `<ol${start !== 1 ? attribute('start', start) : ''}${attribute('type', node.attrs?.type)}>${children()}</ol>`;\n }\n case 'codeBlock': {\n const language = node.attrs?.language;\n const text = (node.content ?? []).map((child) => escapeHtml(child.text ?? '')).join('');\n return `<pre><code${language ? attribute('class', `language-${textOf(language)}`) : ''}>${text}</code></pre>`;\n }\n case 'image': {\n const mediaId = textOf(node.attrs?.mediaId);\n const src = resolveMedia?.(mediaId);\n if (!src) {\n // Unknown or private-and-unsigned media renders nothing rather than a broken or leaking link.\n return '';\n }\n return `<img${attribute('src', src)}${attribute('alt', node.attrs?.alt ?? '')}${attribute('title', node.attrs?.title)}>`;\n }\n case 'table':\n return `<table><tbody>${children()}</tbody></table>`;\n case 'tableHeader':\n case 'tableCell': {\n const tag = BLOCK_TAGS[node.type] as string;\n return `<${tag}${cellAttributes(node)}>${children()}</${tag}>`;\n }\n default: {\n const tag = BLOCK_TAGS[node.type];\n return tag ? `<${tag}>${children()}</${tag}>` : '';\n }\n }\n};\n\n/** Renders a validated document to sanitized HTML. */\nexport const renderRichTextHtml = (document: RichTextDocument, resolveMedia?: MediaUrlResolver): string =>\n renderNode(document.doc, resolveMedia);\n\n/** The document's text, blocks separated by blank lines (rich text → plain text conversions, search). */\nexport const richTextToPlainText = (document: RichTextDocument): string => {\n const blocks: string[] = [];\n const inline = (node: RichTextNode): string =>\n node.type === 'text'\n ? (node.text ?? '')\n : node.type === 'hardBreak'\n ? '\\n'\n : (node.content ?? []).map(inline).join('');\n const walk = (node: RichTextNode) => {\n if (node.type === 'paragraph' || node.type === 'heading' || node.type === 'codeBlock') {\n blocks.push(inline(node));\n return;\n }\n (node.content ?? []).forEach(walk);\n };\n walk(document.doc);\n return blocks.join('\\n\\n');\n};\n\n/** Plain text → a document of paragraphs (blank lines split paragraphs; single newlines are hard breaks). */\nexport const plainTextToRichText = (text: string): RichTextDocument => {\n const paragraphs = text\n .replace(/\\r\\n?/g, '\\n')\n .split(/\\n{2,}/)\n .filter((paragraph) => paragraph.length > 0)\n .map((paragraph): RichTextNode => {\n const content = paragraph\n .split('\\n')\n .flatMap((line, index): RichTextNode[] => [\n ...(index > 0 ? [{ type: 'hardBreak' }] : []),\n ...(line.length > 0 ? [{ type: 'text', text: line }] : []),\n ]);\n return content.length > 0 ? { type: 'paragraph', content } : { type: 'paragraph' };\n });\n return {\n format: RICHTEXT_FORMAT,\n version: RICHTEXT_FORMAT_VERSION,\n doc: { type: 'doc', content: paragraphs.length > 0 ? paragraphs : [{ type: 'paragraph' }] },\n };\n};\n","/**\n * Admin themes (docs/plans/themes.md): a theme is a named, complete set of these tokens for a light variant, a\n * dark variant or both. One list, shared by the admin's stylesheets (and their tests) and the API, which\n * validates themes declared by extensions (`shapio.config` `themes`).\n */\n/** The UI tokens: every theme variant sets all of them. */\nexport const THEME_SEMANTIC_TOKENS = [\n 'background',\n 'foreground',\n 'card',\n 'card-foreground',\n 'popover',\n 'popover-foreground',\n 'primary',\n 'primary-foreground',\n 'primary-hover',\n 'secondary',\n 'secondary-foreground',\n 'muted',\n 'muted-foreground',\n 'accent',\n 'accent-foreground',\n 'destructive',\n 'destructive-foreground',\n 'destructive-muted',\n 'success',\n 'success-muted',\n 'warning',\n 'warning-muted',\n 'info',\n 'info-muted',\n 'border',\n 'input',\n 'ring',\n 'link',\n 'overlay',\n 'sidebar',\n 'sidebar-foreground',\n 'sidebar-primary',\n 'sidebar-primary-foreground',\n 'sidebar-accent',\n 'sidebar-accent-foreground',\n 'sidebar-border',\n 'sidebar-ring',\n] as const;\n\n/**\n * The logo (tile, S, letters) and the signed-out screens' brand panel. Built-in themes set them all; an\n * extension theme may leave them out and gets Shapio's for that variant.\n */\nexport const THEME_BRAND_TOKENS = [\n 'brand-logo',\n 'brand-logo-foreground',\n 'brand-letters',\n 'brand-panel-from',\n 'brand-panel-to',\n 'brand-panel-foreground',\n 'brand-panel-mark',\n] as const;\n\nexport const THEME_TOKENS = [...THEME_SEMANTIC_TOKENS, ...THEME_BRAND_TOKENS] as const;\n\nexport type ThemeToken = (typeof THEME_TOKENS)[number];\n\nexport const THEME_VARIANTS = ['light', 'dark'] as const;\n\nexport type ThemeVariant = (typeof THEME_VARIANTS)[number];\n\n/** A theme key: used in `data-theme` and in CSS selectors, so deliberately narrow. */\nexport const THEME_KEY_PATTERN = /^[a-z][a-z0-9-]{0,40}$/;\n\n/** The themes the admin ships; an extension theme may not reuse these keys. */\nexport const BUILT_IN_THEME_KEYS = ['shapio', 'classic', 'murdered-out', 'snowed'] as const;\n\nexport type BuiltInThemeKey = (typeof BUILT_IN_THEME_KEYS)[number];\n\n/**\n * A token value an extension may use: a hex colour or a colour function whose arguments are numbers, units\n * and separators only (no `;`, quotes, braces or nested functions such as `url()` or `var()`), so a value\n * can never escape its declaration.\n */\nexport const THEME_COLOUR_PATTERN =\n /^(?:#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|(?:rgba?|hsla?|oklch|oklab)\\([0-9a-z.,%\\s/+-]{1,80}\\))$/;\n","import type { ThemeVariant } from './tokens.js';\n\n/**\n * WCAG 2.1 AA contrast of a theme's tokens: text pairs need 4.5:1 (1.4.3); what identifies a control or the\n * focus (input borders, unchecked switches, focus rings, primary buttons against the page) needs 3:1 (1.4.11).\n * The admin's built-in themes are gated on this by a unit test; extension themes get warnings from\n * `shapio extensions check`. axe checks rendered text only, not these pairs.\n */\nexport type ContrastPair = readonly [foreground: string, background: string];\n\nconst SURFACES = ['background', 'card', 'popover'];\n\nexport const THEME_TEXT_PAIRS: readonly ContrastPair[] = [\n ...SURFACES.map((surface): ContrastPair => ['foreground', surface]),\n ...[...SURFACES, 'muted', 'secondary', 'accent', 'sidebar'].map((surface): ContrastPair => [\n 'muted-foreground',\n surface,\n ]),\n ['primary-foreground', 'primary'],\n ['primary-foreground', 'primary-hover'],\n ['secondary-foreground', 'secondary'],\n ['accent-foreground', 'accent'],\n ['destructive-foreground', 'destructive'],\n ['destructive', 'background'],\n ['destructive', 'card'],\n ['success', 'background'],\n ['success', 'card'],\n ['success', 'success-muted'],\n // Status chips (StatusChip): tone text on its own tinted background, and on plain surfaces.\n ['warning', 'warning-muted'],\n ['warning', 'card'],\n ['info', 'info-muted'],\n ['info', 'card'],\n ['destructive', 'destructive-muted'],\n ['foreground', 'muted'],\n ['link', 'background'],\n ['link', 'card'],\n ['sidebar-foreground', 'sidebar'],\n ['sidebar-primary-foreground', 'sidebar-primary'],\n ['sidebar-accent-foreground', 'sidebar-accent'],\n ['sidebar-foreground', 'sidebar-accent'],\n ['muted-foreground', 'sidebar-accent'],\n // Status and link text on raised and muted surfaces (popovers, sheets, muted bands).\n ...['destructive', 'success', 'warning', 'link'].flatMap((text): ContrastPair[] => [\n [text, 'popover'],\n [text, 'muted'],\n ]),\n // The signed-out screens' brand panel (tagline and pitch on both ends of the gradient).\n ['brand-panel-foreground', 'brand-panel-from'],\n ['brand-panel-foreground', 'brand-panel-to'],\n];\n\nexport const THEME_UI_PAIRS: readonly ContrastPair[] = [\n ...[...SURFACES, 'muted', 'secondary'].map((surface): ContrastPair => ['input', surface]),\n ...SURFACES.map((surface): ContrastPair => ['ring', surface]),\n ['ring', 'muted'],\n ['ring', 'accent'],\n ['primary', 'background'],\n ['primary', 'card'],\n ['primary', 'popover'],\n // Primary icons on neutral tiles (IconTile accent) and the info alert's icon.\n ['primary', 'muted'],\n ['info', 'muted'],\n ['sidebar-ring', 'sidebar'],\n // The active nav item's left bar.\n ['sidebar-primary', 'sidebar'],\n ['sidebar-primary', 'sidebar-accent'],\n];\n\n/**\n * Dark only: control borders on the selection surface. In light, selected table rows use accent/40, which\n * passes, and other selected surfaces hold no controls.\n */\nexport const THEME_DARK_UI_PAIRS: readonly ContrastPair[] = [['input', 'accent']];\n\nconst HEX = /^#[0-9a-fA-F]{6}$/;\n\nconst channel = (value: number) => {\n const c = value / 255;\n return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n};\n\nconst luminance = (hex: string) => {\n const [r, g, b] = [1, 3, 5].map((index) => channel(parseInt(hex.slice(index, index + 2), 16)));\n return 0.2126 * (r ?? 0) + 0.7152 * (g ?? 0) + 0.0722 * (b ?? 0);\n};\n\n/** The WCAG contrast ratio of two `#rrggbb` colours. */\nexport const contrastRatio = (a: string, b: string): number => {\n const [high = 0, low = 0] = [luminance(a), luminance(b)].sort((x, y) => y - x);\n return (high + 0.05) / (low + 0.05);\n};\n\nexport type ContrastCheck = {\n foreground: string;\n background: string;\n /** 4.5 for text, 3 for controls. */\n required: number;\n /** Undefined when a value is not a `#rrggbb` colour (functions such as `oklch()` are not checked). */\n ratio: number | undefined;\n};\n\n/** Every pair the variant must meet, with its ratio. Missing tokens report an undefined ratio. */\nexport const checkThemeContrast = (\n tokens: Readonly<Record<string, string>>,\n variant: ThemeVariant,\n): ContrastCheck[] => {\n const uiPairs = variant === 'dark' ? [...THEME_UI_PAIRS, ...THEME_DARK_UI_PAIRS] : THEME_UI_PAIRS;\n const measure = ([foreground, background]: ContrastPair, required: number): ContrastCheck => {\n const a = tokens[foreground];\n const b = tokens[background];\n return {\n foreground,\n background,\n required,\n ratio: a && b && HEX.test(a) && HEX.test(b) ? contrastRatio(a, b) : undefined,\n };\n };\n return [...THEME_TEXT_PAIRS.map((pair) => measure(pair, 4.5)), ...uiPairs.map((pair) => measure(pair, 3))];\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["closed","closed","closed"],"sources":["../src/types/dataTypes.ts","../src/types/definitions.ts","../src/types/locales.ts","../src/types/settings.ts","../src/seo/field.ts","../src/editors/catalogue.ts","../src/display/titleField.ts","../src/display/layout.ts","../src/validators/apiKey.ts","../src/naming/plural.ts","../src/normalize.ts","../src/validators/defaultValue.ts","../src/validators/issues.ts","../src/validators/naming.ts","../src/validators/typeboxIssues.ts","../src/validators/definition.ts","../src/validators/parse.ts","../src/validators/schema.ts","../src/diff/types.ts","../src/fileFormat/canonical.ts","../src/diff/diffDefinitions.ts","../src/diff/classify.ts","../src/fileFormat/hash.ts","../src/fileFormat/layout.ts","../src/fileFormat/lockFile.ts","../src/sync/threeWay.ts","../src/richtext/render.ts","../src/themes/tokens.ts","../src/themes/contrast.ts","../src/seo/definition.ts","../src/seo/defaults.ts"],"sourcesContent":["/** Every stored data type. A field's data type is separate from the editor that renders it (brief §2.5). */\nexport const DATA_TYPES = [\n 'string',\n 'text',\n 'richtext',\n 'number',\n 'integer',\n 'decimal',\n 'biginteger',\n 'boolean',\n 'date',\n 'datetime',\n 'time',\n 'enum',\n 'json',\n 'slug',\n 'email',\n 'url',\n 'uid',\n 'media',\n 'relation',\n 'component',\n 'dynamiczone',\n] as const;\n\nexport type DataType = (typeof DATA_TYPES)[number];\n\nexport const isDataType = (value: unknown): value is DataType =>\n typeof value === 'string' && (DATA_TYPES as readonly string[]).includes(value);\n\n/**\n * Scalar types stored as one JSON value per field (string, number or boolean). Only these can be unique,\n * filterable or sortable: their index expression is a single cast of `data ->> fieldId` (ADR 0001).\n */\nexport const SCALAR_DATA_TYPES: ReadonlySet<DataType> = new Set<DataType>([\n 'string',\n 'text',\n 'number',\n 'integer',\n 'decimal',\n 'biginteger',\n 'boolean',\n 'date',\n 'datetime',\n 'time',\n 'enum',\n 'slug',\n 'email',\n 'url',\n 'uid',\n]);\n\n/** Types that may carry `unique: true` (boolean and long text make no sense as unique keys). */\nexport const UNIQUE_CAPABLE_DATA_TYPES: ReadonlySet<DataType> = new Set<DataType>([\n 'string',\n 'number',\n 'integer',\n 'decimal',\n 'biginteger',\n 'date',\n 'datetime',\n 'time',\n 'slug',\n 'email',\n 'url',\n 'uid',\n]);\n\n/** Types whose values point at other definitions; the reference checks look at these. */\nexport const REFERENCE_DATA_TYPES: ReadonlySet<DataType> = new Set<DataType>([\n 'relation',\n 'component',\n 'dynamiczone',\n]);\n\n/**\n * How a value is physically represented in the content JSON. Changing a field's type within a storage\n * family never needs a data conversion, only a validity check; across families it is a conversion.\n */\nexport type StorageFamily =\n | 'jsonString'\n | 'jsonNumber'\n | 'numericString'\n | 'boolean'\n | 'json'\n | 'richtext'\n | 'media'\n | 'relation'\n | 'component'\n | 'dynamiczone';\n\nexport const STORAGE_FAMILY: Readonly<Record<DataType, StorageFamily>> = {\n string: 'jsonString',\n text: 'jsonString',\n slug: 'jsonString',\n email: 'jsonString',\n url: 'jsonString',\n uid: 'jsonString',\n enum: 'jsonString',\n date: 'jsonString',\n datetime: 'jsonString',\n time: 'jsonString',\n number: 'jsonNumber',\n integer: 'jsonNumber',\n decimal: 'numericString',\n biginteger: 'numericString',\n boolean: 'boolean',\n json: 'json',\n richtext: 'richtext',\n media: 'media',\n relation: 'relation',\n component: 'component',\n dynamiczone: 'dynamiczone',\n};\n","import { Type, type Static } from 'typebox';\nimport { DATA_TYPES, type DataType } from './dataTypes.js';\nimport type { JsonValue } from './json.js';\nimport type { DataTypeSettings } from './settings.js';\n\n/**\n * Model and component definitions. Both kinds share one table (`models`, with a `kind` discriminator) but\n * have distinct TypeScript types: a component cannot be published, localised or addressed by a route.\n *\n * The `*InputSchema` TypeBox schemas describe what callers send and what schema files contain: IDs and\n * defaulted properties may be omitted. `normalizeDefinition` turns input into the normalized types below,\n * which are what Shapio stores, hashes and diffs.\n */\nconst closed = { additionalProperties: false } as const;\n\nexport const MODEL_KINDS = ['collection', 'singleton'] as const;\nexport type ModelKind = (typeof MODEL_KINDS)[number];\nexport const DEFINITION_KINDS = [...MODEL_KINDS, 'component'] as const;\nexport type DefinitionKind = (typeof DEFINITION_KINDS)[number];\n\nexport const SORT_DIRECTIONS = ['asc', 'desc'] as const;\nexport type SortDirection = (typeof SORT_DIRECTIONS)[number];\n\nexport const MAX_FIELDS_PER_DEFINITION = 500;\nexport const MAX_LABEL_LENGTH = 200;\nexport const MAX_DESCRIPTION_LENGTH = 2000;\n\nconst Label = Type.String({ minLength: 1, maxLength: MAX_LABEL_LENGTH });\nconst Description = Type.Optional(Type.String({ maxLength: MAX_DESCRIPTION_LENGTH }));\n\nexport const EditorChoiceInputSchema = Type.Object(\n {\n id: Type.String({ minLength: 1, maxLength: 128 }),\n options: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n },\n closed,\n);\n\nexport const FieldInputSchema = Type.Object(\n {\n id: Type.Optional(Type.String()),\n apiKey: Type.String(),\n label: Label,\n /** Help text shown under the control. */\n description: Description,\n type: Type.Enum(DATA_TYPES),\n required: Type.Optional(Type.Boolean()),\n /** Per-locale value. Ignored (must be false) when the model is not localized. */\n localized: Type.Optional(Type.Boolean()),\n /** Readable by delivery principals wherever the model is readable (ADR 0005). Default true. */\n public: Type.Optional(Type.Boolean()),\n unique: Type.Optional(Type.Boolean()),\n filterable: Type.Optional(Type.Boolean()),\n sortable: Type.Optional(Type.Boolean()),\n /** Hidden from editors and the API; stored values are preserved until an explicit cleanup. */\n deprecated: Type.Optional(Type.Boolean()),\n /** Used for new entries and to backfill existing ones when the field becomes required. */\n defaultValue: Type.Optional(Type.Unknown()),\n /** Type-specific settings, validated against SETTINGS_SCHEMAS[type]. */\n settings: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n editor: Type.Optional(EditorChoiceInputSchema),\n },\n closed,\n);\n\nconst FieldGroupSchema = Type.Object(\n { id: Type.String({ minLength: 1, maxLength: 64 }), label: Label, fieldIds: Type.Array(Type.String()) },\n closed,\n);\n\nexport const ModelDisplayInputSchema = Type.Object(\n {\n /** Field whose value labels an entry in lists, pickers and relation summaries. */\n titleFieldId: Type.Optional(Type.String()),\n /** Columns of the content list, in order. */\n listFieldIds: Type.Optional(Type.Array(Type.String())),\n defaultSort: Type.Optional(\n Type.Object({ fieldId: Type.String(), direction: Type.Enum(SORT_DIRECTIONS) }, closed),\n ),\n /** Editor layout: named sections of the entry form. */\n groups: Type.Optional(Type.Array(FieldGroupSchema)),\n /** Fields rendered as blocks in the entry document's canvas, in order. Default: see `effectiveLayout`. */\n canvasFieldIds: Type.Optional(Type.Array(Type.String())),\n /** A single image `media` field shown as the cover above the title. Default: see `effectiveLayout`. */\n coverFieldId: Type.Optional(Type.String()),\n /** Properties shown as chips in the document's strip. Default: the first non-empty ones. */\n stripFieldIds: Type.Optional(Type.Array(Type.String())),\n },\n closed,\n);\n\nexport const ComponentDisplayInputSchema = Type.Object(\n {\n titleFieldId: Type.Optional(Type.String()),\n groups: Type.Optional(Type.Array(FieldGroupSchema)),\n },\n closed,\n);\n\nconst definitionBase = {\n id: Type.Optional(Type.String()),\n apiKey: Type.String(),\n label: Label,\n description: Description,\n fields: Type.Array(FieldInputSchema, { maxItems: MAX_FIELDS_PER_DEFINITION }),\n};\n\nexport const ModelDefinitionInputSchema = Type.Object(\n {\n ...definitionBase,\n kind: Type.Enum(MODEL_KINDS),\n /**\n * Collections only: names the list route and query (`/api/content/articles`, `articles(…)`). Optional\n * here so files written before plural API IDs still parse; normalizing fills it on a collection.\n */\n pluralApiKey: Type.Optional(Type.String()),\n localized: Type.Optional(Type.Boolean()),\n /** Entries have separate draft and published states. Default true. */\n draftAndPublish: Type.Optional(Type.Boolean()),\n display: Type.Optional(ModelDisplayInputSchema),\n },\n closed,\n);\n\nexport const ComponentDefinitionInputSchema = Type.Object(\n {\n ...definitionBase,\n kind: Type.Literal('component'),\n category: Type.Optional(Type.String({ minLength: 1, maxLength: 100 })),\n icon: Type.Optional(Type.String({ minLength: 1, maxLength: 64 })),\n display: Type.Optional(ComponentDisplayInputSchema),\n },\n closed,\n);\n\nexport const DefinitionInputSchema = Type.Union([ModelDefinitionInputSchema, ComponentDefinitionInputSchema]);\n\nexport type FieldInput = Static<typeof FieldInputSchema>;\nexport type ModelDefinitionInput = Static<typeof ModelDefinitionInputSchema>;\nexport type ComponentDefinitionInput = Static<typeof ComponentDefinitionInputSchema>;\nexport type DefinitionInput = ModelDefinitionInput | ComponentDefinitionInput;\n\nexport type EditorChoice = { id: string; options: Record<string, JsonValue> };\n\ntype FieldBase = {\n id: string;\n apiKey: string;\n label: string;\n description?: string;\n required: boolean;\n localized: boolean;\n public: boolean;\n unique: boolean;\n filterable: boolean;\n sortable: boolean;\n deprecated: boolean;\n defaultValue?: JsonValue;\n editor: EditorChoice;\n};\n\n/** A normalized field. Narrow on `type` to get typed `settings`. */\nexport type FieldDefinition<T extends DataType = DataType> = {\n [K in T]: FieldBase & { type: K; settings: DataTypeSettings[K] };\n}[T];\n\nexport type FieldGroup = { id: string; label: string; fieldIds: string[] };\n\nexport type ModelDisplay = {\n titleFieldId?: string;\n listFieldIds?: string[];\n defaultSort?: { fieldId: string; direction: SortDirection };\n groups?: FieldGroup[];\n canvasFieldIds?: string[];\n coverFieldId?: string;\n stripFieldIds?: string[];\n};\n\nexport type ComponentDisplay = { titleFieldId?: string; groups?: FieldGroup[] };\n\nexport type ModelDefinition = {\n id: string;\n kind: ModelKind;\n apiKey: string;\n /**\n * Present on collections (filled by normalizing), absent on singletons. Read it through `routeKeyOf`,\n * which also covers a stored definition that predates plural API IDs.\n */\n pluralApiKey?: string;\n label: string;\n description?: string;\n localized: boolean;\n draftAndPublish: boolean;\n fields: FieldDefinition[];\n display: ModelDisplay;\n};\n\nexport type ComponentDefinition = {\n id: string;\n kind: 'component';\n apiKey: string;\n label: string;\n description?: string;\n category?: string;\n icon?: string;\n fields: FieldDefinition[];\n display: ComponentDisplay;\n};\n\n/** Either kind. Most schema machinery (diff, file format, registry) works on both. */\nexport type SchemaDefinition = ModelDefinition | ComponentDefinition;\n\nexport const isComponentDefinition = (definition: SchemaDefinition): definition is ComponentDefinition =>\n definition.kind === 'component';\n\nexport const isModelDefinition = (definition: SchemaDefinition): definition is ModelDefinition =>\n definition.kind !== 'component';\n","import { Type, type Static } from 'typebox';\n\n/** BCP 47 subset: language (2–3 letters) plus optional subtags, e.g. `en`, `fr-CA`, `zh-Hant-TW`. */\nexport const LOCALE_CODE_PATTERN = /^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/;\nexport const MAX_FALLBACK_CHAIN = 10;\n\nexport const LocaleInputSchema = Type.Object(\n {\n code: Type.String({ pattern: LOCALE_CODE_PATTERN.source, maxLength: 35 }),\n label: Type.String({ minLength: 1, maxLength: 100 }),\n /** Locales tried in order when content is missing in this one; the default locale is always last. */\n fallbacks: Type.Optional(Type.Array(Type.String(), { maxItems: MAX_FALLBACK_CHAIN })),\n },\n { additionalProperties: false },\n);\n\nexport type LocaleInput = Static<typeof LocaleInputSchema>;\n\nexport type LocaleDefinition = {\n code: string;\n label: string;\n isDefault: boolean;\n fallbacks: string[];\n};\n","import { Type, type Static, type TSchema } from 'typebox';\nimport type { DataType } from './dataTypes.js';\nimport {\n BIGINTEGER_PATTERN,\n DATE_PATTERN,\n DATETIME_PATTERN,\n DECIMAL_PATTERN,\n TIME_PATTERN,\n} from './valueFormats.js';\n\n/**\n * Per-data-type settings: validation rules and type configuration (relation target, component reference,\n * enum values...). Each schema is closed (`additionalProperties: false`) so a typo in a hand-edited schema\n * file is reported instead of ignored. Defaults are applied by `normalizeDefinition`.\n */\nconst closed = { additionalProperties: false } as const;\nconst NonNegativeInt = Type.Integer({ minimum: 0 });\nconst pattern = (regex: RegExp) => Type.String({ pattern: regex.source });\n\nconst lengthRules = {\n minLength: Type.Optional(NonNegativeInt),\n maxLength: Type.Optional(Type.Integer({ minimum: 1 })),\n};\nconst countRules = {\n min: Type.Optional(NonNegativeInt),\n max: Type.Optional(Type.Integer({ minimum: 1 })),\n};\n\nexport const MEDIA_KINDS = ['image', 'video', 'audio', 'document', 'other'] as const;\nexport const RELATION_CARDINALITIES = ['one', 'many'] as const;\n\nexport const EnumValueSchema = Type.Object(\n {\n value: Type.String({ minLength: 1, maxLength: 64 }),\n label: Type.String({ minLength: 1, maxLength: 200 }),\n },\n closed,\n);\n\nexport const SETTINGS_SCHEMAS = {\n string: Type.Object(\n { ...lengthRules, pattern: Type.Optional(Type.String({ minLength: 1, maxLength: 500 })) },\n closed,\n ),\n text: Type.Object(lengthRules, closed),\n richtext: Type.Object(\n {\n formatVersion: Type.Optional(Type.Integer({ minimum: 1 })),\n maxLength: Type.Optional(Type.Integer({ minimum: 1 })),\n },\n closed,\n ),\n number: Type.Object({ min: Type.Optional(Type.Number()), max: Type.Optional(Type.Number()) }, closed),\n integer: Type.Object({ min: Type.Optional(Type.Integer()), max: Type.Optional(Type.Integer()) }, closed),\n decimal: Type.Object(\n {\n precision: Type.Optional(Type.Integer({ minimum: 1, maximum: 1000 })),\n scale: Type.Optional(Type.Integer({ minimum: 0, maximum: 1000 })),\n min: Type.Optional(pattern(DECIMAL_PATTERN)),\n max: Type.Optional(pattern(DECIMAL_PATTERN)),\n },\n closed,\n ),\n biginteger: Type.Object(\n { min: Type.Optional(pattern(BIGINTEGER_PATTERN)), max: Type.Optional(pattern(BIGINTEGER_PATTERN)) },\n closed,\n ),\n boolean: Type.Object({}, closed),\n date: Type.Object(\n { min: Type.Optional(pattern(DATE_PATTERN)), max: Type.Optional(pattern(DATE_PATTERN)) },\n closed,\n ),\n datetime: Type.Object(\n { min: Type.Optional(pattern(DATETIME_PATTERN)), max: Type.Optional(pattern(DATETIME_PATTERN)) },\n closed,\n ),\n time: Type.Object(\n { min: Type.Optional(pattern(TIME_PATTERN)), max: Type.Optional(pattern(TIME_PATTERN)) },\n closed,\n ),\n enum: Type.Object(\n {\n values: Type.Array(EnumValueSchema, { minItems: 1, maxItems: 500 }),\n multiple: Type.Optional(Type.Boolean()),\n },\n closed,\n ),\n json: Type.Object({}, closed),\n slug: Type.Object({ ...lengthRules, sourceFieldId: Type.Optional(Type.String()) }, closed),\n email: Type.Object({}, closed),\n url: Type.Object(\n { protocols: Type.Optional(Type.Array(Type.Enum(['http', 'https', 'mailto', 'tel']), { minItems: 1 })) },\n closed,\n ),\n uid: Type.Object(lengthRules, closed),\n media: Type.Object(\n {\n multiple: Type.Optional(Type.Boolean()),\n allowedKinds: Type.Optional(Type.Array(Type.Enum(MEDIA_KINDS), { minItems: 1 })),\n ...countRules,\n },\n closed,\n ),\n relation: Type.Object(\n { target: Type.String(), cardinality: Type.Enum(RELATION_CARDINALITIES), ...countRules },\n closed,\n ),\n component: Type.Object(\n { component: Type.String(), repeatable: Type.Optional(Type.Boolean()), ...countRules },\n closed,\n ),\n dynamiczone: Type.Object(\n { components: Type.Array(Type.String(), { minItems: 1, maxItems: 100 }), ...countRules },\n closed,\n ),\n} satisfies Record<DataType, TSchema>;\n\ntype SettingsSchemas = typeof SETTINGS_SCHEMAS;\n\n/** Settings as authored (defaults may be missing). */\nexport type DataTypeSettingsInput = { [T in DataType]: Static<SettingsSchemas[T]> };\n\n/** Settings after normalization: the defaulted keys are always present. */\nexport type DataTypeSettings = Omit<DataTypeSettingsInput, 'richtext' | 'enum' | 'media' | 'component'> & {\n richtext: DataTypeSettingsInput['richtext'] & { formatVersion: number };\n enum: DataTypeSettingsInput['enum'] & { multiple: boolean };\n media: DataTypeSettingsInput['media'] & { multiple: boolean };\n component: DataTypeSettingsInput['component'] & { repeatable: boolean };\n};\n","import type { FieldDefinition } from '../types/definitions.js';\nimport { SEO_COMPONENT_ID } from './ids.js';\n\n/** Whether a field holds the built-in SEO component (by stable ID, whatever its API ID or editor). */\nexport const isSeoField = (field: FieldDefinition): boolean =>\n field.type === 'component' && field.settings.component === SEO_COMPONENT_ID && !field.settings.repeatable;\n","import { Type, type TSchema } from 'typebox';\nimport { isSeoField } from '../seo/field.js';\nimport { SEO_EDITOR_ID } from '../seo/ids.js';\nimport type { DataType } from '../types/dataTypes.js';\nimport type { FieldDefinition } from '../types/definitions.js';\n\n/**\n * Built-in editors (ADR 0009): which data types each can edit and the schema of its options. The server\n * validates every field's editor choice against this catalogue, so selecting and configuring an editor is\n * runtime metadata. Custom editors (loaded at runtime from the project) use namespaced IDs containing a dot,\n * e.g. `acme.colorWheel`; their options are free-form JSON here because their schema lives in the project.\n */\nexport type EditorCatalogueEntry = {\n id: string;\n dataTypes: readonly DataType[];\n optionsSchema: TSchema;\n /** Extra compatibility rule beyond the data type (e.g. radio buttons only for single-value enums). */\n supports?: (field: FieldDefinition) => boolean;\n};\n\nconst closed = { additionalProperties: false } as const;\nconst Placeholder = Type.Optional(Type.String({ maxLength: 200 }));\nconst isMultipleEnum = (field: FieldDefinition) => field.type === 'enum' && field.settings.multiple;\n\nconst entries: EditorCatalogueEntry[] = [\n {\n id: 'textInput',\n dataTypes: ['string', 'email', 'url', 'uid'],\n optionsSchema: Type.Object({ placeholder: Placeholder }, closed),\n },\n {\n id: 'textarea',\n dataTypes: ['text', 'string'],\n optionsSchema: Type.Object(\n { placeholder: Placeholder, rows: Type.Optional(Type.Integer({ minimum: 2, maximum: 40 })) },\n closed,\n ),\n },\n {\n id: 'color',\n dataTypes: ['string'],\n optionsSchema: Type.Object(\n {\n format: Type.Optional(Type.Enum(['hex', 'rgb'])),\n presets: Type.Optional(Type.Array(Type.String({ maxLength: 32 }), { maxItems: 50 })),\n },\n closed,\n ),\n },\n {\n id: 'richText',\n dataTypes: ['richtext'],\n optionsSchema: Type.Object({ toolbar: Type.Optional(Type.Enum(['full', 'minimal'])) }, closed),\n },\n {\n id: 'numberInput',\n dataTypes: ['number', 'integer', 'decimal', 'biginteger'],\n optionsSchema: Type.Object(\n { placeholder: Placeholder, step: Type.Optional(Type.Number({ exclusiveMinimum: 0 })) },\n closed,\n ),\n },\n {\n id: 'toggle',\n dataTypes: ['boolean'],\n optionsSchema: Type.Object({}, closed),\n },\n {\n id: 'checkbox',\n dataTypes: ['boolean'],\n optionsSchema: Type.Object({}, closed),\n },\n {\n id: 'segmented',\n dataTypes: ['boolean', 'enum'],\n optionsSchema: Type.Object(\n {\n trueLabel: Type.Optional(Type.String({ maxLength: 50 })),\n falseLabel: Type.Optional(Type.String({ maxLength: 50 })),\n },\n closed,\n ),\n supports: (field) => !isMultipleEnum(field),\n },\n {\n id: 'select',\n dataTypes: ['enum'],\n optionsSchema: Type.Object({ placeholder: Placeholder }, closed),\n },\n {\n id: 'radio',\n dataTypes: ['enum'],\n optionsSchema: Type.Object({ layout: Type.Optional(Type.Enum(['vertical', 'horizontal'])) }, closed),\n supports: (field) => !isMultipleEnum(field),\n },\n {\n id: 'checkboxGroup',\n dataTypes: ['enum'],\n optionsSchema: Type.Object({ layout: Type.Optional(Type.Enum(['vertical', 'horizontal'])) }, closed),\n supports: isMultipleEnum,\n },\n {\n id: 'datePicker',\n dataTypes: ['date'],\n optionsSchema: Type.Object({}, closed),\n },\n {\n id: 'dateTimePicker',\n dataTypes: ['datetime'],\n optionsSchema: Type.Object({ display: Type.Optional(Type.Enum(['local', 'utc'])) }, closed),\n },\n {\n id: 'timePicker',\n dataTypes: ['time'],\n optionsSchema: Type.Object(\n { stepMinutes: Type.Optional(Type.Integer({ minimum: 1, maximum: 60 })) },\n closed,\n ),\n },\n {\n id: 'slugInput',\n dataTypes: ['slug'],\n optionsSchema: Type.Object({ placeholder: Placeholder }, closed),\n },\n {\n id: 'jsonEditor',\n dataTypes: ['json'],\n optionsSchema: Type.Object({ rows: Type.Optional(Type.Integer({ minimum: 3, maximum: 80 })) }, closed),\n },\n {\n id: 'mediaPicker',\n dataTypes: ['media'],\n optionsSchema: Type.Object({}, closed),\n },\n {\n id: 'relationPicker',\n dataTypes: ['relation'],\n optionsSchema: Type.Object({ allowInlineCreate: Type.Optional(Type.Boolean()) }, closed),\n },\n {\n id: 'componentEditor',\n dataTypes: ['component'],\n optionsSchema: Type.Object({ collapsed: Type.Optional(Type.Boolean()) }, closed),\n },\n {\n // The built-in SEO component's editor: its fields with length counters and a search-result preview.\n id: SEO_EDITOR_ID,\n dataTypes: ['component'],\n optionsSchema: Type.Object({}, closed),\n supports: isSeoField,\n },\n {\n id: 'dynamicZoneEditor',\n dataTypes: ['dynamiczone'],\n optionsSchema: Type.Object({ collapsed: Type.Optional(Type.Boolean()) }, closed),\n },\n];\n\nexport const EDITOR_CATALOGUE: ReadonlyMap<string, EditorCatalogueEntry> = new Map(\n entries.map((entry) => [entry.id, entry]),\n);\n\n/** The editor a field gets when its definition names none. */\nexport const DEFAULT_EDITORS: Readonly<Record<DataType, string>> = {\n string: 'textInput',\n text: 'textarea',\n richtext: 'richText',\n number: 'numberInput',\n integer: 'numberInput',\n decimal: 'numberInput',\n biginteger: 'numberInput',\n boolean: 'toggle',\n date: 'datePicker',\n datetime: 'dateTimePicker',\n time: 'timePicker',\n enum: 'select',\n json: 'jsonEditor',\n slug: 'slugInput',\n email: 'textInput',\n url: 'textInput',\n uid: 'textInput',\n media: 'mediaPicker',\n relation: 'relationPicker',\n component: 'componentEditor',\n dynamiczone: 'dynamicZoneEditor',\n};\n\n/** `vendor.name` (letters, digits, `_`, `-`), e.g. `acme.colorWheel`. Built-in IDs never contain a dot. */\nexport const CUSTOM_EDITOR_ID_PATTERN = /^[A-Za-z][A-Za-z0-9_-]*(\\.[A-Za-z][A-Za-z0-9_-]*)+$/;\n\nexport const isCustomEditorId = (id: string): boolean => CUSTOM_EDITOR_ID_PATTERN.test(id);\n\n/** Built-in editors that can edit this field (for the admin's editor picker). */\nexport const listCompatibleEditors = (field: FieldDefinition): EditorCatalogueEntry[] =>\n entries.filter((entry) => entry.dataTypes.includes(field.type) && (entry.supports?.(field) ?? true));\n","import type { FieldDefinition, SchemaDefinition } from '../types/definitions.js';\n\n/** Field types that may label entries: the only types `display.titleFieldId` accepts, and the fallback's. */\nexport const TITLE_FIELD_TYPES: ReadonlySet<string> = new Set([\n 'string',\n 'text',\n 'slug',\n 'email',\n 'uid',\n 'enum',\n]);\n\n/**\n * Field types the list API's `q` search runs on, checked on top of the title field: an enum title is not\n * searchable. `url` is listed for search only; it is never a title.\n */\nexport const TEXT_TITLE_FIELD_TYPES: ReadonlySet<string> = new Set([\n 'string',\n 'text',\n 'slug',\n 'email',\n 'url',\n 'uid',\n]);\n\n/**\n * The field that labels a definition's entries in lists, pickers, relation summaries and search: the\n * configured `display.titleFieldId` when it points at a live (non-deprecated) field, otherwise the first\n * live field of a title type (TITLE_FIELD_TYPES) in field order, otherwise undefined. `titleFieldId` is\n * optional, so a model built without one still gets a readable title.\n */\nexport const effectiveTitleField = (definition: SchemaDefinition): FieldDefinition | undefined => {\n const live = definition.fields.filter((field) => !field.deprecated);\n const configured = definition.display.titleFieldId;\n return (\n (configured === undefined ? undefined : live.find((field) => field.id === configured)) ??\n live.find((field) => TITLE_FIELD_TYPES.has(field.type))\n );\n};\n","import type { DataType } from '../types/dataTypes.js';\nimport type { FieldDefinition, ModelDefinition } from '../types/definitions.js';\nimport { effectiveTitleField } from './titleField.js';\n\n/**\n * Data types that are blocks of the entry document's canvas by default. Components must also be repeatable\n * and media must hold several files (`isCanvasEligible`); a single component or file is a property unless\n * `display.canvasFieldIds` places it in the document.\n */\nexport const CANVAS_ELIGIBLE: ReadonlySet<DataType> = new Set<DataType>([\n 'richtext',\n 'dynamiczone',\n 'component',\n 'media',\n]);\n\n/** Title types that the document edits inline as its H1; any other title type stays a property. */\nexport const INLINE_TITLE_TYPES: ReadonlySet<DataType> = new Set<DataType>(['string', 'text']);\n\n/** How many properties the strip shows when `display.stripFieldIds` is not set. */\nexport const STRIP_DEFAULT_COUNT = 5;\n\n/**\n * The automatic rule: the fields written in the document while `display.canvasFieldIds` is unset (rich\n * text, dynamic zones, repeatable components, media with several files). Also what a canvas field can take\n * between blocks: only these hold blocks.\n */\nexport const isCanvasEligible = (field: FieldDefinition): boolean => {\n switch (field.type) {\n case 'richtext':\n case 'dynamiczone':\n return true;\n case 'component':\n return field.settings.repeatable;\n case 'media':\n return field.settings.multiple;\n default:\n return false;\n }\n};\n\n/**\n * Whether `display.canvasFieldIds` may list the field: any field but the entry's title (`effectiveTitleField`),\n * which the document shows as its heading. A configured cover is refused by the validator; an automatically\n * chosen one placed in the document simply stops being the cover.\n */\nexport const isDocumentPlaceable = (field: FieldDefinition, title: FieldDefinition | undefined): boolean =>\n field.id !== title?.id;\n\n/** A single `media` field that may hold an image. */\nexport const isCoverEligible = (field: FieldDefinition): boolean =>\n field.type === 'media' &&\n !field.settings.multiple &&\n (field.settings.allowedKinds === undefined || field.settings.allowedKinds.includes('image'));\n\n/** Properties under one of the model's `display.groups` (`label` undefined for ungrouped fields). */\nexport type PropertyGroup = { id: string; label: string | undefined; fields: FieldDefinition[] };\n\nexport type DocumentLayout = {\n /** The field that labels the entry (`effectiveTitleField`), if any. */\n title: FieldDefinition | undefined;\n /** The title is edited inline as the H1 (string/text); otherwise it is shown read-only and is a property. */\n titleInline: boolean;\n cover: FieldDefinition | undefined;\n /**\n * The fields written in the document, in order: block fields (`isCanvasEligible`) and any other field\n * that `display.canvasFieldIds` places there, each under its heading.\n */\n canvas: FieldDefinition[];\n /** Every other live field, ordered by `display.groups`, then field order. */\n properties: FieldDefinition[];\n /** `properties` split by group, for the settings drawer and the property grid. */\n propertyGroups: PropertyGroup[];\n /**\n * The strip's configured properties, or null when it is not configured: then it shows the first\n * STRIP_DEFAULT_COUNT non-empty properties (`stripFieldsOf`), which depends on the entry's values.\n */\n strip: FieldDefinition[] | null;\n};\n\nconst byIds = (live: readonly FieldDefinition[], ids: readonly string[] | undefined) =>\n (ids ?? [])\n .map((id) => live.find((field) => field.id === id))\n .filter((field): field is FieldDefinition => field !== undefined);\n\nconst unique = (fields: readonly FieldDefinition[]) => [...new Map(fields.map((f) => [f.id, f])).values()];\n\nconst groupProperties = (model: ModelDefinition, properties: readonly FieldDefinition[]): PropertyGroup[] => {\n const groups = (model.display.groups ?? [])\n .map((group) => ({ id: group.id, label: group.label, fields: byIds(properties, group.fieldIds) }))\n .filter((group) => group.fields.length > 0);\n const grouped = new Set(groups.flatMap((group) => group.fields.map((field) => field.id)));\n const rest = properties.filter((field) => !grouped.has(field.id));\n return rest.length > 0 ? [...groups, { id: 'other', label: undefined, fields: rest }] : groups;\n};\n\nconst coverOf = (model: ModelDefinition, live: readonly FieldDefinition[], canvas: ReadonlySet<string>) => {\n const configured = byIds(live, model.display.coverFieldId ? [model.display.coverFieldId] : [])[0];\n if (configured && isCoverEligible(configured) && !canvas.has(configured.id)) {\n return configured;\n }\n return live.find((field) => isCoverEligible(field) && !canvas.has(field.id));\n};\n\n/**\n * The entry document's layout: title, cover, document fields and properties. Configured `display` ids win\n * when they point at live, eligible fields; anything else falls back to the defaults (canvas: every block\n * field in field order; cover: the first single image field not in the canvas). Deprecated, unknown ids and\n * the title are skipped, so a stale definition never breaks the editor. Pure: no values, no I/O.\n */\nexport const effectiveLayout = (model: ModelDefinition): DocumentLayout => {\n const live = model.fields.filter((field) => !field.deprecated);\n const title = effectiveTitleField(model);\n const titleInline = title !== undefined && INLINE_TITLE_TYPES.has(title.type);\n const configuredCanvas = unique(\n byIds(live, model.display.canvasFieldIds).filter((field) => isDocumentPlaceable(field, title)),\n );\n const canvasCandidates =\n model.display.canvasFieldIds === undefined ? live.filter(isCanvasEligible) : configuredCanvas;\n const cover = coverOf(model, live, new Set(configuredCanvas.map((field) => field.id)));\n const canvas = canvasCandidates.filter((field) => field.id !== cover?.id);\n const placed = new Set([\n ...canvas.map((field) => field.id),\n ...(cover ? [cover.id] : []),\n ...(titleInline && title ? [title.id] : []),\n ]);\n const propertyGroups = groupProperties(\n model,\n live.filter((field) => !placed.has(field.id)),\n );\n const properties = propertyGroups.flatMap((group) => group.fields);\n const strip =\n model.display.stripFieldIds === undefined ? null : unique(byIds(properties, model.display.stripFieldIds));\n return { title, titleInline, cover, canvas, properties, propertyGroups, strip };\n};\n\n/** The strip's properties: the configured ones, or the first `limit` that `hasValue` says are non-empty. */\nexport const stripFieldsOf = (\n layout: DocumentLayout,\n hasValue: (field: FieldDefinition) => boolean,\n limit = STRIP_DEFAULT_COUNT,\n): FieldDefinition[] => layout.strip ?? layout.properties.filter(hasValue).slice(0, limit);\n","import type { IssueCode } from './issues.js';\n\n/**\n * API keys (models, components, fields) must be valid GraphQL names from day one (CONTRIBUTING.md rule 4),\n * so GraphQL can expose them without renames.\n */\nexport const API_KEY_PATTERN = /^[_A-Za-z][_0-9A-Za-z]*$/;\nexport const MAX_API_KEY_LENGTH = 64;\n\nexport const isApiKeySyntaxValid = (key: string): boolean => API_KEY_PATTERN.test(key);\n\n/**\n * Syntax checks shared by every kind of API key (`noun` names it in messages, e.g. \"plural API ID\").\n * Returns the first problem, or null.\n */\nexport const checkApiKeySyntax = (\n key: string,\n noun = 'API ID',\n): { code: IssueCode; message: string } | null => {\n if (!isApiKeySyntaxValid(key)) {\n return {\n code: 'API_KEY_INVALID',\n message: `\"${key}\" is not a valid ${noun}: use letters, digits and _, not starting with a digit`,\n };\n }\n if (key.length > MAX_API_KEY_LENGTH) {\n return { code: 'API_KEY_TOO_LONG', message: `${noun}s are at most ${MAX_API_KEY_LENGTH} characters` };\n }\n // GraphQL reserves the `__` prefix for introspection.\n if (key.startsWith('__')) {\n return {\n code: 'API_KEY_RESERVED_PREFIX',\n message: `${noun}s must not start with \"__\" (reserved by GraphQL)`,\n };\n }\n return null;\n};\n\n/** Case-folded form used for every collision check: `Title` and `title` collide. */\nexport const foldApiKey = (key: string): string => key.toLowerCase();\n","import pluralize from 'pluralize';\nimport { foldApiKey, MAX_API_KEY_LENGTH } from '../validators/apiKey.js';\n\n/** Appended when English has no distinct plural (`news` → `newsItems`, `series` → `seriesItems`). */\nexport const PLURAL_FALLBACK_SUFFIX = 'Items';\n\n/**\n * Suggests the plural API ID of a collection from its singular one (`article` → `articles`,\n * `category` → `categories`). Only a suggestion for the admin and the value filled into definitions that\n * predate plural API IDs: the plural is stored on the definition and nothing pluralises at request time.\n * Deterministic for a given `pluralize` version, which is pinned exactly for that reason.\n */\nexport const suggestPlural = (apiKey: string): string => {\n if (apiKey === '') {\n return '';\n }\n const plural = pluralize(apiKey);\n if (plural.length <= MAX_API_KEY_LENGTH && foldApiKey(plural) !== foldApiKey(apiKey)) {\n return plural;\n }\n return `${apiKey.slice(0, MAX_API_KEY_LENGTH - PLURAL_FALLBACK_SUFFIX.length)}${PLURAL_FALLBACK_SUFFIX}`;\n};\n","import { DEFAULT_EDITORS } from './editors/catalogue.js';\nimport { suggestPlural } from './naming/plural.js';\nimport type {\n ComponentDefinition,\n ComponentDefinitionInput,\n ComponentDisplay,\n FieldDefinition,\n FieldInput,\n ModelDefinition,\n ModelDefinitionInput,\n ModelDisplay,\n SchemaDefinition,\n} from './types/definitions.js';\nimport type { JsonValue } from './types/json.js';\nimport { RICHTEXT_FORMAT_VERSION } from './types/valueFormats.js';\n\n/** Input whose IDs have been assigned (see `assignIds`). */\ntype WithIds<T extends { id?: string }> = T & { id: string };\nexport type FieldInputWithId = WithIds<FieldInput>;\nexport type DefinitionInputWithIds =\n | (WithIds<ModelDefinitionInput> & { fields: FieldInputWithId[] })\n | (WithIds<ComponentDefinitionInput> & { fields: FieldInputWithId[] });\n\nconst SETTINGS_DEFAULTS: Partial<Record<FieldDefinition['type'], Record<string, unknown>>> = {\n richtext: { formatVersion: RICHTEXT_FORMAT_VERSION },\n enum: { multiple: false },\n media: { multiple: false },\n component: { repeatable: false },\n};\n\n/** Optional text properties where an empty string means \"not set\". */\nconst OPTIONAL_TEXT_KEYS: ReadonlySet<string> = new Set([\n 'description',\n 'category',\n 'icon',\n 'titleFieldId',\n 'coverFieldId',\n 'pluralApiKey',\n]);\n/** Optional list properties where an empty list means \"not set\". `fields` is never optional. */\nconst OPTIONAL_LIST_KEYS: ReadonlySet<string> = new Set([\n 'listFieldIds',\n 'groups',\n 'canvasFieldIds',\n 'stripFieldIds',\n]);\n\nconst withoutEmpty = <T extends Record<string, unknown>>(value: T): T => {\n const result: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value)) {\n const isEmptyText = OPTIONAL_TEXT_KEYS.has(key) && entry === '';\n const isEmptyList = OPTIONAL_LIST_KEYS.has(key) && Array.isArray(entry) && entry.length === 0;\n if (entry === undefined || isEmptyText || isEmptyList) {\n continue;\n }\n result[key] = entry;\n }\n return result as T;\n};\n\nconst normalizeField = (field: FieldInputWithId): FieldDefinition => {\n const normalized = {\n id: field.id,\n apiKey: field.apiKey,\n label: field.label,\n description: field.description,\n type: field.type,\n required: field.required ?? false,\n localized: field.localized ?? false,\n public: field.public ?? true,\n unique: field.unique ?? false,\n filterable: field.filterable ?? false,\n sortable: field.sortable ?? false,\n deprecated: field.deprecated ?? false,\n defaultValue: field.defaultValue as JsonValue | undefined,\n settings: { ...SETTINGS_DEFAULTS[field.type], ...field.settings },\n editor: {\n id: field.editor?.id ?? DEFAULT_EDITORS[field.type],\n options: (field.editor?.options ?? {}) as Record<string, JsonValue>,\n },\n };\n return withoutEmpty(normalized) as FieldDefinition;\n};\n\nconst normalizeModelDisplay = (display: ModelDefinitionInput['display']): ModelDisplay =>\n withoutEmpty({ ...display });\n\nconst normalizeComponentDisplay = (display: ComponentDefinitionInput['display']): ComponentDisplay =>\n withoutEmpty({ ...display });\n\n/**\n * Applies defaults so that two definitions meaning the same thing are byte-identical once serialized\n * canonically: a hand-written file that omits `public` hashes the same as one that says `public: true`.\n * Empty optional strings and arrays are dropped. A collection without a plural API ID gets the suggested\n * one (`suggestPlural`), so files and definitions from before plural API IDs keep working.\n */\nexport const normalizeDefinition = (input: DefinitionInputWithIds): SchemaDefinition => {\n const fields = input.fields.map(normalizeField);\n if (input.kind === 'component') {\n const component: ComponentDefinition = withoutEmpty({\n id: input.id,\n kind: 'component',\n apiKey: input.apiKey,\n label: input.label,\n description: input.description,\n category: input.category,\n icon: input.icon,\n fields,\n display: normalizeComponentDisplay(input.display),\n });\n return component;\n }\n const model: ModelDefinition = withoutEmpty({\n id: input.id,\n kind: input.kind,\n apiKey: input.apiKey,\n // Collections always carry a plural API ID (filled from the singular when missing or empty);\n // singletons never do, so switching a collection to a singleton drops it.\n pluralApiKey: input.kind === 'collection' ? input.pluralApiKey || suggestPlural(input.apiKey) : undefined,\n label: input.label,\n description: input.description,\n localized: input.localized ?? false,\n draftAndPublish: input.draftAndPublish ?? true,\n fields,\n display: normalizeModelDisplay(input.display),\n });\n return model;\n};\n\n/** Normalizes a definition that is already normalized-shaped (e.g. read back from the database). */\nexport const renormalizeDefinition = (definition: SchemaDefinition): SchemaDefinition =>\n normalizeDefinition(definition as unknown as DefinitionInputWithIds);\n","import type { FieldDefinition } from '../types/definitions.js';\nimport {\n BIGINTEGER_PATTERN,\n DATE_PATTERN,\n DATETIME_PATTERN,\n DECIMAL_PATTERN,\n SLUG_PATTERN,\n TIME_PATTERN,\n UID_PATTERN,\n} from '../types/valueFormats.js';\n\n/**\n * Checks that a field's `defaultValue` has the right JSON shape for its type. Full content rules\n * (lengths, ranges) are applied by the content validator when the default is used.\n * Returns a message, or null when the default is acceptable.\n */\nexport const checkDefaultValue = (field: FieldDefinition): string | null => {\n const value = field.defaultValue;\n if (value === undefined) {\n return null;\n }\n const isString = typeof value === 'string';\n const matches = (pattern: RegExp) => isString && pattern.test(value);\n switch (field.type) {\n case 'string':\n case 'text':\n case 'email':\n case 'url':\n return isString ? null : 'must be a string';\n case 'slug':\n return matches(SLUG_PATTERN) ? null : 'must be a lower-case slug';\n case 'uid':\n return matches(UID_PATTERN) ? null : 'must contain only URL-safe characters';\n case 'number':\n return typeof value === 'number' && Number.isFinite(value) ? null : 'must be a number';\n case 'integer':\n return Number.isSafeInteger(value) ? null : 'must be an integer';\n case 'decimal':\n return matches(DECIMAL_PATTERN) ? null : 'must be a decimal string, e.g. \"12.50\"';\n case 'biginteger':\n return matches(BIGINTEGER_PATTERN) ? null : 'must be an integer string, e.g. \"9007199254740993\"';\n case 'boolean':\n return typeof value === 'boolean' ? null : 'must be true or false';\n case 'date':\n return matches(DATE_PATTERN) ? null : 'must be a date, YYYY-MM-DD';\n case 'datetime':\n return matches(DATETIME_PATTERN) ? null : 'must be a UTC date-time, YYYY-MM-DDTHH:mm:ssZ';\n case 'time':\n return matches(TIME_PATTERN) ? null : 'must be a time, HH:mm[:ss]';\n case 'enum': {\n const allowed = new Set(field.settings.values.map((entry) => entry.value));\n if (field.settings.multiple) {\n return Array.isArray(value) && value.every((item) => typeof item === 'string' && allowed.has(item))\n ? null\n : 'must be a list of the enum values';\n }\n return isString && allowed.has(value) ? null : 'must be one of the enum values';\n }\n case 'json':\n return null;\n default:\n return `${field.type} fields cannot have a default value`;\n }\n};\n","/**\n * A problem found in a definition. `path` is a JSON pointer into the definition (`/fields/2/apiKey`), so\n * the admin can put the message next to the control and the CLI can point at the file location.\n */\nexport type ValidationIssue = {\n path: string;\n code: IssueCode;\n message: string;\n /** Set by cross-definition checks so a multi-definition apply can say which file is wrong. */\n definitionId?: string;\n};\n\nexport type IssueCode =\n | 'INVALID_STRUCTURE'\n | 'INVALID_ID'\n | 'DUPLICATE_ID'\n | 'API_KEY_INVALID'\n | 'API_KEY_TOO_LONG'\n | 'API_KEY_RESERVED_PREFIX'\n | 'API_KEY_RESERVED'\n | 'API_KEY_COLLISION'\n | 'PLURAL_API_KEY_SAME_AS_SINGULAR'\n | 'GENERATED_NAME_COLLISION'\n | 'INVALID_SETTINGS'\n | 'INVALID_RANGE'\n | 'INVALID_PATTERN'\n | 'DUPLICATE_ENUM_VALUE'\n | 'INVALID_ENUM_VALUE'\n | 'UNSUPPORTED_FLAG'\n | 'INVALID_DEFAULT_VALUE'\n | 'UNKNOWN_EDITOR'\n | 'INCOMPATIBLE_EDITOR'\n | 'INVALID_EDITOR_OPTIONS'\n | 'UNKNOWN_FIELD_REFERENCE'\n | 'INVALID_FIELD_REFERENCE'\n | 'DUPLICATE_GROUP'\n | 'UNKNOWN_REFERENCE'\n | 'INVALID_REFERENCE_TARGET'\n | 'COMPONENT_CYCLE'\n | 'COMPONENT_TOO_DEEP'\n | 'REFERENCED_DEFINITION';\n\nexport class SchemaValidationError extends Error {\n readonly issues: readonly ValidationIssue[];\n\n constructor(issues: readonly ValidationIssue[]) {\n super(\n `Schema definition is invalid: ${issues.map((issue) => `${issue.path} ${issue.message}`).join('; ')}`,\n );\n this.name = 'SchemaValidationError';\n this.issues = issues;\n }\n}\n\nexport const issue = (path: string, code: IssueCode, message: string): ValidationIssue => ({\n path,\n code,\n message,\n});\n","import { suggestPlural } from '../naming/plural.js';\nimport type { ModelDefinition, SchemaDefinition } from '../types/definitions.js';\n\n/**\n * The names GraphQL (package J) and other generated contracts derive from API keys. Defined here, with the\n * validator, so a name that would collide in GraphQL is rejected when the model is saved, never later.\n * Package J must generate exactly these names.\n */\nexport const toTypeName = (apiKey: string): string => apiKey.charAt(0).toUpperCase() + apiKey.slice(1);\n\n/** Suffixes of the types generated for each model (`Page`, `PageFilter`, `PageInput`...). */\nexport const MODEL_TYPE_SUFFIXES = [\n '',\n 'Filter',\n 'Input',\n 'Connection',\n 'Edge',\n 'Localizations',\n 'Sort',\n] as const;\nexport const COMPONENT_TYPE_SUFFIXES = ['', 'Input'] as const;\nexport const MUTATION_PREFIXES = ['create', 'update', 'delete', 'publish', 'unpublish'] as const;\n\n/**\n * The key a model is addressed by in the delivery API (`/api/content/:routeKey`, preview routes): the\n * plural API ID of a collection, the API ID of a singleton. A collection stored before plural API IDs\n * existed gets the same derived value normalizing would fill, so this never returns undefined.\n */\nexport const routeKeyOf = (definition: ModelDefinition): string =>\n definition.kind === 'collection'\n ? definition.pluralApiKey || suggestPlural(definition.apiKey)\n : definition.apiKey;\n\n/** GraphQL list query of a collection (`articles(…)`): its plural API ID. */\nexport const collectionQueryName = (definition: ModelDefinition): string => routeKeyOf(definition);\n\n/**\n * A stored definition with the plural API ID a collection gets when it predates them (the value\n * normalizing fills), and whether anything was filled. Callers that hash definitions re-hash when `filled`.\n */\nexport const withDerivedPlural = <T extends SchemaDefinition>(\n definition: T,\n): { definition: T; filled: boolean } => {\n if (definition.kind !== 'collection' || definition.pluralApiKey) {\n return { definition, filled: false };\n }\n const { id, kind, apiKey, ...rest } = definition;\n const filled = { id, kind, apiKey, pluralApiKey: suggestPlural(apiKey), ...rest } as T;\n return { definition: filled, filled: true };\n};\n\n/**\n * GraphQL built-ins and the fixed types Shapio's schema always defines. Compared case-folded, so a model\n * called `string` (type `String`) or `pageInfo` is rejected.\n */\nexport const RESERVED_TYPE_NAMES: readonly string[] = [\n 'Query',\n 'Mutation',\n 'Subscription',\n 'String',\n 'Int',\n 'Float',\n 'Boolean',\n 'ID',\n 'JSON',\n 'Date',\n 'DateTime',\n 'Time',\n 'Decimal',\n 'BigInt',\n 'RichText',\n 'Media',\n 'MediaAsset',\n 'MediaVariant',\n 'FocalPoint',\n 'MediaKind',\n 'Int53',\n 'PageInfo',\n 'Locale',\n 'PublicationState',\n 'SortDirection',\n 'Node',\n 'Entry',\n 'Upload',\n 'StringFilter',\n 'IntFilter',\n 'FloatFilter',\n 'BooleanFilter',\n 'IDFilter',\n 'DateFilter',\n 'DateTimeFilter',\n 'TimeFilter',\n 'DecimalFilter',\n 'BigIntFilter',\n 'JSONFilter',\n // The snapshot diff (`_changes`, `_snapshot`).\n 'SnapshotChange',\n 'SnapshotChangeKind',\n 'SnapshotChangeLocale',\n 'SnapshotChangePage',\n 'SnapshotInfo',\n // The site and its SEO defaults (`_site`).\n 'SiteInfo',\n 'SiteSeoDefaults',\n 'SiteSeoLocale',\n];\n\n/**\n * Model and component API keys the admin uses as static URL segments (`/content/new`,\n * `/develop/components`), so a type with one of these keys could not be opened. Compared case-folded.\n */\nexport const RESERVED_DEFINITION_API_KEYS: readonly string[] = ['new', 'components'];\n\n/**\n * Field API keys that collide with the system fields every entry exposes in REST and GraphQL.\n * Compared case-folded.\n */\nexport const RESERVED_FIELD_API_KEYS: readonly string[] = [\n 'id',\n 'locale',\n 'localizations',\n 'status',\n 'version',\n 'createdAt',\n 'updatedAt',\n 'publishedAt',\n 'createdBy',\n 'updatedBy',\n 'publicationState',\n // Logical operators of every model's GraphQL filter input (`XFilter`), next to the field keys.\n 'and',\n 'or',\n 'not',\n];\n\n/**\n * Root query fields every GraphQL schema has, whatever models exist. Compared case-folded. The first is the\n * schema version field (schemaBuilder.ts reads it by position).\n */\nexport const RESERVED_QUERY_NAMES: readonly string[] = ['_schemaVersion', '_changes', '_snapshot', '_site'];\n\nexport type NameNamespace = 'type' | 'query' | 'mutation';\n\nexport type GeneratedName = {\n namespace: NameNamespace;\n name: string;\n /** Which definition (and field, for per-field types) produced the name, for error messages. */\n definitionId: string;\n fieldId?: string;\n /** The definition property the name comes from, when not `apiKey` (for the issue path). */\n property?: 'pluralApiKey';\n};\n\n/** Every name a definition contributes to the GraphQL schema. */\nexport const generatedNames = (definition: SchemaDefinition): GeneratedName[] => {\n const typeName = toTypeName(definition.apiKey);\n const definitionId = definition.id;\n const suffixes = definition.kind === 'component' ? COMPONENT_TYPE_SUFFIXES : MODEL_TYPE_SUFFIXES;\n const names: GeneratedName[] = suffixes.map((suffix) => ({\n namespace: 'type',\n name: `${typeName}${suffix}`,\n definitionId,\n }));\n for (const field of definition.fields) {\n const fieldType = `${typeName}${toTypeName(field.apiKey)}`;\n if (field.type === 'enum') {\n names.push({ namespace: 'type', name: `${fieldType}Enum`, definitionId, fieldId: field.id });\n }\n if (field.type === 'dynamiczone') {\n names.push({ namespace: 'type', name: `${fieldType}Zone`, definitionId, fieldId: field.id });\n names.push({ namespace: 'type', name: `${fieldType}ZoneInput`, definitionId, fieldId: field.id });\n }\n }\n if (definition.kind !== 'component') {\n names.push({ namespace: 'query', name: definition.apiKey, definitionId });\n // Only collections have a list query, so switching a singleton to a collection adds a name; the\n // switch is validated against the whole schema like any other change.\n if (definition.kind === 'collection') {\n names.push({\n namespace: 'query',\n name: collectionQueryName(definition),\n definitionId,\n property: 'pluralApiKey',\n });\n }\n for (const prefix of MUTATION_PREFIXES) {\n names.push({ namespace: 'mutation', name: `${prefix}${typeName}`, definitionId });\n }\n }\n return names;\n};\n","import type { TSchema } from 'typebox';\nimport { Value } from 'typebox/value';\n\nexport type SchemaError = { path: string; message: string };\n\n/**\n * TypeBox errors as (JSON pointer, message) pairs. The `schema is false` echo that accompanies every\n * `additionalProperties` error is dropped, and unknown properties are named in the message.\n */\nexport const collectSchemaErrors = (schema: TSchema, value: unknown, basePath = ''): SchemaError[] =>\n [...Value.Errors(schema, value)]\n .filter((error) => error.keyword !== 'boolean')\n .map((error) => {\n const extra = (error.params as { additionalProperties?: unknown }).additionalProperties;\n const message =\n error.keyword === 'additionalProperties' && Array.isArray(extra)\n ? `unknown propert${extra.length === 1 ? 'y' : 'ies'}: ${extra.join(', ')}`\n : error.message;\n return { path: `${basePath}${error.instancePath}`, message };\n });\n","import { isCoverEligible, isDocumentPlaceable } from '../display/layout.js';\nimport { effectiveTitleField, TITLE_FIELD_TYPES } from '../display/titleField.js';\nimport { EDITOR_CATALOGUE, isCustomEditorId } from '../editors/catalogue.js';\nimport { isStableId } from '../ids.js';\nimport { SCALAR_DATA_TYPES, UNIQUE_CAPABLE_DATA_TYPES } from '../types/dataTypes.js';\nimport type { FieldDefinition, FieldGroup, ModelDefinition, SchemaDefinition } from '../types/definitions.js';\nimport { checkApiKeySyntax, foldApiKey, isApiKeySyntaxValid } from './apiKey.js';\nimport { checkDefaultValue } from './defaultValue.js';\nimport { issue, type ValidationIssue } from './issues.js';\nimport { RESERVED_DEFINITION_API_KEYS, RESERVED_FIELD_API_KEYS } from './naming.js';\nimport { collectSchemaErrors } from './typeboxIssues.js';\n\n/**\n * Checks one normalized definition on its own: IDs, API keys, per-type settings, flags, editor choice and\n * display references. References to other definitions are checked by `validateSchema`.\n */\nconst RESERVED_FIELD_KEYS: ReadonlySet<string> = new Set(RESERVED_FIELD_API_KEYS.map(foldApiKey));\nconst RESERVED_DEFINITION_KEYS: ReadonlySet<string> = new Set(RESERVED_DEFINITION_API_KEYS.map(foldApiKey));\n/** GraphQL enum values must be names and cannot be `true`, `false` or `null`. */\nconst RESERVED_ENUM_VALUES: ReadonlySet<string> = new Set(['true', 'false', 'null']);\n\ntype RangeCheck = { min: unknown; max: unknown; compare: (a: never, b: never) => number; path: string };\n\nconst compareNumbers = (a: number, b: number) => a - b;\nconst compareBigInts = (a: string, b: string) => {\n const diff = BigInt(a) - BigInt(b);\n return diff === 0n ? 0 : diff > 0n ? 1 : -1;\n};\nconst compareDecimals = (a: string, b: string) => Number(a) - Number(b);\nconst compareText = (a: string, b: string) => (a === b ? 0 : a > b ? 1 : -1);\n\nconst checkRange = ({ min, max, compare, path }: RangeCheck): ValidationIssue[] =>\n min !== undefined && max !== undefined && compare(min as never, max as never) > 0\n ? [issue(path, 'INVALID_RANGE', 'minimum is greater than maximum')]\n : [];\n\nconst settingsRanges = (field: FieldDefinition, path: string): ValidationIssue[] => {\n const s = field.settings as Record<string, unknown>;\n const issues: ValidationIssue[] = [];\n issues.push(\n ...checkRange({ min: s.minLength, max: s.maxLength, compare: compareNumbers, path: `${path}/minLength` }),\n );\n switch (field.type) {\n case 'number':\n case 'integer':\n case 'media':\n case 'relation':\n case 'component':\n case 'dynamiczone':\n issues.push(...checkRange({ min: s.min, max: s.max, compare: compareNumbers, path: `${path}/min` }));\n break;\n case 'biginteger':\n issues.push(...checkRange({ min: s.min, max: s.max, compare: compareBigInts, path: `${path}/min` }));\n break;\n case 'decimal':\n issues.push(...checkRange({ min: s.min, max: s.max, compare: compareDecimals, path: `${path}/min` }));\n if (field.settings.scale !== undefined && field.settings.precision !== undefined) {\n issues.push(\n ...checkRange({\n min: field.settings.scale,\n max: field.settings.precision,\n compare: compareNumbers,\n path: `${path}/scale`,\n }),\n );\n }\n break;\n case 'date':\n case 'datetime':\n case 'time':\n issues.push(...checkRange({ min: s.min, max: s.max, compare: compareText, path: `${path}/min` }));\n break;\n default:\n break;\n }\n return issues;\n};\n\nconst checkSettings = (\n field: FieldDefinition,\n path: string,\n definition: SchemaDefinition,\n): ValidationIssue[] => {\n const issues = settingsRanges(field, `${path}/settings`);\n if (field.type === 'string' && field.settings.pattern !== undefined) {\n try {\n new RegExp(field.settings.pattern, 'u');\n } catch {\n issues.push(issue(`${path}/settings/pattern`, 'INVALID_PATTERN', 'is not a valid regular expression'));\n }\n }\n if (field.type === 'enum') {\n const seen = new Set<string>();\n field.settings.values.forEach((entry, index) => {\n const entryPath = `${path}/settings/values/${index}/value`;\n if (\n !isApiKeySyntaxValid(entry.value) ||\n entry.value.startsWith('__') ||\n RESERVED_ENUM_VALUES.has(entry.value)\n ) {\n issues.push(\n issue(\n entryPath,\n 'INVALID_ENUM_VALUE',\n 'enum values must be GraphQL names (letters, digits, _), not true/false/null',\n ),\n );\n }\n if (seen.has(entry.value)) {\n issues.push(issue(entryPath, 'DUPLICATE_ENUM_VALUE', `\"${entry.value}\" is listed twice`));\n }\n seen.add(entry.value);\n });\n }\n if (field.type === 'slug' && field.settings.sourceFieldId !== undefined) {\n const source = definition.fields.find((candidate) => candidate.id === field.settings.sourceFieldId);\n if (!source) {\n issues.push(\n issue(\n `${path}/settings/sourceFieldId`,\n 'UNKNOWN_FIELD_REFERENCE',\n 'refers to no field of this definition',\n ),\n );\n } else if (source.type !== 'string' && source.type !== 'text') {\n issues.push(\n issue(\n `${path}/settings/sourceFieldId`,\n 'INVALID_FIELD_REFERENCE',\n 'must refer to a string or text field',\n ),\n );\n }\n }\n if (field.type === 'richtext' && field.settings.formatVersion !== 1) {\n issues.push(\n issue(`${path}/settings/formatVersion`, 'INVALID_SETTINGS', 'unsupported rich-text format version'),\n );\n }\n if (field.type === 'relation' && !isStableId(field.settings.target)) {\n issues.push(issue(`${path}/settings/target`, 'INVALID_ID', 'must be the ID of a model'));\n }\n if (field.type === 'component' && !isStableId(field.settings.component)) {\n issues.push(issue(`${path}/settings/component`, 'INVALID_ID', 'must be the ID of a component'));\n }\n if (field.type === 'dynamiczone') {\n field.settings.components.forEach((id, index) => {\n if (!isStableId(id)) {\n issues.push(\n issue(`${path}/settings/components/${index}`, 'INVALID_ID', 'must be the ID of a component'),\n );\n }\n });\n }\n return issues;\n};\n\nconst checkFlags = (field: FieldDefinition, path: string, isComponent: boolean): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n const reject = (flag: string, why: string) =>\n issues.push(issue(`${path}/${flag}`, 'UNSUPPORTED_FLAG', why));\n if (field.unique && !UNIQUE_CAPABLE_DATA_TYPES.has(field.type)) {\n reject('unique', `${field.type} fields cannot be unique`);\n }\n for (const flag of ['filterable', 'sortable'] as const) {\n if (field[flag] && !SCALAR_DATA_TYPES.has(field.type)) {\n reject(flag, `${field.type} fields cannot be ${flag}`);\n }\n if (field[flag] && field.type === 'enum' && field.settings.multiple) {\n reject(flag, `multi-value enum fields cannot be ${flag}`);\n }\n }\n if (isComponent) {\n // Component values live inside a parent entry field; uniqueness and indexes apply to entry fields only.\n for (const flag of ['unique', 'filterable', 'sortable'] as const) {\n if (field[flag]) {\n reject(flag, `fields of a component cannot be ${flag}`);\n }\n }\n }\n if (field.deprecated && field.required) {\n reject('required', 'a deprecated field cannot be required');\n }\n return issues;\n};\n\nconst checkEditor = (field: FieldDefinition, path: string): ValidationIssue[] => {\n const { id, options } = field.editor;\n if (isCustomEditorId(id)) {\n return [];\n }\n const entry = EDITOR_CATALOGUE.get(id);\n if (!entry) {\n return [\n issue(\n `${path}/editor/id`,\n 'UNKNOWN_EDITOR',\n `\"${id}\" is not a built-in editor (custom editors use a vendor.name ID)`,\n ),\n ];\n }\n if (!entry.dataTypes.includes(field.type) || !(entry.supports?.(field) ?? true)) {\n return [\n issue(\n `${path}/editor/id`,\n 'INCOMPATIBLE_EDITOR',\n `the ${id} editor cannot edit this ${field.type} field`,\n ),\n ];\n }\n return collectSchemaErrors(entry.optionsSchema, options, `${path}/editor/options`).map((error) =>\n issue(error.path, 'INVALID_EDITOR_OPTIONS', error.message),\n );\n};\n\nconst checkField = (\n field: FieldDefinition,\n index: number,\n definition: SchemaDefinition,\n): ValidationIssue[] => {\n const path = `/fields/${index}`;\n const issues: ValidationIssue[] = [];\n if (!isStableId(field.id)) {\n issues.push(issue(`${path}/id`, 'INVALID_ID', 'must be a lower-case UUID'));\n }\n const syntax = checkApiKeySyntax(field.apiKey);\n if (syntax) {\n issues.push(issue(`${path}/apiKey`, syntax.code, syntax.message));\n } else if (RESERVED_FIELD_KEYS.has(foldApiKey(field.apiKey))) {\n issues.push(issue(`${path}/apiKey`, 'API_KEY_RESERVED', `\"${field.apiKey}\" is a system field name`));\n }\n issues.push(...checkSettings(field, path, definition));\n issues.push(...checkFlags(field, path, definition.kind === 'component'));\n const defaultProblem = checkDefaultValue(field);\n if (defaultProblem) {\n issues.push(issue(`${path}/defaultValue`, 'INVALID_DEFAULT_VALUE', defaultProblem));\n }\n issues.push(...checkEditor(field, path));\n return issues;\n};\n\nconst checkFieldUniqueness = (definition: SchemaDefinition): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n const ids = new Set<string>();\n const keys = new Map<string, string>();\n definition.fields.forEach((field, index) => {\n if (ids.has(field.id)) {\n issues.push(issue(`/fields/${index}/id`, 'DUPLICATE_ID', 'another field has the same ID'));\n }\n ids.add(field.id);\n const folded = foldApiKey(field.apiKey);\n const clash = keys.get(folded);\n if (clash !== undefined) {\n issues.push(\n issue(\n `/fields/${index}/apiKey`,\n 'API_KEY_COLLISION',\n `\"${field.apiKey}\" collides with field \"${clash}\" (keys are case-insensitive)`,\n ),\n );\n }\n keys.set(folded, field.apiKey);\n });\n return issues;\n};\n\nconst checkGroups = (\n groups: readonly FieldGroup[] | undefined,\n fieldIds: ReadonlySet<string>,\n): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n const groupIds = new Set<string>();\n const placed = new Set<string>();\n (groups ?? []).forEach((group, groupIndex) => {\n if (groupIds.has(group.id)) {\n issues.push(\n issue(`/display/groups/${groupIndex}/id`, 'DUPLICATE_GROUP', 'another group has the same ID'),\n );\n }\n groupIds.add(group.id);\n group.fieldIds.forEach((fieldId, index) => {\n const path = `/display/groups/${groupIndex}/fieldIds/${index}`;\n if (!fieldIds.has(fieldId)) {\n issues.push(issue(path, 'UNKNOWN_FIELD_REFERENCE', 'refers to no field of this definition'));\n } else if (placed.has(fieldId)) {\n issues.push(issue(path, 'INVALID_FIELD_REFERENCE', 'a field can be in one group only'));\n }\n placed.add(fieldId);\n });\n });\n return issues;\n};\n\ntype FieldReferenceCheck = {\n path: string;\n fields: ReadonlyMap<string, FieldDefinition>;\n /** Returns why the field can't be used here, or undefined when it can. */\n reject: (field: FieldDefinition) => string | undefined;\n};\n\n/** A list of field IDs: each must exist, appear once and pass `reject`. */\nconst checkFieldList = (\n ids: readonly string[] | undefined,\n check: FieldReferenceCheck,\n): ValidationIssue[] => {\n const seen = new Set<string>();\n return (ids ?? []).flatMap((fieldId, index) => {\n const path = `${check.path}/${index}`;\n const field = check.fields.get(fieldId);\n if (!field) {\n return [issue(path, 'UNKNOWN_FIELD_REFERENCE', 'refers to no field of this definition')];\n }\n if (seen.has(fieldId)) {\n return [issue(path, 'INVALID_FIELD_REFERENCE', 'the field is listed more than once')];\n }\n seen.add(fieldId);\n const reason = check.reject(field);\n return reason ? [issue(path, 'INVALID_FIELD_REFERENCE', reason)] : [];\n });\n};\n\n/**\n * The entry document's layout (`effectiveLayout`): document fields, cover and strip. Title, cover and\n * canvas are disjoint: any field but the title (configured or automatic) may be in the canvas, the\n * configured cover may not; strip entries are properties, so never the cover or a document field.\n */\nconst checkDocumentLayout = (\n model: ModelDefinition,\n fields: ReadonlyMap<string, FieldDefinition>,\n): ValidationIssue[] => {\n const { canvasFieldIds, coverFieldId, stripFieldIds } = model.display;\n const canvas = new Set(canvasFieldIds ?? []);\n const title = effectiveTitleField(model);\n const issues = checkFieldList(canvasFieldIds, {\n path: '/display/canvasFieldIds',\n fields,\n reject: (field) =>\n isDocumentPlaceable(field, title)\n ? undefined\n : 'the title is the heading of the document, not a field in it',\n });\n if (coverFieldId !== undefined) {\n issues.push(\n ...checkFieldList([coverFieldId], {\n path: '/display/coverFieldId',\n fields,\n reject: (field) =>\n !isCoverEligible(field)\n ? 'the cover must be a single media field that allows images'\n : canvas.has(field.id)\n ? 'the cover cannot also be in the canvas'\n : undefined,\n }).map((found) => ({ ...found, path: '/display/coverFieldId' })),\n );\n }\n issues.push(\n ...checkFieldList(stripFieldIds, {\n path: '/display/stripFieldIds',\n fields,\n reject: (field) =>\n canvas.has(field.id) || field.id === coverFieldId\n ? 'the strip shows properties, not the cover or canvas blocks'\n : undefined,\n }),\n );\n return issues;\n};\n\nconst checkDisplay = (definition: SchemaDefinition): ValidationIssue[] => {\n const fields = new Map(definition.fields.map((field) => [field.id, field]));\n const fieldIds = new Set(fields.keys());\n const issues: ValidationIssue[] = [];\n const { titleFieldId } = definition.display;\n if (titleFieldId !== undefined) {\n const title = fields.get(titleFieldId);\n if (!title) {\n issues.push(\n issue('/display/titleFieldId', 'UNKNOWN_FIELD_REFERENCE', 'refers to no field of this definition'),\n );\n } else if (!TITLE_FIELD_TYPES.has(title.type)) {\n issues.push(\n issue(\n '/display/titleFieldId',\n 'INVALID_FIELD_REFERENCE',\n `a ${title.type} field cannot be the title`,\n ),\n );\n }\n }\n if (definition.kind !== 'component') {\n definition.display.listFieldIds?.forEach((fieldId, index) => {\n if (!fieldIds.has(fieldId)) {\n issues.push(\n issue(\n `/display/listFieldIds/${index}`,\n 'UNKNOWN_FIELD_REFERENCE',\n 'refers to no field of this definition',\n ),\n );\n }\n });\n const sort = definition.display.defaultSort;\n if (sort) {\n const field = fields.get(sort.fieldId);\n if (!field) {\n issues.push(\n issue(\n '/display/defaultSort/fieldId',\n 'UNKNOWN_FIELD_REFERENCE',\n 'refers to no field of this definition',\n ),\n );\n } else if (!field.sortable) {\n issues.push(\n issue(\n '/display/defaultSort/fieldId',\n 'INVALID_FIELD_REFERENCE',\n 'the default sort field must be sortable',\n ),\n );\n }\n }\n issues.push(...checkDocumentLayout(definition, fields));\n }\n issues.push(...checkGroups(definition.display.groups, fieldIds));\n return issues;\n};\n\n/**\n * A collection's plural API ID follows the API ID rules and must differ from its singular. Singletons and\n * components have none (normalizing drops it).\n */\nconst checkPluralApiKey = (definition: SchemaDefinition): ValidationIssue[] => {\n if (definition.kind !== 'collection' || definition.pluralApiKey === undefined) {\n return [];\n }\n const syntax = checkApiKeySyntax(definition.pluralApiKey, 'plural API ID');\n if (syntax) {\n return [issue('/pluralApiKey', syntax.code, syntax.message)];\n }\n if (foldApiKey(definition.pluralApiKey) === foldApiKey(definition.apiKey)) {\n return [\n issue(\n '/pluralApiKey',\n 'PLURAL_API_KEY_SAME_AS_SINGULAR',\n 'the plural API ID must differ from the API ID (case-insensitively)',\n ),\n ];\n }\n return [];\n};\n\n/** All problems with one definition, in document order. Empty means valid on its own. */\nexport const validateDefinition = (definition: SchemaDefinition): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n if (!isStableId(definition.id)) {\n issues.push(issue('/id', 'INVALID_ID', 'must be a lower-case UUID'));\n }\n const syntax = checkApiKeySyntax(definition.apiKey);\n if (syntax) {\n issues.push(issue('/apiKey', syntax.code, syntax.message));\n } else if (RESERVED_DEFINITION_KEYS.has(foldApiKey(definition.apiKey))) {\n issues.push(issue('/apiKey', 'API_KEY_RESERVED', `\"${definition.apiKey}\" is reserved by the admin`));\n }\n // A plural derived from an invalid API ID is invalid too; report the API ID once.\n if (!syntax) {\n issues.push(...checkPluralApiKey(definition));\n }\n definition.fields.forEach((field, index) => issues.push(...checkField(field, index, definition)));\n issues.push(...checkFieldUniqueness(definition));\n issues.push(...checkDisplay(definition));\n return issues;\n};\n","import { createStableId } from '../ids.js';\nimport { normalizeDefinition, type DefinitionInputWithIds, type FieldInputWithId } from '../normalize.js';\nimport {\n ComponentDefinitionInputSchema,\n ModelDefinitionInputSchema,\n type DefinitionInput,\n type FieldInput,\n type SchemaDefinition,\n} from '../types/definitions.js';\nimport { SETTINGS_SCHEMAS } from '../types/settings.js';\nimport { foldApiKey } from './apiKey.js';\nimport { validateDefinition } from './definition.js';\nimport { issue, type ValidationIssue } from './issues.js';\nimport { collectSchemaErrors } from './typeboxIssues.js';\n\nexport type ParseDefinitionResult =\n { ok: true; definition: SchemaDefinition } | { ok: false; issues: ValidationIssue[] };\n\nexport type ParseDefinitionOptions = {\n /**\n * The current definition, if this is an edit. Fields sent without an `id` are matched to the current\n * field with the same API key (case-insensitive) and keep its ID; unmatched fields get a new ID.\n */\n previous?: SchemaDefinition;\n createId?: () => string;\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst structuralIssues = (raw: Record<string, unknown>): ValidationIssue[] => {\n const schema = raw.kind === 'component' ? ComponentDefinitionInputSchema : ModelDefinitionInputSchema;\n const issues = collectSchemaErrors(schema, raw).map((error) =>\n issue(error.path, 'INVALID_STRUCTURE', error.message),\n );\n if (issues.length > 0) {\n return issues;\n }\n const fields = raw.fields as FieldInput[];\n fields.forEach((field, index) => {\n const settingsSchema = SETTINGS_SCHEMAS[field.type];\n for (const error of collectSchemaErrors(\n settingsSchema,\n field.settings ?? {},\n `/fields/${index}/settings`,\n )) {\n issues.push(issue(error.path, 'INVALID_SETTINGS', error.message));\n }\n });\n return issues;\n};\n\n/** Fills in missing definition and field IDs (see ParseDefinitionOptions.previous). */\nexport const assignIds = (\n input: DefinitionInput,\n { previous, createId = createStableId }: ParseDefinitionOptions = {},\n): DefinitionInputWithIds => {\n const explicitIds = new Set(input.fields.flatMap((field) => (field.id ? [field.id] : [])));\n const previousByKey = new Map(\n (previous?.fields ?? [])\n .filter((field) => !explicitIds.has(field.id))\n .map((field) => [foldApiKey(field.apiKey), field.id]),\n );\n const fields: FieldInputWithId[] = input.fields.map((field) => {\n if (field.id) {\n return { ...field, id: field.id };\n }\n const matched = previousByKey.get(foldApiKey(field.apiKey));\n previousByKey.delete(foldApiKey(field.apiKey));\n return { ...field, id: matched ?? createId() };\n });\n return { ...input, id: input.id ?? previous?.id ?? createId(), fields };\n};\n\n/**\n * The single entry point from untrusted input (request bodies, schema files) to a normalized definition:\n * structure, settings per data type, ID assignment, defaults, then the per-definition semantic checks.\n * Cross-definition rules (references, cycles, GraphQL name collisions) are `validateSchema`'s job.\n */\nexport const parseDefinition = (\n raw: unknown,\n options: ParseDefinitionOptions = {},\n): ParseDefinitionResult => {\n if (!isObject(raw)) {\n return { ok: false, issues: [issue('', 'INVALID_STRUCTURE', 'a definition must be a JSON object')] };\n }\n const structural = structuralIssues(raw);\n if (structural.length > 0) {\n return { ok: false, issues: structural };\n }\n const definition = normalizeDefinition(assignIds(raw as DefinitionInput, options));\n const issues = validateDefinition(definition);\n return issues.length > 0 ? { ok: false, issues } : { ok: true, definition };\n};\n","import type { SchemaDefinition } from '../types/definitions.js';\nimport { foldApiKey } from './apiKey.js';\nimport { issue, type ValidationIssue } from './issues.js';\nimport {\n generatedNames,\n RESERVED_QUERY_NAMES,\n RESERVED_TYPE_NAMES,\n routeKeyOf,\n type GeneratedName,\n} from './naming.js';\n\n/** Deepest allowed nesting of components (a component inside a component inside ... ) below an entry. */\nexport const MAX_COMPONENT_DEPTH = 5;\n\nconst RESERVED_TYPES: ReadonlySet<string> = new Set(RESERVED_TYPE_NAMES.map(foldApiKey));\nconst RESERVED_QUERIES: ReadonlySet<string> = new Set(RESERVED_QUERY_NAMES.map(foldApiKey));\n\nconst withDefinition = (definition: SchemaDefinition, found: ValidationIssue): ValidationIssue => ({\n ...found,\n definitionId: definition.id,\n});\n\nconst describeOrigin = (name: GeneratedName, byId: ReadonlyMap<string, SchemaDefinition>) => {\n const definition = byId.get(name.definitionId);\n const field = name.fieldId\n ? definition?.fields.find((candidate) => candidate.id === name.fieldId)\n : undefined;\n return field ? `${definition?.apiKey ?? '?'}.${field.apiKey}` : (definition?.apiKey ?? '?');\n};\n\n/** The API IDs a definition claims in the shared case-insensitive namespace, with their issue paths. */\nconst claimedKeys = (definition: SchemaDefinition): Array<{ key: string; path: string; plural: boolean }> => {\n const keys = [{ key: definition.apiKey, path: '/apiKey', plural: false }];\n const plural = definition.kind === 'collection' ? routeKeyOf(definition) : '';\n if (plural) {\n keys.push({ key: plural, path: '/pluralApiKey', plural: true });\n }\n return keys;\n};\n\nconst describeKey = ({ definition, key }: { definition: SchemaDefinition; key: string }) =>\n key === definition.apiKey ? `\"${key}\"` : `the plural API ID \"${key}\" of \"${definition.apiKey}\"`;\n\nconst checkIdentity = (definitions: readonly SchemaDefinition[]): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n const ids = new Set<string>();\n const keys = new Map<string, { definition: SchemaDefinition; key: string }>();\n const fieldOwners = new Map<string, SchemaDefinition>();\n for (const definition of definitions) {\n if (ids.has(definition.id)) {\n issues.push(\n withDefinition(definition, issue('/id', 'DUPLICATE_ID', 'another definition has the same ID')),\n );\n }\n ids.add(definition.id);\n // Plural API IDs share the namespace: `/api/content/posts` and the `posts` query must be unambiguous.\n for (const { key, path, plural } of claimedKeys(definition)) {\n const folded = foldApiKey(key);\n const clash = keys.get(folded);\n if (clash && clash.definition.id !== definition.id) {\n issues.push(\n withDefinition(\n definition,\n issue(\n path,\n 'API_KEY_COLLISION',\n `${plural ? 'the plural API ID ' : ''}\"${key}\" collides with ${describeKey(clash)} (models and components share one case-insensitive namespace)`,\n ),\n ),\n );\n }\n if (!clash) {\n keys.set(folded, { definition, key });\n }\n }\n definition.fields.forEach((field, index) => {\n const owner = fieldOwners.get(field.id);\n if (owner && owner.id !== definition.id) {\n issues.push(\n withDefinition(\n definition,\n issue(\n `/fields/${index}/id`,\n 'DUPLICATE_ID',\n `field ID is already used by \"${owner.apiKey}\"; field IDs are global`,\n ),\n ),\n );\n }\n fieldOwners.set(field.id, definition);\n });\n }\n return issues;\n};\n\nconst checkGeneratedNames = (definitions: readonly SchemaDefinition[]): ValidationIssue[] => {\n const byId = new Map(definitions.map((definition) => [definition.id, definition]));\n const issues: ValidationIssue[] = [];\n const seen = new Map<string, GeneratedName>();\n for (const definition of definitions) {\n for (const name of generatedNames(definition)) {\n const folded = `${name.namespace}:${foldApiKey(name.name)}`;\n const path = name.fieldId\n ? `/fields/${definition.fields.findIndex((field) => field.id === name.fieldId)}/apiKey`\n : `/${name.property ?? 'apiKey'}`;\n if (name.namespace === 'type' && RESERVED_TYPES.has(foldApiKey(name.name))) {\n issues.push(\n withDefinition(\n definition,\n issue(path, 'API_KEY_RESERVED', `generates the GraphQL type \"${name.name}\", which is reserved`),\n ),\n );\n continue;\n }\n if (name.namespace === 'query' && RESERVED_QUERIES.has(foldApiKey(name.name))) {\n issues.push(\n withDefinition(\n definition,\n issue(path, 'API_KEY_RESERVED', `generates the GraphQL query \"${name.name}\", which is reserved`),\n ),\n );\n continue;\n }\n const clash = seen.get(folded);\n if (clash && (clash.definitionId !== name.definitionId || clash.fieldId !== name.fieldId)) {\n issues.push(\n withDefinition(\n definition,\n issue(\n path,\n 'GENERATED_NAME_COLLISION',\n `generates the GraphQL ${name.namespace} name \"${name.name}\", which \"${describeOrigin(clash, byId)}\" already generates`,\n ),\n ),\n );\n continue;\n }\n seen.set(folded, name);\n }\n }\n return issues;\n};\n\n/** Component IDs a definition embeds directly (component and dynamic-zone fields). */\nexport const embeddedComponentIds = (definition: SchemaDefinition): string[] =>\n definition.fields.flatMap((field) => {\n if (field.type === 'component') {\n return [field.settings.component];\n }\n if (field.type === 'dynamiczone') {\n return field.settings.components;\n }\n return [];\n });\n\nconst checkReferences = (definitions: readonly SchemaDefinition[]): ValidationIssue[] => {\n const byId = new Map(definitions.map((definition) => [definition.id, definition]));\n const issues: ValidationIssue[] = [];\n for (const definition of definitions) {\n definition.fields.forEach((field, index) => {\n const path = `/fields/${index}/settings`;\n const expectComponent = (id: string, at: string) => {\n const target = byId.get(id);\n if (!target) {\n issues.push(withDefinition(definition, issue(at, 'UNKNOWN_REFERENCE', 'refers to no component')));\n } else if (target.kind !== 'component') {\n issues.push(\n withDefinition(\n definition,\n issue(at, 'INVALID_REFERENCE_TARGET', `\"${target.apiKey}\" is a model, not a component`),\n ),\n );\n }\n };\n if (field.type === 'relation') {\n const target = byId.get(field.settings.target);\n if (!target) {\n issues.push(\n withDefinition(definition, issue(`${path}/target`, 'UNKNOWN_REFERENCE', 'refers to no model')),\n );\n } else if (target.kind !== 'collection') {\n issues.push(\n withDefinition(\n definition,\n issue(\n `${path}/target`,\n 'INVALID_REFERENCE_TARGET',\n `relations must target a collection model; \"${target.apiKey}\" is a ${target.kind}`,\n ),\n ),\n );\n }\n }\n if (field.type === 'component') {\n expectComponent(field.settings.component, `${path}/component`);\n }\n if (field.type === 'dynamiczone') {\n const seen = new Set<string>();\n field.settings.components.forEach((id, componentIndex) => {\n const at = `${path}/components/${componentIndex}`;\n if (seen.has(id)) {\n issues.push(withDefinition(definition, issue(at, 'DUPLICATE_ID', 'component listed twice')));\n }\n seen.add(id);\n expectComponent(id, at);\n });\n }\n });\n }\n return issues;\n};\n\n/**\n * Longest chain of nested components below each definition, or a cycle. Depth 1 means the definition\n * embeds components that embed nothing.\n */\nconst checkNesting = (definitions: readonly SchemaDefinition[]): ValidationIssue[] => {\n const byId = new Map(definitions.map((definition) => [definition.id, definition]));\n const depthOf = new Map<string, number>();\n const issues: ValidationIssue[] = [];\n const reported = new Set<string>();\n\n const visit = (id: string, stack: string[]): number => {\n const known = depthOf.get(id);\n if (known !== undefined) {\n return known;\n }\n if (stack.includes(id)) {\n const cycle = [...stack.slice(stack.indexOf(id)), id].map(\n (member) => byId.get(member)?.apiKey ?? member,\n );\n const definition = byId.get(id);\n if (definition && !reported.has(id)) {\n reported.add(id);\n issues.push(\n withDefinition(\n definition,\n issue('/fields', 'COMPONENT_CYCLE', `components nest in a cycle: ${cycle.join(' → ')}`),\n ),\n );\n }\n return Number.POSITIVE_INFINITY;\n }\n const definition = byId.get(id);\n if (!definition) {\n return 0;\n }\n const children = embeddedComponentIds(definition).filter(\n (child) => byId.get(child)?.kind === 'component',\n );\n const depth =\n children.length === 0 ? 0 : 1 + Math.max(...children.map((child) => visit(child, [...stack, id])));\n depthOf.set(id, depth);\n return depth;\n };\n\n for (const definition of definitions) {\n const depth = visit(definition.id, []);\n if (Number.isFinite(depth) && depth > MAX_COMPONENT_DEPTH && definition.kind !== 'component') {\n issues.push(\n withDefinition(\n definition,\n issue(\n '/fields',\n 'COMPONENT_TOO_DEEP',\n `components nest ${depth} levels deep; the limit is ${MAX_COMPONENT_DEPTH}`,\n ),\n ),\n );\n }\n }\n return issues;\n};\n\n/**\n * Cross-definition checks over a whole schema (every active definition with the proposed change applied):\n * unique IDs and API keys, GraphQL name collisions, relation and component targets, component cycles and\n * nesting depth. Each definition must already pass `validateDefinition`.\n */\nexport const validateSchema = (definitions: readonly SchemaDefinition[]): ValidationIssue[] => [\n ...checkIdentity(definitions),\n ...checkGeneratedNames(definitions),\n ...checkReferences(definitions),\n ...checkNesting(definitions),\n];\n\n/** Definitions that reference `id` (relations, components, dynamic zones). Used to block deletions. */\nexport const findReferencingDefinitions = (\n definitions: readonly SchemaDefinition[],\n id: string,\n): SchemaDefinition[] =>\n definitions.filter(\n (definition) =>\n definition.id !== id &&\n definition.fields.some(\n (field) =>\n (field.type === 'relation' && field.settings.target === id) ||\n (field.type === 'component' && field.settings.component === id) ||\n (field.type === 'dynamiczone' && field.settings.components.includes(id)),\n ),\n );\n\n/**\n * Models that embed a component directly or through other components, i.e. whose entries change shape\n * when the component does (brief §5: \"editing a shared component must account for all dependent models\").\n */\nexport const findDependentModels = (\n definitions: readonly SchemaDefinition[],\n componentId: string,\n): SchemaDefinition[] => {\n const embeddedBy = new Map<string, SchemaDefinition[]>();\n for (const definition of definitions) {\n for (const child of embeddedComponentIds(definition)) {\n embeddedBy.set(child, [...(embeddedBy.get(child) ?? []), definition]);\n }\n }\n const models = new Map<string, SchemaDefinition>();\n const visited = new Set<string>();\n const queue = [componentId];\n while (queue.length > 0) {\n const current = queue.shift() as string;\n if (visited.has(current)) {\n continue;\n }\n visited.add(current);\n for (const parent of embeddedBy.get(current) ?? []) {\n if (parent.kind === 'component') {\n queue.push(parent.id);\n } else {\n models.set(parent.id, parent);\n }\n }\n }\n return [...models.values()];\n};\n","import type { JsonValue } from '../types/json.js';\n\nexport const CHANGE_KINDS = [\n 'definition.added',\n 'definition.removed',\n 'definition.apiKey',\n 'definition.pluralApiKey',\n 'definition.metadata',\n 'model.kind',\n 'model.localized',\n 'model.draftAndPublish',\n 'field.added',\n 'field.removed',\n 'field.order',\n 'field.apiKey',\n 'field.metadata',\n 'field.editor',\n 'field.type',\n 'field.required',\n 'field.localized',\n 'field.public',\n 'field.deprecated',\n 'field.unique',\n 'field.filterable',\n 'field.sortable',\n 'field.settings',\n] as const;\n\nexport type ChangeKind = (typeof CHANGE_KINDS)[number];\n\n/**\n * One difference between two versions of a definition. `property` names the changed property for\n * `*.metadata` (`label`, `description`, ...) and `field.settings` (the settings key); `from`/`to` hold the\n * old and new values (absent when the side does not exist).\n */\nexport type SchemaChange = {\n kind: ChangeKind;\n definitionId: string;\n fieldId?: string;\n property?: string;\n from?: JsonValue;\n to?: JsonValue;\n};\n","import type { SchemaDefinition } from '../types/definitions.js';\n\n/**\n * Canonical JSON: object keys sorted by code point at every level, arrays in their given order (field\n * order is meaningful: it is the form order), two-space indentation and a trailing newline. Two equal\n * definitions always serialize to the same bytes, so files diff cleanly in git and hashes are stable.\n */\nconst sortKeys = (value: unknown): unknown => {\n if (Array.isArray(value)) {\n return value.map(sortKeys);\n }\n if (typeof value === 'object' && value !== null) {\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(value).sort()) {\n const entry = (value as Record<string, unknown>)[key];\n if (entry !== undefined) {\n sorted[key] = sortKeys(entry);\n }\n }\n return sorted;\n }\n return value;\n};\n\nexport const canonicalJson = (value: unknown): string => `${JSON.stringify(sortKeys(value), null, 2)}\\n`;\n\n/**\n * The bytes Shapio hashes and writes for a definition. The definition must be normalized\n * (`normalizeDefinition`), so defaults are explicit and the same meaning has one spelling.\n */\nexport const serializeDefinition = (definition: SchemaDefinition): string => canonicalJson(definition);\n","import { canonicalJson } from '../fileFormat/canonical.js';\nimport type { FieldDefinition, SchemaDefinition } from '../types/definitions.js';\nimport type { JsonValue } from '../types/json.js';\nimport { routeKeyOf } from '../validators/naming.js';\nimport type { SchemaChange } from './types.js';\n\nconst same = (a: unknown, b: unknown): boolean => canonicalJson(a ?? null) === canonicalJson(b ?? null);\nconst asJson = (value: unknown): JsonValue | undefined => value as JsonValue | undefined;\n\nconst DEFINITION_METADATA = ['label', 'description', 'category', 'icon', 'display'] as const;\nconst FIELD_METADATA = ['label', 'description', 'defaultValue'] as const;\nconst FIELD_FLAGS = [\n ['required', 'field.required'],\n ['localized', 'field.localized'],\n ['public', 'field.public'],\n ['deprecated', 'field.deprecated'],\n ['unique', 'field.unique'],\n ['filterable', 'field.filterable'],\n ['sortable', 'field.sortable'],\n] as const;\n\nconst diffFieldSettings = (\n definitionId: string,\n before: FieldDefinition,\n after: FieldDefinition,\n): SchemaChange[] => {\n const from = before.settings as Record<string, unknown>;\n const to = after.settings as Record<string, unknown>;\n const keys = [...new Set([...Object.keys(from), ...Object.keys(to)])].sort();\n return keys\n .filter((key) => !same(from[key], to[key]))\n .map((key) => ({\n kind: 'field.settings',\n definitionId,\n fieldId: after.id,\n property: key,\n from: asJson(from[key]),\n to: asJson(to[key]),\n }));\n};\n\nconst diffField = (definitionId: string, before: FieldDefinition, after: FieldDefinition): SchemaChange[] => {\n const changes: SchemaChange[] = [];\n const base = { definitionId, fieldId: after.id };\n if (before.apiKey !== after.apiKey) {\n changes.push({ ...base, kind: 'field.apiKey', from: before.apiKey, to: after.apiKey });\n }\n for (const property of FIELD_METADATA) {\n if (!same(before[property], after[property])) {\n changes.push({\n ...base,\n kind: 'field.metadata',\n property,\n from: asJson(before[property]),\n to: asJson(after[property]),\n });\n }\n }\n if (!same(before.editor, after.editor)) {\n changes.push({ ...base, kind: 'field.editor', from: before.editor, to: after.editor });\n }\n if (before.type !== after.type) {\n // Settings are type-specific; a type change is planned as one conversion including its new settings.\n changes.push({ ...base, kind: 'field.type', from: before.type, to: after.type });\n } else {\n changes.push(...diffFieldSettings(definitionId, before, after));\n }\n for (const [flag, kind] of FIELD_FLAGS) {\n if (before[flag] !== after[flag]) {\n changes.push({ ...base, kind, from: before[flag], to: after[flag] });\n }\n }\n return changes;\n};\n\n/**\n * Every difference between two versions of a definition, matched by stable IDs (so a renamed field is a\n * rename, not a removal plus an addition). Pass `null` for a side that does not exist. The order is\n * deterministic: definition-level changes, then fields in the new order, then removed fields.\n */\nexport const diffDefinitions = (\n before: SchemaDefinition | null,\n after: SchemaDefinition | null,\n): SchemaChange[] => {\n if (!before && !after) {\n return [];\n }\n if (!before) {\n return [\n {\n kind: 'definition.added',\n definitionId: (after as SchemaDefinition).id,\n to: (after as SchemaDefinition).apiKey,\n },\n ];\n }\n if (!after) {\n return [{ kind: 'definition.removed', definitionId: before.id, from: before.apiKey }];\n }\n const definitionId = after.id;\n const changes: SchemaChange[] = [];\n if (before.apiKey !== after.apiKey) {\n changes.push({ kind: 'definition.apiKey', definitionId, from: before.apiKey, to: after.apiKey });\n }\n const beforeRecord = before as unknown as Record<string, unknown>;\n const afterRecord = after as unknown as Record<string, unknown>;\n for (const property of DEFINITION_METADATA) {\n if (!same(beforeRecord[property], afterRecord[property])) {\n changes.push({\n kind: 'definition.metadata',\n definitionId,\n property,\n from: asJson(beforeRecord[property]),\n to: asJson(afterRecord[property]),\n });\n }\n }\n if (before.kind !== after.kind) {\n changes.push({ kind: 'model.kind', definitionId, from: before.kind, to: after.kind });\n }\n // Only between two collections: a kind switch is its own (breaking) change and adds or drops the plural.\n if (before.kind === 'collection' && after.kind === 'collection') {\n const [from, to] = [routeKeyOf(before), routeKeyOf(after)];\n if (from !== to) {\n changes.push({ kind: 'definition.pluralApiKey', definitionId, from, to });\n }\n }\n if (before.kind !== 'component' && after.kind !== 'component') {\n if (before.localized !== after.localized) {\n changes.push({ kind: 'model.localized', definitionId, from: before.localized, to: after.localized });\n }\n if (before.draftAndPublish !== after.draftAndPublish) {\n changes.push({\n kind: 'model.draftAndPublish',\n definitionId,\n from: before.draftAndPublish,\n to: after.draftAndPublish,\n });\n }\n }\n\n const beforeFields = new Map(before.fields.map((field) => [field.id, field]));\n const afterIds = new Set(after.fields.map((field) => field.id));\n for (const field of after.fields) {\n const previous = beforeFields.get(field.id);\n if (!previous) {\n changes.push({\n kind: 'field.added',\n definitionId,\n fieldId: field.id,\n to: field as unknown as JsonValue,\n });\n } else {\n changes.push(...diffField(definitionId, previous, field));\n }\n }\n for (const field of before.fields) {\n if (!afterIds.has(field.id)) {\n changes.push({\n kind: 'field.removed',\n definitionId,\n fieldId: field.id,\n from: field as unknown as JsonValue,\n });\n }\n }\n const keptBefore = before.fields.filter((field) => afterIds.has(field.id)).map((field) => field.id);\n const keptAfter = after.fields.filter((field) => beforeFields.has(field.id)).map((field) => field.id);\n if (!same(keptBefore, keptAfter)) {\n changes.push({ kind: 'field.order', definitionId, from: keptBefore, to: keptAfter });\n }\n return changes;\n};\n","import { STORAGE_FAMILY, type DataType } from '../types/dataTypes.js';\nimport type { FieldDefinition, SchemaDefinition } from '../types/definitions.js';\nimport type { SchemaChange } from './types.js';\n\n/**\n * Change classification (brief §5, ADR 0002). Each change gets a category, whether it needs prerequisite\n * work before the new revision can be activated, and flags for breaking API contracts and destroying data.\n *\n * | Brief §5 row | category | activation |\n * | ------------------------------------ | -------------------------------- | ----------------------------- |\n * | Label, help text, editor layout | metadata | immediate |\n * | Compatible editor swap | editorSwap | immediate |\n * | Optional field or new model | additive | immediate (live) |\n * | Required field | requiredField | validateRequired / backfill |\n * | Type or rich-text format conversion | conversion | convert (+ validate) |\n * | API key rename | contract (breaking) | immediate, needs ack |\n * | Field removal | removal (breaking, data kept) | immediate, needs ack |\n * | Unique/index constraint | constraint / index | checkUnique / buildIndex |\n * | (plus) type change of a unique field | as its type change | + checkUnique |\n * | (plus) tightened validation rules | validation | validateValues |\n * | (plus) localized true→false | conversion (destructive) | convert |\n */\nexport type ChangeCategory =\n | 'metadata'\n | 'editorSwap'\n | 'additive'\n | 'requiredField'\n | 'validation'\n | 'conversion'\n | 'contract'\n | 'removal'\n | 'constraint'\n | 'index';\n\n/** Work that must succeed before activation. Content-touching kinds run through the content ports. */\nexport type PrerequisiteKind =\n 'validateRequired' | 'backfill' | 'validateValues' | 'checkUnique' | 'buildIndex' | 'convert';\n\n/** Work done after activation, once nothing reads the old structure. */\nexport type CleanupKind = 'dropIndex' | 'releaseUnique';\n\nexport type ClassifiedChange = SchemaChange & {\n category: ChangeCategory;\n /** Changes the public API contract (REST/GraphQL shape or visibility); needs explicit acknowledgement. */\n breaking: boolean;\n /** Loses stored information that a schema rollback cannot restore. */\n destructive: boolean;\n /** False for conversions Shapio cannot perform; the planner refuses them. */\n supported: boolean;\n prerequisites: PrerequisiteKind[];\n cleanup: CleanupKind[];\n};\n\nexport type ClassifyContext = { before: SchemaDefinition | null; after: SchemaDefinition | null };\n\ntype Classification = Omit<ClassifiedChange, keyof SchemaChange>;\n\nconst result = (category: ChangeCategory, extra: Partial<Classification> = {}): Classification => ({\n category,\n breaking: false,\n destructive: false,\n supported: true,\n prerequisites: [],\n cleanup: [],\n ...extra,\n});\n\nconst findField = (\n definition: SchemaDefinition | null,\n fieldId: string | undefined,\n): FieldDefinition | undefined => definition?.fields.find((field) => field.id === fieldId);\n\nconst hasIndex = (field: FieldDefinition | undefined): boolean =>\n Boolean(field && (field.filterable || field.sortable));\n\n/** Names delivery APIs use for a type; a change of name is a contract change. */\nconst API_SCALAR: Readonly<Record<DataType, string>> = {\n string: 'String',\n text: 'String',\n slug: 'String',\n email: 'String',\n url: 'String',\n uid: 'String',\n enum: 'Enum',\n date: 'Date',\n datetime: 'DateTime',\n time: 'Time',\n number: 'Float',\n integer: 'Int',\n decimal: 'Decimal',\n biginteger: 'BigInt',\n boolean: 'Boolean',\n json: 'JSON',\n richtext: 'RichText',\n media: 'Media',\n relation: 'Relation',\n component: 'Component',\n dynamiczone: 'DynamicZone',\n};\n\nconst PLAIN_TEXT_TYPES: ReadonlySet<DataType> = new Set(['string', 'text']);\nconst SCALAR_FAMILIES = new Set(['jsonString', 'jsonNumber', 'numericString', 'boolean']);\n\nconst hasTextConstraints = (field: FieldDefinition | undefined) => {\n const settings = (field?.settings ?? {}) as Record<string, unknown>;\n return (\n settings.minLength !== undefined || settings.maxLength !== undefined || settings.pattern !== undefined\n );\n};\n\n/**\n * A type change. Within one storage family the stored JSON stays as it is: widening is live, anything else\n * re-validates existing values. Across families Shapio converts values with a job, for the pairs it knows.\n */\nconst classifyTypeChange = (\n from: DataType,\n to: DataType,\n after: FieldDefinition | undefined,\n): Classification => {\n const breaking = API_SCALAR[from] !== API_SCALAR[to];\n const fromFamily = STORAGE_FAMILY[from];\n const toFamily = STORAGE_FAMILY[to];\n if (fromFamily === toFamily) {\n const widening =\n (fromFamily === 'jsonString' && PLAIN_TEXT_TYPES.has(to) && !hasTextConstraints(after)) ||\n (from === 'integer' && to === 'number') ||\n (from === 'biginteger' &&\n to === 'decimal' &&\n after?.type === 'decimal' &&\n after.settings.precision === undefined);\n return widening\n ? result('additive', { breaking })\n : result('validation', { breaking, prerequisites: ['validateValues'] });\n }\n const numericPair =\n (fromFamily === 'jsonNumber' && toFamily === 'numericString') ||\n (fromFamily === 'numericString' && toFamily === 'jsonNumber');\n const toText = SCALAR_FAMILIES.has(fromFamily) && PLAIN_TEXT_TYPES.has(to);\n const textToRichtext = fromFamily === 'jsonString' && to === 'richtext';\n const richtextToText = from === 'richtext' && PLAIN_TEXT_TYPES.has(to);\n const supported = numericPair || toText || textToRichtext || richtextToText;\n return result('conversion', {\n breaking,\n supported,\n destructive: richtextToText,\n prerequisites: supported ? ['convert', 'validateValues'] : [],\n });\n};\n\ntype Comparable = number | string;\nconst compareValues = (a: Comparable, b: Comparable): number => {\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b;\n }\n try {\n const diff = BigInt(String(a)) - BigInt(String(b));\n return diff === 0n ? 0 : diff > 0n ? 1 : -1;\n } catch {\n const numeric = Number(a) - Number(b);\n return Number.isNaN(numeric) ? String(a).localeCompare(String(b)) : numeric;\n }\n};\n\n/** A lower bound (min, minLength) that appears or rises, or an upper bound that appears or falls. */\nconst isTightened = (bound: 'lower' | 'upper', from: unknown, to: unknown): boolean => {\n if (to === undefined || to === null) {\n return false;\n }\n if (from === undefined || from === null) {\n return true;\n }\n const order = compareValues(from as Comparable, to as Comparable);\n return bound === 'lower' ? order < 0 : order > 0;\n};\n\nconst asStrings = (value: unknown): string[] =>\n Array.isArray(value)\n ? value.map((entry) =>\n typeof entry === 'object' && entry !== null\n ? String((entry as { value?: unknown }).value)\n : String(entry),\n )\n : [];\n\nconst removesAny = (from: unknown, to: unknown): boolean => {\n const kept = new Set(asStrings(to));\n return asStrings(from).some((entry) => !kept.has(entry));\n};\n\nconst validation = (tightened: boolean) =>\n tightened ? result('validation', { prerequisites: ['validateValues'] }) : result('additive');\n\nconst classifySettingsChange = (change: SchemaChange): Classification => {\n const { property, from, to } = change;\n switch (property) {\n case 'minLength':\n case 'min':\n return validation(isTightened('lower', from, to));\n case 'maxLength':\n case 'max':\n case 'precision':\n case 'scale':\n return validation(isTightened('upper', from, to));\n case 'pattern':\n return validation(to !== undefined);\n case 'values':\n // Removing an enum value invalidates entries using it; adding values or relabelling does not.\n return validation(removesAny(from, to));\n case 'components':\n case 'allowedKinds':\n case 'protocols':\n // Narrowing the allowed set re-validates; an absent allowedKinds/protocols list means \"any\".\n return validation(to !== undefined && (from === undefined || removesAny(from, to)));\n case 'sourceFieldId':\n return result('metadata');\n case 'multiple':\n case 'repeatable':\n case 'cardinality': {\n const becomesSingle = to === false || to === 'one';\n return result('conversion', {\n breaking: true,\n destructive: becomesSingle,\n prerequisites: ['convert', 'validateValues'],\n });\n }\n case 'formatVersion':\n return result('conversion', { prerequisites: ['convert', 'validateValues'] });\n case 'target':\n case 'component':\n // Existing values point at entries of the old target; they are cleared by the conversion.\n return result('conversion', { breaking: true, destructive: true, prerequisites: ['convert'] });\n default:\n // An unknown setting: be safe and re-validate existing values.\n return result('validation', { prerequisites: ['validateValues'] });\n }\n};\n\nconst classifyFieldChange = (change: SchemaChange, { before, after }: ClassifyContext): Classification => {\n const previous = findField(before, change.fieldId);\n const field = findField(after, change.fieldId);\n switch (change.kind) {\n case 'field.added': {\n const prerequisites: Classification['prerequisites'] = [];\n if (field?.required) {\n prerequisites.push(field.defaultValue !== undefined ? 'backfill' : 'validateRequired');\n }\n if (field?.unique) {\n prerequisites.push('checkUnique');\n }\n if (hasIndex(field)) {\n prerequisites.push('buildIndex');\n }\n return result(field?.required ? 'requiredField' : 'additive', { prerequisites });\n }\n case 'field.removed':\n // Values stay in stored revisions; removing them is a separate, explicit cleanup.\n return result('removal', {\n breaking: true,\n cleanup: [\n ...(hasIndex(previous) ? (['dropIndex'] as const) : []),\n ...(previous?.unique ? (['releaseUnique'] as const) : []),\n ],\n });\n case 'field.order':\n case 'field.metadata':\n return result('metadata');\n case 'field.editor':\n return result('editorSwap');\n case 'field.apiKey':\n return result('contract', { breaking: true });\n case 'field.type': {\n const classification = classifyTypeChange(change.from as DataType, change.to as DataType, field);\n // A unique field's values may normalize differently under the new type (e.g. string → email ignores\n // case): check them for duplicates before activation.\n return field?.unique && previous?.unique && !classification.prerequisites.includes('checkUnique')\n ? { ...classification, prerequisites: [...classification.prerequisites, 'checkUnique'] }\n : classification;\n }\n case 'field.required':\n if (change.to !== true) {\n return result('additive');\n }\n return result('requiredField', {\n prerequisites: [field?.defaultValue !== undefined ? 'backfill' : 'validateRequired'],\n });\n case 'field.localized': {\n const modelLocalized = after?.kind !== 'component' && after?.localized === true;\n if (!modelLocalized) {\n return result('metadata');\n }\n // false→true: every locale's head already holds the shared value (ADR 0004), so nothing to copy.\n return change.to === true\n ? result('additive')\n : result('conversion', { destructive: true, prerequisites: ['convert'] });\n }\n case 'field.public':\n case 'field.deprecated': {\n const hides = change.kind === 'field.public' ? change.to === false : change.to === true;\n return result('metadata', { breaking: hides });\n }\n case 'field.unique':\n return change.to === true\n ? result('constraint', { prerequisites: ['checkUnique'] })\n : result('additive', { cleanup: ['releaseUnique'] });\n case 'field.filterable':\n case 'field.sortable': {\n // Filtering and sorting share one expression index per field.\n if (hasIndex(field) && !hasIndex(previous)) {\n return result('index', { prerequisites: ['buildIndex'] });\n }\n if (!hasIndex(field) && hasIndex(previous)) {\n return result('index', { cleanup: ['dropIndex'] });\n }\n return result('metadata');\n }\n case 'field.settings':\n return classifySettingsChange(change);\n default:\n return result('metadata');\n }\n};\n\n/** Classifies one change in the context of the definitions it was diffed from. */\nexport const classifyChange = (change: SchemaChange, context: ClassifyContext): ClassifiedChange => {\n let classification: Classification;\n switch (change.kind) {\n case 'definition.added':\n classification = result('additive');\n break;\n case 'definition.removed':\n // Soft delete: entries are kept and reappear if the definition is restored.\n classification = result('removal', { breaking: true });\n break;\n case 'definition.apiKey':\n case 'definition.pluralApiKey':\n classification = result('contract', { breaking: true });\n break;\n case 'definition.metadata':\n classification = result('metadata');\n break;\n case 'model.kind':\n classification =\n change.to === 'singleton'\n ? result('validation', { breaking: true, prerequisites: ['validateValues'] })\n : result('contract', { breaking: true });\n break;\n case 'model.localized':\n classification =\n change.to === true\n ? result('additive')\n : result('conversion', { destructive: true, prerequisites: ['convert'] });\n break;\n case 'model.draftAndPublish':\n classification =\n change.to === true\n ? result('additive')\n : result('conversion', { destructive: true, prerequisites: ['convert'] });\n break;\n default:\n classification = classifyFieldChange(change, context);\n }\n return { ...change, ...classification };\n};\n\nexport const classifyChanges = (\n changes: readonly SchemaChange[],\n context: ClassifyContext,\n): ClassifiedChange[] => changes.map((change) => classifyChange(change, context));\n\nexport type ChangeSummary = {\n breaking: boolean;\n destructive: boolean;\n supported: boolean;\n prerequisites: PrerequisiteKind[];\n cleanup: CleanupKind[];\n /** True when nothing but metadata/editor changes are involved. */\n metadataOnly: boolean;\n};\n\nconst PREREQUISITE_ORDER: readonly PrerequisiteKind[] = [\n 'convert',\n 'backfill',\n 'validateRequired',\n 'validateValues',\n 'checkUnique',\n 'buildIndex',\n];\n\nexport const summarizeChanges = (changes: readonly ClassifiedChange[]): ChangeSummary => {\n const prerequisites = new Set(changes.flatMap((change) => change.prerequisites));\n return {\n breaking: changes.some((change) => change.breaking),\n destructive: changes.some((change) => change.destructive),\n supported: changes.every((change) => change.supported),\n prerequisites: PREREQUISITE_ORDER.filter((kind) => prerequisites.has(kind)),\n cleanup: [...new Set(changes.flatMap((change) => change.cleanup))],\n metadataOnly: changes.every(\n (change) => change.category === 'metadata' || change.category === 'editorSwap',\n ),\n };\n};\n\n/** Locale configuration changes (ADR 0002/0004). Locales are global, so they are planned on their own. */\nexport type LocaleChangeKind =\n 'locale.added' | 'locale.removed' | 'locale.defaultChanged' | 'locale.metadata';\n\nexport type ClassifiedLocaleChange = {\n kind: LocaleChangeKind;\n code: string;\n category: ChangeCategory;\n breaking: boolean;\n destructive: boolean;\n};\n\n/**\n * - added: live (entries gain the locale as editors fill it in);\n * - removed: destroys that locale's content (purged by a follow-up job), so it needs explicit consent;\n * - default changed: delivery falls back to a different locale, a contract change for API consumers;\n * - label or fallback chain: metadata.\n */\nexport const classifyLocaleChange = (kind: LocaleChangeKind, code: string): ClassifiedLocaleChange => {\n switch (kind) {\n case 'locale.added':\n return { kind, code, category: 'additive', breaking: false, destructive: false };\n case 'locale.removed':\n return { kind, code, category: 'removal', breaking: true, destructive: true };\n case 'locale.defaultChanged':\n return { kind, code, category: 'contract', breaking: true, destructive: false };\n default:\n return { kind, code, category: 'metadata', breaking: false, destructive: false };\n }\n};\n","import type { SchemaDefinition } from '../types/definitions.js';\nimport { serializeDefinition } from './canonical.js';\n\nconst toHex = (buffer: ArrayBuffer) =>\n Array.from(new Uint8Array(buffer), (byte) => byte.toString(16).padStart(2, '0')).join('');\n\n/** `sha256:<hex>` of a UTF-8 string, via Web Crypto (Node and browsers alike). */\nexport const sha256 = async (text: string): Promise<string> =>\n `sha256:${toHex(await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(text)))}`;\n\n/** Hash of a normalized definition's canonical serialization; recorded per model in the lock file. */\nexport const hashDefinition = (definition: SchemaDefinition): Promise<string> =>\n sha256(serializeDefinition(definition));\n","import type { SchemaDefinition } from '../types/definitions.js';\n\n/**\n * Where schema files live in a repository (plan site-schema): shared definitions in `models/` and\n * `components/`, a site's own in `sites/<siteKey>/models/` and `sites/<siteKey>/components/`. Paths are\n * relative to the schema directory and always use `/` (git paths); callers join them for their file system.\n */\nexport const SCHEMA_KIND_DIRECTORIES = ['models', 'components'] as const;\nexport type SchemaKindDirectory = (typeof SCHEMA_KIND_DIRECTORIES)[number];\n\n/** The folder that holds one directory per site key. */\nexport const SITES_DIRECTORY = 'sites';\n\nconst kindDirectoryOf = (definition: Pick<SchemaDefinition, 'kind'>): SchemaKindDirectory =>\n definition.kind === 'component' ? 'components' : 'models';\n\n/** The directory of a scope's files: `''` (shared) or `sites/<siteKey>`. */\nexport const scopeDirectory = (siteKey: string | null): string =>\n siteKey === null ? '' : `${SITES_DIRECTORY}/${siteKey}`;\n\n/** A definition's file path: `models/post.json`, or `sites/blog/models/post.json` for site `blog`. */\nexport const schemaFilePath = (\n definition: Pick<SchemaDefinition, 'kind' | 'apiKey'>,\n siteKey: string | null,\n): string => {\n const file = `${kindDirectoryOf(definition)}/${definition.apiKey}.json`;\n return siteKey === null ? file : `${scopeDirectory(siteKey)}/${file}`;\n};\n\n/**\n * The scope a schema file path is in: `{ site: null }` for `models/x.json` or `components/x.json`,\n * `{ site: key }` under `sites/<key>/`, undefined for anything else (not a schema file).\n */\nexport const scopeOfSchemaFilePath = (path: string): { site: string | null } | undefined => {\n const parts = path.split('/').filter((part) => part.length > 0);\n const isFile = (kind: string | undefined, name: string | undefined) =>\n (SCHEMA_KIND_DIRECTORIES as readonly string[]).includes(kind ?? '') && (name ?? '').endsWith('.json');\n if (parts.length === 2 && isFile(parts[0], parts[1])) {\n return { site: null };\n }\n if (parts.length === 4 && parts[0] === SITES_DIRECTORY && parts[1] && isFile(parts[2], parts[3])) {\n return { site: parts[1] };\n }\n return undefined;\n};\n","import { Type, type Static } from 'typebox';\nimport { DEFINITION_KINDS, type SchemaDefinition } from '../types/definitions.js';\nimport { collectSchemaErrors } from '../validators/typeboxIssues.js';\nimport { canonicalJson } from './canonical.js';\n\n/** Where `shapio schema pull` keeps its record of what it pulled, relative to the project root. */\nexport const LOCK_FILE_PATH = '.shapio/schema-lock.json';\n/**\n * Format 2 (per-site schemas): each entry records its scope (`site`: a site key, or null when shared) and\n * the lock lists the sites the tree covers. Format 1 (every definition shared) still reads: its entries\n * have no `site`, which means shared, and it covers no site. `upgradeLockFile` spells both the same way.\n */\nexport const LOCK_FILE_FORMAT_VERSION = 2;\n\nexport const LockEntrySchema = Type.Object(\n {\n kind: Type.Enum(DEFINITION_KINDS),\n apiKey: Type.String(),\n /** The definition's per-model version on the instance when it was pulled. */\n version: Type.Integer({ minimum: 1 }),\n /** `hashDefinition` of the pulled definition; a local file with another hash has been edited. */\n hash: Type.String(),\n /**\n * The key of the site the definition belongs to; null (or absent, format 1) when shared. Null comes first:\n * Fastify's Ajv coerces types, and a string branch tried first would turn null into \"\" (no site at all).\n */\n site: Type.Optional(Type.Union([Type.Null(), Type.String()])),\n },\n { additionalProperties: false },\n);\n\nexport const LockFileSchema = Type.Object(\n {\n formatVersion: Type.Union([Type.Literal(1), Type.Literal(LOCK_FILE_FORMAT_VERSION)]),\n /** The instance's global schema version at pull time (informational; the guard is per model). */\n schemaVersion: Type.Integer({ minimum: 0 }),\n /** Keys of the sites whose definitions this tree holds (format 2; absent: none, shared only). */\n sites: Type.Optional(Type.Array(Type.String())),\n /** Keyed by definition ID. */\n definitions: Type.Record(Type.String(), LockEntrySchema),\n },\n { additionalProperties: false },\n);\n\nexport type LockEntry = Static<typeof LockEntrySchema>;\nexport type LockFile = Static<typeof LockFileSchema>;\n\n/** A lock in format 2 with every scope spelled out. */\nexport type ScopedLockEntry = LockEntry & { site: string | null };\nexport type ScopedLockFile = Omit<LockFile, 'formatVersion' | 'sites' | 'definitions'> & {\n formatVersion: typeof LOCK_FILE_FORMAT_VERSION;\n sites: string[];\n definitions: Record<string, ScopedLockEntry>;\n};\n\n/** Format 1 or 2 → format 2: absent scopes are shared, absent sites none. */\nexport const upgradeLockFile = (lock: LockFile): ScopedLockFile => ({\n formatVersion: LOCK_FILE_FORMAT_VERSION,\n schemaVersion: lock.schemaVersion,\n sites: [...(lock.sites ?? [])],\n definitions: Object.fromEntries(\n Object.entries(lock.definitions).map(([id, entry]) => [id, { ...entry, site: entry.site ?? null }]),\n ),\n});\n\n/** The lock entries one site's tree is about: the shared definitions and that site's (`siteKey`). */\nexport const lockEntriesForSite = (lock: LockFile, siteKey: string | null): LockFile['definitions'] =>\n Object.fromEntries(\n Object.entries(lock.definitions).filter(\n ([, entry]) => (entry.site ?? null) === null || entry.site === siteKey,\n ),\n );\n\n/** A tree applies to a site when it covers no site yet (shared only, or format 1) or lists that site. */\nexport const lockCoversSite = (lock: LockFile, siteKey: string): boolean => {\n const sites = lock.sites ?? [];\n return sites.length === 0 || sites.includes(siteKey);\n};\n\n/** `sites` plus `siteKey`, sorted and without duplicates (stable diffs in git). */\nexport const withSiteCovered = (sites: readonly string[], siteKey: string): string[] =>\n [...new Set([...sites, siteKey])].sort();\n\n/**\n * The lock after pulling one site's view (`shapio schema pull --site <siteKey>`): the shared entries and that\n * site's are replaced by what was pulled, another site's entries are kept as they are (one tree can hold\n * several sites), and the tree now covers `siteKey`. A format 1 lock upgrades first (every entry shared).\n */\nexport const mergePulledLock = (\n lock: LockFile | undefined,\n pulled: { schemaVersion: number; siteKey: string; definitions: readonly ExportedDefinition[] },\n): ScopedLockFile => {\n const current = lock ? upgradeLockFile(lock) : undefined;\n const pulledIds = new Set(pulled.definitions.map(({ definition }) => definition.id));\n const kept = Object.entries(current?.definitions ?? {}).filter(\n ([id, entry]) => entry.site !== null && entry.site !== pulled.siteKey && !pulledIds.has(id),\n );\n return {\n formatVersion: LOCK_FILE_FORMAT_VERSION,\n schemaVersion: pulled.schemaVersion,\n sites: withSiteCovered(current?.sites ?? [], pulled.siteKey),\n definitions: Object.fromEntries([\n ...kept,\n ...pulled.definitions.map(({ definition, version, hash, site }): [string, ScopedLockEntry] => [\n definition.id,\n { kind: definition.kind, apiKey: definition.apiKey, version, hash, site },\n ]),\n ]),\n };\n};\n\n/** One definition as `schema export` returns it, with its scope (a site key, or null when shared). */\nexport type ExportedDefinition = {\n definition: SchemaDefinition;\n version: number;\n hash: string;\n site: string | null;\n};\n\nexport class LockFileError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LockFileError';\n }\n}\n\nexport const parseLockFile = (text: string): LockFile => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n throw new LockFileError(`${LOCK_FILE_PATH} is not valid JSON`);\n }\n const errors = collectSchemaErrors(LockFileSchema, parsed);\n if (errors.length > 0) {\n throw new LockFileError(\n `${LOCK_FILE_PATH} is invalid: ${errors.map((error) => `${error.path || '/'} ${error.message}`).join('; ')}`,\n );\n }\n return parsed as LockFile;\n};\n\nexport const serializeLockFile = (lock: LockFile): string => canonicalJson(lock);\n","import type { SchemaDefinition } from '../types/definitions.js';\n\n/**\n * Per-definition three-way decision for `shapio schema apply` (ADR 0002). The base is what the lock file\n * recorded at pull time; local is the file in the repository; remote is the target instance now.\n *\n * - unchanged locally → skip, even if the target changed it since (no silent revert of production edits);\n * - changed locally and unchanged on the target → apply, guarded by the target's current version;\n * - changed on both → refuse and show the diff, like a rejected non-fast-forward push.\n *\n * Deletions need `prune`. Identical content on both sides is never a conflict.\n */\nexport type SyncSide = { version: number; hash: string };\nexport type SyncLocal = { definition: SchemaDefinition; hash: string };\nexport type SyncRemote = SyncSide & { definition: SchemaDefinition };\n\nexport type SyncInput = {\n local?: SyncLocal;\n base?: SyncSide;\n remote?: SyncRemote;\n prune: boolean;\n};\n\nexport type SyncSkipReason =\n 'unchangedLocally' | 'alreadyApplied' | 'remoteOnly' | 'deletedLocallyWithoutPrune' | 'alreadyDeleted';\n\nexport type SyncConflictReason =\n 'changedOnBoth' | 'deletedOnTarget' | 'existsOnTarget' | 'changedOnTargetBeforeDelete';\n\nexport type SyncDecision =\n | { action: 'skip'; reason: SyncSkipReason }\n | { action: 'create' }\n | { action: 'update'; expectedVersion: number }\n | { action: 'delete'; expectedVersion: number }\n | { action: 'conflict'; reason: SyncConflictReason };\n\nconst unchangedSinceBase = (remote: SyncSide, base: SyncSide) =>\n remote.version === base.version || remote.hash === base.hash;\n\nconst decideForLocal = (\n local: SyncLocal,\n base: SyncSide | undefined,\n remote: SyncRemote | undefined,\n): SyncDecision => {\n if (base && local.hash === base.hash) {\n return { action: 'skip', reason: 'unchangedLocally' };\n }\n if (!remote) {\n return base ? { action: 'conflict', reason: 'deletedOnTarget' } : { action: 'create' };\n }\n if (remote.hash === local.hash) {\n return { action: 'skip', reason: 'alreadyApplied' };\n }\n if (!base) {\n return { action: 'conflict', reason: 'existsOnTarget' };\n }\n return unchangedSinceBase(remote, base)\n ? { action: 'update', expectedVersion: remote.version }\n : { action: 'conflict', reason: 'changedOnBoth' };\n};\n\nexport const decideSync = ({ local, base, remote, prune }: SyncInput): SyncDecision => {\n if (local) {\n return decideForLocal(local, base, remote);\n }\n if (!base) {\n return { action: 'skip', reason: 'remoteOnly' };\n }\n if (!remote) {\n return { action: 'skip', reason: 'alreadyDeleted' };\n }\n if (!prune) {\n return { action: 'skip', reason: 'deletedLocallyWithoutPrune' };\n }\n return unchangedSinceBase(remote, base)\n ? { action: 'delete', expectedVersion: remote.version }\n : { action: 'conflict', reason: 'changedOnTargetBeforeDelete' };\n};\n","import { RICHTEXT_FORMAT, RICHTEXT_FORMAT_VERSION } from '../types/valueFormats.js';\nimport { SAFE_LINK_PATTERN } from './spec.js';\nimport type { RichTextDocument, RichTextNode } from './validate.js';\n\n/**\n * HTML rendering of stored rich text for delivery (ADR 0003). Rendered from JSON only, never from stored\n * HTML: every tag comes from this allow-list and every text and attribute value is escaped, so the output\n * is safe whatever the document held. Deterministic, so a site built at a pinned snapshot gets the same HTML.\n */\n\n/** Resolves an image's media ID to a deliverable URL; undefined when the asset is missing or not visible. */\nexport type MediaUrlResolver = (mediaId: string) => string | undefined;\n\nconst ESCAPES: Readonly<Record<string, string>> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n};\n\nexport const escapeHtml = (value: string): string =>\n value.replace(/[&<>\"']/g, (char) => ESCAPES[char] ?? char);\n\n/** Attribute values come from validated documents: strings and numbers only. */\nconst textOf = (value: unknown): string =>\n typeof value === 'string' || typeof value === 'number' ? String(value) : '';\n\nconst attribute = (name: string, value: unknown) =>\n value === null || value === undefined ? '' : ` ${name}=\"${escapeHtml(textOf(value))}\"`;\n\nconst BLOCK_TAGS: Readonly<Record<string, string>> = {\n paragraph: 'p',\n blockquote: 'blockquote',\n bulletList: 'ul',\n listItem: 'li',\n table: 'table',\n tableRow: 'tr',\n tableHeader: 'th',\n tableCell: 'td',\n};\n\nconst renderMarks = (text: string, marks: RichTextNode['marks']): string =>\n (marks ?? []).reduceRight((inner, mark) => {\n switch (mark.type) {\n case 'bold':\n return `<strong>${inner}</strong>`;\n case 'italic':\n return `<em>${inner}</em>`;\n case 'code':\n return `<code>${inner}</code>`;\n case 'link': {\n const href = textOf(mark.attrs?.href).trim();\n if (!SAFE_LINK_PATTERN.test(href)) {\n return inner;\n }\n const blank = mark.attrs?.target === '_blank';\n return `<a${attribute('href', href)}${blank ? ' target=\"_blank\" rel=\"noopener noreferrer nofollow\"' : ''}>${inner}</a>`;\n }\n default:\n return inner;\n }\n }, escapeHtml(text));\n\nconst cellAttributes = (node: RichTextNode) => {\n const colspan = Number(node.attrs?.colspan ?? 1);\n const rowspan = Number(node.attrs?.rowspan ?? 1);\n return `${colspan > 1 ? attribute('colspan', colspan) : ''}${rowspan > 1 ? attribute('rowspan', rowspan) : ''}`;\n};\n\nconst renderNode = (node: RichTextNode, resolveMedia: MediaUrlResolver | undefined): string => {\n const children = () => (node.content ?? []).map((child) => renderNode(child, resolveMedia)).join('');\n switch (node.type) {\n case 'doc':\n return children();\n case 'text':\n return renderMarks(node.text ?? '', node.marks);\n case 'hardBreak':\n return '<br>';\n case 'horizontalRule':\n return '<hr>';\n case 'heading': {\n const level = Math.min(6, Math.max(1, Number(node.attrs?.level ?? 1)));\n return `<h${level}>${children()}</h${level}>`;\n }\n case 'orderedList': {\n const start = Number(node.attrs?.start ?? 1);\n return `<ol${start !== 1 ? attribute('start', start) : ''}${attribute('type', node.attrs?.type)}>${children()}</ol>`;\n }\n case 'codeBlock': {\n const language = node.attrs?.language;\n const text = (node.content ?? []).map((child) => escapeHtml(child.text ?? '')).join('');\n return `<pre><code${language ? attribute('class', `language-${textOf(language)}`) : ''}>${text}</code></pre>`;\n }\n case 'image': {\n const mediaId = textOf(node.attrs?.mediaId);\n const src = resolveMedia?.(mediaId);\n if (!src) {\n // Unknown or private-and-unsigned media renders nothing rather than a broken or leaking link.\n return '';\n }\n return `<img${attribute('src', src)}${attribute('alt', node.attrs?.alt ?? '')}${attribute('title', node.attrs?.title)}>`;\n }\n case 'table':\n return `<table><tbody>${children()}</tbody></table>`;\n case 'tableHeader':\n case 'tableCell': {\n const tag = BLOCK_TAGS[node.type] as string;\n return `<${tag}${cellAttributes(node)}>${children()}</${tag}>`;\n }\n default: {\n const tag = BLOCK_TAGS[node.type];\n return tag ? `<${tag}>${children()}</${tag}>` : '';\n }\n }\n};\n\n/** Renders a validated document to sanitized HTML. */\nexport const renderRichTextHtml = (document: RichTextDocument, resolveMedia?: MediaUrlResolver): string =>\n renderNode(document.doc, resolveMedia);\n\n/** The document's text, blocks separated by blank lines (rich text → plain text conversions, search). */\nexport const richTextToPlainText = (document: RichTextDocument): string => {\n const blocks: string[] = [];\n const inline = (node: RichTextNode): string =>\n node.type === 'text'\n ? (node.text ?? '')\n : node.type === 'hardBreak'\n ? '\\n'\n : (node.content ?? []).map(inline).join('');\n const walk = (node: RichTextNode) => {\n if (node.type === 'paragraph' || node.type === 'heading' || node.type === 'codeBlock') {\n blocks.push(inline(node));\n return;\n }\n (node.content ?? []).forEach(walk);\n };\n walk(document.doc);\n return blocks.join('\\n\\n');\n};\n\n/** Plain text → a document of paragraphs (blank lines split paragraphs; single newlines are hard breaks). */\nexport const plainTextToRichText = (text: string): RichTextDocument => {\n const paragraphs = text\n .replace(/\\r\\n?/g, '\\n')\n .split(/\\n{2,}/)\n .filter((paragraph) => paragraph.length > 0)\n .map((paragraph): RichTextNode => {\n const content = paragraph\n .split('\\n')\n .flatMap((line, index): RichTextNode[] => [\n ...(index > 0 ? [{ type: 'hardBreak' }] : []),\n ...(line.length > 0 ? [{ type: 'text', text: line }] : []),\n ]);\n return content.length > 0 ? { type: 'paragraph', content } : { type: 'paragraph' };\n });\n return {\n format: RICHTEXT_FORMAT,\n version: RICHTEXT_FORMAT_VERSION,\n doc: { type: 'doc', content: paragraphs.length > 0 ? paragraphs : [{ type: 'paragraph' }] },\n };\n};\n","/**\n * Admin themes (docs/plans/themes.md): a theme is a named, complete set of these tokens for a light variant, a\n * dark variant or both. One list, shared by the admin's stylesheets (and their tests) and the API, which\n * validates themes declared by extensions (`shapio.config` `themes`).\n */\n/** The UI tokens: every theme variant sets all of them. */\nexport const THEME_SEMANTIC_TOKENS = [\n 'background',\n 'foreground',\n 'card',\n 'card-foreground',\n 'popover',\n 'popover-foreground',\n 'primary',\n 'primary-foreground',\n 'primary-hover',\n 'secondary',\n 'secondary-foreground',\n 'muted',\n 'muted-foreground',\n 'accent',\n 'accent-foreground',\n 'destructive',\n 'destructive-foreground',\n 'destructive-muted',\n 'success',\n 'success-muted',\n 'warning',\n 'warning-muted',\n 'info',\n 'info-muted',\n 'border',\n 'input',\n 'ring',\n 'link',\n 'overlay',\n 'sidebar',\n 'sidebar-foreground',\n 'sidebar-primary',\n 'sidebar-primary-foreground',\n 'sidebar-accent',\n 'sidebar-accent-foreground',\n 'sidebar-border',\n 'sidebar-ring',\n] as const;\n\n/**\n * The logo (tile, S, letters) and the signed-out screens' brand panel. Built-in themes set them all; an\n * extension theme may leave them out and gets Shapio's for that variant.\n */\nexport const THEME_BRAND_TOKENS = [\n 'brand-logo',\n 'brand-logo-foreground',\n 'brand-letters',\n 'brand-panel-from',\n 'brand-panel-to',\n 'brand-panel-foreground',\n 'brand-panel-mark',\n] as const;\n\nexport const THEME_TOKENS = [...THEME_SEMANTIC_TOKENS, ...THEME_BRAND_TOKENS] as const;\n\nexport type ThemeToken = (typeof THEME_TOKENS)[number];\n\nexport const THEME_VARIANTS = ['light', 'dark'] as const;\n\nexport type ThemeVariant = (typeof THEME_VARIANTS)[number];\n\n/** A theme key: used in `data-theme` and in CSS selectors, so deliberately narrow. */\nexport const THEME_KEY_PATTERN = /^[a-z][a-z0-9-]{0,40}$/;\n\n/** The themes the admin ships; an extension theme may not reuse these keys. */\nexport const BUILT_IN_THEME_KEYS = [\n 'shapio',\n 'classic',\n 'murdered-out',\n 'forest',\n 'snowed',\n 'butter',\n] as const;\n\nexport type BuiltInThemeKey = (typeof BUILT_IN_THEME_KEYS)[number];\n\n/**\n * A token value an extension may use: a hex colour or a colour function whose arguments are numbers, units\n * and separators only (no `;`, quotes, braces or nested functions such as `url()` or `var()`), so a value\n * can never escape its declaration.\n */\nexport const THEME_COLOUR_PATTERN =\n /^(?:#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|(?:rgba?|hsla?|oklch|oklab)\\([0-9a-z.,%\\s/+-]{1,80}\\))$/;\n","import type { ThemeVariant } from './tokens.js';\n\n/**\n * WCAG 2.1 AA contrast of a theme's tokens: text pairs need 4.5:1 (1.4.3); what identifies a control or the\n * focus (input borders, unchecked switches, focus rings, primary buttons against the page) needs 3:1 (1.4.11).\n * The admin's built-in themes are gated on this by a unit test; extension themes get warnings from\n * `shapio extensions check`. axe checks rendered text only, not these pairs.\n */\nexport type ContrastPair = readonly [foreground: string, background: string];\n\nconst SURFACES = ['background', 'card', 'popover'];\n\nexport const THEME_TEXT_PAIRS: readonly ContrastPair[] = [\n ...SURFACES.map((surface): ContrastPair => ['foreground', surface]),\n ...[...SURFACES, 'muted', 'secondary', 'accent', 'sidebar'].map((surface): ContrastPair => [\n 'muted-foreground',\n surface,\n ]),\n ['primary-foreground', 'primary'],\n ['primary-foreground', 'primary-hover'],\n ['secondary-foreground', 'secondary'],\n ['accent-foreground', 'accent'],\n ['destructive-foreground', 'destructive'],\n ['destructive', 'background'],\n ['destructive', 'card'],\n ['success', 'background'],\n ['success', 'card'],\n ['success', 'success-muted'],\n // Status chips (StatusChip): tone text on its own tinted background, and on plain surfaces.\n ['warning', 'warning-muted'],\n ['warning', 'card'],\n ['info', 'info-muted'],\n ['info', 'card'],\n ['destructive', 'destructive-muted'],\n ['foreground', 'muted'],\n ['link', 'background'],\n ['link', 'card'],\n ['sidebar-foreground', 'sidebar'],\n ['sidebar-primary-foreground', 'sidebar-primary'],\n ['sidebar-accent-foreground', 'sidebar-accent'],\n ['sidebar-foreground', 'sidebar-accent'],\n ['muted-foreground', 'sidebar-accent'],\n // Status and link text on raised and muted surfaces (popovers, sheets, muted bands).\n ...['destructive', 'success', 'warning', 'link'].flatMap((text): ContrastPair[] => [\n [text, 'popover'],\n [text, 'muted'],\n ]),\n // The signed-out screens' brand panel (tagline and pitch on both ends of the gradient).\n ['brand-panel-foreground', 'brand-panel-from'],\n ['brand-panel-foreground', 'brand-panel-to'],\n];\n\nexport const THEME_UI_PAIRS: readonly ContrastPair[] = [\n ...[...SURFACES, 'muted', 'secondary'].map((surface): ContrastPair => ['input', surface]),\n ...SURFACES.map((surface): ContrastPair => ['ring', surface]),\n ['ring', 'muted'],\n ['ring', 'accent'],\n ['primary', 'background'],\n ['primary', 'card'],\n ['primary', 'popover'],\n // Primary icons on neutral tiles (IconTile accent) and the info alert's icon.\n ['primary', 'muted'],\n ['info', 'muted'],\n ['sidebar-ring', 'sidebar'],\n // The active nav item's left bar.\n ['sidebar-primary', 'sidebar'],\n ['sidebar-primary', 'sidebar-accent'],\n];\n\n/**\n * Dark only: control borders on the selection surface. In light, selected table rows use accent/40, which\n * passes, and other selected surfaces hold no controls.\n */\nexport const THEME_DARK_UI_PAIRS: readonly ContrastPair[] = [['input', 'accent']];\n\nconst HEX = /^#[0-9a-fA-F]{6}$/;\n\nconst channel = (value: number) => {\n const c = value / 255;\n return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n};\n\nconst luminance = (hex: string) => {\n const [r, g, b] = [1, 3, 5].map((index) => channel(parseInt(hex.slice(index, index + 2), 16)));\n return 0.2126 * (r ?? 0) + 0.7152 * (g ?? 0) + 0.0722 * (b ?? 0);\n};\n\n/** The WCAG contrast ratio of two `#rrggbb` colours. */\nexport const contrastRatio = (a: string, b: string): number => {\n const [high = 0, low = 0] = [luminance(a), luminance(b)].sort((x, y) => y - x);\n return (high + 0.05) / (low + 0.05);\n};\n\nexport type ContrastCheck = {\n foreground: string;\n background: string;\n /** 4.5 for text, 3 for controls. */\n required: number;\n /** Undefined when a value is not a `#rrggbb` colour (functions such as `oklch()` are not checked). */\n ratio: number | undefined;\n};\n\n/** Every pair the variant must meet, with its ratio. Missing tokens report an undefined ratio. */\nexport const checkThemeContrast = (\n tokens: Readonly<Record<string, string>>,\n variant: ThemeVariant,\n): ContrastCheck[] => {\n const uiPairs = variant === 'dark' ? [...THEME_UI_PAIRS, ...THEME_DARK_UI_PAIRS] : THEME_UI_PAIRS;\n const measure = ([foreground, background]: ContrastPair, required: number): ContrastCheck => {\n const a = tokens[foreground];\n const b = tokens[background];\n return {\n foreground,\n background,\n required,\n ratio: a && b && HEX.test(a) && HEX.test(b) ? contrastRatio(a, b) : undefined,\n };\n };\n return [...THEME_TEXT_PAIRS.map((pair) => measure(pair, 4.5)), ...uiPairs.map((pair) => measure(pair, 3))];\n};\n","import { normalizeDefinition } from '../normalize.js';\nimport type { ComponentDefinition } from '../types/definitions.js';\nimport { SEO_COMPONENT_API_KEY, SEO_COMPONENT_ID, SEO_FIELD_IDS } from './ids.js';\n\n/**\n * The built-in SEO component as first created. All fields are public and none has a length limit: the 70 and\n * 160 character marks are admin-only counters (`SEO_TITLE_SOFT_MAX`), never validation.\n */\nexport const seoComponentDefinition = (): ComponentDefinition =>\n normalizeDefinition({\n id: SEO_COMPONENT_ID,\n kind: 'component',\n apiKey: SEO_COMPONENT_API_KEY,\n label: 'SEO',\n description: 'Search and social metadata: title, description, image, canonical URL and indexing.',\n category: 'Built-in',\n icon: 'search',\n fields: [\n { id: SEO_FIELD_IDS.title, apiKey: 'title', label: 'Title', type: 'string' },\n { id: SEO_FIELD_IDS.description, apiKey: 'description', label: 'Description', type: 'text' },\n {\n id: SEO_FIELD_IDS.image,\n apiKey: 'image',\n label: 'Social image',\n type: 'media',\n settings: { multiple: false, allowedKinds: ['image'] },\n },\n {\n id: SEO_FIELD_IDS.canonical,\n apiKey: 'canonical',\n label: 'Canonical URL',\n type: 'url',\n settings: { protocols: ['https', 'http'] },\n },\n { id: SEO_FIELD_IDS.noindex, apiKey: 'noindex', label: 'Hide from search engines', type: 'boolean' },\n ],\n display: { titleFieldId: SEO_FIELD_IDS.title },\n }) as ComponentDefinition;\n","import { Type, type Static } from 'typebox';\nimport { LOCALE_CODE_PATTERN } from '../types/locales.js';\nimport { SEO_TITLE_TEMPLATE_PATTERN, SEO_TWITTER_HANDLE_PATTERN } from './ids.js';\n\nconst closed = { additionalProperties: false } as const;\n\n/** Media asset IDs are UUIDs. */\nconst ASSET_ID_PATTERN = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;\n\n/** One locale's default texts. Every key is optional: a missing one falls back along the locale chain. */\nexport const SeoLocaleDefaultsSchema = Type.Object(\n {\n siteName: Type.Optional(Type.String({ minLength: 1, maxLength: 200 })),\n titleTemplate: Type.Optional(\n Type.String({ minLength: 2, maxLength: 200, pattern: SEO_TITLE_TEMPLATE_PATTERN.source }),\n ),\n description: Type.Optional(Type.String({ minLength: 1, maxLength: 1000 })),\n },\n closed,\n);\n\n/**\n * A site's SEO defaults (`sites.seo_defaults`): texts per locale code, the default social image (a public\n * image asset of the same site) and the Twitter handle for the whole site.\n */\nexport const SeoDefaultsSchema = Type.Object(\n {\n locales: Type.Record(Type.String({ pattern: LOCALE_CODE_PATTERN.source }), SeoLocaleDefaultsSchema, {\n additionalProperties: false,\n }),\n imageId: Type.Union([Type.String({ pattern: ASSET_ID_PATTERN.source }), Type.Null()]),\n twitterHandle: Type.Union([Type.String({ pattern: SEO_TWITTER_HANDLE_PATTERN.source }), Type.Null()]),\n },\n closed,\n);\n\nexport type SeoLocaleDefaults = Static<typeof SeoLocaleDefaultsSchema>;\nexport type SeoDefaults = Static<typeof SeoDefaultsSchema>;\n"],"mappings":"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"}
|