@shapio/schema 0.5.7 → 0.5.9
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 +144 -9
- package/dist/index.js +461 -157
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -284,6 +284,11 @@ export declare const ModelDefinitionInputSchema: Type.TObject<{
|
|
|
284
284
|
localized: Type.TOptional<Type.TBoolean>;
|
|
285
285
|
/** Entries have separate draft and published states. Default true. */
|
|
286
286
|
draftAndPublish: Type.TOptional<Type.TBoolean>;
|
|
287
|
+
/**
|
|
288
|
+
* Collections only: the stable ID of the collection this one extends (its parent). The model inherits
|
|
289
|
+
* the parent's fields, locked, and adds its own (plan polymorphic-types).
|
|
290
|
+
*/
|
|
291
|
+
extends: Type.TOptional<Type.TString>;
|
|
287
292
|
display: Type.TOptional<Type.TObject<{
|
|
288
293
|
/** How entries open: `document` (default) or `form`. See `ENTRY_LAYOUTS`. */
|
|
289
294
|
layout: Type.TOptional<Type.TEnum<["document", "form"]>>;
|
|
@@ -402,6 +407,11 @@ export declare const DefinitionInputSchema: Type.TUnion<[Type.TObject<{
|
|
|
402
407
|
localized: Type.TOptional<Type.TBoolean>;
|
|
403
408
|
/** Entries have separate draft and published states. Default true. */
|
|
404
409
|
draftAndPublish: Type.TOptional<Type.TBoolean>;
|
|
410
|
+
/**
|
|
411
|
+
* Collections only: the stable ID of the collection this one extends (its parent). The model inherits
|
|
412
|
+
* the parent's fields, locked, and adds its own (plan polymorphic-types).
|
|
413
|
+
*/
|
|
414
|
+
extends: Type.TOptional<Type.TString>;
|
|
405
415
|
display: Type.TOptional<Type.TObject<{
|
|
406
416
|
/** How entries open: `document` (default) or `form`. See `ENTRY_LAYOUTS`. */
|
|
407
417
|
layout: Type.TOptional<Type.TEnum<["document", "form"]>>;
|
|
@@ -575,9 +585,28 @@ export type ModelDefinition = {
|
|
|
575
585
|
description?: string;
|
|
576
586
|
localized: boolean;
|
|
577
587
|
draftAndPublish: boolean;
|
|
588
|
+
/**
|
|
589
|
+
* The stable ID of the collection this one extends. The stored definition holds its own fields only;
|
|
590
|
+
* `resolveModelDefinition` adds the inherited ones (ancestors' first).
|
|
591
|
+
*/
|
|
592
|
+
extends?: string;
|
|
578
593
|
fields: FieldDefinition[];
|
|
579
594
|
display: ModelDisplay;
|
|
580
595
|
};
|
|
596
|
+
/** A field as a model sees it after inheritance: `inheritedFrom` names the declaring ancestor's ID. */
|
|
597
|
+
export type ResolvedField = FieldDefinition & {
|
|
598
|
+
inheritedFrom?: string;
|
|
599
|
+
};
|
|
600
|
+
/**
|
|
601
|
+
* A model with its effective fields: every ancestor's fields (root first), then its own, and its display
|
|
602
|
+
* merged with its ancestors' (`resolveModelDefinition`). `ancestorIds` is required so code that needs
|
|
603
|
+
* effective fields can demand this type; a stored definition does not satisfy it.
|
|
604
|
+
*/
|
|
605
|
+
export type ResolvedModelDefinition = Omit<ModelDefinition, 'fields'> & {
|
|
606
|
+
fields: ResolvedField[];
|
|
607
|
+
/** Ancestors' stable IDs, root first; empty for a model that extends nothing. */
|
|
608
|
+
ancestorIds: readonly string[];
|
|
609
|
+
};
|
|
581
610
|
export type ComponentDefinition = {
|
|
582
611
|
id: string;
|
|
583
612
|
kind: 'component';
|
|
@@ -771,6 +800,87 @@ export declare const PLURAL_FALLBACK_SUFFIX = "Items";
|
|
|
771
800
|
*/
|
|
772
801
|
export declare const suggestPlural: (apiKey: string) => string;
|
|
773
802
|
//#endregion
|
|
803
|
+
//#region src/naming/routePath.d.ts
|
|
804
|
+
/** A route key: one to MAX_INHERITANCE_DEPTH API IDs joined by `/` (`products/digital`). */
|
|
805
|
+
export declare const ROUTE_KEY_PATTERN: RegExp;
|
|
806
|
+
/** Longest route key: every level at the longest API ID, plus the separators. */
|
|
807
|
+
export declare const MAX_ROUTE_KEY_LENGTH: number;
|
|
808
|
+
/** The route key of a model under its ancestors (root first): `products/digital`. A root's is `routeKeyOf`. */
|
|
809
|
+
export declare const routePathOf: (definition: ModelDefinition, ancestors: readonly ModelDefinition[]) => string;
|
|
810
|
+
/**
|
|
811
|
+
* Splits the path segments after a content prefix (`/api/content/`) into the route key and the rest: the
|
|
812
|
+
* leading segments that are API IDs (at most MAX_INHERITANCE_DEPTH) form the key; the first one that is not
|
|
813
|
+
* (an entry ID is a UUID, which always has a hyphen) starts the rest. A single segment that already holds a
|
|
814
|
+
* whole route key (`products%2Fdigital`, decoded) is taken as it is. Undefined when no segment is a key.
|
|
815
|
+
* Purely syntactic: shared by the server's URL rewrite and the in-process delivery matcher.
|
|
816
|
+
*/
|
|
817
|
+
export declare const splitRoutePath: (segments: readonly string[]) => {
|
|
818
|
+
routeKey: string;
|
|
819
|
+
rest: string[];
|
|
820
|
+
} | undefined;
|
|
821
|
+
//#endregion
|
|
822
|
+
//#region src/inheritance/resolve.d.ts
|
|
823
|
+
/**
|
|
824
|
+
* Model inheritance (plan polymorphic-types). A collection may extend another (`extends`, the parent's stable
|
|
825
|
+
* ID). Stored definitions hold their own fields only; the effective definition is resolved at read time:
|
|
826
|
+
* every ancestor's fields (root first, each marked `inheritedFrom`), then the model's own, and the display
|
|
827
|
+
* merged down the chain. Nothing is copied into children, so a parent edit changes one definition.
|
|
828
|
+
*/
|
|
829
|
+
/** Most levels a family may have, root included (`Products > Physical > Apparel` is three). */
|
|
830
|
+
export declare const MAX_INHERITANCE_DEPTH = 8;
|
|
831
|
+
export type DefinitionLookup = (id: string) => SchemaDefinition | undefined;
|
|
832
|
+
/** Why an ancestor chain stops early. `invalid`: the parent is a component, a singleton or the model itself. */
|
|
833
|
+
export type AncestorProblem = 'missing' | 'invalid' | 'cycle' | 'tooDeep';
|
|
834
|
+
export type AncestorChain = {
|
|
835
|
+
/** The ancestors that resolve, root first (the parent last). */
|
|
836
|
+
ids: string[];
|
|
837
|
+
problem?: AncestorProblem;
|
|
838
|
+
/** The definition whose `extends` is the problem (the model itself or one of its ancestors). */
|
|
839
|
+
problemAt?: string;
|
|
840
|
+
};
|
|
841
|
+
/**
|
|
842
|
+
* The ancestors of a definition, root first, walking `extends` up. Stops at the first problem (missing,
|
|
843
|
+
* invalid or cyclic parent, or more than MAX_INHERITANCE_DEPTH levels) and returns what resolved so far.
|
|
844
|
+
*/
|
|
845
|
+
export declare const ancestorChain: (definition: SchemaDefinition, lookup: DefinitionLookup) => AncestorChain;
|
|
846
|
+
/**
|
|
847
|
+
* A child's display over its parent's (already merged) one. Scalars and `listFieldIds` take the child's value
|
|
848
|
+
* when set, else the parent's. Groups are the parent's, then the child's. Canvas and strip take the child's
|
|
849
|
+
* list when set; else the parent's list (when set) with the child's own fields appended where the automatic
|
|
850
|
+
* rule would put them: canvas-eligible fields to the canvas, the other fields (not the cover) to the strip.
|
|
851
|
+
*/
|
|
852
|
+
export declare const mergeDisplay: (parent: ModelDisplay, child: ModelDisplay, ownFields: readonly FieldDefinition[]) => ModelDisplay;
|
|
853
|
+
/**
|
|
854
|
+
* The effective definition of a model: ancestors' fields first (root first, `inheritedFrom` set, otherwise the
|
|
855
|
+
* same field objects' values and IDs), then its own fields; display merged root → model. A broken chain
|
|
856
|
+
* (see `ancestorChain`) resolves over the part that resolved; the validator reports the problem.
|
|
857
|
+
*/
|
|
858
|
+
export declare const resolveModelDefinition: (definition: ModelDefinition, lookup: DefinitionLookup) => ResolvedModelDefinition;
|
|
859
|
+
/** The fields a resolved model declares itself (not inherited). */
|
|
860
|
+
export declare const ownFields: (resolved: ResolvedModelDefinition) => FieldDefinition[];
|
|
861
|
+
/** Definitions whose parent is `id`, in the given order. */
|
|
862
|
+
export declare const findChildDefinitions: (definitions: readonly SchemaDefinition[], id: string) => ModelDefinition[];
|
|
863
|
+
/**
|
|
864
|
+
* Inheritance lookups over one set of definitions (the active schema, a proposed one, a site's view), each
|
|
865
|
+
* memoised. Unknown IDs give empty answers; components and singletons are never resolved.
|
|
866
|
+
*/
|
|
867
|
+
export type DefinitionIndex = {
|
|
868
|
+
get: (id: string) => SchemaDefinition | undefined;
|
|
869
|
+
/** The effective definition of a collection or singleton; undefined for components and unknown IDs. */
|
|
870
|
+
resolve: (id: string) => ResolvedModelDefinition | undefined;
|
|
871
|
+
/** Ancestors' IDs, root first; [] for a root or an unknown ID. */
|
|
872
|
+
ancestors: (id: string) => readonly string[];
|
|
873
|
+
/** Direct children's IDs, in definition order. */
|
|
874
|
+
childrenOf: (id: string) => readonly string[];
|
|
875
|
+
/** Every descendant's ID (children, then their children, depth first), not the model itself. */
|
|
876
|
+
descendants: (id: string) => readonly string[];
|
|
877
|
+
/** The model and its descendants, the model first. */
|
|
878
|
+
family: (id: string) => readonly string[];
|
|
879
|
+
/** The family's root (the model itself when it extends nothing). */
|
|
880
|
+
rootOf: (id: string) => string;
|
|
881
|
+
};
|
|
882
|
+
export declare const createDefinitionIndex: (definitions: readonly SchemaDefinition[]) => DefinitionIndex;
|
|
883
|
+
//#endregion
|
|
774
884
|
//#region src/normalize.d.ts
|
|
775
885
|
/** Input whose IDs have been assigned (see `assignIds`). */
|
|
776
886
|
type WithIds<T extends {
|
|
@@ -807,7 +917,7 @@ export type ValidationIssue = {
|
|
|
807
917
|
/** Set by cross-definition checks so a multi-definition apply can say which file is wrong. */
|
|
808
918
|
definitionId?: string;
|
|
809
919
|
};
|
|
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';
|
|
920
|
+
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' | 'UNKNOWN_PARENT' | 'INVALID_PARENT' | 'INHERITANCE_CYCLE' | 'INHERITANCE_TOO_DEEP' | 'INHERITED_FIELD_COLLISION' | 'INHERITED_FLAG_MISMATCH' | 'HAS_CHILDREN';
|
|
811
921
|
export declare class SchemaValidationError extends Error {
|
|
812
922
|
readonly issues: readonly ValidationIssue[];
|
|
813
923
|
constructor(issues: readonly ValidationIssue[]);
|
|
@@ -842,9 +952,18 @@ export declare const foldApiKey: (key: string) => string;
|
|
|
842
952
|
export declare const checkDefaultValue: (field: FieldDefinition) => string | null;
|
|
843
953
|
//#endregion
|
|
844
954
|
//#region src/validators/definition.d.ts
|
|
955
|
+
/**
|
|
956
|
+
* The display's references to fields. Also run by the inheritance check on a child's resolved definition,
|
|
957
|
+
* whose display may name inherited fields.
|
|
958
|
+
*/
|
|
959
|
+
export declare const checkDisplay: (definition: SchemaDefinition) => ValidationIssue[];
|
|
845
960
|
/** All problems with one definition, in document order. Empty means valid on its own. */
|
|
846
961
|
export declare const validateDefinition: (definition: SchemaDefinition) => ValidationIssue[];
|
|
847
962
|
//#endregion
|
|
963
|
+
//#region src/validators/inheritance.d.ts
|
|
964
|
+
/** Every inheritance problem of a schema (see the module comment). */
|
|
965
|
+
export declare const checkInheritance: (definitions: readonly SchemaDefinition[], index?: DefinitionIndex) => ValidationIssue[];
|
|
966
|
+
//#endregion
|
|
848
967
|
//#region src/validators/naming.d.ts
|
|
849
968
|
/**
|
|
850
969
|
* The names GraphQL (package J) and other generated contracts derive from API keys. Defined here, with the
|
|
@@ -855,6 +974,11 @@ export declare const toTypeName: (apiKey: string) => string;
|
|
|
855
974
|
/** Suffixes of the types generated for each model (`Page`, `PageFilter`, `PageInput`...). */
|
|
856
975
|
export declare const MODEL_TYPE_SUFFIXES: readonly ["", "Filter", "Input", "Connection", "Edge", "Localizations", "Sort"];
|
|
857
976
|
export declare const COMPONENT_TYPE_SUFFIXES: readonly ["", "Input"];
|
|
977
|
+
/**
|
|
978
|
+
* Suffix of the GraphQL interface a model with children gets (`ProductInterface`, plan polymorphic-types).
|
|
979
|
+
* Claimed only by models that have children, so existing schemas keep validating.
|
|
980
|
+
*/
|
|
981
|
+
export declare const INTERFACE_TYPE_SUFFIX = "Interface";
|
|
858
982
|
export declare const MUTATION_PREFIXES: readonly ["create", "update", "delete", "publish", "unpublish"];
|
|
859
983
|
/**
|
|
860
984
|
* The key a model is addressed by in the delivery API (`/api/content/:routeKey`, preview routes): the
|
|
@@ -902,8 +1026,14 @@ export type GeneratedName = {
|
|
|
902
1026
|
/** The definition property the name comes from, when not `apiKey` (for the issue path). */
|
|
903
1027
|
property?: 'pluralApiKey';
|
|
904
1028
|
};
|
|
905
|
-
/**
|
|
906
|
-
|
|
1029
|
+
/**
|
|
1030
|
+
* Every name a definition contributes to the GraphQL schema. Fields are its own: a model that extends another
|
|
1031
|
+
* reuses the enum and zone types of inherited fields, which belong to the declaring model. `hasChildren` adds
|
|
1032
|
+
* the interface name of a model other models extend.
|
|
1033
|
+
*/
|
|
1034
|
+
export declare const generatedNames: (definition: SchemaDefinition, options?: {
|
|
1035
|
+
hasChildren?: boolean;
|
|
1036
|
+
}) => GeneratedName[];
|
|
907
1037
|
//#endregion
|
|
908
1038
|
//#region src/validators/parse.d.ts
|
|
909
1039
|
export type ParseDefinitionResult = {
|
|
@@ -937,15 +1067,16 @@ export declare const MAX_COMPONENT_DEPTH = 5;
|
|
|
937
1067
|
export declare const embeddedComponentIds: (definition: SchemaDefinition) => string[];
|
|
938
1068
|
/**
|
|
939
1069
|
* Cross-definition checks over a whole schema (every active definition with the proposed change applied):
|
|
940
|
-
* unique IDs and API keys, GraphQL name collisions, relation and component targets,
|
|
941
|
-
* nesting depth. Each definition must already pass `validateDefinition`.
|
|
1070
|
+
* unique IDs and API keys, model inheritance, GraphQL name collisions, relation and component targets,
|
|
1071
|
+
* component cycles and nesting depth. Each definition must already pass `validateDefinition`.
|
|
942
1072
|
*/
|
|
943
1073
|
export declare const validateSchema: (definitions: readonly SchemaDefinition[]) => ValidationIssue[];
|
|
944
1074
|
/** Definitions that reference `id` (relations, components, dynamic zones). Used to block deletions. */
|
|
945
1075
|
export declare const findReferencingDefinitions: (definitions: readonly SchemaDefinition[], id: string) => SchemaDefinition[];
|
|
946
1076
|
/**
|
|
947
|
-
* Models that embed a component directly or through
|
|
948
|
-
* when the component does (brief §5: "editing a shared component must account for
|
|
1077
|
+
* Models that embed a component directly, through other components or through an inherited field, i.e.
|
|
1078
|
+
* whose entries change shape when the component does (brief §5: "editing a shared component must account for
|
|
1079
|
+
* all dependent models").
|
|
949
1080
|
*/
|
|
950
1081
|
export declare const findDependentModels: (definitions: readonly SchemaDefinition[], componentId: string) => SchemaDefinition[];
|
|
951
1082
|
//#endregion
|
|
@@ -965,7 +1096,7 @@ export declare const isValidText: (text: string) => boolean;
|
|
|
965
1096
|
export declare const findInvalidText: (value: unknown, path?: string) => string | undefined;
|
|
966
1097
|
//#endregion
|
|
967
1098
|
//#region src/diff/types.d.ts
|
|
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"];
|
|
1099
|
+
export declare const CHANGE_KINDS: readonly ["definition.added", "definition.removed", "definition.apiKey", "definition.pluralApiKey", "definition.metadata", "model.kind", "model.localized", "model.draftAndPublish", "model.extends", "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"];
|
|
969
1100
|
export type ChangeKind = (typeof CHANGE_KINDS)[number];
|
|
970
1101
|
/**
|
|
971
1102
|
* One difference between two versions of a definition. `property` names the changed property for
|
|
@@ -1045,7 +1176,11 @@ export declare const typeChangeDropsValues: (from: StoredFieldShape, to: StoredF
|
|
|
1045
1176
|
export type PlannedChange = SchemaChange & {
|
|
1046
1177
|
dropsValues?: boolean;
|
|
1047
1178
|
};
|
|
1048
|
-
/**
|
|
1179
|
+
/**
|
|
1180
|
+
* Whether a (classified) change drops every stored value of its field; false for plans without the flag. A
|
|
1181
|
+
* type change Shapio cannot convert, or an inherited field a model loses when it moves to another parent
|
|
1182
|
+
* (`field.removed` marked by the planner, plan polymorphic-types decision 6).
|
|
1183
|
+
*/
|
|
1049
1184
|
export declare const changeDropsValues: (change: PlannedChange) => boolean;
|
|
1050
1185
|
/** Classifies one change in the context of the definitions it was diffed from. */
|
|
1051
1186
|
export declare const classifyChange: (change: SchemaChange, context: ClassifyContext) => ClassifiedChange;
|