@shapio/schema 0.5.6 → 0.5.7

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 CHANGED
@@ -33,8 +33,18 @@ export declare const REFERENCE_DATA_TYPES: ReadonlySet<DataType>;
33
33
  * How a value is physically represented in the content JSON. Changing a field's type within a storage
34
34
  * family never needs a data conversion, only a validity check; across families it is a conversion.
35
35
  */
36
- export type StorageFamily = 'jsonString' | 'jsonNumber' | 'numericString' | 'boolean' | 'json' | 'richtext' | 'media' | 'relation' | 'component' | 'dynamiczone';
36
+ export type StorageFamily = 'jsonString' | 'jsonStringArray' | 'jsonNumber' | 'numericString' | 'boolean' | 'json' | 'richtext' | 'media' | 'relation' | 'component' | 'dynamiczone';
37
37
  export declare const STORAGE_FAMILY: Readonly<Record<DataType, StorageFamily>>;
38
+ /** The parts of a field that decide how its values are stored. */
39
+ export type StoredFieldShape = {
40
+ type: DataType;
41
+ settings?: object;
42
+ };
43
+ /**
44
+ * The storage family of a field's values, from its type and settings: a multi-value enum holds an array of
45
+ * strings, not a string. Use this rather than `STORAGE_FAMILY[type]` wherever a field's settings are known.
46
+ */
47
+ export declare const storageFamilyOf: (field: StoredFieldShape) => StorageFamily;
38
48
  //#endregion
39
49
  //#region src/types/json.d.ts
40
50
  export type JsonPrimitive = string | number | boolean | null;
@@ -797,7 +807,7 @@ export type ValidationIssue = {
797
807
  /** Set by cross-definition checks so a multi-definition apply can say which file is wrong. */
798
808
  definitionId?: string;
799
809
  };
