@fougere/schema 0.5.0-alpha.1 → 0.7.0-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/README.md +5 -4
- package/dist/{schema/Schema.d.ts → Schema.d.ts} +18 -28
- package/dist/Schema.d.ts.map +1 -0
- package/dist/Schema.js +136 -0
- package/dist/Schema.js.map +1 -0
- package/dist/SchemaDefinition.d.ts +73 -0
- package/dist/SchemaDefinition.d.ts.map +1 -0
- package/dist/SchemaDefinition.js +184 -0
- package/dist/SchemaDefinition.js.map +1 -0
- package/dist/SchemaDerivation.d.ts +16 -0
- package/dist/SchemaDerivation.d.ts.map +1 -0
- package/dist/SchemaDerivation.js +31 -0
- package/dist/SchemaDerivation.js.map +1 -0
- package/dist/{schema/SchemaView.d.ts → SchemaView.d.ts} +9 -9
- package/dist/SchemaView.d.ts.map +1 -0
- package/dist/{schema/SchemaView.js.map → SchemaView.js.map} +1 -1
- package/dist/axis/Axis.d.ts +2 -2
- package/dist/axis/Axis.d.ts.map +1 -1
- package/dist/axis/boundary/Boundaries.d.ts +13 -12
- package/dist/axis/boundary/Boundaries.d.ts.map +1 -1
- package/dist/axis/boundary/Boundaries.js +18 -24
- package/dist/axis/boundary/Boundaries.js.map +1 -1
- package/dist/axis/boundary/Boundary.d.ts +3 -1
- package/dist/axis/boundary/Boundary.d.ts.map +1 -1
- package/dist/axis/boundary/Boundary.js +16 -7
- package/dist/axis/boundary/Boundary.js.map +1 -1
- package/dist/axis/boundary/BoundaryAxis.js +4 -4
- package/dist/axis/boundary/BoundaryAxis.js.map +1 -1
- package/dist/axis/lifecycle/Clock.d.ts +1 -1
- package/dist/axis/lifecycle/Clock.d.ts.map +1 -1
- package/dist/axis/lifecycle/Clock.js +1 -1
- package/dist/axis/lifecycle/Clock.js.map +1 -1
- package/dist/axis/lifecycle/Generators.d.ts +6 -14
- package/dist/axis/lifecycle/Generators.d.ts.map +1 -1
- package/dist/axis/lifecycle/Generators.js +10 -28
- package/dist/axis/lifecycle/Generators.js.map +1 -1
- package/dist/axis/lifecycle/LifecycleAxis.js +11 -6
- package/dist/axis/lifecycle/LifecycleAxis.js.map +1 -1
- package/dist/axis/lifecycle/apply.d.ts +14 -5
- package/dist/axis/lifecycle/apply.d.ts.map +1 -1
- package/dist/axis/lifecycle/apply.js +26 -10
- package/dist/axis/lifecycle/apply.js.map +1 -1
- package/dist/axis/role/Relation.d.ts +3 -2
- package/dist/axis/role/Relation.d.ts.map +1 -1
- package/dist/axis/role/Relation.js +6 -5
- package/dist/axis/role/Relation.js.map +1 -1
- package/dist/axis/role/Role.d.ts +6 -6
- package/dist/axis/role/Role.d.ts.map +1 -1
- package/dist/axis/role/Role.js +13 -17
- package/dist/axis/role/Role.js.map +1 -1
- package/dist/axis/role/RoleAxis.d.ts +1 -1
- package/dist/axis/role/RoleAxis.d.ts.map +1 -1
- package/dist/axis/role/RoleAxis.js +28 -37
- package/dist/axis/role/RoleAxis.js.map +1 -1
- package/dist/axis/shape/Formats.d.ts +8 -5
- package/dist/axis/shape/Formats.d.ts.map +1 -1
- package/dist/axis/shape/Formats.js +8 -9
- package/dist/axis/shape/Formats.js.map +1 -1
- package/dist/axis/shape/Shape.d.ts +5 -3
- package/dist/axis/shape/Shape.d.ts.map +1 -1
- package/dist/axis/shape/Shape.js +13 -13
- package/dist/axis/shape/Shape.js.map +1 -1
- package/dist/entity/EntityAdapterSet.d.ts +22 -0
- package/dist/entity/EntityAdapterSet.d.ts.map +1 -0
- package/dist/entity/EntityAdapterSet.js +63 -0
- package/dist/entity/EntityAdapterSet.js.map +1 -0
- package/dist/entity/EntityAdapters.d.ts +5 -0
- package/dist/entity/EntityAdapters.d.ts.map +1 -0
- package/dist/entity/EntityAdapters.js +2 -0
- package/dist/entity/EntityAdapters.js.map +1 -0
- package/dist/{EntityDeclarations.d.ts → entity/EntityDeclarations.d.ts} +2 -7
- package/dist/entity/EntityDeclarations.d.ts.map +1 -0
- package/dist/entity/EntityDeclarations.js.map +1 -0
- package/dist/entity.d.ts +8 -3
- package/dist/entity.d.ts.map +1 -1
- package/dist/entity.js +6 -1
- package/dist/entity.js.map +1 -1
- package/dist/{fields → field}/Field.d.ts +8 -9
- package/dist/field/Field.d.ts.map +1 -0
- package/dist/field/Field.js +35 -0
- package/dist/field/Field.js.map +1 -0
- package/dist/field/FieldSet.d.ts +22 -0
- package/dist/field/FieldSet.d.ts.map +1 -0
- package/dist/field/FieldSet.js +58 -0
- package/dist/field/FieldSet.js.map +1 -0
- package/dist/index.d.ts +24 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -21
- package/dist/index.js.map +1 -1
- package/dist/lib/Registry.d.ts +12 -0
- package/dist/lib/Registry.d.ts.map +1 -0
- package/dist/lib/Registry.js +29 -0
- package/dist/lib/Registry.js.map +1 -0
- package/dist/{utils.d.ts → lib/utils.d.ts} +1 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/{utils.js → lib/utils.js} +1 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/projection/Cases.d.ts +39 -0
- package/dist/projection/Cases.d.ts.map +1 -0
- package/dist/projection/Cases.js +146 -0
- package/dist/projection/Cases.js.map +1 -0
- package/dist/projection/Visibility.d.ts +2 -1
- package/dist/projection/Visibility.d.ts.map +1 -1
- package/dist/projection/Visibility.js +1 -0
- package/dist/projection/Visibility.js.map +1 -1
- package/dist/{card → projection/card}/Bundle.d.ts +1 -1
- package/dist/projection/card/Bundle.d.ts.map +1 -0
- package/dist/{card → projection/card}/Bundle.js +7 -7
- package/dist/projection/card/Bundle.js.map +1 -0
- package/dist/projection/card/Card.d.ts +21 -0
- package/dist/projection/card/Card.d.ts.map +1 -0
- package/dist/{card → projection/card}/Card.js +119 -58
- package/dist/projection/card/Card.js.map +1 -0
- package/dist/{card → projection/card}/Descriptor.d.ts +7 -7
- package/dist/projection/card/Descriptor.d.ts.map +1 -0
- package/dist/projection/card/Descriptor.js.map +1 -0
- package/dist/projection/card/admission.d.ts +20 -0
- package/dist/projection/card/admission.d.ts.map +1 -0
- package/dist/projection/card/admission.js +27 -0
- package/dist/projection/card/admission.js.map +1 -0
- package/dist/{card → projection/card}/diff.d.ts +3 -3
- package/dist/projection/card/diff.d.ts.map +1 -0
- package/dist/{card → projection/card}/diff.js.map +1 -1
- package/dist/{judge/result.d.ts → validation.d.ts} +1 -1
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +2 -0
- package/dist/validation.js.map +1 -0
- package/dist/validator/AdapterFieldValidator.d.ts +14 -0
- package/dist/validator/AdapterFieldValidator.d.ts.map +1 -0
- package/dist/validator/AdapterFieldValidator.js +36 -0
- package/dist/validator/AdapterFieldValidator.js.map +1 -0
- package/dist/validator/FieldDeclarationValidator.d.ts +9 -0
- package/dist/validator/FieldDeclarationValidator.d.ts.map +1 -0
- package/dist/{judge/FieldJudge.js → validator/FieldDeclarationValidator.js} +13 -13
- package/dist/validator/FieldDeclarationValidator.js.map +1 -0
- package/dist/validator/FieldValueValidator.d.ts +13 -0
- package/dist/validator/FieldValueValidator.d.ts.map +1 -0
- package/dist/{judge/ValueJudge.js → validator/FieldValueValidator.js} +14 -11
- package/dist/validator/FieldValueValidator.js.map +1 -0
- package/dist/{judge/RowRefusal.d.ts → validator/InputRefusal.d.ts} +3 -4
- package/dist/validator/InputRefusal.d.ts.map +1 -0
- package/dist/{judge/RowRefusal.js → validator/InputRefusal.js} +3 -3
- package/dist/validator/InputRefusal.js.map +1 -0
- package/dist/validator/InputValidator.d.ts +15 -0
- package/dist/validator/InputValidator.d.ts.map +1 -0
- package/dist/{judge/RowJudge.js → validator/InputValidator.js} +21 -17
- package/dist/validator/InputValidator.js.map +1 -0
- package/dist/vocabulary/bool.d.ts +6 -1
- package/dist/vocabulary/bool.d.ts.map +1 -1
- package/dist/vocabulary/bool.js +6 -1
- package/dist/vocabulary/bool.js.map +1 -1
- package/dist/vocabulary/created.d.ts +6 -1
- package/dist/vocabulary/created.d.ts.map +1 -1
- package/dist/vocabulary/created.js +6 -1
- package/dist/vocabulary/created.js.map +1 -1
- package/dist/vocabulary/date.d.ts +6 -1
- package/dist/vocabulary/date.d.ts.map +1 -1
- package/dist/vocabulary/date.js +6 -1
- package/dist/vocabulary/date.js.map +1 -1
- package/dist/vocabulary/email.d.ts +6 -1
- package/dist/vocabulary/email.d.ts.map +1 -1
- package/dist/vocabulary/email.js +5 -0
- package/dist/vocabulary/email.js.map +1 -1
- package/dist/vocabulary/immutable.d.ts +6 -1
- package/dist/vocabulary/immutable.d.ts.map +1 -1
- package/dist/vocabulary/immutable.js +5 -0
- package/dist/vocabulary/immutable.js.map +1 -1
- package/dist/vocabulary/indexed.d.ts +6 -1
- package/dist/vocabulary/indexed.d.ts.map +1 -1
- package/dist/vocabulary/indexed.js +8 -1
- package/dist/vocabulary/indexed.js.map +1 -1
- package/dist/vocabulary/json.d.ts +2 -2
- package/dist/vocabulary/json.d.ts.map +1 -1
- package/dist/vocabulary/json.js +9 -4
- package/dist/vocabulary/json.js.map +1 -1
- package/dist/vocabulary/list.d.ts +6 -1
- package/dist/vocabulary/list.d.ts.map +1 -1
- package/dist/vocabulary/list.js +6 -1
- package/dist/vocabulary/list.js.map +1 -1
- package/dist/vocabulary/many.d.ts +6 -1
- package/dist/vocabulary/many.d.ts.map +1 -1
- package/dist/vocabulary/many.js +6 -1
- package/dist/vocabulary/many.js.map +1 -1
- package/dist/vocabulary/nullable.d.ts +6 -1
- package/dist/vocabulary/nullable.d.ts.map +1 -1
- package/dist/vocabulary/nullable.js +7 -2
- package/dist/vocabulary/nullable.js.map +1 -1
- package/dist/vocabulary/number.d.ts +6 -1
- package/dist/vocabulary/number.d.ts.map +1 -1
- package/dist/vocabulary/number.js +11 -2
- package/dist/vocabulary/number.js.map +1 -1
- package/dist/vocabulary/oneOf.d.ts +1 -1
- package/dist/vocabulary/oneOf.d.ts.map +1 -1
- package/dist/vocabulary/oneOf.js +6 -1
- package/dist/vocabulary/oneOf.js.map +1 -1
- package/dist/vocabulary/optional.d.ts +6 -1
- package/dist/vocabulary/optional.d.ts.map +1 -1
- package/dist/vocabulary/optional.js +10 -3
- package/dist/vocabulary/optional.js.map +1 -1
- package/dist/vocabulary/primary.d.ts +1 -1
- package/dist/vocabulary/primary.d.ts.map +1 -1
- package/dist/vocabulary/primary.js +10 -5
- package/dist/vocabulary/primary.js.map +1 -1
- package/dist/vocabulary/readOnly.d.ts +6 -1
- package/dist/vocabulary/readOnly.d.ts.map +1 -1
- package/dist/vocabulary/readOnly.js +5 -0
- package/dist/vocabulary/readOnly.js.map +1 -1
- package/dist/vocabulary/ref.d.ts +6 -1
- package/dist/vocabulary/ref.d.ts.map +1 -1
- package/dist/vocabulary/ref.js +6 -1
- package/dist/vocabulary/ref.js.map +1 -1
- package/dist/vocabulary/text.d.ts +6 -1
- package/dist/vocabulary/text.d.ts.map +1 -1
- package/dist/vocabulary/text.js +13 -2
- package/dist/vocabulary/text.js.map +1 -1
- package/dist/vocabulary/unique.d.ts +6 -1
- package/dist/vocabulary/unique.d.ts.map +1 -1
- package/dist/vocabulary/unique.js +8 -4
- package/dist/vocabulary/unique.js.map +1 -1
- package/dist/vocabulary/updated.d.ts +6 -1
- package/dist/vocabulary/updated.d.ts.map +1 -1
- package/dist/vocabulary/updated.js +5 -0
- package/dist/vocabulary/updated.js.map +1 -1
- package/dist/vocabulary/url.d.ts +6 -1
- package/dist/vocabulary/url.d.ts.map +1 -1
- package/dist/vocabulary/url.js +5 -0
- package/dist/vocabulary/url.js.map +1 -1
- package/dist/vocabulary/vocabulary.d.ts +6 -1
- package/dist/vocabulary/vocabulary.d.ts.map +1 -1
- package/dist/vocabulary/vocabulary.js +21 -11
- package/dist/vocabulary/vocabulary.js.map +1 -1
- package/dist/vocabulary/writeOnly.d.ts +6 -1
- package/dist/vocabulary/writeOnly.d.ts.map +1 -1
- package/dist/vocabulary/writeOnly.js +5 -0
- package/dist/vocabulary/writeOnly.js.map +1 -1
- package/package.json +1 -1
- package/src/Schema.ts +208 -0
- package/src/SchemaDefinition.ts +257 -0
- package/src/SchemaDerivation.ts +44 -0
- package/src/{schema/SchemaView.ts → SchemaView.ts} +9 -9
- package/src/axis/Axis.ts +2 -2
- package/src/axis/boundary/Boundaries.ts +25 -32
- package/src/axis/boundary/Boundary.ts +23 -10
- package/src/axis/boundary/BoundaryAxis.ts +4 -4
- package/src/axis/lifecycle/Clock.ts +1 -1
- package/src/axis/lifecycle/Generators.ts +12 -29
- package/src/axis/lifecycle/LifecycleAxis.ts +12 -7
- package/src/axis/lifecycle/apply.ts +30 -15
- package/src/axis/role/Relation.ts +6 -5
- package/src/axis/role/Role.ts +16 -20
- package/src/axis/role/RoleAxis.ts +28 -41
- package/src/axis/shape/Formats.ts +9 -11
- package/src/axis/shape/Shape.ts +18 -18
- package/src/entity/EntityAdapterSet.ts +81 -0
- package/src/entity/EntityAdapters.ts +8 -0
- package/src/entity/EntityDeclarations.ts +16 -0
- package/src/entity.ts +8 -3
- package/src/field/Field.ts +61 -0
- package/src/field/FieldSet.ts +75 -0
- package/src/index.ts +50 -28
- package/src/lib/Registry.ts +37 -0
- package/src/{utils.ts → lib/utils.ts} +3 -0
- package/src/projection/Cases.ts +176 -0
- package/src/projection/Visibility.ts +6 -2
- package/src/{card → projection/card}/Bundle.ts +9 -9
- package/src/projection/card/Card.ts +342 -0
- package/src/{card → projection/card}/Descriptor.ts +7 -7
- package/src/projection/card/admission.ts +40 -0
- package/src/{card → projection/card}/diff.ts +3 -3
- package/src/validator/AdapterFieldValidator.ts +40 -0
- package/src/{judge/FieldJudge.ts → validator/FieldDeclarationValidator.ts} +15 -15
- package/src/{judge/ValueJudge.ts → validator/FieldValueValidator.ts} +18 -13
- package/src/{judge/RowRefusal.ts → validator/InputRefusal.ts} +2 -4
- package/src/{judge/RowJudge.ts → validator/InputValidator.ts} +27 -20
- package/src/vocabulary/bool.ts +8 -2
- package/src/vocabulary/created.ts +7 -2
- package/src/vocabulary/date.ts +6 -1
- package/src/vocabulary/email.ts +6 -1
- package/src/vocabulary/immutable.ts +12 -4
- package/src/vocabulary/indexed.ts +9 -2
- package/src/vocabulary/json.ts +13 -6
- package/src/vocabulary/list.ts +10 -2
- package/src/vocabulary/many.ts +9 -2
- package/src/vocabulary/nullable.ts +13 -5
- package/src/vocabulary/number.ts +13 -3
- package/src/vocabulary/oneOf.ts +11 -3
- package/src/vocabulary/optional.ts +16 -6
- package/src/vocabulary/primary.ts +10 -5
- package/src/vocabulary/readOnly.ts +12 -4
- package/src/vocabulary/ref.ts +10 -2
- package/src/vocabulary/text.ts +15 -3
- package/src/vocabulary/unique.ts +10 -9
- package/src/vocabulary/updated.ts +6 -1
- package/src/vocabulary/url.ts +6 -1
- package/src/vocabulary/vocabulary.ts +21 -12
- package/src/vocabulary/writeOnly.ts +12 -4
- package/dist/EntityAdapters.d.ts +0 -28
- package/dist/EntityAdapters.d.ts.map +0 -1
- package/dist/EntityAdapters.js +0 -75
- package/dist/EntityAdapters.js.map +0 -1
- package/dist/EntityDeclarations.d.ts.map +0 -1
- package/dist/EntityDeclarations.js.map +0 -1
- package/dist/card/Bundle.d.ts.map +0 -1
- package/dist/card/Bundle.js.map +0 -1
- package/dist/card/Card.d.ts +0 -27
- package/dist/card/Card.d.ts.map +0 -1
- package/dist/card/Card.js.map +0 -1
- package/dist/card/Descriptor.d.ts.map +0 -1
- package/dist/card/Descriptor.js.map +0 -1
- package/dist/card/EntityTypeSource.d.ts +0 -12
- package/dist/card/EntityTypeSource.d.ts.map +0 -1
- package/dist/card/EntityTypeSource.js +0 -78
- package/dist/card/EntityTypeSource.js.map +0 -1
- package/dist/card/FacadeTypeSource.d.ts +0 -19
- package/dist/card/FacadeTypeSource.d.ts.map +0 -1
- package/dist/card/FacadeTypeSource.js +0 -40
- package/dist/card/FacadeTypeSource.js.map +0 -1
- package/dist/card/admission.d.ts +0 -9
- package/dist/card/admission.d.ts.map +0 -1
- package/dist/card/admission.js +0 -16
- package/dist/card/admission.js.map +0 -1
- package/dist/card/diff.d.ts.map +0 -1
- package/dist/constraint/FieldGroup.d.ts +0 -21
- package/dist/constraint/FieldGroup.d.ts.map +0 -1
- package/dist/constraint/FieldGroup.js +0 -65
- package/dist/constraint/FieldGroup.js.map +0 -1
- package/dist/constraint/Unique.d.ts +0 -4
- package/dist/constraint/Unique.d.ts.map +0 -1
- package/dist/constraint/Unique.js +0 -4
- package/dist/constraint/Unique.js.map +0 -1
- package/dist/fields/Field.d.ts.map +0 -1
- package/dist/fields/Field.js +0 -52
- package/dist/fields/Field.js.map +0 -1
- package/dist/fields/FieldSet.d.ts +0 -28
- package/dist/fields/FieldSet.d.ts.map +0 -1
- package/dist/fields/FieldSet.js +0 -55
- package/dist/fields/FieldSet.js.map +0 -1
- package/dist/judge/Cases.d.ts +0 -50
- package/dist/judge/Cases.d.ts.map +0 -1
- package/dist/judge/Cases.js +0 -108
- package/dist/judge/Cases.js.map +0 -1
- package/dist/judge/FieldJudge.d.ts +0 -9
- package/dist/judge/FieldJudge.d.ts.map +0 -1
- package/dist/judge/FieldJudge.js.map +0 -1
- package/dist/judge/RowJudge.d.ts +0 -12
- package/dist/judge/RowJudge.d.ts.map +0 -1
- package/dist/judge/RowJudge.js.map +0 -1
- package/dist/judge/RowRefusal.d.ts.map +0 -1
- package/dist/judge/RowRefusal.js.map +0 -1
- package/dist/judge/ValueForm.d.ts +0 -3
- package/dist/judge/ValueForm.d.ts.map +0 -1
- package/dist/judge/ValueForm.js +0 -3
- package/dist/judge/ValueForm.js.map +0 -1
- package/dist/judge/ValueJudge.d.ts +0 -12
- package/dist/judge/ValueJudge.d.ts.map +0 -1
- package/dist/judge/ValueJudge.js.map +0 -1
- package/dist/judge/options.d.ts +0 -4
- package/dist/judge/options.d.ts.map +0 -1
- package/dist/judge/options.js +0 -2
- package/dist/judge/options.js.map +0 -1
- package/dist/judge/result.d.ts.map +0 -1
- package/dist/judge/result.js +0 -2
- package/dist/judge/result.js.map +0 -1
- package/dist/projection/SchemaOrCard.d.ts +0 -7
- package/dist/projection/SchemaOrCard.d.ts.map +0 -1
- package/dist/projection/SchemaOrCard.js +0 -11
- package/dist/projection/SchemaOrCard.js.map +0 -1
- package/dist/schema/Schema.d.ts.map +0 -1
- package/dist/schema/Schema.js +0 -150
- package/dist/schema/Schema.js.map +0 -1
- package/dist/schema/SchemaDefinition.d.ts +0 -60
- package/dist/schema/SchemaDefinition.d.ts.map +0 -1
- package/dist/schema/SchemaDefinition.js +0 -85
- package/dist/schema/SchemaDefinition.js.map +0 -1
- package/dist/schema/SchemaDerivation.d.ts +0 -34
- package/dist/schema/SchemaDerivation.d.ts.map +0 -1
- package/dist/schema/SchemaDerivation.js +0 -46
- package/dist/schema/SchemaDerivation.js.map +0 -1
- package/dist/schema/SchemaView.d.ts.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
- package/src/EntityAdapters.ts +0 -100
- package/src/EntityDeclarations.ts +0 -19
- package/src/card/Card.ts +0 -256
- package/src/card/EntityTypeSource.ts +0 -90
- package/src/card/FacadeTypeSource.ts +0 -55
- package/src/card/admission.ts +0 -25
- package/src/constraint/FieldGroup.ts +0 -91
- package/src/constraint/Unique.ts +0 -3
- package/src/fields/Field.ts +0 -80
- package/src/fields/FieldSet.ts +0 -62
- package/src/judge/Cases.ts +0 -139
- package/src/judge/ValueForm.ts +0 -7
- package/src/judge/options.ts +0 -3
- package/src/projection/SchemaOrCard.ts +0 -18
- package/src/schema/Schema.ts +0 -197
- package/src/schema/SchemaDefinition.ts +0 -120
- package/src/schema/SchemaDerivation.ts +0 -57
- /package/dist/{schema/SchemaView.js → SchemaView.js} +0 -0
- /package/dist/{EntityDeclarations.js → entity/EntityDeclarations.js} +0 -0
- /package/dist/{card → projection/card}/Descriptor.js +0 -0
- /package/dist/{card → projection/card}/diff.js +0 -0
- /package/src/{judge/result.ts → validation.ts} +0 -0
package/src/judge/Cases.ts
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { Anatomy } from '../axis/shape/Shape.js';
|
|
2
|
-
import { Boundary } from '../axis/boundary/Boundary.js';
|
|
3
|
-
import { Lifecycle } from '../axis/lifecycle/Lifecycle.js';
|
|
4
|
-
import { Role } from '../axis/role/Role.js';
|
|
5
|
-
import type { Field } from '../fields/Field.js';
|
|
6
|
-
import type { SchemaView } from '../schema/SchemaView.js';
|
|
7
|
-
import { RowJudge } from './RowJudge.js';
|
|
8
|
-
import { RowRefusal } from './RowRefusal.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* One input, and what the judge must answer.
|
|
12
|
-
*
|
|
13
|
-
* `expect` carries the PATH of the field at fault and never the message. We know which
|
|
14
|
-
* field must be refused because we are the ones who broke it; naming the message would
|
|
15
|
-
* make this list a second judge, and the two would then have to be kept in step by hand —
|
|
16
|
-
* which is the duplication the whole thing exists to remove.
|
|
17
|
-
*/
|
|
18
|
-
export interface Case {
|
|
19
|
-
/** What this input does, in one clause — carried into the assertion so a failure reads. */
|
|
20
|
-
why: string;
|
|
21
|
-
body: unknown;
|
|
22
|
-
/**
|
|
23
|
-
* Judged as an update rather than a creation. The two modes refuse different things:
|
|
24
|
-
* an absence is `Required` on create and legal on patch, an immutable field is legal
|
|
25
|
-
* on create and refused on patch.
|
|
26
|
-
*/
|
|
27
|
-
patch: boolean;
|
|
28
|
-
expect: 'accept' | { reject: string };
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** A value of the wrong type for the declared shape — the one violation every field has. */
|
|
32
|
-
function wrongTypeFor(field: Field): unknown {
|
|
33
|
-
const declared = (field.shape as { type?: string | readonly string[] }).type;
|
|
34
|
-
const names = Array.isArray(declared) ? declared : [declared];
|
|
35
|
-
return names.includes('string') ? 42 : 'not-a-value-of-this-shape';
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** Values that break a stated bound. Empty when the field states none. */
|
|
39
|
-
function outOfBoundsFor(field: Field): { why: string; value: unknown }[] {
|
|
40
|
-
// Through `Anatomy`, not a cast: the cast admitted any keyword, and it declared
|
|
41
|
-
// `maxItems` — which no branch below ever produced. In the one function whose job is
|
|
42
|
-
// to be exhaustive, a bound the type does not carry is a case nobody notices missing.
|
|
43
|
-
const shape = Anatomy.of(field.shape).base;
|
|
44
|
-
const out: { why: string; value: unknown }[] = [];
|
|
45
|
-
if (shape?.type === 'string') {
|
|
46
|
-
if (typeof shape.minLength === 'number' && shape.minLength > 0)
|
|
47
|
-
out.push({ why: 'shorter than min', value: 'x'.repeat(shape.minLength - 1) });
|
|
48
|
-
if (typeof shape.maxLength === 'number')
|
|
49
|
-
out.push({ why: 'longer than max', value: 'x'.repeat(shape.maxLength + 1) });
|
|
50
|
-
if (shape.enum) out.push({ why: 'outside the stated set', value: '__not-in-enum__' });
|
|
51
|
-
}
|
|
52
|
-
if (shape?.type === 'number' || shape?.type === 'integer') {
|
|
53
|
-
if (typeof shape.minimum === 'number') out.push({ why: 'below minimum', value: shape.minimum - 1 });
|
|
54
|
-
if (typeof shape.maximum === 'number') out.push({ why: 'above maximum', value: shape.maximum + 1 });
|
|
55
|
-
}
|
|
56
|
-
if (shape?.type === 'array') {
|
|
57
|
-
if (typeof shape.minItems === 'number' && shape.minItems > 0)
|
|
58
|
-
out.push({ why: 'fewer items than min', value: [] });
|
|
59
|
-
if (typeof shape.maxItems === 'number')
|
|
60
|
-
out.push({ why: 'more items than max', value: Array.from({ length: shape.maxItems + 1 }, () => null) });
|
|
61
|
-
}
|
|
62
|
-
return out;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* The decision table, enumerated on the entity's own fields.
|
|
67
|
-
*
|
|
68
|
-
* Use the complete entity so a derived view cannot hide a divergent field. The caller
|
|
69
|
-
* supplies a valid row; generating data belongs to the testing package.
|
|
70
|
-
*/
|
|
71
|
-
export class Cases {
|
|
72
|
-
private constructor(
|
|
73
|
-
readonly all: readonly Case[],
|
|
74
|
-
) {}
|
|
75
|
-
|
|
76
|
-
static of(entity: SchemaView, valid: Record<string, unknown>): Cases {
|
|
77
|
-
return new Cases(enumerate(entity, valid));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Whether a verdict is the one a case expected.
|
|
82
|
-
*
|
|
83
|
-
* Takes the RESULT rather than the input so the same reader serves the local judge, the
|
|
84
|
-
* façade and a door — the three that have to agree.
|
|
85
|
-
*/
|
|
86
|
-
static holds(expected: Case['expect'], result: { success: boolean; errors?: { path: string }[] }): boolean {
|
|
87
|
-
if (expected === 'accept') return result.success;
|
|
88
|
-
if (result.success) return false;
|
|
89
|
-
return (result.errors ?? []).some((error) => error.path === expected.reject);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/** Every way a row is refused for its structure — the closed set this table must cover. */
|
|
93
|
-
static get refusals(): string[] {
|
|
94
|
-
return Object.values(RowRefusal);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
[Symbol.iterator](): Iterator<Case> {
|
|
98
|
-
return this.all[Symbol.iterator]();
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function enumerate(entity: SchemaView, valid: Record<string, unknown>): Case[] {
|
|
103
|
-
const fields = entity.getFields();
|
|
104
|
-
const judge = RowJudge.of(fields);
|
|
105
|
-
const cases: Case[] = [];
|
|
106
|
-
const withField = (name: string, value: unknown) => ({ ...valid, [name]: value });
|
|
107
|
-
|
|
108
|
-
cases.push({ why: 'a valid body', body: valid, patch: false, expect: 'accept' });
|
|
109
|
-
cases.push({ why: 'a key outside the contract', body: { ...valid, __unknown__: 'x' }, patch: false, expect: { reject: '__unknown__' } });
|
|
110
|
-
cases.push({ why: 'not an object at all', body: 'a string', patch: false, expect: { reject: '.' } });
|
|
111
|
-
|
|
112
|
-
for (const [name, field] of Object.entries(fields) as [string, Field][]) {
|
|
113
|
-
// A reference names a row that must exist; the caller supplied its id and we do not
|
|
114
|
-
// get to invent a second one, so the only case we can state about it is the bound one.
|
|
115
|
-
const isRef = Role.of(field).isReference;
|
|
116
|
-
|
|
117
|
-
if (judge.onAbsent(field) === null && name in valid) {
|
|
118
|
-
const body = { ...valid };
|
|
119
|
-
delete body[name];
|
|
120
|
-
cases.push({ why: `${name} absent`, body, patch: false, expect: { reject: name } });
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (Boundary.of(field).readOnly) {
|
|
124
|
-
cases.push({ why: `${name} supplied although read-only`, body: withField(name, wrongTypeFor(field)), patch: false, expect: { reject: name } });
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (Lifecycle.of(field).immutable && !Role.of(field).isPrimary) {
|
|
128
|
-
cases.push({ why: `${name} supplied on an update`, body: { [name]: valid[name] ?? wrongTypeFor(field) }, patch: true, expect: { reject: name } });
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (name in valid && !isRef) {
|
|
132
|
-
cases.push({ why: `${name} of the wrong type`, body: withField(name, wrongTypeFor(field)), patch: false, expect: { reject: name } });
|
|
133
|
-
for (const { why, value } of outOfBoundsFor(field))
|
|
134
|
-
cases.push({ why: `${name} ${why}`, body: withField(name, value), patch: false, expect: { reject: name } });
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return cases;
|
|
139
|
-
}
|
package/src/judge/ValueForm.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export const isObject = (value: unknown): value is Record<string, unknown> =>
|
|
2
|
-
typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3
|
-
|
|
4
|
-
export const oneOfTokens = <T extends readonly string[]>(
|
|
5
|
-
value: unknown,
|
|
6
|
-
tokens: T,
|
|
7
|
-
): value is T[number] => typeof value === 'string' && (tokens as readonly string[]).includes(value);
|
package/src/judge/options.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { Fields } from '../fields/Field.js';
|
|
2
|
-
import type { SchemaView } from '../schema/SchemaView.js';
|
|
3
|
-
import type { SchemaDescriptor } from '../card/Descriptor.js';
|
|
4
|
-
import { Card } from '../card/Card.js';
|
|
5
|
-
|
|
6
|
-
export type SchemaOrCard = SchemaView | SchemaDescriptor;
|
|
7
|
-
|
|
8
|
-
function isDescriptor(source: SchemaOrCard): source is SchemaDescriptor {
|
|
9
|
-
return typeof (source as SchemaView).getFields !== 'function';
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function schemaOf(source: SchemaOrCard): SchemaView {
|
|
13
|
-
return isDescriptor(source) ? Card.fromDescriptor(source).toSchema() : source;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function fieldsOf(source: SchemaOrCard): Fields {
|
|
17
|
-
return schemaOf(source).getFields();
|
|
18
|
-
}
|
package/src/schema/Schema.ts
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import { Boundary } from '../axis/boundary/Boundary.js';
|
|
2
|
-
import { type Fields } from '../fields/Field.js';
|
|
3
|
-
import {
|
|
4
|
-
type CompositeUnique,
|
|
5
|
-
type EntityDeclarations,
|
|
6
|
-
type PreviousNames,
|
|
7
|
-
} from '../EntityDeclarations.js';
|
|
8
|
-
import { EntityAdapterSet, type EntityAdapters } from '../EntityAdapters.js';
|
|
9
|
-
import { FieldGroup } from '../constraint/FieldGroup.js';
|
|
10
|
-
import { Unique } from '../constraint/Unique.js';
|
|
11
|
-
import { RowJudge } from '../judge/RowJudge.js';
|
|
12
|
-
import { SchemaDerivation } from './SchemaDerivation.js';
|
|
13
|
-
import { SchemaDefinition } from './SchemaDefinition.js';
|
|
14
|
-
import { type ValidateOptions } from '../judge/options.js';
|
|
15
|
-
import type { StandardSchemaV1 } from '../projection/standard.js';
|
|
16
|
-
import type { PartialRow, Row, SchemaView } from './SchemaView.js';
|
|
17
|
-
|
|
18
|
-
export const ANONYMOUS_SCHEMA_NAME = "Schema";
|
|
19
|
-
|
|
20
|
-
export interface SchemaConstructor<TFields extends Fields> extends SchemaView<TFields> {
|
|
21
|
-
new (data: PartialRow<TFields>): Row<TFields>;
|
|
22
|
-
readonly "~standard": StandardSchemaV1.Props<Record<string, unknown>, Row<TFields>>;
|
|
23
|
-
readonly derivation?: SchemaDerivation;
|
|
24
|
-
readonly previous?: PreviousNames<TFields>;
|
|
25
|
-
readonly anchored?: boolean;
|
|
26
|
-
from(data: Record<string, unknown>): Row<TFields>;
|
|
27
|
-
pick<K extends string & keyof TFields>(...keys: K[]): SchemaConstructor<Pick<TFields, K>>;
|
|
28
|
-
omit<K extends string & keyof TFields>(...keys: K[]): SchemaConstructor<Omit<TFields, K>>;
|
|
29
|
-
partial(): SchemaConstructor<TFields>;
|
|
30
|
-
extend<E extends Fields>(extra: E): SchemaConstructor<TFields & E>;
|
|
31
|
-
declares(declarations: EntityDeclarations<TFields>): SchemaConstructor<TFields>;
|
|
32
|
-
anchor(): SchemaConstructor<TFields>;
|
|
33
|
-
named(name: string): SchemaConstructor<TFields>;
|
|
34
|
-
rename(mapping: Partial<Record<string & keyof TFields, string>>): SchemaConstructor<Fields>;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export class Schema {
|
|
38
|
-
/** The one place a schema holds what it is. The readings below are its projections. */
|
|
39
|
-
static definition: SchemaDefinition = SchemaDefinition.stated({ fields: {} });
|
|
40
|
-
|
|
41
|
-
static get fields(): Fields { return this.definition.fields; }
|
|
42
|
-
static get adapters(): EntityAdapters<Fields> | undefined { return this.definition.adapters; }
|
|
43
|
-
static get opts(): ValidateOptions { return this.definition.opts; }
|
|
44
|
-
static get derivation(): SchemaDerivation | undefined { return this.definition.derivation; }
|
|
45
|
-
static get previous(): PreviousNames<Fields> | undefined { return this.definition.previous; }
|
|
46
|
-
static get anchored(): boolean { return this.definition.anchored; }
|
|
47
|
-
|
|
48
|
-
constructor(data?: Record<string, unknown>) {
|
|
49
|
-
if (!data) return;
|
|
50
|
-
for (const [key, value] of Object.entries(data)) {
|
|
51
|
-
Object.defineProperty(this, key, { value, writable: true, enumerable: true, configurable: true });
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
static getFields() { return this.fields; }
|
|
56
|
-
static getAdapters() { return this.adapters; }
|
|
57
|
-
static getUnique(): CompositeUnique<Fields> | undefined {
|
|
58
|
-
const groups = FieldGroup.groupsOf(this.fields, Unique);
|
|
59
|
-
return groups.length ? groups.map((group) => [...group.members]) : undefined;
|
|
60
|
-
}
|
|
61
|
-
static getOpts() { return this.opts; }
|
|
62
|
-
|
|
63
|
-
static validate(input: unknown) {
|
|
64
|
-
return RowJudge.of(this.fields, this.opts).check(input);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
static from(data: Record<string, unknown>) {
|
|
68
|
-
const out: Record<string, unknown> = {};
|
|
69
|
-
for (const [key, field] of Object.entries(this.fields)) {
|
|
70
|
-
if (!(key in data)) continue;
|
|
71
|
-
const value = data[key];
|
|
72
|
-
if (value === null || value === undefined) { out[key] = value; continue; }
|
|
73
|
-
const decoded = Boundary.of(field).decode(value);
|
|
74
|
-
out[key] = "error" in decoded ? value : decoded.value;
|
|
75
|
-
}
|
|
76
|
-
return out;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
static get ["~standard"](): StandardSchemaV1.Props<Record<string, unknown>> {
|
|
80
|
-
const { fields, opts } = this;
|
|
81
|
-
return {
|
|
82
|
-
version: 1,
|
|
83
|
-
vendor: "fougere",
|
|
84
|
-
validate(value: unknown) {
|
|
85
|
-
const result = RowJudge.of(fields, opts).check(value);
|
|
86
|
-
if (result.success) return { value: result.data };
|
|
87
|
-
return {
|
|
88
|
-
issues: result.errors.map((e) => ({
|
|
89
|
-
message: e.message,
|
|
90
|
-
path: e.path && e.path !== "." ? [{ key: e.path }] : undefined,
|
|
91
|
-
})),
|
|
92
|
-
};
|
|
93
|
-
},
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
static pick(...keys: string[]) {
|
|
98
|
-
assertKnownKeys("pick", keys, this.fields);
|
|
99
|
-
const picked: Fields = {};
|
|
100
|
-
for (const key of keys) if (this.fields[key]) picked[key] = this.fields[key];
|
|
101
|
-
return this.derive(picked, (k) => (keys.includes(k) ? k : undefined));
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
static omit(...keys: string[]) {
|
|
105
|
-
assertKnownKeys("omit", keys, this.fields);
|
|
106
|
-
const kept: Fields = {};
|
|
107
|
-
for (const [key, field] of Object.entries(this.fields)) if (!keys.includes(key)) kept[key] = field;
|
|
108
|
-
return this.derive(kept, (k) => (keys.includes(k) ? undefined : k));
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
static rename(mapping: Record<string, string>) {
|
|
112
|
-
assertKnownKeys("rename", Object.keys(mapping), this.fields);
|
|
113
|
-
const renamed: Fields = {};
|
|
114
|
-
for (const [key, field] of Object.entries(this.fields)) renamed[mapping[key] ?? key] = field;
|
|
115
|
-
return this.derive(renamed, (k) => mapping[k] ?? k);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Everything a schema states about ITSELF, available wherever a schema is. `entity(fields, …)`
|
|
120
|
-
* is this same gesture at the declaration site; the fields do not move, so neither does the type.
|
|
121
|
-
*/
|
|
122
|
-
static declares(declarations: EntityDeclarations<Fields>) {
|
|
123
|
-
const addressed = EntityAdapterSet.of(declarations.adapters)?.fieldNames ?? [];
|
|
124
|
-
assertKnownKeys("declares", [...addressed, ...Object.keys(declarations.previous ?? {})], this.fields);
|
|
125
|
-
|
|
126
|
-
return Schema.subclass(this.definition.declaring(declarations));
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* This schema holds rows of its own — every entity is one, and a derivation says so.
|
|
131
|
-
*
|
|
132
|
-
* An anchor is where a walk STOPS: `derivation.anchor` climbs to the nearest one, and what
|
|
133
|
-
* is cut from an anchor roots on it. Two anchors are two entities that happen to share a
|
|
134
|
-
* shape, never a hierarchy — nothing here subtypes, so a relation between them is `ref()`.
|
|
135
|
-
*/
|
|
136
|
-
static anchor() {
|
|
137
|
-
return Schema.subclass(this.definition.anchoring());
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
static partial() {
|
|
141
|
-
return Schema.subclass(this.definition.patched(this));
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
static extend(extra: Fields) {
|
|
145
|
-
return Schema.subclass(this.definition.extended(extra, this));
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
static named(name: string) {
|
|
149
|
-
if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name)) {
|
|
150
|
-
throw new Error(`named(): \`${name}\` is not a valid class name.`);
|
|
151
|
-
}
|
|
152
|
-
if (this.name !== ANONYMOUS_SCHEMA_NAME) {
|
|
153
|
-
throw new Error(`named(): \`${this.name}\` is already named by its class declaration.`);
|
|
154
|
-
}
|
|
155
|
-
Object.defineProperty(this, "name", { value: name, configurable: true });
|
|
156
|
-
return this;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
static compose<T extends SchemaView[]>(...sources: T): SchemaConstructor<Merged<T>> {
|
|
160
|
-
return Schema.subclass(SchemaDefinition.merged(sources)) as unknown as SchemaConstructor<Merged<T>>;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
static of<TFields extends Fields>(stated: {
|
|
164
|
-
fields: TFields;
|
|
165
|
-
derivation?: SchemaDerivation;
|
|
166
|
-
adapters?: EntityAdapters<TFields>;
|
|
167
|
-
opts?: ValidateOptions;
|
|
168
|
-
previous?: PreviousNames<TFields>;
|
|
169
|
-
anchored?: boolean;
|
|
170
|
-
}): SchemaConstructor<TFields> {
|
|
171
|
-
return Schema.subclass(SchemaDefinition.stated(stated)) as unknown as SchemaConstructor<TFields>;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/** The class a definition becomes. The one place a Schema subclass is born. */
|
|
175
|
-
private static subclass(definition: SchemaDefinition): SchemaConstructor<Fields> {
|
|
176
|
-
class Derived extends Schema {}
|
|
177
|
-
Derived.definition = definition;
|
|
178
|
-
Object.defineProperty(Derived, "name", { value: ANONYMOUS_SCHEMA_NAME, configurable: true });
|
|
179
|
-
return Derived as unknown as SchemaConstructor<Fields>;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
private static derive(fields: Fields, survives: (key: string) => string | undefined) {
|
|
183
|
-
return Schema.subclass(this.definition.cut(fields, survives, this));
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function assertKnownKeys(operation: string, keys: string[], fields: Fields): void {
|
|
188
|
-
const strangers = keys.filter((key) => !(key in fields));
|
|
189
|
-
if (strangers.length === 0) return;
|
|
190
|
-
throw new Error(
|
|
191
|
-
`${operation}(): unknown field ${strangers.map((s) => `\`${s}\``).join(", ")}. ` +
|
|
192
|
-
`This schema carries ${Object.keys(fields).join(", ")}.`,
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
197
|
-
type Merged<T extends SchemaView[]> = UnionToIntersection<T[number] extends { getFields(): infer F } ? F : Fields> & Fields;
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { type Fields } from '../fields/Field.js';
|
|
2
|
-
import { FieldSet } from '../fields/FieldSet.js';
|
|
3
|
-
import { type EntityDeclarations, type PreviousNames } from '../EntityDeclarations.js';
|
|
4
|
-
import { EntityAdapterSet, type EntityAdapters } from '../EntityAdapters.js';
|
|
5
|
-
import { SchemaDerivation } from './SchemaDerivation.js';
|
|
6
|
-
import { type ValidateOptions } from '../judge/options.js';
|
|
7
|
-
import type { SchemaView } from './SchemaView.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Everything a schema IS, apart from being a class whose instances are rows.
|
|
11
|
-
*
|
|
12
|
-
* The members used to be that many statics assigned side by side, and every derivation
|
|
13
|
-
* re-threaded them by hand — which is how one of them came to be dropped from a list
|
|
14
|
-
* without anyone noticing. A transformation here returns a COMPLETE definition or it does
|
|
15
|
-
* not compile, so no gesture can mix the fields of one with the options of another.
|
|
16
|
-
*
|
|
17
|
-
* Internal: it is not exported from the package and never appears on `SchemaConstructor`.
|
|
18
|
-
* A user derives with `Order.pick(…)`, never `Order.definition.pick(…)`.
|
|
19
|
-
*/
|
|
20
|
-
export class SchemaDefinition {
|
|
21
|
-
private constructor(
|
|
22
|
-
readonly fields: Fields,
|
|
23
|
-
readonly adapters: EntityAdapters<Fields> | undefined,
|
|
24
|
-
readonly opts: ValidateOptions,
|
|
25
|
-
readonly previous: PreviousNames<Fields> | undefined,
|
|
26
|
-
readonly derivation: SchemaDerivation | undefined,
|
|
27
|
-
readonly anchored: boolean,
|
|
28
|
-
) {}
|
|
29
|
-
|
|
30
|
-
static stated(said: {
|
|
31
|
-
fields: Fields;
|
|
32
|
-
adapters?: EntityAdapters<Fields>;
|
|
33
|
-
opts?: ValidateOptions;
|
|
34
|
-
previous?: PreviousNames<Fields>;
|
|
35
|
-
derivation?: SchemaDerivation;
|
|
36
|
-
anchored?: boolean;
|
|
37
|
-
}): SchemaDefinition {
|
|
38
|
-
return new SchemaDefinition(
|
|
39
|
-
said.fields, EntityAdapterSet.of(said.adapters)?.stated, said.opts ?? {}, said.previous, said.derivation, said.anchored ?? false,
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* What a schema states about ITSELF, folded into what it already states — one adapter
|
|
45
|
-
* entry per field wins the later spelling, and a unique group is stamped on its members.
|
|
46
|
-
*/
|
|
47
|
-
declaring(said: EntityDeclarations<Fields>): SchemaDefinition {
|
|
48
|
-
return new SchemaDefinition(
|
|
49
|
-
FieldSet.declared(this.fields, said.unique),
|
|
50
|
-
EntityAdapterSet.merged([this.adapters, said.adapters])?.stated,
|
|
51
|
-
this.opts,
|
|
52
|
-
said.previous ?? this.previous,
|
|
53
|
-
this.derivation,
|
|
54
|
-
this.anchored,
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* The same schema, holding rows of its own. A derivation is an answer until it says this.
|
|
60
|
-
*/
|
|
61
|
-
anchoring(): SchemaDefinition {
|
|
62
|
-
return new SchemaDefinition(
|
|
63
|
-
this.fields, this.adapters, this.opts, this.previous, this.derivation, true,
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* `pick`, `omit` and `rename` are one gesture: the fields that remain, and what became
|
|
69
|
-
* of each name. What each adapter was handed follows the same correspondence, and so does the origin.
|
|
70
|
-
*/
|
|
71
|
-
cut(fields: Fields, survives: (key: string) => string | undefined, root: SchemaView): SchemaDefinition {
|
|
72
|
-
const renamed: Fields = {};
|
|
73
|
-
for (const [key, field] of Object.entries(fields)) renamed[key] = field.rename(survives);
|
|
74
|
-
return new SchemaDefinition(
|
|
75
|
-
renamed,
|
|
76
|
-
EntityAdapterSet.of(this.adapters)?.cut(survives)?.stated,
|
|
77
|
-
this.opts,
|
|
78
|
-
undefined,
|
|
79
|
-
this.origin(root).compose(survives),
|
|
80
|
-
false,
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/** The same fields, judged as an update. */
|
|
85
|
-
patched(root: SchemaView): SchemaDefinition {
|
|
86
|
-
return new SchemaDefinition(
|
|
87
|
-
{ ...this.fields }, this.adapters, { ...this.opts, patch: true }, undefined, this.origin(root), false,
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** The added fields have no origin, so the derivation is unchanged: it speaks of the root. */
|
|
92
|
-
extended(extra: Fields, root: SchemaView): SchemaDefinition {
|
|
93
|
-
return new SchemaDefinition(
|
|
94
|
-
{ ...this.fields, ...extra }, this.adapters, this.opts, undefined, this.origin(root), false,
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/** Several views folded into one definition, which therefore has no single origin. */
|
|
99
|
-
static merged(views: readonly SchemaView[]): SchemaDefinition {
|
|
100
|
-
const fields: Fields = {};
|
|
101
|
-
let opts: ValidateOptions = {};
|
|
102
|
-
for (const view of views) {
|
|
103
|
-
Object.assign(fields, view.getFields());
|
|
104
|
-
opts = { ...opts, ...view.getOpts() };
|
|
105
|
-
}
|
|
106
|
-
const adapters = EntityAdapterSet.merged(views.map((view) => view.getAdapters()))?.stated;
|
|
107
|
-
|
|
108
|
-
return new SchemaDefinition(fields, adapters, opts, undefined, undefined, false);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* The origin this definition already carries, or the one `root` becomes. A schema that
|
|
113
|
-
* is an ANCHOR holds rows of its own, so what is cut from it roots on IT and not on its own origin.
|
|
114
|
-
*/
|
|
115
|
-
private origin(root: SchemaView): SchemaDerivation {
|
|
116
|
-
if (!this.anchored && this.derivation) return this.derivation;
|
|
117
|
-
|
|
118
|
-
return SchemaDerivation.first(root, this.fields);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { type Fields } from '../fields/Field.js';
|
|
2
|
-
import type { SchemaView } from './SchemaView.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* What a derived schema says about its ORIGIN: the class it was cut from, and what the cut
|
|
6
|
-
* left of each of that class's fields.
|
|
7
|
-
*
|
|
8
|
-
* The origin is the ROOT — `Post.pick(a, b).omit(b)` answers `Post` and never the
|
|
9
|
-
* intermediate — so a chain is flattened rather than journalled, and the two halves cannot
|
|
10
|
-
* disagree: a derivation always carries both, which `source` and `survived` as independent
|
|
11
|
-
* properties could not promise.
|
|
12
|
-
*/
|
|
13
|
-
export class SchemaDerivation {
|
|
14
|
-
private constructor(
|
|
15
|
-
readonly source: SchemaView,
|
|
16
|
-
readonly survived: Readonly<Record<string, string | undefined>>,
|
|
17
|
-
) {}
|
|
18
|
-
|
|
19
|
-
/** The first cut: every field of the origin still answers to its own name. */
|
|
20
|
-
static first(source: SchemaView, fields: Fields): SchemaDerivation {
|
|
21
|
-
return new SchemaDerivation(source, Object.fromEntries(Object.keys(fields).map((key) => [key, key])));
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** The same origin, seen through one more cut. */
|
|
25
|
-
compose(survives: (key: string) => string | undefined): SchemaDerivation {
|
|
26
|
-
return new SchemaDerivation(
|
|
27
|
-
this.source,
|
|
28
|
-
Object.fromEntries(
|
|
29
|
-
Object.entries(this.survived).map(([origin, here]) => [origin, here === undefined ? undefined : survives(here)]),
|
|
30
|
-
),
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
get sourceName(): string {
|
|
35
|
-
return this.source.name;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* The anchor whose rows this describes — the nearest one going up, and a schema with no
|
|
40
|
-
* origin of its own is one. An answer borrows its rows; this says from whom. Whether
|
|
41
|
-
* those rows carry a key is a separate question: an anchor may have none.
|
|
42
|
-
*/
|
|
43
|
-
get anchor(): SchemaView {
|
|
44
|
-
const source = this.source;
|
|
45
|
-
|
|
46
|
-
return source.anchored !== undefined || !source.derivation ? source : source.derivation.anchor;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* What the ROOT calls `key`, translated to the name it carries here — `undefined` when a
|
|
51
|
-
* cut dropped it. A reader that needs something the root declared about a field asks the
|
|
52
|
-
* root and comes back through this; it does not keep a copy of the answer.
|
|
53
|
-
*/
|
|
54
|
-
hereFor(key: string): string | undefined {
|
|
55
|
-
return this.survived[key];
|
|
56
|
-
}
|
|
57
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|