@shapio/schema 0.5.5 → 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,8 @@ 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 |
1011
+ * | (plus) type change Shapio can't convert | conversion (destructive, drops) | convert (+ validate/required) |
985
1012
  */
986
1013
  export type ChangeCategory = 'metadata' | 'editorSwap' | 'additive' | 'requiredField' | 'validation' | 'conversion' | 'contract' | 'removal' | 'constraint' | 'index';
987
1014
  /** Work that must succeed before activation. Content-touching kinds run through the content ports. */
@@ -994,8 +1021,10 @@ export type ClassifiedChange = SchemaChange & {
994
1021
  breaking: boolean;
995
1022
  /** Loses stored information that a schema rollback cannot restore. */
996
1023
  destructive: boolean;
997
- /** False for conversions Shapio cannot perform; the planner refuses them. */
1024
+ /** False for changes Shapio cannot perform; the planner refuses them. None today; kept for future refusals. */
998
1025
  supported: boolean;
1026
+ /** A type change Shapio cannot convert: every stored value of the field is dropped (destructive). */
1027
+ dropsValues: boolean;
999
1028
  prerequisites: PrerequisiteKind[];
1000
1029
  cleanup: CleanupKind[];
1001
1030
  };
@@ -1003,6 +1032,21 @@ export type ClassifyContext = {
1003
1032
  before: SchemaDefinition | null;
1004
1033
  after: SchemaDefinition | null;
1005
1034
  };
1035
+ /**
1036
+ * A type change Shapio cannot convert: the field keeps its stable ID and API ID, and every stored value is
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).
1044
+ */
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;
1006
1050
  /** Classifies one change in the context of the definitions it was diffed from. */
1007
1051
  export declare const classifyChange: (change: SchemaChange, context: ClassifyContext) => ClassifiedChange;
1008
1052
  export declare const classifyChanges: (changes: readonly SchemaChange[], context: ClassifyContext) => ClassifiedChange[];
@@ -1033,6 +1077,15 @@ export type ClassifiedLocaleChange = {
1033
1077
  */
1034
1078
  export declare const classifyLocaleChange: (kind: LocaleChangeKind, code: string) => ClassifiedLocaleChange;
1035
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
1036
1089
  //#region src/fileFormat/canonical.d.ts
1037
1090
  export declare const canonicalJson: (value: unknown) => string;
1038
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,12 +1964,33 @@ 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,
1923
1990
  breaking: false,
1924
1991
  destructive: false,
1925
1992
  supported: true,
1993
+ dropsValues: false,
1926
1994
  prerequisites: [],
1927
1995
  cleanup: [],
1928
1996
  ...extra
@@ -1972,27 +2040,67 @@ const hasTextConstraints = (field) => {
1972
2040
  return settings.minLength !== void 0 || settings.maxLength !== void 0 || settings.pattern !== void 0 || settings.validate === true;
1973
2041
  };
1974
2042
  /**
2043
+ * Whether Shapio converts a cross-family type change value by value (the pairs it knows); within one storage
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.
2046
+ */
2047
+ const convertsAcrossFamilies = (from, to) => {
2048
+ const fromFamily = storageFamilyOf(from);
2049
+ const toFamily = storageFamilyOf(to);
2050
+ const numericPair = fromFamily === "jsonNumber" && toFamily === "numericString" || fromFamily === "numericString" && toFamily === "jsonNumber";
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";
2055
+ };
2056
+ /**
2057
+ * A type change Shapio cannot convert: the field keeps its stable ID and API ID, and every stored value is
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.
2061
+ */
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;
2065
+ /** A required field whose values are dropped is backfilled from its default, else checked (no silent nulls). */
2066
+ const requiredStep = (field) => {
2067
+ if (!field?.required) return [];
2068
+ return [field.defaultValue !== void 0 ? "backfill" : "validateRequired"];
2069
+ };
2070
+ /**
1975
2071
  * A type change. Within one storage family the stored JSON stays as it is: widening is live, anything else
1976
- * re-validates existing values. Across families Shapio converts values with a job, for the pairs it knows.
2072
+ * re-validates existing values. Across families Shapio converts values with a job, for the pairs it knows;
2073
+ * any other pair drops the values (destructive, acknowledged in the review).
1977
2074
  */
1978
- const classifyTypeChange = (from, to, after) => {
2075
+ const classifyTypeChange = (from, to, previous, after) => {
1979
2076
  const breaking = API_SCALAR[from] !== API_SCALAR[to] || to === "code" && from !== "code";
1980
- const fromFamily = STORAGE_FAMILY[from];
1981
- const toFamily = STORAGE_FAMILY[to];
1982
- if (fromFamily === toFamily) 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", {
1983
2087
  breaking,
1984
2088
  prerequisites: ["validateValues"]
1985
2089
  });
1986
- const numericPair = fromFamily === "jsonNumber" && toFamily === "numericString" || fromFamily === "numericString" && toFamily === "jsonNumber";
1987
- const toText = SCALAR_FAMILIES.has(fromFamily) && PLAIN_TEXT_TYPES.has(to);
1988
- const textToRichtext = fromFamily === "jsonString" && from !== "code" && to === "richtext";
1989
- const richtextToText = from === "richtext" && PLAIN_TEXT_TYPES.has(to);
1990
- const supported = numericPair || toText || textToRichtext || richtextToText;
2090
+ if (typeChangeDropsValues(fromShape, toShape)) return result("conversion", {
2091
+ breaking,
2092
+ destructive: true,
2093
+ dropsValues: true,
2094
+ prerequisites: [
2095
+ "convert",
2096
+ "validateValues",
2097
+ ...requiredStep(after)
2098
+ ]
2099
+ });
1991
2100
  return result("conversion", {
1992
2101
  breaking,
1993
- supported,
1994
- destructive: richtextToText,
1995
- prerequisites: supported ? ["convert", "validateValues"] : []
2102
+ destructive: from === "richtext" && PLAIN_TEXT_TYPES.has(to),
2103
+ prerequisites: ["convert", "validateValues"]
1996
2104
  });
1997
2105
  };
