@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,15 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { format as engineFormats } from '@cfworker/json-schema';
|
|
2
2
|
import { Boundary } from '../axis/boundary/Boundary.js';
|
|
3
3
|
import { type FormatPredicate } from '../axis/shape/FormatPredicate.js';
|
|
4
|
-
import {
|
|
4
|
+
import { StringFormats } from '../axis/shape/StringFormats.js';
|
|
5
5
|
import { type Shape } from '../axis/shape/Shape.js';
|
|
6
6
|
import { Shapes } from '../axis/shape/Shape.js';
|
|
7
7
|
import type { Field } from '../field/Field.js';
|
|
8
|
-
import type {
|
|
9
|
-
import
|
|
8
|
+
import type { Verdict } from '../lib/Verdict.js';
|
|
9
|
+
import { SchemaError } from '../SchemaError.js';
|
|
10
|
+
import type { JsonSchema } from '../lib/JsonSchema.js';
|
|
11
|
+
import { JsonSchemaValidator } from './JsonSchemaValidator.js';
|
|
10
12
|
|
|
11
13
|
interface ShapePlan {
|
|
12
|
-
validator: Validator;
|
|
13
14
|
custom?: FormatPredicate;
|
|
14
15
|
formatName?: string;
|
|
15
16
|
}
|
|
@@ -24,24 +25,26 @@ export class FieldValueValidator {
|
|
|
24
25
|
return new FieldValueValidator(field);
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
validate(value: unknown):
|
|
28
|
+
validate(value: unknown): Verdict {
|
|
28
29
|
const shape = this.field.shape;
|
|
29
30
|
const type = Shapes.typeOf(shape);
|
|
30
31
|
const base = Shapes.of(shape).base;
|
|
31
32
|
if (value !== null) {
|
|
32
33
|
if (base?.type === 'object' && !base.properties) return { value };
|
|
33
34
|
if (type === 'date' && value instanceof Date) {
|
|
34
|
-
return Number.isNaN(value.getTime()) ? {
|
|
35
|
+
return Number.isNaN(value.getTime()) ? { message: 'Invalid date' } : { value };
|
|
35
36
|
}
|
|
36
37
|
if ((type === 'number' || type === 'integer') && typeof value === 'number' && Number.isNaN(value)) {
|
|
37
|
-
return {
|
|
38
|
+
return { message: 'Expected a number' };
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
const plan = FieldValueValidator.planFor(shape);
|
|
41
|
-
const
|
|
42
|
-
if (
|
|
42
|
+
const refusal = JsonSchemaValidator.of(shape as JsonSchema).refusalOf(value, []);
|
|
43
|
+
if (refusal) {
|
|
44
|
+
return refusal.path.length > 0 ? { message: refusal.message, path: refusal.path } : { message: refusal.message };
|
|
45
|
+
}
|
|
43
46
|
if (plan.custom && typeof value === 'string' && !plan.custom(value)) {
|
|
44
|
-
return {
|
|
47
|
+
return { message: `String does not match format "${plan.formatName}".` };
|
|
45
48
|
}
|
|
46
49
|
return { value };
|
|
47
50
|
}
|
|
@@ -50,12 +53,12 @@ export class FieldValueValidator {
|
|
|
50
53
|
* The value admitted, then handed back in the form the domain writes — an ISO string
|
|
51
54
|
* arrives as a `Date`. `null` passes untouched, and a refusal stops before the codec.
|
|
52
55
|
*/
|
|
53
|
-
parse(value: unknown):
|
|
54
|
-
const
|
|
55
|
-
if ('
|
|
56
|
-
if (
|
|
56
|
+
parse(value: unknown): Verdict {
|
|
57
|
+
const verdict = this.validate(value);
|
|
58
|
+
if ('message' in verdict) return verdict;
|
|
59
|
+
if (verdict.value === null) return { value: null };
|
|
57
60
|
|
|
58
|
-
return Boundary.of(this.field).decode(
|
|
61
|
+
return Boundary.of(this.field).decode(verdict.value);
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
private static planFor(shape: Shape): ShapePlan {
|
|
@@ -64,7 +67,6 @@ export class FieldValueValidator {
|
|
|
64
67
|
const base = Shapes.of(shape).base;
|
|
65
68
|
const formatName = base?.type === 'string' ? base.format : undefined;
|
|
66
69
|
plan = {
|
|
67
|
-
validator: new Validator(shape as object, '2020-12', true),
|
|
68
70
|
custom: formatName === undefined ? undefined : this.customFormatOf(formatName),
|
|
69
71
|
formatName,
|
|
70
72
|
};
|
|
@@ -74,39 +76,13 @@ export class FieldValueValidator {
|
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
private static customFormatOf(name: string): FormatPredicate | undefined {
|
|
77
|
-
const custom =
|
|
79
|
+
const custom = StringFormats.find(name);
|
|
78
80
|
if (!custom && !(name in engineFormats)) {
|
|
79
|
-
throw new
|
|
80
|
-
`Unknown format: '${name}'. Register it with
|
|
81
|
+
throw new SchemaError(
|
|
82
|
+
`Unknown format: '${name}'. Register it with StringFormats.register('${name}', …) — ` +
|
|
81
83
|
`the engine validates ${Object.keys(engineFormats).length} formats natively and this is not one of them.`,
|
|
82
84
|
);
|
|
83
85
|
}
|
|
84
86
|
return custom;
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* The engine states its refusals outermost first, so `errors[0]` on a nested shape is the
|
|
90
|
-
* parent's `Property "street" does not match schema.` — true, and never the reason. The
|
|
91
|
-
* DEEPEST one is the reason, and it is the one that says where.
|
|
92
|
-
*/
|
|
93
|
-
function refusalOf(errors: readonly OutputUnit[]): Checked {
|
|
94
|
-
const deepest = errors.reduce<OutputUnit | undefined>(
|
|
95
|
-
(held, one) => (held && depthOf(held) >= depthOf(one) ? held : one),
|
|
96
|
-
undefined,
|
|
97
|
-
);
|
|
98
|
-
if (!deepest) return { error: 'Invalid value' };
|
|
99
|
-
const path = locationOf(deepest.instanceLocation);
|
|
100
|
-
|
|
101
|
-
return path.length > 0 ? { error: deepest.error, path } : { error: deepest.error };
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const depthOf = (unit: OutputUnit): number => locationOf(unit.instanceLocation).length;
|
|
105
|
-
|
|
106
|
-
/** `#/city/zip` — a JSON Pointer fragment, and `~1`/`~0` are how it spells `/` and `~`. */
|
|
107
|
-
const locationOf = (instanceLocation: string): string[] =>
|
|
108
|
-
instanceLocation
|
|
109
|
-
.replace(/^#/, '')
|
|
110
|
-
.split('/')
|
|
111
|
-
.filter(Boolean)
|
|
112
|
-
.map((segment) => segment.replace(/~1/g, '/').replace(/~0/g, '~'));
|
|
@@ -3,6 +3,7 @@ import { Lifecycle } from '../axis/lifecycle/Lifecycle.js';
|
|
|
3
3
|
import { Role } from '../axis/role/Role.js';
|
|
4
4
|
import type { Field } from '../field/Field.js';
|
|
5
5
|
import type { Fields } from '../field/Fields.js';
|
|
6
|
+
import type { Verdict } from '../lib/Verdict.js';
|
|
6
7
|
import type { ValidationError } from '../lib/ValidationError.js';
|
|
7
8
|
import type { ValidationResult } from '../lib/ValidationResult.js';
|
|
8
9
|
import { FieldValueValidator } from './FieldValueValidator.js';
|
|
@@ -36,45 +37,42 @@ export class InputValidator {
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
const data = input as Record<string, unknown>;
|
|
39
|
-
const errors: ValidationError[] =
|
|
40
|
+
const errors: ValidationError[] = this.unknownIn(data);
|
|
40
41
|
const row: Record<string, unknown> = {};
|
|
41
42
|
|
|
42
|
-
for (const key of Object.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
43
|
+
for (const [key, field] of Object.entries(this.fields)) {
|
|
44
|
+
const verdict = this.admit(field, data[key]);
|
|
45
|
+
if (verdict === undefined) continue;
|
|
46
|
+
if ('message' in verdict) errors.push({ path: [key, ...(verdict.path ?? [])], message: verdict.message });
|
|
47
|
+
else row[key] = verdict.value;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
const path = [key];
|
|
50
|
-
const value = data[key];
|
|
50
|
+
if (errors.length > 0) return { success: false, errors };
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const absence = this.onAbsent(field);
|
|
55
|
-
if (absence === null) {
|
|
56
|
-
errors.push({ path, message: InputRefusal.required });
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
if (absence === 'empty-list') row[key] = [];
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
52
|
+
return { success: true, data: row };
|
|
53
|
+
}
|
|
62
54
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
errors.push({ path, message: InputRefusal.immutable });
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
55
|
+
private unknownIn(data: Record<string, unknown>): ValidationError[] {
|
|
56
|
+
return Object.keys(data)
|
|
57
|
+
.filter((key) => !Object.hasOwn(this.fields, key))
|
|
58
|
+
.map((key) => ({ path: [key], message: InputRefusal.unknownField }));
|
|
59
|
+
}
|
|
71
60
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
else row[key] = parsed.value;
|
|
75
|
-
}
|
|
61
|
+
private admit(field: Field, value: unknown): Verdict | undefined {
|
|
62
|
+
if (value === undefined) return this.whenAbsent(field);
|
|
76
63
|
|
|
77
|
-
if (
|
|
78
|
-
return {
|
|
64
|
+
if (Boundary.of(field).readOnly) return { message: InputRefusal.readOnly };
|
|
65
|
+
if (this.options.patch && Lifecycle.of(field).immutable) return { message: InputRefusal.immutable };
|
|
66
|
+
|
|
67
|
+
return FieldValueValidator.of(field).parse(value);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private whenAbsent(field: Field): Verdict | undefined {
|
|
71
|
+
if (this.options.patch) return undefined;
|
|
72
|
+
|
|
73
|
+
const absence = this.onAbsent(field);
|
|
74
|
+
if (absence === null) return { message: InputRefusal.required };
|
|
75
|
+
|
|
76
|
+
return absence === 'empty-list' ? { value: [] } : undefined;
|
|
79
77
|
}
|
|
80
78
|
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { Validator, type OutputUnit } from '@cfworker/json-schema';
|
|
2
|
+
import type { JsonSchema } from '../lib/JsonSchema.js';
|
|
3
|
+
import { isObject } from '../lib/utils.js';
|
|
4
|
+
import type { ValidationError } from '../lib/ValidationError.js';
|
|
5
|
+
import { locationOf } from '../lib/ValidationResult.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The one door onto the engine: a field's value against its shape, a declaration against the
|
|
9
|
+
* format of its key. The format is DATA, not a TypeScript interface: an interface is erased
|
|
10
|
+
* before a JS caller, a config or a card from another language could be measured against it.
|
|
11
|
+
*/
|
|
12
|
+
export class JsonSchemaValidator {
|
|
13
|
+
private static readonly held = new WeakMap<JsonSchema, JsonSchemaValidator>();
|
|
14
|
+
|
|
15
|
+
private first?: Validator;
|
|
16
|
+
private every?: Validator;
|
|
17
|
+
|
|
18
|
+
private constructor(private readonly schema: JsonSchema) {}
|
|
19
|
+
|
|
20
|
+
static of(schema: JsonSchema): JsonSchemaValidator {
|
|
21
|
+
let validator = this.held.get(schema);
|
|
22
|
+
|
|
23
|
+
if (!validator) {
|
|
24
|
+
validator = new JsonSchemaValidator(schema);
|
|
25
|
+
this.held.set(schema, validator);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return validator;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** `refusalOf({ update: 'maybe' }, ['lifecycle'])` → `lifecycle.update: Instance does not match any of ["now","forbidden"].` */
|
|
32
|
+
refusalOf(value: unknown, path: readonly string[]): ValidationError | undefined {
|
|
33
|
+
this.first ??= new Validator(this.schema, '2020-12', true);
|
|
34
|
+
|
|
35
|
+
const refused = refusedBy(this.first, value);
|
|
36
|
+
|
|
37
|
+
if (!Array.isArray(refused)) return under(path, refused);
|
|
38
|
+
if (!refused.length) return undefined;
|
|
39
|
+
|
|
40
|
+
const reasons = named(refused);
|
|
41
|
+
|
|
42
|
+
return at(path, reasons.length ? deepestOf(reasons) : refused[0]);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* One refusal per key, so a declaration hears every fault at once. It reads through an engine
|
|
47
|
+
* of its own: the other stops at the first, which is what a single value wants.
|
|
48
|
+
*/
|
|
49
|
+
refusalsOf(value: unknown, path: readonly string[]): ValidationError[] {
|
|
50
|
+
this.every ??= new Validator(this.schema, '2020-12', false);
|
|
51
|
+
|
|
52
|
+
const refused = refusedBy(this.every, value);
|
|
53
|
+
|
|
54
|
+
if (!Array.isArray(refused)) return [under(path, refused)];
|
|
55
|
+
if (!refused.length) return [];
|
|
56
|
+
|
|
57
|
+
const faults = [...byKey(named(refused)).values()];
|
|
58
|
+
|
|
59
|
+
return faults.length ? faults.map((units) => at(path, deepestOf(units))) : [at(path, refused[0])];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** What it refused on, or the member JSON cannot hold — the engine throws on one rather than refusing. */
|
|
64
|
+
function refusedBy(engine: Validator, value: unknown): OutputUnit[] | ValidationError {
|
|
65
|
+
const json = stated(value);
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const verdict = engine.validate(json);
|
|
69
|
+
|
|
70
|
+
return verdict.valid ? [] : verdict.errors;
|
|
71
|
+
} catch {
|
|
72
|
+
const where = unreadableIn(json) ?? { path: [], value: json };
|
|
73
|
+
|
|
74
|
+
return { path: where.path, message: `Expected a JSON value — got ${typeof where.value}` };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** `False boolean schema` names nothing: the unit above it carries the offending key. */
|
|
79
|
+
const named = (units: readonly OutputUnit[]): OutputUnit[] =>
|
|
80
|
+
units.filter((unit) => unit.keyword !== 'false');
|
|
81
|
+
|
|
82
|
+
/** The engine states its refusals outermost first: the deepest says where, the last one is why. */
|
|
83
|
+
function deepestOf(units: readonly OutputUnit[]): OutputUnit {
|
|
84
|
+
return units.reduce((held, unit) => (depthOf(held) > depthOf(unit) ? held : unit));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The units of one fault, addressed by the key they happened under. A unit on the value ITSELF
|
|
89
|
+
* points at a key when another one is deeper — `Property "lifecycle" does not match schema.` —
|
|
90
|
+
* so it is kept only when it is all there is.
|
|
91
|
+
*/
|
|
92
|
+
function byKey(units: readonly OutputUnit[]): Map<string, OutputUnit[]> {
|
|
93
|
+
const held = new Map<string, OutputUnit[]>();
|
|
94
|
+
|
|
95
|
+
for (const unit of units) {
|
|
96
|
+
const key = locationOf(unit.instanceLocation)[0] ?? '';
|
|
97
|
+
held.set(key, [...(held.get(key) ?? []), unit]);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (held.size > 1) held.delete('');
|
|
101
|
+
|
|
102
|
+
return held;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const at = (path: readonly string[], unit: OutputUnit): ValidationError => ({
|
|
106
|
+
path: [...path, ...locationOf(unit.instanceLocation)],
|
|
107
|
+
message: unit.error,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const under = (path: readonly string[], refusal: ValidationError): ValidationError => ({
|
|
111
|
+
path: [...path, ...refusal.path],
|
|
112
|
+
message: refusal.message,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const depthOf = (unit: OutputUnit): number => locationOf(unit.instanceLocation).length;
|
|
116
|
+
|
|
117
|
+
/** A key set to `undefined` states nothing, as in JSON — and the engine refuses to read one. */
|
|
118
|
+
function stated(value: unknown): unknown {
|
|
119
|
+
if (Array.isArray(value)) return value.map(stated);
|
|
120
|
+
|
|
121
|
+
if (!isObject(value)) return value;
|
|
122
|
+
|
|
123
|
+
const present = Object.entries(value).filter(([, member]) => member !== undefined);
|
|
124
|
+
|
|
125
|
+
return Object.fromEntries(present.map(([key, member]) => [key, stated(member)]));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Where the engine stopped: a function, a symbol or a bigint is not a value JSON holds. */
|
|
129
|
+
function unreadableIn(
|
|
130
|
+
value: unknown,
|
|
131
|
+
path: readonly string[] = [],
|
|
132
|
+
): { path: readonly string[]; value: unknown } | undefined {
|
|
133
|
+
if (['function', 'symbol', 'bigint'].includes(typeof value)) return { path, value };
|
|
134
|
+
|
|
135
|
+
if (Array.isArray(value)) {
|
|
136
|
+
return value.flatMap((member, index) => unreadableIn(member, [...path, String(index)]) ?? [])[0];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (!isObject(value)) return undefined;
|
|
140
|
+
|
|
141
|
+
return Object.entries(value).flatMap(([key, member]) => unreadableIn(member, [...path, key]) ?? [])[0];
|
|
142
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Field } from '../../field/Field.js';
|
|
2
|
+
import { SchemaError } from '../../SchemaError.js';
|
|
2
3
|
|
|
3
4
|
export interface ListOptions {
|
|
4
5
|
min?: number;
|
|
@@ -12,7 +13,7 @@ export interface ListOptions {
|
|
|
12
13
|
*/
|
|
13
14
|
export function list<T>(item: Field<T>, opts?: ListOptions): Field<T[]> {
|
|
14
15
|
if (item.role?.relation)
|
|
15
|
-
throw new
|
|
16
|
+
throw new SchemaError(
|
|
16
17
|
'list() takes a value field (text(), number()…) — a relation has no value shape',
|
|
17
18
|
);
|
|
18
19
|
return new Field<T[]>({
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Field } from '../field/Field.js';
|
|
2
|
-
import {
|
|
2
|
+
import { Axes } from '../axis/Axes.js';
|
|
3
3
|
import { dequal } from 'dequal';
|
|
4
|
+
import { SchemaError } from '../SchemaError.js';
|
|
4
5
|
|
|
5
|
-
const
|
|
6
|
+
const memberSlots = (): string[] => [...Axes.names, 'meta'];
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Builds a `rule/` word, which states members on the field it receives.
|
|
@@ -25,12 +26,14 @@ export type FieldWord = (field: Field<any>) => Field<any>;
|
|
|
25
26
|
*/
|
|
26
27
|
function merge(name: string, field: Field, given: Partial<Field>): Partial<Field> {
|
|
27
28
|
const merged: Record<string, unknown> = {};
|
|
29
|
+
const stated = given as Record<string, unknown>;
|
|
30
|
+
const held = field as unknown as Record<string, unknown>;
|
|
28
31
|
if ('shape' in given) merged.shape = given.shape;
|
|
29
32
|
|
|
30
|
-
for (const slot of
|
|
31
|
-
const members =
|
|
33
|
+
for (const slot of memberSlots()) {
|
|
34
|
+
const members = stated[slot];
|
|
32
35
|
if (members === undefined) continue;
|
|
33
|
-
const already =
|
|
36
|
+
const already = held[slot] as Record<string, unknown> | undefined;
|
|
34
37
|
if (typeof members !== 'object' || members === null || typeof already !== 'object') {
|
|
35
38
|
merged[slot] = members;
|
|
36
39
|
continue;
|
|
@@ -38,7 +41,7 @@ function merge(name: string, field: Field, given: Partial<Field>): Partial<Field
|
|
|
38
41
|
for (const [member, value] of Object.entries(members)) {
|
|
39
42
|
const previous = already?.[member];
|
|
40
43
|
if (previous === undefined || dequal(previous, value)) continue;
|
|
41
|
-
throw new
|
|
44
|
+
throw new SchemaError(
|
|
42
45
|
`vocabulary: \`${name}\` states ${slot}.${member} = ${JSON.stringify(value)}, but the ` +
|
|
43
46
|
`field already states ${JSON.stringify(previous)}. Apply one or the other, not both.`,
|
|
44
47
|
);
|
package/dist/PartialValues.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PartialValues.d.ts","sourceRoot":"","sources":["../src/PartialValues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC"}
|
package/dist/PartialValues.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PartialValues.js","sourceRoot":"","sources":["../src/PartialValues.ts"],"names":[],"mappings":""}
|
package/dist/Values.d.ts
DELETED
package/dist/Values.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Values.d.ts","sourceRoot":"","sources":["../src/Values.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,MAAM,MAAM,CAAC,OAAO,SAAS,MAAM,IAAI;KAC1C,CAAC,IAAI,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK;CACpE,CAAC"}
|
package/dist/Values.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Values.js","sourceRoot":"","sources":["../src/Values.ts"],"names":[],"mappings":""}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { Decoder } from './Decoder.js';
|
|
2
|
-
import type { Encoder } from './Encoder.js';
|
|
3
|
-
import type { BoundaryRules } from './BoundaryRules.js';
|
|
4
|
-
import { Registry } from '../../lib/Registry.js';
|
|
5
|
-
/**
|
|
6
|
-
* `decoders` for a value coming in, `encoders` for one going out, `aliases` for the word
|
|
7
|
-
* that names a pair. Three registries, so a codec is never half declared.
|
|
8
|
-
* FR : `decoders` à l'entrée, `encoders` à la sortie, `aliases` pour le mot qui nomme la paire.
|
|
9
|
-
* `Boundaries.aliases.register('isoDate', { in: { decode: 'isoDate' }, out: { encode: 'isoDate' } })`
|
|
10
|
-
* → a field saying `boundary: 'isoDate'` decodes to a `Date` and leaves as a string
|
|
11
|
-
*/
|
|
12
|
-
export declare const Boundaries: {
|
|
13
|
-
decoders: Registry<Decoder>;
|
|
14
|
-
encoders: Registry<Encoder>;
|
|
15
|
-
aliases: Registry<BoundaryRules>;
|
|
16
|
-
};
|
|
17
|
-
//# sourceMappingURL=Boundaries.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Boundaries.d.ts","sourceRoot":"","sources":["../../../src/axis/boundary/Boundaries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU;IACrB,QAAQ;IAIR,QAAQ;IAIR,OAAO;CACR,CAAC"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { Registry } from '../../lib/Registry.js';
|
|
2
|
-
/**
|
|
3
|
-
* `decoders` for a value coming in, `encoders` for one going out, `aliases` for the word
|
|
4
|
-
* that names a pair. Three registries, so a codec is never half declared.
|
|
5
|
-
* FR : `decoders` à l'entrée, `encoders` à la sortie, `aliases` pour le mot qui nomme la paire.
|
|
6
|
-
* `Boundaries.aliases.register('isoDate', { in: { decode: 'isoDate' }, out: { encode: 'isoDate' } })`
|
|
7
|
-
* → a field saying `boundary: 'isoDate'` decodes to a `Date` and leaves as a string
|
|
8
|
-
*/
|
|
9
|
-
export const Boundaries = {
|
|
10
|
-
decoders: new Registry('boundary decoder', 'call Boundaries.decoders.register(name, fn)'),
|
|
11
|
-
encoders: new Registry('boundary encoder', 'call Boundaries.encoders.register(name, fn)'),
|
|
12
|
-
aliases: new Registry('boundary alias'),
|
|
13
|
-
};
|
|
14
|
-
Boundaries.decoders.register('isoDate', (value) => {
|
|
15
|
-
if (value instanceof Date)
|
|
16
|
-
return { value };
|
|
17
|
-
if (typeof value === 'string') {
|
|
18
|
-
const date = new Date(value);
|
|
19
|
-
return Number.isNaN(date.getTime()) ? { error: 'Invalid date' } : { value: date };
|
|
20
|
-
}
|
|
21
|
-
return { error: 'Expected a date' };
|
|
22
|
-
});
|
|
23
|
-
Boundaries.encoders.register('isoDate', (value) => value instanceof Date ? value.toISOString() : value);
|
|
24
|
-
Boundaries.aliases.register('isoDate', { in: { decode: 'isoDate' }, out: { encode: 'isoDate' } });
|
|
25
|
-
//# sourceMappingURL=Boundaries.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Boundaries.js","sourceRoot":"","sources":["../../../src/axis/boundary/Boundaries.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,QAAQ,EAAE,IAAI,QAAQ,CACpB,kBAAkB,EAClB,6CAA6C,CAC9C;IACD,QAAQ,EAAE,IAAI,QAAQ,CACpB,kBAAkB,EAClB,6CAA6C,CAC9C;IACD,OAAO,EAAE,IAAI,QAAQ,CAAgB,gBAAgB,CAAC;CACvD,CAAC;AAEF,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;IAChD,IAAI,KAAK,YAAY,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACpF,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;AACtC,CAAC,CAAC,CAAC;AACH,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAChD,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,KAAK,CACpD,CAAC;AACF,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BoundaryAxis.d.ts","sourceRoot":"","sources":["../../../src/axis/boundary/BoundaryAxis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,eAAO,MAAM,YAAY,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,CA0BvD,CAAC"}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { admitWire } from '../../projection/card/admission.js';
|
|
2
|
-
import { isObject, shown } from '../../lib/utils.js';
|
|
3
|
-
export const boundaryAxis = {
|
|
4
|
-
slot: 'boundary',
|
|
5
|
-
validator(value, errors) {
|
|
6
|
-
if (typeof value === 'string')
|
|
7
|
-
return;
|
|
8
|
-
if (!isObject(value)) {
|
|
9
|
-
errors.push({
|
|
10
|
-
path: ['boundary'],
|
|
11
|
-
message: `Expected an alias name or { in, out } — got ${shown(value)}`,
|
|
12
|
-
});
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
for (const [side, verb] of [['in', 'decode'], ['out', 'encode']]) {
|
|
16
|
-
const rule = value[side];
|
|
17
|
-
if (rule === undefined || rule === 'closed')
|
|
18
|
-
continue;
|
|
19
|
-
if (!isObject(rule) || typeof rule[verb] !== 'string') {
|
|
20
|
-
errors.push({ path: ['boundary', side], message: `Expected 'closed' or { ${verb}: <name> }` });
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
describe: (value) => value,
|
|
25
|
-
reconstruct: (wire) => {
|
|
26
|
-
admitWire(boundaryAxis.validator, wire, 'boundary');
|
|
27
|
-
return wire;
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
//# sourceMappingURL=BoundaryAxis.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BoundaryAxis.js","sourceRoot":"","sources":["../../../src/axis/boundary/BoundaryAxis.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAGrD,MAAM,CAAC,MAAM,YAAY,GAAmC;IAC1D,IAAI,EAAE,UAAU;IAEhB,SAAS,CAAC,KAAK,EAAE,MAAM;QACrB,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO;QACtC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,CAAC,UAAU,CAAC;gBAClB,OAAO,EAAE,+CAA+C,KAAK,CAAC,KAAK,CAAC,EAAE;aACvE,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAU,EAAE,CAAC;YAC1E,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;YACzB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ;gBAAE,SAAS;YACtD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;gBACtD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,0BAA0B,IAAI,YAAY,EAAE,CAAC,CAAC;YACjG,CAAC;QACH,CAAC;IACH,CAAC;IAED,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK;IAC1B,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE;QACpB,SAAS,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BoundaryRef.d.ts","sourceRoot":"","sources":["../../../src/axis/boundary/BoundaryRef.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,GAAG,aAAa,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BoundaryRef.js","sourceRoot":"","sources":["../../../src/axis/boundary/BoundaryRef.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BoundaryRules.d.ts","sourceRoot":"","sources":["../../../src/axis/boundary/BoundaryRules.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,EAAE,CAAC,EAAE,QAAQ,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,GAAG,CAAC,EAAE,QAAQ,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACrC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BoundaryRules.js","sourceRoot":"","sources":["../../../src/axis/boundary/BoundaryRules.ts"],"names":[],"mappings":""}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What "now" means, for the two functions that stamp it.
|
|
3
|
-
*
|
|
4
|
-
* The ONE place either of them reads the time, which is what makes it substitutable at
|
|
5
|
-
* all: `created()`, `updated()` and `create: 'now'` are realized through this and nowhere
|
|
6
|
-
* else, so a test that needs a stable instant sets it here instead of intercepting `Date`
|
|
7
|
-
* globally — where Rails had to build `travel_to` over the language.
|
|
8
|
-
*
|
|
9
|
-
* A value rather than a mock: nothing here is a channel, and a frozen clock is a fact
|
|
10
|
-
* about the run, not an interception of a call.
|
|
11
|
-
*/
|
|
12
|
-
export declare class Clock {
|
|
13
|
-
private static reading;
|
|
14
|
-
static now(): number;
|
|
15
|
-
/** One substitution moves time for every stamp in the process at once. */
|
|
16
|
-
static freeze(at: number | Date): () => void;
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=Clock.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Clock.d.ts","sourceRoot":"","sources":["../../../src/axis/lifecycle/Clock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,MAAM,CAAC,OAAO,CAA0B;IAEhD,MAAM,CAAC,GAAG,IAAI,MAAM,CAEnB;IAED,0EAA0E;IAC1E,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,IAAI,CAK3C;CACF"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What "now" means, for the two functions that stamp it.
|
|
3
|
-
*
|
|
4
|
-
* The ONE place either of them reads the time, which is what makes it substitutable at
|
|
5
|
-
* all: `created()`, `updated()` and `create: 'now'` are realized through this and nowhere
|
|
6
|
-
* else, so a test that needs a stable instant sets it here instead of intercepting `Date`
|
|
7
|
-
* globally — where Rails had to build `travel_to` over the language.
|
|
8
|
-
*
|
|
9
|
-
* A value rather than a mock: nothing here is a channel, and a frozen clock is a fact
|
|
10
|
-
* about the run, not an interception of a call.
|
|
11
|
-
*/
|
|
12
|
-
export class Clock {
|
|
13
|
-
static reading = Date.now;
|
|
14
|
-
static now() {
|
|
15
|
-
return this.reading();
|
|
16
|
-
}
|
|
17
|
-
/** One substitution moves time for every stamp in the process at once. */
|
|
18
|
-
static freeze(at) {
|
|
19
|
-
const previous = this.reading;
|
|
20
|
-
const instant = at instanceof Date ? at.getTime() : at;
|
|
21
|
-
this.reading = () => instant;
|
|
22
|
-
return () => { this.reading = previous; };
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
//# sourceMappingURL=Clock.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Clock.js","sourceRoot":"","sources":["../../../src/axis/lifecycle/Clock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,KAAK;IACR,MAAM,CAAC,OAAO,GAAiB,IAAI,CAAC,GAAG,CAAC;IAEhD,MAAM,CAAC,GAAG;QACR,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;IAED,0EAA0E;IAC1E,MAAM,CAAC,MAAM,CAAC,EAAiB;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;QAC9B,MAAM,OAAO,GAAG,EAAE,YAAY,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,IAAI,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC;QAC7B,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LifecycleAxis.d.ts","sourceRoot":"","sources":["../../../src/axis/lifecycle/LifecycleAxis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAKvC,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,eAAO,MAAM,aAAa,EAAE,IAAI,CAAC,cAAc,EAAE,cAAc,CAsB9D,CAAC"}
|