800
- export type IssueCode = 'INVALID_STRUCTURE' | 'INVALID_ID' | 'DUPLICATE_ID' | 'API_KEY_INVALID' | 'API_KEY_TOO_LONG' | 'API_KEY_RESERVED_PREFIX' | 'API_KEY_RESERVED' | 'API_KEY_COLLISION' | 'PLURAL_API_KEY_SAME_AS_SINGULAR' | 'GENERATED_NAME_COLLISION' | 'INVALID_SETTINGS' | 'INVALID_RANGE' | 'INVALID_PATTERN' | 'DUPLICATE_ENUM_VALUE' | 'INVALID_ENUM_VALUE' | 'UNSUPPORTED_FLAG' | 'INVALID_DEFAULT_VALUE' | 'UNKNOWN_EDITOR' | 'INCOMPATIBLE_EDITOR' | 'INVALID_EDITOR_OPTIONS' | 'UNKNOWN_FIELD_REFERENCE' | 'INVALID_FIELD_REFERENCE' | 'DUPLICATE_GROUP' | 'UNKNOWN_REFERENCE' | 'INVALID_REFERENCE_TARGET' | 'COMPONENT_CYCLE' | 'COMPONENT_TOO_DEEP' | 'REFERENCED_DEFINITION';
810
+ export type IssueCode = 'INVALID_STRUCTURE' | 'INVALID_TEXT' | 'INVALID_ID' | 'DUPLICATE_ID' | 'API_KEY_INVALID' | 'API_KEY_TOO_LONG' | 'API_KEY_RESERVED_PREFIX' | 'API_KEY_RESERVED' | 'API_KEY_COLLISION' | 'PLURAL_API_KEY_SAME_AS_SINGULAR' | 'GENERATED_NAME_COLLISION' | 'INVALID_SETTINGS' | 'INVALID_RANGE' | 'INVALID_PATTERN' | 'DUPLICATE_ENUM_VALUE' | 'INVALID_ENUM_VALUE' | 'UNSUPPORTED_FLAG' | 'INVALID_DEFAULT_VALUE' | 'UNKNOWN_EDITOR' | 'INCOMPATIBLE_EDITOR' | 'INVALID_EDITOR_OPTIONS' | 'UNKNOWN_FIELD_REFERENCE' | 'INVALID_FIELD_REFERENCE' | 'DUPLICATE_GROUP' | 'UNKNOWN_REFERENCE' | 'INVALID_REFERENCE_TARGET' | 'COMPONENT_CYCLE' | 'COMPONENT_TOO_DEEP' | 'REFERENCED_DEFINITION';
801
811
  export declare class SchemaValidationError extends Error {
802
812
  readonly issues: readonly ValidationIssue[];
803
813
  constructor(issues: readonly ValidationIssue[]);
@@ -939,6 +949,21 @@ export declare const findReferencingDefinitions: (definitions: readonly SchemaDe
939
949
  */
940
950
  export declare const findDependentModels: (definitions: readonly SchemaDefinition[], componentId: string) => SchemaDefinition[];
941
951
  //#endregion
952
+ //#region src/validators/text.d.ts
953
+ /**
954
+ * Text no database can store as is: PostgreSQL `text` and `jsonb` reject U+0000, and `jsonb` rejects an
955
+ * unpaired UTF-16 surrogate. Shapio refuses both everywhere it takes input, so every database accepts the same
956
+ * values (SQLite would store them).
957
+ */
958
+ export declare const INVALID_TEXT_MESSAGE = "must not contain NUL characters or unpaired surrogates";
959
+ export declare const isValidText: (text: string) => boolean;
960
+ /**
961
+ * The JSON pointer (relative to `value`, `''` for the value itself) of the first string, or object key, that
962
+ * is not valid text; undefined when everything is. Walks arrays and plain objects; other values (numbers,
963
+ * buffers, dates) hold no text.
964
+ */
965
+ export declare const findInvalidText: (value: unknown, path?: string) => string | undefined;
966
+ //#endregion
942
967
  //#region src/diff/types.d.ts
943
968
  export declare const CHANGE_KINDS: readonly ["definition.added", "definition.removed", "definition.apiKey", "definition.pluralApiKey", "definition.metadata", "model.kind", "model.localized", "model.draftAndPublish", "field.added", "field.removed", "field.order", "field.apiKey", "field.metadata", "field.editor", "field.type", "field.required", "field.localized", "field.public", "field.deprecated", "field.unique", "field.filterable", "field.sortable", "field.settings"];
944
969
  export type ChangeKind = (typeof CHANGE_KINDS)[number];
@@ -982,6 +1007,7 @@ export declare const diffDefinitions: (before: SchemaDefinition | null, after: S
982
1007
  * | (plus) type change of a unique field | as its type change | + checkUnique |
983
1008
  * | (plus) tightened validation rules | validation | validateValues |
984
1009
  * | (plus) localized true→false | conversion (destructive) | convert |
1010
+ * | (plus) localized flip of a unique field | as the flip | + checkUnique |
985
1011
  * | (plus) type change Shapio can't convert | conversion (destructive, drops) | convert (+ validate/required) |
986
1012
  */
987
1013
  export type ChangeCategory = 'metadata' | 'editorSwap' | 'additive' | 'requiredField' | 'validation' | 'conversion' | 'contract' | 'removal' | 'constraint' | 'index';
@@ -1008,9 +1034,19 @@ export type ClassifyContext = {
1008
1034
  };
1009
1035
  /**
1010
1036
  * A type change Shapio cannot convert: the field keeps its stable ID and API ID, and every stored value is
1011
- * dropped. The planner (`classifyChange`) and the content conversion share this one rule.
1037
+ * dropped. The planner (`classifyChange`) decides it from both sides' type and settings and records it as
1038
+ * `dropsValues` on the classified change; everything downstream (conversion job, impact, review, CLI) reads
1039
+ * that flag rather than deciding again from the type names.
1040
+ */
1041
+ export declare const typeChangeDropsValues: (from: StoredFieldShape, to: StoredFieldShape) => boolean;
1042
+ /**
1043
+ * A change as a stored plan step carries it: classified since 0.5.6, plain before (no drops existed then).
1012
1044
  */
1013
- export declare const typeChangeDropsValues: (from: DataType, to: DataType) => boolean;
1045
+ export type PlannedChange = SchemaChange & {
1046
+ dropsValues?: boolean;
1047
+ };
1048
+ /** Whether a (classified) change drops every stored value of its field; false for plans without the flag. */
1049
+ export declare const changeDropsValues: (change: PlannedChange) => boolean;
1014
1050
  /** Classifies one change in the context of the definitions it was diffed from. */
1015
1051
  export declare const classifyChange: (change: SchemaChange, context: ClassifyContext) => ClassifiedChange;
1016
1052
  export declare const classifyChanges: (changes: readonly SchemaChange[], context: ClassifyContext) => ClassifiedChange[];
@@ -1041,6 +1077,15 @@ export type ClassifiedLocaleChange = {
1041
1077
  */
1042
1078
  export declare const classifyLocaleChange: (kind: LocaleChangeKind, code: string) => ClassifiedLocaleChange;
1043
1079
  //#endregion
1080
+ //#region src/diff/uniqueLocalization.d.ts
1081
+ /**
1082
+ * Unique fields of a model whose values move between per-locale and shared storage in this change (the field's
1083
+ * or the model's `localized` flips). Their registry rows change key (locale ↔ `*`), and values that were unique
1084
+ * per locale may collide once shared, so each needs a uniqueness check that rebuilds its rows. Deprecated fields
1085
+ * are skipped: the registry does not track them.
1086
+ */
1087
+ export declare const uniqueFieldsChangingLocalization: (before: SchemaDefinition | null, after: SchemaDefinition | null) => FieldDefinition[];
1088
+ //#endregion
1044
1089
  //#region src/fileFormat/canonical.d.ts
1045
1090
  export declare const canonicalJson: (value: unknown) => string;
1046
1091
  /**
package/dist/index.js CHANGED
@@ -96,6 +96,11 @@ const STORAGE_FAMILY = {
96
96
  component: "component",
97
97
  dynamiczone: "dynamiczone"
98
98
  };
99
+ /**
100
+ * The storage family of a field's values, from its type and settings: a multi-value enum holds an array of
101
+ * strings, not a string. Use this rather than `STORAGE_FAMILY[type]` wherever a field's settings are known.
102
+ */
103
+ const storageFamilyOf = (field) => field.type === "enum" && field.settings?.multiple === true ? "jsonStringArray" : STORAGE_FAMILY[field.type];
99
104
  //#endregion
100
105
  //#region src/types/definitions.ts
101
106
  /**
@@ -1172,6 +1177,46 @@ const generatedNames = (definition) => {
1172
1177
  return names;
1173
1178
  };
1174
1179
  //#endregion
1180
+ //#region src/validators/text.ts
1181
+ /**
1182
+ * Text no database can store as is: PostgreSQL `text` and `jsonb` reject U+0000, and `jsonb` rejects an
1183
+ * unpaired UTF-16 surrogate. Shapio refuses both everywhere it takes input, so every database accepts the same
1184
+ * values (SQLite would store them).
1185
+ */
1186
+ const INVALID_TEXT_MESSAGE = "must not contain NUL characters or unpaired surrogates";
1187
+ const isValidText = (text) => !text.includes("\0") && text.isWellFormed();
1188
+ /**
1189
+ * Parsed JSON and querystrings; not buffers, dates or class instances. Querystring parsers build objects
1190
+ * without `Object.prototype`, either with no prototype or with an empty one that has none.
1191
+ */
1192
+ const isPlainObject = (value) => {
1193
+ const prototype = Object.getPrototypeOf(value);
1194
+ return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
1195
+ };
1196
+ const escapeSegment = (segment) => segment.replaceAll("~", "~0").replaceAll("/", "~1");
1197
+ /**
1198
+ * The JSON pointer (relative to `value`, `''` for the value itself) of the first string, or object key, that
1199
+ * is not valid text; undefined when everything is. Walks arrays and plain objects; other values (numbers,
1200
+ * buffers, dates) hold no text.
1201
+ */
1202
+ const findInvalidText = (value, path = "") => {
1203
+ if (typeof value === "string") return isValidText(value) ? void 0 : path;
1204
+ if (Array.isArray(value)) {
1205
+ for (const [index, item] of value.entries()) {
1206
+ const found = findInvalidText(item, `${path}/${index}`);
1207
+ if (found !== void 0) return found;
1208
+ }
1209
+ return;
1210
+ }
1211
+ if (typeof value !== "object" || value === null || !isPlainObject(value)) return;
1212
+ for (const [key, item] of Object.entries(value)) {
1213
+ const at = `${path}/${escapeSegment(key)}`;
1214
+ if (!isValidText(key)) return at;
1215
+ const found = findInvalidText(item, at);
1216
+ if (found !== void 0) return found;
1217
+ }
1218
+ };
1219
+ //#endregion
1175
1220
  //#region src/validators/typeboxIssues.ts
1176
1221
  /**
1177
1222
  * TypeBox errors as (JSON pointer, message) pairs. The `schema is false` echo that accompanies every
@@ -1445,6 +1490,8 @@ const checkPluralApiKey = (definition) => {
1445
1490
  /** All problems with one definition, in document order. Empty means valid on its own. */
1446
1491
  const validateDefinition = (definition) => {
1447
1492
  const issues = [];
1493
+ const invalidText = findInvalidText(definition);
1494
+ if (invalidText !== void 0) issues.push(issue(invalidText, "INVALID_TEXT", INVALID_TEXT_MESSAGE));
1448
1495
  if (!isStableId(definition.id)) issues.push(issue("/id", "INVALID_ID", "must be a lower-case UUID"));
1449
1496
  const syntax = checkApiKeySyntax(definition.apiKey);
1450
1497
  if (syntax) issues.push(issue("/apiKey", syntax.code, syntax.message));
@@ -1917,6 +1964,26 @@ const diffDefinitions = (before, after) => {
1917
1964
  return changes;
1918
1965
  };
1919
1966
  //#endregion
1967
+ //#region src/diff/uniqueLocalization.ts
1968
+ /**
1969
+ * Whether a field's values are stored per locale: on a localized model only (ADR 0004). The unique registry
1970
+ * keys such a field by locale and a shared one by `*`.
1971
+ */
1972
+ const storedPerLocale = (definition, field) => definition.kind !== "component" && definition.localized === true && field.localized === true;
1973
+ /**
1974
+ * Unique fields of a model whose values move between per-locale and shared storage in this change (the field's
1975
+ * or the model's `localized` flips). Their registry rows change key (locale ↔ `*`), and values that were unique
1976
+ * per locale may collide once shared, so each needs a uniqueness check that rebuilds its rows. Deprecated fields
1977
+ * are skipped: the registry does not track them.
1978
+ */
1979
+ const uniqueFieldsChangingLocalization = (before, after) => {
1980
+ if (!before || !after || after.kind === "component") return [];
1981
+ return after.fields.filter((field) => {
1982
+ const previous = before.fields.find((candidate) => candidate.id === field.id);
1983
+ return previous !== void 0 && field.unique === true && !field.deprecated && storedPerLocale(before, previous) !== storedPerLocale(after, field);
1984
+ });
1985
+ };
1986
+ //#endregion
1920
1987
  //#region src/diff/classify.ts
1921
1988
  const result = (category, extra = {}) => ({
1922
1989
  category,
@@ -1974,22 +2041,27 @@ const hasTextConstraints = (field) => {
1974
2041
  };
1975
2042
  /**
1976
2043
  * Whether Shapio converts a cross-family type change value by value (the pairs it knows); within one storage
1977
- * family the stored JSON stays as it is.
2044
+ * family the stored JSON stays as it is. Families come from type and settings, so a multi-value enum's
2045
+ * arrays are never taken for text.
1978
2046
  */
1979
2047
  const convertsAcrossFamilies = (from, to) => {
1980
- const fromFamily = STORAGE_FAMILY[from];
1981
- const toFamily = STORAGE_FAMILY[to];
2048
+ const fromFamily = storageFamilyOf(from);
2049
+ const toFamily = storageFamilyOf(to);
1982
2050
  const numericPair = fromFamily === "jsonNumber" && toFamily === "numericString" || fromFamily === "numericString" && toFamily === "jsonNumber";
1983
- const toText = SCALAR_FAMILIES.has(fromFamily) && PLAIN_TEXT_TYPES.has(to);
1984
- const textToRichtext = fromFamily === "jsonString" && from !== "code" && to === "richtext";
1985
- const richtextToText = from === "richtext" && PLAIN_TEXT_TYPES.has(to);
1986
- return numericPair || toText || textToRichtext || richtextToText;
2051
+ const toText = SCALAR_FAMILIES.has(fromFamily) && PLAIN_TEXT_TYPES.has(to.type);
2052
+ const textToRichtext = fromFamily === "jsonString" && from.type !== "code" && to.type === "richtext";
2053
+ const richtextToText = from.type === "richtext" && PLAIN_TEXT_TYPES.has(to.type);
2054
+ return numericPair || toText || textToRichtext || richtextToText || fromFamily === "jsonString" && toFamily === "jsonStringArray";
1987
2055
  };
1988
2056
  /**
1989
2057
  * A type change Shapio cannot convert: the field keeps its stable ID and API ID, and every stored value is
1990
- * dropped. The planner (`classifyChange`) and the content conversion share this one rule.
2058
+ * dropped. The planner (`classifyChange`) decides it from both sides' type and settings and records it as
2059
+ * `dropsValues` on the classified change; everything downstream (conversion job, impact, review, CLI) reads
2060
+ * that flag rather than deciding again from the type names.
1991
2061
  */
1992
- const typeChangeDropsValues = (from, to) => STORAGE_FAMILY[from] !== STORAGE_FAMILY[to] && !convertsAcrossFamilies(from, to);
2062
+ const typeChangeDropsValues = (from, to) => storageFamilyOf(from) !== storageFamilyOf(to) && !convertsAcrossFamilies(from, to);
2063
+ /** Whether a (classified) change drops every stored value of its field; false for plans without the flag. */
2064
+ const changeDropsValues = (change) => change.kind === "field.type" && change.dropsValues === true;
1993
2065
  /** A required field whose values are dropped is backfilled from its default, else checked (no silent nulls). */
1994
2066
  const requiredStep = (field) => {
1995
2067
  if (!field?.required) return [];
@@ -2000,14 +2072,22 @@ const requiredStep = (field) => {
2000
2072
  * re-validates existing values. Across families Shapio converts values with a job, for the pairs it knows;
2001
2073
  * any other pair drops the values (destructive, acknowledged in the review).
2002
2074
  */
2003
- const classifyTypeChange = (from, to, after) => {
2075
+ const classifyTypeChange = (from, to, previous, after) => {
2004
2076
  const breaking = API_SCALAR[from] !== API_SCALAR[to] || to === "code" && from !== "code";
2005
- const fromFamily = STORAGE_FAMILY[from];
2006
- if (fromFamily === STORAGE_FAMILY[to]) return fromFamily === "jsonString" && TEXT_TARGETS.has(to) && !hasTextConstraints(after) || from === "integer" && to === "number" || from === "biginteger" && to === "decimal" && after?.type === "decimal" && after.settings.precision === void 0 ? result("additive", { breaking }) : result("validation", {
2077
+ const fromShape = {
2078
+ type: from,
2079
+ ...previous ? { settings: previous.settings } : {}
2080
+ };
2081
+ const toShape = {
2082
+ type: to,
2083
+ ...after ? { settings: after.settings } : {}
2084
+ };
2085
+ const fromFamily = storageFamilyOf(fromShape);
2086
+ if (fromFamily === storageFamilyOf(toShape)) return fromFamily === "jsonString" && TEXT_TARGETS.has(to) && !hasTextConstraints(after) || from === "integer" && to === "number" || from === "biginteger" && to === "decimal" && after?.type === "decimal" && after.settings.precision === void 0 ? result("additive", { breaking }) : result("validation", {
2007
2087
  breaking,
2008
2088
  prerequisites: ["validateValues"]
2009
2089
  });
2010
- if (typeChangeDropsValues(from, to)) return result("conversion", {
2090
+ if (typeChangeDropsValues(fromShape, toShape)) return result("conversion", {
2011
2091
  breaking,
2012
2092
  destructive: true,
2013
2093
  dropsValues: true,
@@ -2100,7 +2180,7 @@ const classifyFieldChange = (change, { before, after }) => {
2100
2180
  case "field.editor": return result("editorSwap");
2101
2181
  case "field.apiKey": return result("contract", { breaking: true });
2102
2182
  case "field.type": {
2103
- const classification = classifyTypeChange(change.from, change.to, field);
2183
+ const classification = classifyTypeChange(change.from, change.to, previous, field);
2104
2184
  return field?.unique && previous?.unique && !classification.prerequisites.includes("checkUnique") ? {
2105
2185
  ...classification,
2106
2186
  prerequisites: [...classification.prerequisites, "checkUnique"]
@@ -2109,12 +2189,14 @@ const classifyFieldChange = (change, { before, after }) => {
2109
2189
  case "field.required":
2110
2190
  if (change.to !== true) return result("additive");
2111
2191
  return result("requiredField", { prerequisites: [field?.defaultValue !== void 0 ? "backfill" : "validateRequired"] });
2112
- case "field.localized":
2192
+ case "field.localized": {
2113
2193
  if (!(after?.kind !== "component" && after?.localized === true)) return result("metadata");
2114
- return change.to === true ? result("additive") : result("conversion", {
2194
+ const checks = uniqueFieldsChangingLocalization(before, after).some((candidate) => candidate.id === change.fieldId) ? ["checkUnique"] : [];
2195
+ return change.to === true ? result("additive", { prerequisites: checks }) : result("conversion", {
2115
2196
  destructive: true,
2116
- prerequisites: ["convert"]
2197
+ prerequisites: ["convert", ...checks]
2117
2198
  });
2199
+ }
2118
2200
  case "field.public":
2119
2201
  case "field.deprecated": {
2120
2202
  const hides = change.kind === "field.public" ? change.to === false : change.to === true;
@@ -2153,12 +2235,14 @@ const classifyChange = (change, context) => {
2153
2235
  prerequisites: ["validateValues"]
2154
2236
  }) : result("contract", { breaking: true });
2155
2237
  break;
2156
- case "model.localized":
2157
- classification = change.to === true ? result("additive") : result("conversion", {
2238
+ case "model.localized": {
2239
+ const checks = uniqueFieldsChangingLocalization(context.before, context.after).length > 0 ? ["checkUnique"] : [];
2240
+ classification = change.to === true ? result("additive", { prerequisites: checks }) : result("conversion", {
2158
2241
  destructive: true,
2159
- prerequisites: ["convert"]
2242
+ prerequisites: ["convert", ...checks]
2160
2243
  });
2161
2244
  break;
2245
+ }
2162
2246
  case "model.draftAndPublish":
2163
2247
  classification = change.to === true ? result("additive") : result("conversion", {
2164
2248
  destructive: true,
@@ -2801,6 +2885,6 @@ const SeoDefaultsSchema = Type.Object({
2801
2885
  twitterHandle: Type.Union([Type.String({ pattern: SEO_TWITTER_HANDLE_PATTERN.source }), Type.Null()])
2802
2886
  }, closed);
2803
2887
  //#endregion
2804
- export { API_KEY_PATTERN, BIGINTEGER_PATTERN, BUILT_IN_THEME_KEYS, CANVAS_ELIGIBLE, CHANGE_KINDS, CODE_LANGUAGES, COMPONENT_TYPE_SUFFIXES, CUSTOM_EDITOR_ID_PATTERN, ComponentDefinitionInputSchema, ComponentDisplayInputSchema, DATA_TYPES, DATETIME_PATTERN, DATE_PATTERN, DECIMAL_PATTERN, DEFAULT_EDITORS, DEFAULT_SEO_KEYS, DEFINITION_KINDS, DefinitionInputSchema, EDITOR_CATALOGUE, EMPTY_SEO_DEFAULTS, ENTRY_LAYOUTS, EditorChoiceInputSchema, EnumValueSchema, FIELD_WIDTHS, FieldInputSchema, INLINE_TITLE_TYPES, LOCALE_CODE_PATTERN, LOCK_FILE_FORMAT_VERSION, LOCK_FILE_PATH, LocaleInputSchema, LockEntrySchema, LockFileError, LockFileSchema, MARK_RULES, MAX_API_KEY_LENGTH, MAX_COMPONENT_DEPTH, MAX_DESCRIPTION_LENGTH, MAX_FALLBACK_CHAIN, MAX_FIELDS_PER_DEFINITION, MAX_LABEL_LENGTH, MAX_RICHTEXT_DEPTH, MEDIA_KINDS, MODEL_KINDS, MODEL_TYPE_SUFFIXES, MUTATION_PREFIXES, ModelDefinitionInputSchema, ModelDisplayInputSchema, NODE_RULES, PLURAL_FALLBACK_SUFFIX, REFERENCE_DATA_TYPES, RELATION_CARDINALITIES, RESERVED_DEFINITION_API_KEYS, RESERVED_FIELD_API_KEYS, RESERVED_QUERY_NAMES, RESERVED_TYPE_NAMES, RICHTEXT_FORMAT, RICHTEXT_FORMAT_VERSION, SAFE_LINK_PATTERN, SCALAR_DATA_TYPES, SCHEMA_KIND_DIRECTORIES, SEO_COMPONENT_API_KEY, SEO_COMPONENT_ID, SEO_DESCRIPTION_SOFT_MAX, SEO_EDITOR_ID, SEO_FIELD_IDS, SEO_TITLE_PLACEHOLDER, SEO_TITLE_SOFT_MAX, SEO_TITLE_TEMPLATE_PATTERN, SEO_TWITTER_HANDLE_PATTERN, SETTINGS_SCHEMAS, SITES_DIRECTORY, SLUG_PATTERN, SORT_DIRECTIONS, STABLE_ID_PATTERN, STORAGE_FAMILY, STRIP_DEFAULT_COUNT, SchemaValidationError, SeoDefaultsSchema, SeoLocaleDefaultsSchema, TEXT_TITLE_FIELD_TYPES, THEME_BRAND_TOKENS, THEME_COLOUR_PATTERN, THEME_DARK_UI_PAIRS, THEME_KEY_PATTERN, THEME_SEMANTIC_TOKENS, THEME_TEXT_PAIRS, THEME_TOKENS, THEME_UI_PAIRS, THEME_VARIANTS, TIME_PATTERN, TITLE_FIELD_TYPES, UID_PATTERN, UNIQUE_CAPABLE_DATA_TYPES, applyTitleTemplate, assignIds, canonicalJson, checkApiKeySyntax, checkDefaultValue, checkThemeContrast, classifyChange, classifyChanges, classifyLocaleChange, collectionQueryName, contrastRatio, createStableId, decideSync, diffDefinitions, effectiveFormLayout, effectiveLayout, effectiveTitleField, embeddedComponentIds, entryLayoutOf, escapeHtml, findDependentModels, findReferencingDefinitions, foldApiKey, generatedNames, hashDefinition, isApiKeySyntaxValid, isCanvasEligible, isComponentDefinition, isCoverEligible, isCustomEditorId, isDataType, isDocumentPlaceable, isEmptyRichText, isModelDefinition, isSeoField, isStableId, isValidTitleTemplate, issue, listCompatibleEditors, lockCoversSite, lockEntriesForSite, mergePulledLock, normalizeDefinition, parseDefinition, parseLockFile, plainTextToRichText, renderRichTextHtml, renormalizeDefinition, resolveSeo, richTextBodyOf, richTextMediaIds, richTextPlainText, richTextToPlainText, routeKeyOf, schemaFilePath, scopeDirectory, scopeOfSchemaFilePath, seoComponentDefinition, seoDefaultsForLocale, serializeDefinition, serializeLockFile, sha256, stripFieldsOf, suggestPlural, summarizeChanges, toTypeName, typeChangeDropsValues, upgradeLockFile, validateDefinition, validateRichText, validateSchema, withDerivedPlural, withSiteCovered };
2888
+ export { API_KEY_PATTERN, BIGINTEGER_PATTERN, BUILT_IN_THEME_KEYS, CANVAS_ELIGIBLE, CHANGE_KINDS, CODE_LANGUAGES, COMPONENT_TYPE_SUFFIXES, CUSTOM_EDITOR_ID_PATTERN, ComponentDefinitionInputSchema, ComponentDisplayInputSchema, DATA_TYPES, DATETIME_PATTERN, DATE_PATTERN, DECIMAL_PATTERN, DEFAULT_EDITORS, DEFAULT_SEO_KEYS, DEFINITION_KINDS, DefinitionInputSchema, EDITOR_CATALOGUE, EMPTY_SEO_DEFAULTS, ENTRY_LAYOUTS, EditorChoiceInputSchema, EnumValueSchema, FIELD_WIDTHS, FieldInputSchema, INLINE_TITLE_TYPES, INVALID_TEXT_MESSAGE, LOCALE_CODE_PATTERN, LOCK_FILE_FORMAT_VERSION, LOCK_FILE_PATH, LocaleInputSchema, LockEntrySchema, LockFileError, LockFileSchema, MARK_RULES, MAX_API_KEY_LENGTH, MAX_COMPONENT_DEPTH, MAX_DESCRIPTION_LENGTH, MAX_FALLBACK_CHAIN, MAX_FIELDS_PER_DEFINITION, MAX_LABEL_LENGTH, MAX_RICHTEXT_DEPTH, MEDIA_KINDS, MODEL_KINDS, MODEL_TYPE_SUFFIXES, MUTATION_PREFIXES, ModelDefinitionInputSchema, ModelDisplayInputSchema, NODE_RULES, PLURAL_FALLBACK_SUFFIX, REFERENCE_DATA_TYPES, RELATION_CARDINALITIES, RESERVED_DEFINITION_API_KEYS, RESERVED_FIELD_API_KEYS, RESERVED_QUERY_NAMES, RESERVED_TYPE_NAMES, RICHTEXT_FORMAT, RICHTEXT_FORMAT_VERSION, SAFE_LINK_PATTERN, SCALAR_DATA_TYPES, SCHEMA_KIND_DIRECTORIES, SEO_COMPONENT_API_KEY, SEO_COMPONENT_ID, SEO_DESCRIPTION_SOFT_MAX, SEO_EDITOR_ID, SEO_FIELD_IDS, SEO_TITLE_PLACEHOLDER, SEO_TITLE_SOFT_MAX, SEO_TITLE_TEMPLATE_PATTERN, SEO_TWITTER_HANDLE_PATTERN, SETTINGS_SCHEMAS, SITES_DIRECTORY, SLUG_PATTERN, SORT_DIRECTIONS, STABLE_ID_PATTERN, STORAGE_FAMILY, STRIP_DEFAULT_COUNT, SchemaValidationError, SeoDefaultsSchema, SeoLocaleDefaultsSchema, TEXT_TITLE_FIELD_TYPES, THEME_BRAND_TOKENS, THEME_COLOUR_PATTERN, THEME_DARK_UI_PAIRS, THEME_KEY_PATTERN, THEME_SEMANTIC_TOKENS, THEME_TEXT_PAIRS, THEME_TOKENS, THEME_UI_PAIRS, THEME_VARIANTS, TIME_PATTERN, TITLE_FIELD_TYPES, UID_PATTERN, UNIQUE_CAPABLE_DATA_TYPES, applyTitleTemplate, assignIds, canonicalJson, changeDropsValues, checkApiKeySyntax, checkDefaultValue, checkThemeContrast, classifyChange, classifyChanges, classifyLocaleChange, collectionQueryName, contrastRatio, createStableId, decideSync, diffDefinitions, effectiveFormLayout, effectiveLayout, effectiveTitleField, embeddedComponentIds, entryLayoutOf, escapeHtml, findDependentModels, findInvalidText, findReferencingDefinitions, foldApiKey, generatedNames, hashDefinition, isApiKeySyntaxValid, isCanvasEligible, isComponentDefinition, isCoverEligible, isCustomEditorId, isDataType, isDocumentPlaceable, isEmptyRichText, isModelDefinition, isSeoField, isStableId, isValidText, isValidTitleTemplate, issue, listCompatibleEditors, lockCoversSite, lockEntriesForSite, mergePulledLock, normalizeDefinition, parseDefinition, parseLockFile, plainTextToRichText, renderRichTextHtml, renormalizeDefinition, resolveSeo, richTextBodyOf, richTextMediaIds, richTextPlainText, richTextToPlainText, routeKeyOf, schemaFilePath, scopeDirectory, scopeOfSchemaFilePath, seoComponentDefinition, seoDefaultsForLocale, serializeDefinition, serializeLockFile, sha256, storageFamilyOf, stripFieldsOf, suggestPlural, summarizeChanges, toTypeName, typeChangeDropsValues, uniqueFieldsChangingLocalization, upgradeLockFile, validateDefinition, validateRichText, validateSchema, withDerivedPlural, withSiteCovered };
2805
2889
 
2806
2890
  //# sourceMappingURL=index.js.map