1998
2106
  const compareValues = (a, b) => {
@@ -2072,7 +2180,7 @@ const classifyFieldChange = (change, { before, after }) => {
2072
2180
  case "field.editor": return result("editorSwap");
2073
2181
  case "field.apiKey": return result("contract", { breaking: true });
2074
2182
  case "field.type": {
2075
- const classification = classifyTypeChange(change.from, change.to, field);
2183
+ const classification = classifyTypeChange(change.from, change.to, previous, field);
2076
2184
  return field?.unique && previous?.unique && !classification.prerequisites.includes("checkUnique") ? {
2077
2185
  ...classification,
2078
2186
  prerequisites: [...classification.prerequisites, "checkUnique"]
@@ -2081,12 +2189,14 @@ const classifyFieldChange = (change, { before, after }) => {
2081
2189
  case "field.required":
2082
2190
  if (change.to !== true) return result("additive");
2083
2191
  return result("requiredField", { prerequisites: [field?.defaultValue !== void 0 ? "backfill" : "validateRequired"] });
2084
- case "field.localized":
2192
+ case "field.localized": {
2085
2193
  if (!(after?.kind !== "component" && after?.localized === true)) return result("metadata");
2086
- 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", {
2087
2196
  destructive: true,
2088
- prerequisites: ["convert"]
2197
+ prerequisites: ["convert", ...checks]
2089
2198
  });
2199
+ }
2090
2200
  case "field.public":
2091
2201
  case "field.deprecated": {
2092
2202
  const hides = change.kind === "field.public" ? change.to === false : change.to === true;
@@ -2125,12 +2235,14 @@ const classifyChange = (change, context) => {
2125
2235
  prerequisites: ["validateValues"]
2126
2236
  }) : result("contract", { breaking: true });
2127
2237
  break;
2128
- case "model.localized":
2129
- 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", {
2130
2241
  destructive: true,
2131
- prerequisites: ["convert"]
2242
+ prerequisites: ["convert", ...checks]
2132
2243
  });
2133
2244
  break;
2245
+ }
2134
2246
  case "model.draftAndPublish":
2135
2247
  classification = change.to === true ? result("additive") : result("conversion", {
2136
2248
  destructive: true,
@@ -2773,6 +2885,6 @@ const SeoDefaultsSchema = Type.Object({
2773
2885
  twitterHandle: Type.Union([Type.String({ pattern: SEO_TWITTER_HANDLE_PATTERN.source }), Type.Null()])
2774
2886
  }, closed);
2775
2887
  //#endregion
2776
- 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, 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 };
2777
2889
 
2778
2890
  //# sourceMappingURL=index.js.map