@fougere/schema 0.11.0-alpha.0 → 0.12.1-alpha.0
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/Schema.d.ts +1 -1
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +4 -3
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaConstructor.d.ts +3 -4
- package/dist/SchemaConstructor.d.ts.map +1 -1
- package/dist/SchemaDefinition.d.ts.map +1 -1
- package/dist/SchemaDefinition.js +2 -1
- package/dist/SchemaDefinition.js.map +1 -1
- package/dist/SchemaError.d.ts +4 -0
- package/dist/SchemaError.d.ts.map +1 -0
- package/dist/SchemaError.js +7 -0
- package/dist/SchemaError.js.map +1 -0
- package/dist/SchemaView.d.ts +1 -1
- package/dist/SchemaView.d.ts.map +1 -1
- package/dist/axis/Axes.d.ts +16 -0
- package/dist/axis/Axes.d.ts.map +1 -0
- package/dist/axis/Axes.js +27 -0
- package/dist/axis/Axes.js.map +1 -0
- package/dist/axis/Axis.d.ts +5 -9
- package/dist/axis/Axis.d.ts.map +1 -1
- package/dist/axis/Axis.js +1 -10
- package/dist/axis/Axis.js.map +1 -1
- package/dist/axis/boundary/Boundary.d.ts +29 -3
- package/dist/axis/boundary/Boundary.d.ts.map +1 -1
- package/dist/axis/boundary/Boundary.js +15 -11
- package/dist/axis/boundary/Boundary.js.map +1 -1
- package/dist/axis/boundary/Decoder.d.ts +10 -7
- package/dist/axis/boundary/Decoder.d.ts.map +1 -1
- package/dist/axis/boundary/Decoder.js +2 -2
- package/dist/axis/boundary/Decoder.js.map +1 -1
- package/dist/axis/lifecycle/Generators.d.ts +5 -5
- package/dist/axis/lifecycle/Generators.d.ts.map +1 -1
- package/dist/axis/lifecycle/Generators.js +5 -15
- package/dist/axis/lifecycle/Generators.js.map +1 -1
- package/dist/axis/lifecycle/Lifecycle.d.ts +18 -6
- package/dist/axis/lifecycle/Lifecycle.d.ts.map +1 -1
- package/dist/axis/lifecycle/Lifecycle.js +29 -14
- package/dist/axis/lifecycle/Lifecycle.js.map +1 -1
- package/dist/axis/lifecycle/apply.d.ts.map +1 -1
- package/dist/axis/lifecycle/apply.js +5 -22
- package/dist/axis/lifecycle/apply.js.map +1 -1
- package/dist/axis/role/Role.d.ts +18 -6
- package/dist/axis/role/Role.d.ts.map +1 -1
- package/dist/axis/role/Role.js +30 -16
- package/dist/axis/role/Role.js.map +1 -1
- package/dist/axis/shape/Shape.d.ts +2 -2
- package/dist/axis/shape/Shape.d.ts.map +1 -1
- package/dist/axis/shape/Shape.js +2 -2
- package/dist/axis/shape/Shape.js.map +1 -1
- package/dist/axis/shape/{Formats.d.ts → StringFormats.d.ts} +3 -3
- package/dist/axis/shape/StringFormats.d.ts.map +1 -0
- package/dist/axis/shape/{Formats.js → StringFormats.js} +3 -3
- package/dist/axis/shape/StringFormats.js.map +1 -0
- package/dist/entity/EntityAdapterSet.d.ts.map +1 -1
- package/dist/entity/EntityAdapterSet.js +3 -2
- package/dist/entity/EntityAdapterSet.js.map +1 -1
- package/dist/entity.d.ts +0 -1
- package/dist/entity.d.ts.map +1 -1
- package/dist/entity.js +0 -1
- package/dist/entity.js.map +1 -1
- package/dist/field/Field.d.ts +11 -5
- package/dist/field/Field.d.ts.map +1 -1
- package/dist/field/Field.js +10 -7
- package/dist/field/Field.js.map +1 -1
- package/dist/field/FieldFormat.d.ts +9 -0
- package/dist/field/FieldFormat.d.ts.map +1 -0
- package/dist/field/FieldFormat.js +12 -0
- package/dist/field/FieldFormat.js.map +1 -0
- package/dist/field/FieldSet.d.ts.map +1 -1
- package/dist/field/FieldSet.js +5 -3
- package/dist/field/FieldSet.js.map +1 -1
- package/dist/field/FougereFieldAxes.d.ts +3 -0
- package/dist/field/FougereFieldAxes.d.ts.map +1 -0
- package/dist/field/FougereFieldAxes.js +2 -0
- package/dist/field/FougereFieldAxes.js.map +1 -0
- package/dist/field/Meta.d.ts +5 -3
- package/dist/field/Meta.d.ts.map +1 -1
- package/dist/field/Meta.js +2 -1
- package/dist/field/Meta.js.map +1 -1
- package/dist/field/Values.d.ts +6 -0
- package/dist/field/Values.d.ts.map +1 -0
- package/dist/field/Values.js.map +1 -0
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/Format.d.ts +56 -0
- package/dist/lib/Format.d.ts.map +1 -0
- package/dist/lib/Format.js +95 -0
- package/dist/lib/Format.js.map +1 -0
- package/dist/lib/JsonSchema.d.ts +2 -0
- package/dist/lib/JsonSchema.d.ts.map +1 -0
- package/dist/lib/JsonSchema.js +2 -0
- package/dist/lib/JsonSchema.js.map +1 -0
- package/dist/lib/Registry.d.ts +5 -4
- package/dist/lib/Registry.d.ts.map +1 -1
- package/dist/lib/Registry.js +14 -8
- package/dist/lib/Registry.js.map +1 -1
- package/dist/lib/ValidationResult.d.ts +2 -0
- package/dist/lib/ValidationResult.d.ts.map +1 -1
- package/dist/lib/ValidationResult.js +6 -0
- package/dist/lib/ValidationResult.js.map +1 -1
- package/dist/lib/Verdict.d.ts +12 -0
- package/dist/lib/Verdict.d.ts.map +1 -0
- package/dist/lib/Verdict.js +2 -0
- package/dist/lib/Verdict.js.map +1 -0
- package/dist/projection/Cases.js +52 -54
- package/dist/projection/Cases.js.map +1 -1
- package/dist/projection/Visibility.d.ts +11 -0
- package/dist/projection/Visibility.d.ts.map +1 -1
- package/dist/projection/Visibility.js +22 -0
- package/dist/projection/Visibility.js.map +1 -1
- package/dist/projection/card/Bundle.d.ts.map +1 -1
- package/dist/projection/card/Bundle.js +2 -1
- package/dist/projection/card/Bundle.js.map +1 -1
- package/dist/projection/card/Card.d.ts +1 -1
- package/dist/projection/card/Card.d.ts.map +1 -1
- package/dist/projection/card/Card.js +19 -11
- package/dist/projection/card/Card.js.map +1 -1
- package/dist/projection/card/CardForm.d.ts +7 -0
- package/dist/projection/card/CardForm.d.ts.map +1 -0
- package/dist/projection/card/CardForm.js +2 -0
- package/dist/projection/card/CardForm.js.map +1 -0
- package/dist/projection/card/CardForms.d.ts +10 -0
- package/dist/projection/card/CardForms.d.ts.map +1 -0
- package/dist/projection/card/CardForms.js +12 -0
- package/dist/projection/card/CardForms.js.map +1 -0
- package/dist/projection/card/Change.d.ts +2 -2
- package/dist/projection/card/Change.d.ts.map +1 -1
- package/dist/projection/card/Diff.d.ts.map +1 -1
- package/dist/projection/card/Diff.js +36 -39
- package/dist/projection/card/Diff.js.map +1 -1
- package/dist/projection/card/FieldExtension.d.ts +4 -2
- package/dist/projection/card/FieldExtension.d.ts.map +1 -1
- package/dist/projection/card/RoleDescriptor.d.ts +9 -2
- package/dist/projection/card/RoleDescriptor.d.ts.map +1 -1
- package/dist/projection/card/RoleDescriptor.js +40 -1
- package/dist/projection/card/RoleDescriptor.js.map +1 -1
- package/dist/projection/card/admission.d.ts +0 -14
- package/dist/projection/card/admission.d.ts.map +1 -1
- package/dist/projection/card/admission.js +2 -21
- package/dist/projection/card/admission.js.map +1 -1
- package/dist/validator/FieldDeclarationValidator.d.ts.map +1 -1
- package/dist/validator/FieldDeclarationValidator.js +5 -17
- package/dist/validator/FieldDeclarationValidator.js.map +1 -1
- package/dist/validator/FieldValueValidator.d.ts +3 -3
- package/dist/validator/FieldValueValidator.d.ts.map +1 -1
- package/dist/validator/FieldValueValidator.js +18 -35
- package/dist/validator/FieldValueValidator.js.map +1 -1
- package/dist/validator/InputValidator.d.ts +3 -0
- package/dist/validator/InputValidator.d.ts.map +1 -1
- package/dist/validator/InputValidator.js +28 -31
- package/dist/validator/InputValidator.js.map +1 -1
- package/dist/validator/JsonSchemaValidator.d.ts +23 -0
- package/dist/validator/JsonSchemaValidator.d.ts.map +1 -0
- package/dist/validator/JsonSchemaValidator.js +113 -0
- package/dist/validator/JsonSchemaValidator.js.map +1 -0
- package/dist/vocabulary/primitive/list.d.ts.map +1 -1
- package/dist/vocabulary/primitive/list.js +2 -1
- package/dist/vocabulary/primitive/list.js.map +1 -1
- package/dist/vocabulary/vocabulary.d.ts.map +1 -1
- package/dist/vocabulary/vocabulary.js +9 -6
- package/dist/vocabulary/vocabulary.js.map +1 -1
- package/package.json +1 -1
- package/src/Schema.ts +6 -4
- package/src/SchemaConstructor.ts +4 -4
- package/src/SchemaDefinition.ts +2 -1
- package/src/SchemaError.ts +7 -0
- package/src/SchemaView.ts +1 -1
- package/src/axis/Axes.ts +34 -0
- package/src/axis/Axis.ts +5 -20
- package/src/axis/boundary/Boundary.ts +26 -13
- package/src/axis/boundary/Decoder.ts +5 -4
- package/src/axis/lifecycle/Generators.ts +6 -18
- package/src/axis/lifecycle/Lifecycle.ts +41 -19
- package/src/axis/lifecycle/apply.ts +13 -21
- package/src/axis/role/Role.ts +35 -19
- package/src/axis/shape/Shape.ts +3 -3
- package/src/axis/shape/{Formats.ts → StringFormats.ts} +2 -2
- package/src/entity/EntityAdapterSet.ts +3 -2
- package/src/entity.ts +0 -1
- package/src/field/Field.ts +23 -12
- package/src/field/FieldFormat.ts +18 -0
- package/src/field/FieldSet.ts +5 -3
- package/src/field/FougereFieldAxes.ts +2 -0
- package/src/field/Meta.ts +5 -3
- package/src/{Values.ts → field/Values.ts} +2 -2
- package/src/index.ts +8 -3
- package/src/lib/Format.ts +139 -0
- package/src/lib/JsonSchema.ts +1 -0
- package/src/lib/Registry.ts +18 -9
- package/src/lib/ValidationResult.ts +8 -0
- package/src/lib/Verdict.ts +10 -0
- package/src/projection/Cases.ts +61 -57
- package/src/projection/Visibility.ts +22 -0
- package/src/projection/card/Bundle.ts +2 -1
- package/src/projection/card/Card.ts +24 -13
- package/src/projection/card/CardForm.ts +8 -0
- package/src/projection/card/CardForms.ts +13 -0
- package/src/projection/card/Change.ts +2 -2
- package/src/projection/card/Diff.ts +44 -44
- package/src/projection/card/FieldExtension.ts +5 -2
- package/src/projection/card/RoleDescriptor.ts +48 -2
- package/src/projection/card/admission.ts +2 -34
- package/src/validator/FieldDeclarationValidator.ts +5 -17
- package/src/validator/FieldValueValidator.ts +22 -46
- package/src/validator/InputValidator.ts +30 -32
- package/src/validator/JsonSchemaValidator.ts +142 -0
- package/src/vocabulary/primitive/list.ts +2 -1
- package/src/vocabulary/vocabulary.ts +9 -6
- package/dist/PartialValues.d.ts +0 -4
- package/dist/PartialValues.d.ts.map +0 -1
- package/dist/PartialValues.js +0 -2
- package/dist/PartialValues.js.map +0 -1
- package/dist/Values.d.ts +0 -6
- package/dist/Values.d.ts.map +0 -1
- package/dist/Values.js.map +0 -1
- package/dist/axis/boundary/Boundaries.d.ts +0 -17
- package/dist/axis/boundary/Boundaries.d.ts.map +0 -1
- package/dist/axis/boundary/Boundaries.js +0 -25
- package/dist/axis/boundary/Boundaries.js.map +0 -1
- package/dist/axis/boundary/BoundaryAxis.d.ts +0 -4
- package/dist/axis/boundary/BoundaryAxis.d.ts.map +0 -1
- package/dist/axis/boundary/BoundaryAxis.js +0 -30
- package/dist/axis/boundary/BoundaryAxis.js.map +0 -1
- package/dist/axis/boundary/BoundaryRef.d.ts +0 -3
- package/dist/axis/boundary/BoundaryRef.d.ts.map +0 -1
- package/dist/axis/boundary/BoundaryRef.js +0 -2
- package/dist/axis/boundary/BoundaryRef.js.map +0 -1
- package/dist/axis/boundary/BoundaryRules.d.ts +0 -9
- package/dist/axis/boundary/BoundaryRules.d.ts.map +0 -1
- package/dist/axis/boundary/BoundaryRules.js +0 -2
- package/dist/axis/boundary/BoundaryRules.js.map +0 -1
- package/dist/axis/lifecycle/Clock.d.ts +0 -18
- package/dist/axis/lifecycle/Clock.d.ts.map +0 -1
- package/dist/axis/lifecycle/Clock.js +0 -25
- package/dist/axis/lifecycle/Clock.js.map +0 -1
- package/dist/axis/lifecycle/LifecycleAxis.d.ts +0 -4
- package/dist/axis/lifecycle/LifecycleAxis.d.ts.map +0 -1
- package/dist/axis/lifecycle/LifecycleAxis.js +0 -52
- package/dist/axis/lifecycle/LifecycleAxis.js.map +0 -1
- package/dist/axis/lifecycle/LifecycleRules.d.ts +0 -12
- package/dist/axis/lifecycle/LifecycleRules.d.ts.map +0 -1
- package/dist/axis/lifecycle/LifecycleRules.js +0 -3
- package/dist/axis/lifecycle/LifecycleRules.js.map +0 -1
- package/dist/axis/role/RoleAxis.d.ts +0 -5
- package/dist/axis/role/RoleAxis.d.ts.map +0 -1
- package/dist/axis/role/RoleAxis.js +0 -93
- package/dist/axis/role/RoleAxis.js.map +0 -1
- package/dist/axis/role/RoleRules.d.ts +0 -8
- package/dist/axis/role/RoleRules.d.ts.map +0 -1
- package/dist/axis/role/RoleRules.js +0 -2
- package/dist/axis/role/RoleRules.js.map +0 -1
- package/dist/axis/shape/Formats.d.ts.map +0 -1
- package/dist/axis/shape/Formats.js.map +0 -1
- package/dist/lib/Checked.d.ts +0 -11
- package/dist/lib/Checked.d.ts.map +0 -1
- package/dist/lib/Checked.js +0 -2
- package/dist/lib/Checked.js.map +0 -1
- package/dist/projection/card/RelationDescriptor.d.ts +0 -5
- package/dist/projection/card/RelationDescriptor.d.ts.map +0 -1
- package/dist/projection/card/RelationDescriptor.js +0 -2
- package/dist/projection/card/RelationDescriptor.js.map +0 -1
- package/dist/projection/standard.d.ts +0 -14
- package/dist/projection/standard.d.ts.map +0 -1
- package/dist/projection/standard.js +0 -2
- package/dist/projection/standard.js.map +0 -1
- package/dist/validator/AdapterFieldValidator.d.ts +0 -14
- package/dist/validator/AdapterFieldValidator.d.ts.map +0 -1
- package/dist/validator/AdapterFieldValidator.js +0 -36
- package/dist/validator/AdapterFieldValidator.js.map +0 -1
- package/src/PartialValues.ts +0 -4
- package/src/axis/boundary/Boundaries.ts +0 -36
- package/src/axis/boundary/BoundaryAxis.ts +0 -32
- package/src/axis/boundary/BoundaryRef.ts +0 -3
- package/src/axis/boundary/BoundaryRules.ts +0 -4
- package/src/axis/lifecycle/Clock.ts +0 -26
- package/src/axis/lifecycle/LifecycleAxis.ts +0 -55
- package/src/axis/lifecycle/LifecycleRules.ts +0 -9
- package/src/axis/role/RoleAxis.ts +0 -104
- package/src/axis/role/RoleRules.ts +0 -8
- package/src/lib/Checked.ts +0 -5
- package/src/projection/card/RelationDescriptor.ts +0 -3
- package/src/projection/standard.ts +0 -13
- package/src/validator/AdapterFieldValidator.ts +0 -40
- /package/dist/{Values.js → field/Values.js} +0 -0
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import type { BoundaryRef } from '../../axis/boundary/
|
|
2
|
-
import type { LifecycleRules } from '../../axis/lifecycle/
|
|
1
|
+
import type { BoundaryRef } from '../../axis/boundary/Boundary.js';
|
|
2
|
+
import type { LifecycleRules } from '../../axis/lifecycle/Lifecycle.js';
|
|
3
3
|
import type { RoleDescriptor } from './RoleDescriptor.js';
|
|
4
4
|
export interface FieldExtension {
|
|
5
5
|
role?: RoleDescriptor;
|
|
6
6
|
lifecycle?: LifecycleRules;
|
|
7
7
|
boundary?: BoundaryRef;
|
|
8
|
+
/** An axis registered from outside writes its own slot here, under its own name. */
|
|
9
|
+
[slot: string]: unknown;
|
|
8
10
|
}
|
|
9
11
|
//# sourceMappingURL=FieldExtension.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldExtension.d.ts","sourceRoot":"","sources":["../../../src/projection/card/FieldExtension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"FieldExtension.d.ts","sourceRoot":"","sources":["../../../src/projection/card/FieldExtension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,WAAW,CAAC;IAEvB,oFAAoF;IACpF,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB"}
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { Relation } from '../../axis/role/Relation.js';
|
|
2
|
+
import type { RoleRules } from '../../axis/role/Role.js';
|
|
3
|
+
import type { CardForm } from './CardForm.js';
|
|
4
|
+
/** What a role becomes on a card: a target is a NAME there, and a unique is a group. */
|
|
3
5
|
export type RoleDescriptor = Pick<RoleRules, 'primary' | 'index'> & {
|
|
4
6
|
unique?: string[][];
|
|
5
7
|
relation?: RelationDescriptor;
|
|
6
8
|
};
|
|
9
|
+
export type RelationDescriptor = Pick<Relation, 'kind' | 'onDelete'> & {
|
|
10
|
+
to: string;
|
|
11
|
+
};
|
|
12
|
+
/** A card carries the target's NAME: a class cannot cross a process boundary. */
|
|
13
|
+
export declare const roleOnCard: CardForm<RoleRules, RoleDescriptor>;
|
|
7
14
|
//# sourceMappingURL=RoleDescriptor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RoleDescriptor.d.ts","sourceRoot":"","sources":["../../../src/projection/card/RoleDescriptor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RoleDescriptor.d.ts","sourceRoot":"","sources":["../../../src/projection/card/RoleDescriptor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,wFAAwF;AACxF,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG;IAClE,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAAC,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAItF,iFAAiF;AACjF,eAAO,MAAM,UAAU,EAAE,QAAQ,CAAC,SAAS,EAAE,cAAc,CAkC1D,CAAC"}
|
|
@@ -1,2 +1,41 @@
|
|
|
1
|
-
|
|
1
|
+
import { lowerFirst } from '../../lib/utils.js';
|
|
2
|
+
/** A card carries the target's NAME: a class cannot cross a process boundary. */
|
|
3
|
+
export const roleOnCard = {
|
|
4
|
+
describe(role, key) {
|
|
5
|
+
const descriptor = {};
|
|
6
|
+
if (role.primary)
|
|
7
|
+
descriptor.primary = true;
|
|
8
|
+
if (role.unique)
|
|
9
|
+
descriptor.unique = [[key]];
|
|
10
|
+
if (role.index)
|
|
11
|
+
descriptor.index = true;
|
|
12
|
+
if (role.relation) {
|
|
13
|
+
const target = role.relation.to();
|
|
14
|
+
descriptor.relation = {
|
|
15
|
+
to: lowerFirst(target.name ?? ''),
|
|
16
|
+
kind: role.relation.kind,
|
|
17
|
+
...(role.relation.onDelete ? { onDelete: role.relation.onDelete } : {}),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
return Object.keys(descriptor).length ? descriptor : undefined;
|
|
21
|
+
},
|
|
22
|
+
reconstruct(wire, resolve) {
|
|
23
|
+
const rules = {};
|
|
24
|
+
if (wire.primary)
|
|
25
|
+
rules.primary = true;
|
|
26
|
+
if (wire.unique?.some((group) => group.length === 1))
|
|
27
|
+
rules.unique = true;
|
|
28
|
+
if (wire.index)
|
|
29
|
+
rules.index = true;
|
|
30
|
+
if (wire.relation) {
|
|
31
|
+
const name = wire.relation.to;
|
|
32
|
+
rules.relation = {
|
|
33
|
+
to: () => (resolve?.(name) ?? { name }),
|
|
34
|
+
kind: wire.relation.kind,
|
|
35
|
+
...(wire.relation.onDelete ? { onDelete: wire.relation.onDelete } : {}),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return rules;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
2
41
|
//# sourceMappingURL=RoleDescriptor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RoleDescriptor.js","sourceRoot":"","sources":["../../../src/projection/card/RoleDescriptor.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RoleDescriptor.js","sourceRoot":"","sources":["../../../src/projection/card/RoleDescriptor.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAahD,iFAAiF;AACjF,MAAM,CAAC,MAAM,UAAU,GAAwC;IAC7D,QAAQ,CAAC,IAAI,EAAE,GAAG;QAChB,MAAM,UAAU,GAA4B,EAAE,CAAC;QAC/C,IAAI,IAAI,CAAC,OAAO;YAAE,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;QAC5C,IAAI,IAAI,CAAC,MAAM;YAAE,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7C,IAAI,IAAI,CAAC,KAAK;YAAE,UAAU,CAAC,KAAK,GAAG,IAAI,CAAC;QACxC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAuB,CAAC;YACvD,UAAU,CAAC,QAAQ,GAAG;gBACpB,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBACjC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI;gBACxB,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACxE,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IACjE,CAAC;IAED,WAAW,CAAC,IAAI,EAAE,OAAkB;QAClC,MAAM,KAAK,GAAuB,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,OAAO;YAAE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;QACvC,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;YAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;QAC1E,IAAI,IAAI,CAAC,KAAK;YAAE,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QACnC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9B,KAAK,CAAC,QAAQ,GAAG;gBACf,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,IAAK,EAAE,IAAI,EAAc,CAAsB;gBACzE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI;gBACxB,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACxE,CAAC;QACJ,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF,CAAC"}
|
|
@@ -1,23 +1,9 @@
|
|
|
1
|
-
import type { ValidationError } from '../../lib/ValidationError.js';
|
|
2
1
|
/**
|
|
3
2
|
* Throws with what is wrong AND what to write: a card's author is in another process.
|
|
4
3
|
* FR : lève avec ce qui cloche ET quoi écrire : l'auteur d'une carte est ailleurs.
|
|
5
4
|
* `refuse('role.relation.kind is "maybe"', 'Expected one of one, many.')`
|
|
6
5
|
*/
|
|
7
6
|
export declare function refuse(what: string, fix: string): never;
|
|
8
|
-
/**
|
|
9
|
-
* Runs a card's axis through the validator a hand-written field goes through, so there is
|
|
10
|
-
* one judge and not two.
|
|
11
|
-
* FR : passe l'axe d'une carte par le juge d'un champ écrit à la main : un juge, pas deux.
|
|
12
|
-
* `{ update: 'maybe' }` → `lifecycle is malformed — lifecycle.update: Expected 'now' or 'forbidden'`
|
|
13
|
-
*/
|
|
14
|
-
export declare function admitWire(validator: (value: unknown, errors: ValidationError[]) => void, value: unknown, slot: string): void;
|
|
15
|
-
/**
|
|
16
|
-
* Checks a token against the list that declares it, never against a copy written here.
|
|
17
|
-
* FR : vérifie un mot contre la liste qui le déclare, jamais contre une copie locale.
|
|
18
|
-
* `oneOfTokens('many', RELATION_KINDS)` → `true`
|
|
19
|
-
*/
|
|
20
|
-
export declare const oneOfTokens: <T extends readonly string[]>(value: unknown, tokens: T) => value is T[number];
|
|
21
7
|
/**
|
|
22
8
|
* Compiles every `pattern` at the facade, so a bad one is refused here and not at the first row.
|
|
23
9
|
* FR : compile chaque `pattern` à la porte : un mauvais est refusé ici, pas au premier row.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../../../src/projection/card/admission.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../../../src/projection/card/admission.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAanE"}
|
|
@@ -1,32 +1,13 @@
|
|
|
1
1
|
import { Shapes } from '../../axis/shape/Shape.js';
|
|
2
|
-
import {
|
|
2
|
+
import { SchemaError } from '../../SchemaError.js';
|
|
3
3
|
/**
|
|
4
4
|
* Throws with what is wrong AND what to write: a card's author is in another process.
|
|
5
5
|
* FR : lève avec ce qui cloche ET quoi écrire : l'auteur d'une carte est ailleurs.
|
|
6
6
|
* `refuse('role.relation.kind is "maybe"', 'Expected one of one, many.')`
|
|
7
7
|
*/
|
|
8
8
|
export function refuse(what, fix) {
|
|
9
|
-
throw new
|
|
9
|
+
throw new SchemaError(`This card cannot be read: ${what}.\n ${fix}`);
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
12
|
-
* Runs a card's axis through the validator a hand-written field goes through, so there is
|
|
13
|
-
* one judge and not two.
|
|
14
|
-
* FR : passe l'axe d'une carte par le juge d'un champ écrit à la main : un juge, pas deux.
|
|
15
|
-
* `{ update: 'maybe' }` → `lifecycle is malformed — lifecycle.update: Expected 'now' or 'forbidden'`
|
|
16
|
-
*/
|
|
17
|
-
export function admitWire(validator, value, slot) {
|
|
18
|
-
const errors = [];
|
|
19
|
-
validator(value, errors);
|
|
20
|
-
if (errors.length) {
|
|
21
|
-
refuse(`${slot} is malformed — ${errors.map((e) => `${dotted(e.path)}: ${e.message}`).join('; ')}`, 'A card states an axis the way a declaration does.');
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Checks a token against the list that declares it, never against a copy written here.
|
|
26
|
-
* FR : vérifie un mot contre la liste qui le déclare, jamais contre une copie locale.
|
|
27
|
-
* `oneOfTokens('many', RELATION_KINDS)` → `true`
|
|
28
|
-
*/
|
|
29
|
-
export const oneOfTokens = (value, tokens) => typeof value === 'string' && tokens.includes(value);
|
|
30
11
|
/**
|
|
31
12
|
* Compiles every `pattern` at the facade, so a bad one is refused here and not at the first row.
|
|
32
13
|
* FR : compile chaque `pattern` à la porte : un mauvais est refusé ici, pas au premier row.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admission.js","sourceRoot":"","sources":["../../../src/projection/card/admission.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"admission.js","sourceRoot":"","sources":["../../../src/projection/card/admission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,IAAY,EAAE,GAAW;IAC9C,MAAM,IAAI,WAAW,CAAC,6BAA6B,IAAI,QAAQ,GAAG,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,OAAe;IAC3D,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,mFAAmF;YACnF,uDAAuD;YACvD,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CACJ,GAAG,OAAO,sBAAsB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,uCAAuC,EAC7F,KAAe,CAAC,OAAO,CACzB,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldDeclarationValidator.d.ts","sourceRoot":"","sources":["../../src/validator/FieldDeclarationValidator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"FieldDeclarationValidator.d.ts","sourceRoot":"","sources":["../../src/validator/FieldDeclarationValidator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,qBAAa,yBAAyB;IAChB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAAhD,OAAO,eAAsD;IAE7D,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,GAAG,yBAAyB,CAEzD;IAED,IAAI,OAAO,IAAI,gBAAgB,CAAC,KAAK,CAAC,CAiCrC;CACF"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Axes } from '../axis/Axes.js';
|
|
2
2
|
import { Shapes } from '../axis/shape/Shape.js';
|
|
3
3
|
import { isObject, shown } from '../lib/utils.js';
|
|
4
|
+
import { JsonSchemaValidator } from './JsonSchemaValidator.js';
|
|
4
5
|
export class FieldDeclarationValidator {
|
|
5
6
|
declaration;
|
|
6
7
|
constructor(declaration) {
|
|
@@ -29,22 +30,9 @@ export class FieldDeclarationValidator {
|
|
|
29
30
|
message: `Every field states a shape — got ${shown(declaration.shape)}`,
|
|
30
31
|
});
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
axis.validator(declared, errors);
|
|
36
|
-
}
|
|
37
|
-
if (declaration.meta !== undefined) {
|
|
38
|
-
if (!isObject(declaration.meta)) {
|
|
39
|
-
errors.push({
|
|
40
|
-
path: ['meta'],
|
|
41
|
-
message: `Expected an object — got ${shown(declaration.meta)}`,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
else if (declaration.meta.description !== undefined &&
|
|
45
|
-
typeof declaration.meta.description !== 'string') {
|
|
46
|
-
errors.push({ path: ['meta', 'description'], message: 'Expected a string' });
|
|
47
|
-
}
|
|
33
|
+
errors.push(...JsonSchemaValidator.of(Axes.fieldFormat).refusalsOf(declaration, []));
|
|
34
|
+
for (const [slot, axis] of Axes.entries) {
|
|
35
|
+
errors.push(...(axis.refusals?.(declaration[slot]) ?? []));
|
|
48
36
|
}
|
|
49
37
|
return errors.length
|
|
50
38
|
? { success: false, errors }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldDeclarationValidator.js","sourceRoot":"","sources":["../../src/validator/FieldDeclarationValidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"FieldDeclarationValidator.js","sourceRoot":"","sources":["../../src/validator/FieldDeclarationValidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEhD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAGlD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,MAAM,OAAO,yBAAyB;IACC,WAAW;IAAhD,YAAqC,WAAoB;2BAApB,WAAW;IAAY,CAAC;IAE7D,MAAM,CAAC,EAAE,CAAC,WAAoB;QAC5B,OAAO,IAAI,yBAAyB,CAAC,WAAW,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,OAAO;QACT,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QAErC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3B,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE;oBACN;wBACE,IAAI,EAAE,EAAE;wBACR,OAAO,EAAE,4BAA4B,KAAK,CAAC,WAAW,CAAC,EAAE;qBAC1D;iBACF;aACF,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAsB,EAAE,CAAC;QAErC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,CAAC,OAAO,CAAC;gBACf,OAAO,EAAE,oCAAoC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE;aACxE,CAAC,CAAC;QACL,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;QAErF,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,MAAM,CAAC,MAAM;YAClB,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE;YAC5B,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,WAA+B,EAAE,CAAC;IAC/D,CAAC;CACF"}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import type { Field } from '../field/Field.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { Verdict } from '../lib/Verdict.js';
|
|
3
3
|
export declare class FieldValueValidator {
|
|
4
4
|
private readonly field;
|
|
5
5
|
private static readonly plans;
|
|
6
6
|
private constructor();
|
|
7
7
|
/** The shape is compiled once and reused, not rebuilt per value. */
|
|
8
8
|
static of(field: Field): FieldValueValidator;
|
|
9
|
-
validate(value: unknown):
|
|
9
|
+
validate(value: unknown): Verdict;
|
|
10
10
|
/**
|
|
11
11
|
* The value admitted, then handed back in the form the domain writes — an ISO string
|
|
12
12
|
* arrives as a `Date`. `null` passes untouched, and a refusal stops before the codec.
|
|
13
13
|
*/
|
|
14
|
-
parse(value: unknown):
|
|
14
|
+
parse(value: unknown): Verdict;
|
|
15
15
|
private static planFor;
|
|
16
16
|
private static customFormatOf;
|
|
17
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldValueValidator.d.ts","sourceRoot":"","sources":["../../src/validator/FieldValueValidator.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"FieldValueValidator.d.ts","sourceRoot":"","sources":["../../src/validator/FieldValueValidator.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAUjD,qBAAa,mBAAmB;IAGV,OAAO,CAAC,QAAQ,CAAC,KAAK;IAF1C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAoC;IAEjE,OAAO,eAA8C;IAErD,oEAAoE;IACpE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,mBAAmB,CAE3C;IAED,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAsBhC;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAM7B;IAED,OAAO,CAAC,MAAM,CAAC,OAAO;IActB,OAAO,CAAC,MAAM,CAAC,cAAc;CAU9B"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { format as engineFormats } from '@cfworker/json-schema';
|
|
2
2
|
import { Boundary } from '../axis/boundary/Boundary.js';
|
|
3
|
-
import {
|
|
3
|
+
import { StringFormats } from '../axis/shape/StringFormats.js';
|
|
4
4
|
import { Shapes } from '../axis/shape/Shape.js';
|
|
5
|
+
import { SchemaError } from '../SchemaError.js';
|
|
6
|
+
import { JsonSchemaValidator } from './JsonSchemaValidator.js';
|
|
5
7
|
export class FieldValueValidator {
|
|
6
8
|
field;
|
|
7
9
|
static plans = new WeakMap();
|
|
@@ -20,18 +22,19 @@ export class FieldValueValidator {
|
|
|
20
22
|
if (base?.type === 'object' && !base.properties)
|
|
21
23
|
return { value };
|
|
22
24
|
if (type === 'date' && value instanceof Date) {
|
|
23
|
-
return Number.isNaN(value.getTime()) ? {
|
|
25
|
+
return Number.isNaN(value.getTime()) ? { message: 'Invalid date' } : { value };
|
|
24
26
|
}
|
|
25
27
|
if ((type === 'number' || type === 'integer') && typeof value === 'number' && Number.isNaN(value)) {
|
|
26
|
-
return {
|
|
28
|
+
return { message: 'Expected a number' };
|
|
27
29
|
}
|
|
28
30
|
}
|
|
29
31
|
const plan = FieldValueValidator.planFor(shape);
|
|
30
|
-
const
|
|
31
|
-
if (
|
|
32
|
-
return
|
|
32
|
+
const refusal = JsonSchemaValidator.of(shape).refusalOf(value, []);
|
|
33
|
+
if (refusal) {
|
|
34
|
+
return refusal.path.length > 0 ? { message: refusal.message, path: refusal.path } : { message: refusal.message };
|
|
35
|
+
}
|
|
33
36
|
if (plan.custom && typeof value === 'string' && !plan.custom(value)) {
|
|
34
|
-
return {
|
|
37
|
+
return { message: `String does not match format "${plan.formatName}".` };
|
|
35
38
|
}
|
|
36
39
|
return { value };
|
|
37
40
|
}
|
|
@@ -40,12 +43,12 @@ export class FieldValueValidator {
|
|
|
40
43
|
* arrives as a `Date`. `null` passes untouched, and a refusal stops before the codec.
|
|
41
44
|
*/
|
|
42
45
|
parse(value) {
|
|
43
|
-
const
|
|
44
|
-
if ('
|
|
45
|
-
return
|
|
46
|
-
if (
|
|
46
|
+
const verdict = this.validate(value);
|
|
47
|
+
if ('message' in verdict)
|
|
48
|
+
return verdict;
|
|
49
|
+
if (verdict.value === null)
|
|
47
50
|
return { value: null };
|
|
48
|
-
return Boundary.of(this.field).decode(
|
|
51
|
+
return Boundary.of(this.field).decode(verdict.value);
|
|
49
52
|
}
|
|
50
53
|
static planFor(shape) {
|
|
51
54
|
let plan = this.plans.get(shape);
|
|
@@ -53,7 +56,6 @@ export class FieldValueValidator {
|
|
|
53
56
|
const base = Shapes.of(shape).base;
|
|
54
57
|
const formatName = base?.type === 'string' ? base.format : undefined;
|
|
55
58
|
plan = {
|
|
56
|
-
validator: new Validator(shape, '2020-12', true),
|
|
57
59
|
custom: formatName === undefined ? undefined : this.customFormatOf(formatName),
|
|
58
60
|
formatName,
|
|
59
61
|
};
|
|
@@ -62,31 +64,12 @@ export class FieldValueValidator {
|
|
|
62
64
|
return plan;
|
|
63
65
|
}
|
|
64
66
|
static customFormatOf(name) {
|
|
65
|
-
const custom =
|
|
67
|
+
const custom = StringFormats.find(name);
|
|
66
68
|
if (!custom && !(name in engineFormats)) {
|
|
67
|
-
throw new
|
|
69
|
+
throw new SchemaError(`Unknown format: '${name}'. Register it with StringFormats.register('${name}', …) — ` +
|
|
68
70
|
`the engine validates ${Object.keys(engineFormats).length} formats natively and this is not one of them.`);
|
|
69
71
|
}
|
|
70
72
|
return custom;
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
|
-
/**
|
|
74
|
-
* The engine states its refusals outermost first, so `errors[0]` on a nested shape is the
|
|
75
|
-
* parent's `Property "street" does not match schema.` — true, and never the reason. The
|
|
76
|
-
* DEEPEST one is the reason, and it is the one that says where.
|
|
77
|
-
*/
|
|
78
|
-
function refusalOf(errors) {
|
|
79
|
-
const deepest = errors.reduce((held, one) => (held && depthOf(held) >= depthOf(one) ? held : one), undefined);
|
|
80
|
-
if (!deepest)
|
|
81
|
-
return { error: 'Invalid value' };
|
|
82
|
-
const path = locationOf(deepest.instanceLocation);
|
|
83
|
-
return path.length > 0 ? { error: deepest.error, path } : { error: deepest.error };
|
|
84
|
-
}
|
|
85
|
-
const depthOf = (unit) => locationOf(unit.instanceLocation).length;
|
|
86
|
-
/** `#/city/zip` — a JSON Pointer fragment, and `~1`/`~0` are how it spells `/` and `~`. */
|
|
87
|
-
const locationOf = (instanceLocation) => instanceLocation
|
|
88
|
-
.replace(/^#/, '')
|
|
89
|
-
.split('/')
|
|
90
|
-
.filter(Boolean)
|
|
91
|
-
.map((segment) => segment.replace(/~1/g, '/').replace(/~0/g, '~'));
|
|
92
75
|
//# sourceMappingURL=FieldValueValidator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldValueValidator.js","sourceRoot":"","sources":["../../src/validator/FieldValueValidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"FieldValueValidator.js","sourceRoot":"","sources":["../../src/validator/FieldValueValidator.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,5 +10,8 @@ export declare class InputValidator {
|
|
|
10
10
|
onAbsent(field: Field): 'skip' | 'empty-list' | null;
|
|
11
11
|
/** Hands on the value it PARSED, so a handler never re-checks a row. */
|
|
12
12
|
validate(input: unknown): ValidationResult<Record<string, unknown>>;
|
|
13
|
+
private unknownIn;
|
|
14
|
+
private admit;
|
|
15
|
+
private whenAbsent;
|
|
13
16
|
}
|
|
14
17
|
//# sourceMappingURL=InputValidator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputValidator.d.ts","sourceRoot":"","sources":["../../src/validator/InputValidator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"InputValidator.d.ts","sourceRoot":"","sources":["../../src/validator/InputValidator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAGjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAF1B,OAAO,eAGH;IAEJ,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,cAAc,CAEvE;IAED,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,YAAY,GAAG,IAAI,CAKnD;IAED,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAsBlE;IAED,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,KAAK;IASb,OAAO,CAAC,UAAU;CAQnB"}
|
|
@@ -31,45 +31,42 @@ export class InputValidator {
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
const data = input;
|
|
34
|
-
const errors =
|
|
34
|
+
const errors = this.unknownIn(data);
|
|
35
35
|
const row = {};
|
|
36
|
-
for (const key of Object.keys(data)) {
|
|
37
|
-
if (!Object.hasOwn(this.fields, key)) {
|
|
38
|
-
errors.push({ path: [key], message: InputRefusal.unknownField });
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
36
|
for (const [key, field] of Object.entries(this.fields)) {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
if (value === undefined) {
|
|
45
|
-
if (this.options.patch)
|
|
46
|
-
continue;
|
|
47
|
-
const absence = this.onAbsent(field);
|
|
48
|
-
if (absence === null) {
|
|
49
|
-
errors.push({ path, message: InputRefusal.required });
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
if (absence === 'empty-list')
|
|
53
|
-
row[key] = [];
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
if (Boundary.of(field).readOnly) {
|
|
57
|
-
errors.push({ path, message: InputRefusal.readOnly });
|
|
37
|
+
const verdict = this.admit(field, data[key]);
|
|
38
|
+
if (verdict === undefined)
|
|
58
39
|
continue;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
errors.push({ path, message: InputRefusal.immutable });
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
const parsed = FieldValueValidator.of(field).parse(value);
|
|
65
|
-
if ('error' in parsed)
|
|
66
|
-
errors.push({ path: [...path, ...parsed.path ?? []], message: parsed.error });
|
|
40
|
+
if ('message' in verdict)
|
|
41
|
+
errors.push({ path: [key, ...(verdict.path ?? [])], message: verdict.message });
|
|
67
42
|
else
|
|
68
|
-
row[key] =
|
|
43
|
+
row[key] = verdict.value;
|
|
69
44
|
}
|
|
70
45
|
if (errors.length > 0)
|
|
71
46
|
return { success: false, errors };
|
|
72
47
|
return { success: true, data: row };
|
|
73
48
|
}
|
|
49
|
+
unknownIn(data) {
|
|
50
|
+
return Object.keys(data)
|
|
51
|
+
.filter((key) => !Object.hasOwn(this.fields, key))
|
|
52
|
+
.map((key) => ({ path: [key], message: InputRefusal.unknownField }));
|
|
53
|
+
}
|
|
54
|
+
admit(field, value) {
|
|
55
|
+
if (value === undefined)
|
|
56
|
+
return this.whenAbsent(field);
|
|
57
|
+
if (Boundary.of(field).readOnly)
|
|
58
|
+
return { message: InputRefusal.readOnly };
|
|
59
|
+
if (this.options.patch && Lifecycle.of(field).immutable)
|
|
60
|
+
return { message: InputRefusal.immutable };
|
|
61
|
+
return FieldValueValidator.of(field).parse(value);
|
|
62
|
+
}
|
|
63
|
+
whenAbsent(field) {
|
|
64
|
+
if (this.options.patch)
|
|
65
|
+
return undefined;
|
|
66
|
+
const absence = this.onAbsent(field);
|
|
67
|
+
if (absence === null)
|
|
68
|
+
return { message: InputRefusal.required };
|
|
69
|
+
return absence === 'empty-list' ? { value: [] } : undefined;
|
|
70
|
+
}
|
|
74
71
|
}
|
|
75
72
|
//# sourceMappingURL=InputValidator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputValidator.js","sourceRoot":"","sources":["../../src/validator/InputValidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"InputValidator.js","sourceRoot":"","sources":["../../src/validator/InputValidator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { JsonSchema } from '../lib/JsonSchema.js';
|
|
2
|
+
import type { ValidationError } from '../lib/ValidationError.js';
|
|
3
|
+
/**
|
|
4
|
+
* The one door onto the engine: a field's value against its shape, a declaration against the
|
|
5
|
+
* format of its key. The format is DATA, not a TypeScript interface: an interface is erased
|
|
6
|
+
* before a JS caller, a config or a card from another language could be measured against it.
|
|
7
|
+
*/
|
|
8
|
+
export declare class JsonSchemaValidator {
|
|
9
|
+
private readonly schema;
|
|
10
|
+
private static readonly held;
|
|
11
|
+
private first?;
|
|
12
|
+
private every?;
|
|
13
|
+
private constructor();
|
|
14
|
+
static of(schema: JsonSchema): JsonSchemaValidator;
|
|
15
|
+
/** `refusalOf({ update: 'maybe' }, ['lifecycle'])` → `lifecycle.update: Instance does not match any of ["now","forbidden"].` */
|
|
16
|
+
refusalOf(value: unknown, path: readonly string[]): ValidationError | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* One refusal per key, so a declaration hears every fault at once. It reads through an engine
|
|
19
|
+
* of its own: the other stops at the first, which is what a single value wants.
|
|
20
|
+
*/
|
|
21
|
+
refusalsOf(value: unknown, path: readonly string[]): ValidationError[];
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=JsonSchemaValidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JsonSchemaValidator.d.ts","sourceRoot":"","sources":["../../src/validator/JsonSchemaValidator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAGjE;;;;GAIG;AACH,qBAAa,mBAAmB;IAMV,OAAO,CAAC,QAAQ,CAAC,MAAM;IAL3C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAkD;IAE9E,OAAO,CAAC,KAAK,CAAC,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAC,CAAY;IAE1B,OAAO,eAAoD;IAE3D,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,mBAAmB,CASjD;IAED,gIAAgI;IAChI,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,eAAe,GAAG,SAAS,CAW9E;IAED;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,eAAe,EAAE,CAWrE;CACF"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Validator } from '@cfworker/json-schema';
|
|
2
|
+
import { isObject } from '../lib/utils.js';
|
|
3
|
+
import { locationOf } from '../lib/ValidationResult.js';
|
|
4
|
+
/**
|
|
5
|
+
* The one door onto the engine: a field's value against its shape, a declaration against the
|
|
6
|
+
* format of its key. The format is DATA, not a TypeScript interface: an interface is erased
|
|
7
|
+
* before a JS caller, a config or a card from another language could be measured against it.
|
|
8
|
+
*/
|
|
9
|
+
export class JsonSchemaValidator {
|
|
10
|
+
schema;
|
|
11
|
+
static held = new WeakMap();
|
|
12
|
+
first;
|
|
13
|
+
every;
|
|
14
|
+
constructor(schema) {
|
|
15
|
+
this.schema = schema;
|
|
16
|
+
}
|
|
17
|
+
static of(schema) {
|
|
18
|
+
let validator = this.held.get(schema);
|
|
19
|
+
if (!validator) {
|
|
20
|
+
validator = new JsonSchemaValidator(schema);
|
|
21
|
+
this.held.set(schema, validator);
|
|
22
|
+
}
|
|
23
|
+
return validator;
|
|
24
|
+
}
|
|
25
|
+
/** `refusalOf({ update: 'maybe' }, ['lifecycle'])` → `lifecycle.update: Instance does not match any of ["now","forbidden"].` */
|
|
26
|
+
refusalOf(value, path) {
|
|
27
|
+
this.first ??= new Validator(this.schema, '2020-12', true);
|
|
28
|
+
const refused = refusedBy(this.first, value);
|
|
29
|
+
if (!Array.isArray(refused))
|
|
30
|
+
return under(path, refused);
|
|
31
|
+
if (!refused.length)
|
|
32
|
+
return undefined;
|
|
33
|
+
const reasons = named(refused);
|
|
34
|
+
return at(path, reasons.length ? deepestOf(reasons) : refused[0]);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* One refusal per key, so a declaration hears every fault at once. It reads through an engine
|
|
38
|
+
* of its own: the other stops at the first, which is what a single value wants.
|
|
39
|
+
*/
|
|
40
|
+
refusalsOf(value, path) {
|
|
41
|
+
this.every ??= new Validator(this.schema, '2020-12', false);
|
|
42
|
+
const refused = refusedBy(this.every, value);
|
|
43
|
+
if (!Array.isArray(refused))
|
|
44
|
+
return [under(path, refused)];
|
|
45
|
+
if (!refused.length)
|
|
46
|
+
return [];
|
|
47
|
+
const faults = [...byKey(named(refused)).values()];
|
|
48
|
+
return faults.length ? faults.map((units) => at(path, deepestOf(units))) : [at(path, refused[0])];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** What it refused on, or the member JSON cannot hold — the engine throws on one rather than refusing. */
|
|
52
|
+
function refusedBy(engine, value) {
|
|
53
|
+
const json = stated(value);
|
|
54
|
+
try {
|
|
55
|
+
const verdict = engine.validate(json);
|
|
56
|
+
return verdict.valid ? [] : verdict.errors;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
const where = unreadableIn(json) ?? { path: [], value: json };
|
|
60
|
+
return { path: where.path, message: `Expected a JSON value — got ${typeof where.value}` };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** `False boolean schema` names nothing: the unit above it carries the offending key. */
|
|
64
|
+
const named = (units) => units.filter((unit) => unit.keyword !== 'false');
|
|
65
|
+
/** The engine states its refusals outermost first: the deepest says where, the last one is why. */
|
|
66
|
+
function deepestOf(units) {
|
|
67
|
+
return units.reduce((held, unit) => (depthOf(held) > depthOf(unit) ? held : unit));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The units of one fault, addressed by the key they happened under. A unit on the value ITSELF
|
|
71
|
+
* points at a key when another one is deeper — `Property "lifecycle" does not match schema.` —
|
|
72
|
+
* so it is kept only when it is all there is.
|
|
73
|
+
*/
|
|
74
|
+
function byKey(units) {
|
|
75
|
+
const held = new Map();
|
|
76
|
+
for (const unit of units) {
|
|
77
|
+
const key = locationOf(unit.instanceLocation)[0] ?? '';
|
|
78
|
+
held.set(key, [...(held.get(key) ?? []), unit]);
|
|
79
|
+
}
|
|
80
|
+
if (held.size > 1)
|
|
81
|
+
held.delete('');
|
|
82
|
+
return held;
|
|
83
|
+
}
|
|
84
|
+
const at = (path, unit) => ({
|
|
85
|
+
path: [...path, ...locationOf(unit.instanceLocation)],
|
|
86
|
+
message: unit.error,
|
|
87
|
+
});
|
|
88
|
+
const under = (path, refusal) => ({
|
|
89
|
+
path: [...path, ...refusal.path],
|
|
90
|
+
message: refusal.message,
|
|
91
|
+
});
|
|
92
|
+
const depthOf = (unit) => locationOf(unit.instanceLocation).length;
|
|
93
|
+
/** A key set to `undefined` states nothing, as in JSON — and the engine refuses to read one. */
|
|
94
|
+
function stated(value) {
|
|
95
|
+
if (Array.isArray(value))
|
|
96
|
+
return value.map(stated);
|
|
97
|
+
if (!isObject(value))
|
|
98
|
+
return value;
|
|
99
|
+
const present = Object.entries(value).filter(([, member]) => member !== undefined);
|
|
100
|
+
return Object.fromEntries(present.map(([key, member]) => [key, stated(member)]));
|
|
101
|
+
}
|
|
102
|
+
/** Where the engine stopped: a function, a symbol or a bigint is not a value JSON holds. */
|
|
103
|
+
function unreadableIn(value, path = []) {
|
|
104
|
+
if (['function', 'symbol', 'bigint'].includes(typeof value))
|
|
105
|
+
return { path, value };
|
|
106
|
+
if (Array.isArray(value)) {
|
|
107
|
+
return value.flatMap((member, index) => unreadableIn(member, [...path, String(index)]) ?? [])[0];
|
|
108
|
+
}
|
|
109
|
+
if (!isObject(value))
|
|
110
|
+
return undefined;
|
|
111
|
+
return Object.entries(value).flatMap(([key, member]) => unreadableIn(member, [...path, key]) ?? [])[0];
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=JsonSchemaValidator.js.map
|