@fougere/schema 0.6.0-alpha.0 → 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} +17 -27
- package/dist/Schema.d.ts.map +1 -0
- package/dist/{schema/Schema.js → Schema.js} +21 -61
- 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/{schema/axis → axis}/Axis.d.ts +2 -2
- package/dist/axis/Axis.d.ts.map +1 -0
- package/dist/axis/Axis.js.map +1 -0
- package/dist/axis/Meta.d.ts.map +1 -0
- package/dist/{schema/axis → axis}/Meta.js.map +1 -1
- package/dist/axis/boundary/Boundaries.d.ts +21 -0
- package/dist/axis/boundary/Boundaries.d.ts.map +1 -0
- package/dist/axis/boundary/Boundaries.js +25 -0
- package/dist/axis/boundary/Boundaries.js.map +1 -0
- package/dist/{schema/axis → axis}/boundary/Boundary.d.ts +3 -1
- package/dist/axis/boundary/Boundary.d.ts.map +1 -0
- package/dist/{schema/axis → axis}/boundary/Boundary.js +8 -6
- package/dist/axis/boundary/Boundary.js.map +1 -0
- package/dist/axis/boundary/BoundaryAxis.d.ts.map +1 -0
- package/dist/{schema/axis → axis}/boundary/BoundaryAxis.js +4 -4
- package/dist/axis/boundary/BoundaryAxis.js.map +1 -0
- package/dist/{schema/axis → axis}/lifecycle/Clock.d.ts +1 -1
- package/dist/axis/lifecycle/Clock.d.ts.map +1 -0
- package/dist/{schema/axis → axis}/lifecycle/Clock.js +1 -1
- package/dist/axis/lifecycle/Clock.js.map +1 -0
- package/dist/axis/lifecycle/Generators.d.ts +10 -0
- package/dist/axis/lifecycle/Generators.d.ts.map +1 -0
- package/dist/axis/lifecycle/Generators.js +20 -0
- package/dist/axis/lifecycle/Generators.js.map +1 -0
- package/dist/axis/lifecycle/Lifecycle.d.ts.map +1 -0
- package/dist/axis/lifecycle/Lifecycle.js.map +1 -0
- package/dist/axis/lifecycle/LifecycleAxis.d.ts.map +1 -0
- package/dist/{schema/axis → axis}/lifecycle/LifecycleAxis.js +11 -6
- package/dist/axis/lifecycle/LifecycleAxis.js.map +1 -0
- package/dist/axis/lifecycle/apply.d.ts +15 -0
- package/dist/axis/lifecycle/apply.d.ts.map +1 -0
- package/dist/axis/lifecycle/apply.js +50 -0
- package/dist/axis/lifecycle/apply.js.map +1 -0
- package/dist/{schema/axis → axis}/role/Relation.d.ts +3 -2
- package/dist/axis/role/Relation.d.ts.map +1 -0
- package/dist/{schema/axis → axis}/role/Relation.js +6 -5
- package/dist/axis/role/Relation.js.map +1 -0
- package/dist/{schema/axis → axis}/role/Role.d.ts +6 -6
- package/dist/axis/role/Role.d.ts.map +1 -0
- package/dist/axis/role/Role.js +36 -0
- package/dist/axis/role/Role.js.map +1 -0
- package/dist/{schema/axis → axis}/role/RoleAxis.d.ts +1 -1
- package/dist/axis/role/RoleAxis.d.ts.map +1 -0
- package/dist/{schema/axis → axis}/role/RoleAxis.js +28 -36
- package/dist/axis/role/RoleAxis.js.map +1 -0
- package/dist/axis/shape/Formats.d.ts +11 -0
- package/dist/axis/shape/Formats.d.ts.map +1 -0
- package/dist/axis/shape/Formats.js +9 -0
- package/dist/axis/shape/Formats.js.map +1 -0
- package/dist/{schema/axis → axis}/shape/Shape.d.ts +5 -3
- package/dist/axis/shape/Shape.d.ts.map +1 -0
- package/dist/{schema/axis → axis}/shape/Shape.js +13 -13
- package/dist/axis/shape/Shape.js.map +1 -0
- 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 +1 -24
- package/dist/entity/EntityAdapters.d.ts.map +1 -1
- package/dist/entity/EntityAdapters.js +1 -74
- package/dist/entity/EntityAdapters.js.map +1 -1
- package/dist/entity/EntityDeclarations.d.ts +1 -1
- package/dist/entity/EntityDeclarations.d.ts.map +1 -1
- package/dist/entity.d.ts +7 -2
- package/dist/entity.d.ts.map +1 -1
- package/dist/entity.js +6 -1
- package/dist/entity.js.map +1 -1
- package/dist/{schema/fields → field}/Field.d.ts +2 -3
- 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 +27 -30
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -23
- 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/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/projection/Cases.d.ts +9 -20
- package/dist/projection/Cases.d.ts.map +1 -1
- package/dist/projection/Cases.js +44 -39
- package/dist/projection/Cases.js.map +1 -1
- package/dist/projection/Visibility.d.ts +2 -1
- package/dist/projection/Visibility.d.ts.map +1 -1
- package/dist/projection/Visibility.js +4 -3
- package/dist/projection/Visibility.js.map +1 -1
- package/dist/projection/card/Bundle.d.ts +1 -1
- package/dist/projection/card/Bundle.d.ts.map +1 -1
- package/dist/projection/card/Bundle.js +7 -7
- package/dist/projection/card/Bundle.js.map +1 -1
- package/dist/projection/card/Card.d.ts +7 -13
- package/dist/projection/card/Card.d.ts.map +1 -1
- package/dist/projection/card/Card.js +96 -69
- package/dist/projection/card/Card.js.map +1 -1
- package/dist/projection/card/Descriptor.d.ts +7 -7
- package/dist/projection/card/Descriptor.d.ts.map +1 -1
- package/dist/projection/card/admission.d.ts +15 -5
- package/dist/projection/card/admission.d.ts.map +1 -1
- package/dist/projection/card/admission.js +15 -5
- package/dist/projection/card/admission.js.map +1 -1
- package/dist/projection/card/diff.d.ts +2 -2
- package/dist/projection/card/diff.d.ts.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} +8 -8
- 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} +12 -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} +24 -20
- 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 +5 -0
- 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 +5 -0
- 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 +7 -2
- package/dist/vocabulary/many.d.ts.map +1 -1
- package/dist/vocabulary/many.js +7 -2
- 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 +6 -1
- 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 +7 -2
- package/dist/vocabulary/optional.js.map +1 -1
- package/dist/vocabulary/primary.d.ts +2 -2
- package/dist/vocabulary/primary.d.ts.map +1 -1
- package/dist/vocabulary/primary.js +7 -2
- 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 +6 -1
- package/dist/vocabulary/readOnly.js.map +1 -1
- package/dist/vocabulary/ref.d.ts +7 -2
- package/dist/vocabulary/ref.d.ts.map +1 -1
- package/dist/vocabulary/ref.js +7 -2
- package/dist/vocabulary/ref.js.map +1 -1
- package/dist/vocabulary/text.d.ts +7 -2
- package/dist/vocabulary/text.d.ts.map +1 -1
- package/dist/vocabulary/text.js +6 -1
- 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 +7 -3
- 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 +22 -12
- 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 +6 -1
- package/dist/vocabulary/writeOnly.js.map +1 -1
- package/package.json +1 -1
- package/src/{schema/Schema.ts → Schema.ts} +31 -74
- package/src/SchemaDefinition.ts +257 -0
- package/src/SchemaDerivation.ts +44 -0
- package/src/{schema/SchemaView.ts → SchemaView.ts} +9 -9
- package/src/{schema/axis → axis}/Axis.ts +2 -2
- package/src/axis/boundary/Boundaries.ts +37 -0
- package/src/{schema/axis → axis}/boundary/Boundary.ts +9 -7
- package/src/{schema/axis → axis}/boundary/BoundaryAxis.ts +4 -4
- package/src/{schema/axis → axis}/lifecycle/Clock.ts +1 -1
- package/src/axis/lifecycle/Generators.ts +29 -0
- package/src/{schema/axis → axis}/lifecycle/LifecycleAxis.ts +12 -7
- package/src/axis/lifecycle/apply.ts +53 -0
- package/src/{schema/axis → axis}/role/Relation.ts +6 -5
- package/src/axis/role/Role.ts +52 -0
- package/src/{schema/axis → axis}/role/RoleAxis.ts +28 -40
- package/src/axis/shape/Formats.ts +20 -0
- package/src/{schema/axis → axis}/shape/Shape.ts +18 -18
- package/src/entity/EntityAdapterSet.ts +81 -0
- package/src/entity/EntityAdapters.ts +4 -96
- package/src/entity/EntityDeclarations.ts +1 -1
- package/src/entity.ts +7 -2
- package/src/{schema/fields → field}/Field.ts +8 -26
- package/src/field/FieldSet.ts +75 -0
- package/src/index.ts +29 -44
- package/src/lib/Registry.ts +37 -0
- package/src/projection/Cases.ts +56 -55
- package/src/projection/Visibility.ts +5 -4
- package/src/projection/card/Bundle.ts +9 -9
- package/src/projection/card/Card.ts +101 -74
- package/src/projection/card/Descriptor.ts +7 -7
- package/src/projection/card/admission.ts +16 -6
- package/src/projection/card/diff.ts +2 -2
- package/src/validator/AdapterFieldValidator.ts +40 -0
- package/src/{judge/FieldJudge.ts → validator/FieldDeclarationValidator.ts} +10 -10
- package/src/{judge/ValueJudge.ts → validator/FieldValueValidator.ts} +14 -13
- package/src/{judge/RowRefusal.ts → validator/InputRefusal.ts} +2 -4
- package/src/{judge/RowJudge.ts → validator/InputValidator.ts} +30 -23
- package/src/vocabulary/bool.ts +6 -1
- package/src/vocabulary/created.ts +6 -1
- package/src/vocabulary/date.ts +6 -1
- package/src/vocabulary/email.ts +6 -1
- package/src/vocabulary/immutable.ts +6 -1
- package/src/vocabulary/indexed.ts +6 -1
- package/src/vocabulary/json.ts +10 -5
- package/src/vocabulary/list.ts +6 -1
- package/src/vocabulary/many.ts +7 -2
- package/src/vocabulary/nullable.ts +8 -3
- package/src/vocabulary/number.ts +6 -1
- package/src/vocabulary/oneOf.ts +6 -1
- package/src/vocabulary/optional.ts +8 -3
- package/src/vocabulary/primary.ts +7 -2
- package/src/vocabulary/readOnly.ts +7 -2
- package/src/vocabulary/ref.ts +7 -2
- package/src/vocabulary/text.ts +7 -2
- package/src/vocabulary/unique.ts +8 -4
- package/src/vocabulary/updated.ts +6 -1
- package/src/vocabulary/url.ts +6 -1
- package/src/vocabulary/vocabulary.ts +22 -12
- package/src/vocabulary/writeOnly.ts +7 -2
- 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/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/projection/card/EntityTypeSource.d.ts +0 -12
- package/dist/projection/card/EntityTypeSource.d.ts.map +0 -1
- package/dist/projection/card/EntityTypeSource.js +0 -78
- package/dist/projection/card/EntityTypeSource.js.map +0 -1
- package/dist/projection/card/FacadeTypeSource.d.ts +0 -19
- package/dist/projection/card/FacadeTypeSource.d.ts.map +0 -1
- package/dist/projection/card/FacadeTypeSource.js +0 -40
- package/dist/projection/card/FacadeTypeSource.js.map +0 -1
- package/dist/schema/Schema.d.ts.map +0 -1
- 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 -51
- package/dist/schema/SchemaDerivation.js.map +0 -1
- package/dist/schema/SchemaView.d.ts.map +0 -1
- package/dist/schema/axis/Axis.d.ts.map +0 -1
- package/dist/schema/axis/Axis.js.map +0 -1
- package/dist/schema/axis/Meta.d.ts.map +0 -1
- package/dist/schema/axis/boundary/Boundaries.d.ts +0 -20
- package/dist/schema/axis/boundary/Boundaries.d.ts.map +0 -1
- package/dist/schema/axis/boundary/Boundaries.js +0 -31
- package/dist/schema/axis/boundary/Boundaries.js.map +0 -1
- package/dist/schema/axis/boundary/Boundary.d.ts.map +0 -1
- package/dist/schema/axis/boundary/Boundary.js.map +0 -1
- package/dist/schema/axis/boundary/BoundaryAxis.d.ts.map +0 -1
- package/dist/schema/axis/boundary/BoundaryAxis.js.map +0 -1
- package/dist/schema/axis/lifecycle/Clock.d.ts.map +0 -1
- package/dist/schema/axis/lifecycle/Clock.js.map +0 -1
- package/dist/schema/axis/lifecycle/Generators.d.ts +0 -18
- package/dist/schema/axis/lifecycle/Generators.d.ts.map +0 -1
- package/dist/schema/axis/lifecycle/Generators.js +0 -38
- package/dist/schema/axis/lifecycle/Generators.js.map +0 -1
- package/dist/schema/axis/lifecycle/Lifecycle.d.ts.map +0 -1
- package/dist/schema/axis/lifecycle/Lifecycle.js.map +0 -1
- package/dist/schema/axis/lifecycle/LifecycleAxis.d.ts.map +0 -1
- package/dist/schema/axis/lifecycle/LifecycleAxis.js.map +0 -1
- package/dist/schema/axis/lifecycle/apply.d.ts +0 -6
- package/dist/schema/axis/lifecycle/apply.d.ts.map +0 -1
- package/dist/schema/axis/lifecycle/apply.js +0 -34
- package/dist/schema/axis/lifecycle/apply.js.map +0 -1
- package/dist/schema/axis/role/Relation.d.ts.map +0 -1
- package/dist/schema/axis/role/Relation.js.map +0 -1
- package/dist/schema/axis/role/Role.d.ts.map +0 -1
- package/dist/schema/axis/role/Role.js +0 -40
- package/dist/schema/axis/role/Role.js.map +0 -1
- package/dist/schema/axis/role/RoleAxis.d.ts.map +0 -1
- package/dist/schema/axis/role/RoleAxis.js.map +0 -1
- package/dist/schema/axis/shape/Formats.d.ts +0 -8
- package/dist/schema/axis/shape/Formats.d.ts.map +0 -1
- package/dist/schema/axis/shape/Formats.js +0 -10
- package/dist/schema/axis/shape/Formats.js.map +0 -1
- package/dist/schema/axis/shape/Shape.d.ts.map +0 -1
- package/dist/schema/axis/shape/Shape.js.map +0 -1
- package/dist/schema/fields/Field.d.ts.map +0 -1
- package/dist/schema/fields/Field.js +0 -52
- package/dist/schema/fields/Field.js.map +0 -1
- package/dist/schema/fields/FieldSet.d.ts +0 -28
- package/dist/schema/fields/FieldSet.d.ts.map +0 -1
- package/dist/schema/fields/FieldSet.js +0 -55
- package/dist/schema/fields/FieldSet.js.map +0 -1
- package/dist/schema/fields/constraint/FieldGroup.d.ts +0 -21
- package/dist/schema/fields/constraint/FieldGroup.d.ts.map +0 -1
- package/dist/schema/fields/constraint/FieldGroup.js +0 -65
- package/dist/schema/fields/constraint/FieldGroup.js.map +0 -1
- package/dist/schema/fields/constraint/Unique.d.ts +0 -4
- package/dist/schema/fields/constraint/Unique.d.ts.map +0 -1
- package/dist/schema/fields/constraint/Unique.js +0 -4
- package/dist/schema/fields/constraint/Unique.js.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
- package/src/judge/options.ts +0 -3
- package/src/projection/SchemaOrCard.ts +0 -18
- package/src/projection/card/EntityTypeSource.ts +0 -90
- package/src/projection/card/FacadeTypeSource.ts +0 -55
- package/src/schema/SchemaDefinition.ts +0 -150
- package/src/schema/SchemaDerivation.ts +0 -65
- package/src/schema/axis/boundary/Boundaries.ts +0 -44
- package/src/schema/axis/lifecycle/Generators.ts +0 -46
- package/src/schema/axis/lifecycle/apply.ts +0 -39
- package/src/schema/axis/role/Role.ts +0 -56
- package/src/schema/axis/shape/Formats.ts +0 -22
- package/src/schema/fields/FieldSet.ts +0 -63
- package/src/schema/fields/constraint/FieldGroup.ts +0 -84
- package/src/schema/fields/constraint/Unique.ts +0 -3
- /package/dist/{schema/SchemaView.js → SchemaView.js} +0 -0
- /package/dist/{schema/axis → axis}/Axis.js +0 -0
- /package/dist/{schema/axis → axis}/Meta.d.ts +0 -0
- /package/dist/{schema/axis → axis}/Meta.js +0 -0
- /package/dist/{schema/axis → axis}/boundary/BoundaryAxis.d.ts +0 -0
- /package/dist/{schema/axis → axis}/lifecycle/Lifecycle.d.ts +0 -0
- /package/dist/{schema/axis → axis}/lifecycle/Lifecycle.js +0 -0
- /package/dist/{schema/axis → axis}/lifecycle/LifecycleAxis.d.ts +0 -0
- /package/dist/{utils.d.ts → lib/utils.d.ts} +0 -0
- /package/dist/{utils.js → lib/utils.js} +0 -0
- /package/src/{schema/axis → axis}/Meta.ts +0 -0
- /package/src/{schema/axis → axis}/lifecycle/Lifecycle.ts +0 -0
- /package/src/{utils.ts → lib/utils.ts} +0 -0
- /package/src/{judge/result.ts → validation.ts} +0 -0
|
@@ -1,31 +1,41 @@
|
|
|
1
|
-
import { EXTENSION_SLOTS } from '../
|
|
1
|
+
import { EXTENSION_SLOTS } from '../axis/Axis.js';
|
|
2
2
|
import { dequal } from 'dequal';
|
|
3
3
|
const MEMBER_SLOTS = [...EXTENSION_SLOTS, 'meta'];
|
|
4
|
+
/**
|
|
5
|
+
* So a word is one statement about a field, not a rebuilt field.
|
|
6
|
+
* FR : pour qu'un mot soit une affirmation sur un champ, pas un champ reconstruit.
|
|
7
|
+
* `vocabulary('indexed', () => ({ role: { index: true } }))`
|
|
8
|
+
*/
|
|
4
9
|
export function vocabulary(name, states) {
|
|
5
10
|
return (field) => field.with(merge(name, field, states(field)));
|
|
6
11
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
/**
|
|
13
|
+
* So two words that state the same member differently refuse instead of one winning.
|
|
14
|
+
* FR : pour que deux mots contredisant un même membre refusent, plutôt qu'un l'emporte.
|
|
15
|
+
* `readOnly(writeOnly(text()))` → both close a different side, so both apply
|
|
16
|
+
*/
|
|
17
|
+
function merge(name, field, given) {
|
|
18
|
+
const merged = {};
|
|
19
|
+
if ('shape' in given)
|
|
20
|
+
merged.shape = given.shape;
|
|
11
21
|
for (const slot of MEMBER_SLOTS) {
|
|
12
|
-
const members =
|
|
22
|
+
const members = given[slot];
|
|
13
23
|
if (members === undefined)
|
|
14
24
|
continue;
|
|
15
|
-
const
|
|
16
|
-
if (typeof members !== 'object' || members === null || typeof
|
|
17
|
-
|
|
25
|
+
const already = field[slot];
|
|
26
|
+
if (typeof members !== 'object' || members === null || typeof already !== 'object') {
|
|
27
|
+
merged[slot] = members;
|
|
18
28
|
continue;
|
|
19
29
|
}
|
|
20
30
|
for (const [member, value] of Object.entries(members)) {
|
|
21
|
-
const previous =
|
|
31
|
+
const previous = already?.[member];
|
|
22
32
|
if (previous === undefined || dequal(previous, value))
|
|
23
33
|
continue;
|
|
24
34
|
throw new Error(`vocabulary: \`${name}\` states ${slot}.${member} = ${JSON.stringify(value)}, but the ` +
|
|
25
35
|
`field already states ${JSON.stringify(previous)}. Apply one or the other, not both.`);
|
|
26
36
|
}
|
|
27
|
-
|
|
37
|
+
merged[slot] = { ...already, ...members };
|
|
28
38
|
}
|
|
29
|
-
return
|
|
39
|
+
return merged;
|
|
30
40
|
}
|
|
31
41
|
//# sourceMappingURL=vocabulary.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vocabulary.js","sourceRoot":"","sources":["../../src/vocabulary/vocabulary.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"vocabulary.js","sourceRoot":"","sources":["../../src/vocabulary/vocabulary.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,YAAY,GAAG,CAAC,GAAG,eAAe,EAAE,MAAM,CAAU,CAAC;AAE3D;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,IAAY,EACZ,MAAwC;IAExC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAID;;;;GAIG;AACH,SAAS,KAAK,CAAC,IAAY,EAAE,KAAY,EAAE,KAAqB;IAC9D,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,IAAI,OAAO,IAAI,KAAK;QAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAEjD,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,OAAO,KAAK,SAAS;YAAE,SAAS;QACpC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAwC,CAAC;QACnE,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YACnF,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;YACvB,SAAS;QACX,CAAC;QACD,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACtD,MAAM,QAAQ,GAAG,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;YACnC,IAAI,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC;gBAAE,SAAS;YAChE,MAAM,IAAI,KAAK,CACb,iBAAiB,IAAI,aAAa,IAAI,IAAI,MAAM,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,YAAY;gBACrF,wBAAwB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,qCAAqC,CACxF,CAAC;QACJ,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;IAC5C,CAAC;IACD,OAAO,MAAwB,CAAC;AAClC,CAAC"}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
import { Field } from '../
|
|
1
|
+
import { Field } from '../field/Field.js';
|
|
2
|
+
/**
|
|
3
|
+
* So a secret leaves no response, the dual of `readOnly` on the same axis.
|
|
4
|
+
* FR : pour qu'un secret ne reparte dans aucune réponse, dual de `readOnly`.
|
|
5
|
+
* `writeOnly(text())` → `boundary.out` is `'closed'`
|
|
6
|
+
*/
|
|
2
7
|
export declare const writeOnly: <T>(field: Field<T>) => Field<T>;
|
|
3
8
|
//# sourceMappingURL=writeOnly.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeOnly.d.ts","sourceRoot":"","sources":["../../src/vocabulary/writeOnly.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"writeOnly.d.ts","sourceRoot":"","sources":["../../src/vocabulary/writeOnly.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C;;;;GAIG;AACH,eAAO,MAAM,SAAS,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAKtD,CAAC"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { vocabulary } from './vocabulary.js';
|
|
2
|
-
import { Boundary } from '../
|
|
2
|
+
import { Boundary } from '../axis/boundary/Boundary.js';
|
|
3
|
+
/**
|
|
4
|
+
* So a secret leaves no response, the dual of `readOnly` on the same axis.
|
|
5
|
+
* FR : pour qu'un secret ne reparte dans aucune réponse, dual de `readOnly`.
|
|
6
|
+
* `writeOnly(text())` → `boundary.out` is `'closed'`
|
|
7
|
+
*/
|
|
3
8
|
export const writeOnly = vocabulary('writeOnly', (field) => ({
|
|
4
9
|
boundary: Boundary.declared(field).with({ out: 'closed' }),
|
|
5
10
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeOnly.js","sourceRoot":"","sources":["../../src/vocabulary/writeOnly.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"writeOnly.js","sourceRoot":"","sources":["../../src/vocabulary/writeOnly.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAGxD;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAqC,UAAU,CACnE,WAAW,EACX,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACV,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;CAC3D,CAAC,CACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,29 +1,27 @@
|
|
|
1
1
|
import { Boundary } from './axis/boundary/Boundary.js';
|
|
2
|
-
import { type Fields } from './
|
|
2
|
+
import { type Fields } from './field/Field.js';
|
|
3
3
|
import {
|
|
4
4
|
type CompositeUnique,
|
|
5
5
|
type EntityDeclarations,
|
|
6
6
|
type PreviousNames,
|
|
7
|
-
} from '
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { Unique } from './fields/constraint/Unique.js';
|
|
11
|
-
import { RowJudge } from '../judge/RowJudge.js';
|
|
7
|
+
} from './entity/EntityDeclarations.js';
|
|
8
|
+
import { type EntityAdapters } from './entity/EntityAdapters.js';
|
|
9
|
+
import { InputValidator } from './validator/InputValidator.js';
|
|
12
10
|
import { SchemaDerivation } from './SchemaDerivation.js';
|
|
13
|
-
import { SchemaDefinition } from './SchemaDefinition.js';
|
|
14
|
-
import { type ValidateOptions } from '
|
|
15
|
-
import type { StandardSchemaV1 } from '
|
|
16
|
-
import type {
|
|
11
|
+
import { SchemaDefinition, type SchemaConstraints } from './SchemaDefinition.js';
|
|
12
|
+
import { type ValidateOptions } from './validator/InputValidator.js';
|
|
13
|
+
import type { StandardSchemaV1 } from './projection/standard.js';
|
|
14
|
+
import type { PartialValues, Values, SchemaView } from './SchemaView.js';
|
|
17
15
|
|
|
18
16
|
export const ANONYMOUS_SCHEMA_NAME = 'Schema';
|
|
19
17
|
|
|
20
18
|
export interface SchemaConstructor<TFields extends Fields> extends SchemaView<TFields> {
|
|
21
|
-
new (data:
|
|
22
|
-
readonly '~standard': StandardSchemaV1.Props<Record<string, unknown>,
|
|
19
|
+
new (data: PartialValues<TFields>): Values<TFields>;
|
|
20
|
+
readonly '~standard': StandardSchemaV1.Props<Record<string, unknown>, Values<TFields>>;
|
|
23
21
|
readonly derivation?: SchemaDerivation;
|
|
24
22
|
readonly previous?: PreviousNames<TFields>;
|
|
25
23
|
readonly anchored?: boolean;
|
|
26
|
-
from(data: Record<string, unknown>):
|
|
24
|
+
from(data: Record<string, unknown>): Values<TFields>;
|
|
27
25
|
pick<K extends string & keyof TFields>(
|
|
28
26
|
...keys: K[]
|
|
29
27
|
): SchemaConstructor<Pick<TFields, K>>;
|
|
@@ -42,13 +40,14 @@ export interface SchemaConstructor<TFields extends Fields> extends SchemaView<TF
|
|
|
42
40
|
|
|
43
41
|
export class Schema {
|
|
44
42
|
/** The one place a schema holds what it is. The readings below are its projections. */
|
|
45
|
-
static definition: SchemaDefinition = SchemaDefinition.
|
|
43
|
+
static definition: SchemaDefinition = SchemaDefinition.of({ fields: {} });
|
|
46
44
|
|
|
47
45
|
static get fields(): Fields {
|
|
48
46
|
return this.definition.fields;
|
|
49
47
|
}
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
/** An entry survives every derivation that kept its field: `Post.pick('body').adapters`. */
|
|
49
|
+
static get adapters(): EntityAdapters<Fields> {
|
|
50
|
+
return this.definition.adapterSet.adapters;
|
|
52
51
|
}
|
|
53
52
|
static get opts(): ValidateOptions {
|
|
54
53
|
return this.definition.opts;
|
|
@@ -59,6 +58,7 @@ export class Schema {
|
|
|
59
58
|
static get previous(): PreviousNames<Fields> | undefined {
|
|
60
59
|
return this.definition.previous;
|
|
61
60
|
}
|
|
61
|
+
/** An anchor holds rows of its own; a derivation borrows them. */
|
|
62
62
|
static get anchored(): boolean {
|
|
63
63
|
return this.definition.anchored;
|
|
64
64
|
}
|
|
@@ -82,30 +82,29 @@ export class Schema {
|
|
|
82
82
|
return this.adapters;
|
|
83
83
|
}
|
|
84
84
|
static getUnique(): CompositeUnique<Fields> | undefined {
|
|
85
|
-
|
|
86
|
-
return groups.length ? groups.map((group) => [...group.members]) : undefined;
|
|
85
|
+
return this.definition.constraints.unique;
|
|
87
86
|
}
|
|
88
87
|
static getOpts() {
|
|
89
88
|
return this.opts;
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
static validate(input: unknown) {
|
|
93
|
-
return
|
|
92
|
+
return InputValidator.of(this.fields, this.opts).validate(input);
|
|
94
93
|
}
|
|
95
94
|
|
|
96
95
|
static from(data: Record<string, unknown>) {
|
|
97
|
-
const
|
|
96
|
+
const row: Record<string, unknown> = {};
|
|
98
97
|
for (const [key, field] of Object.entries(this.fields)) {
|
|
99
98
|
if (!(key in data)) continue;
|
|
100
99
|
const value = data[key];
|
|
101
100
|
if (value === null || value === undefined) {
|
|
102
|
-
|
|
101
|
+
row[key] = value;
|
|
103
102
|
continue;
|
|
104
103
|
}
|
|
105
104
|
const decoded = Boundary.of(field).decode(value);
|
|
106
|
-
|
|
105
|
+
row[key] = 'error' in decoded ? value : decoded.value;
|
|
107
106
|
}
|
|
108
|
-
return
|
|
107
|
+
return row;
|
|
109
108
|
}
|
|
110
109
|
|
|
111
110
|
static get ['~standard'](): StandardSchemaV1.Props<Record<string, unknown>> {
|
|
@@ -114,10 +113,10 @@ export class Schema {
|
|
|
114
113
|
version: 1,
|
|
115
114
|
vendor: 'fougere',
|
|
116
115
|
validate(value: unknown) {
|
|
117
|
-
const
|
|
118
|
-
if (
|
|
116
|
+
const verdict = InputValidator.of(fields, opts).validate(value);
|
|
117
|
+
if (verdict.success) return { value: verdict.data };
|
|
119
118
|
return {
|
|
120
|
-
issues:
|
|
119
|
+
issues: verdict.errors.map((e) => ({
|
|
121
120
|
message: e.message,
|
|
122
121
|
path: e.path && e.path !== '.' ? [{ key: e.path }] : undefined,
|
|
123
122
|
})),
|
|
@@ -127,50 +126,21 @@ export class Schema {
|
|
|
127
126
|
}
|
|
128
127
|
|
|
129
128
|
static pick(...keys: string[]) {
|
|
130
|
-
|
|
131
|
-
const picked: Fields = {};
|
|
132
|
-
for (const key of keys) if (this.fields[key]) picked[key] = this.fields[key];
|
|
133
|
-
return this.derive(picked, (k) => (keys.includes(k) ? k : undefined));
|
|
129
|
+
return Schema.subclass(this.definition.pick(keys, this));
|
|
134
130
|
}
|
|
135
131
|
|
|
136
132
|
static omit(...keys: string[]) {
|
|
137
|
-
|
|
138
|
-
const kept: Fields = {};
|
|
139
|
-
for (const [key, field] of Object.entries(this.fields))
|
|
140
|
-
if (!keys.includes(key)) kept[key] = field;
|
|
141
|
-
return this.derive(kept, (k) => (keys.includes(k) ? undefined : k));
|
|
133
|
+
return Schema.subclass(this.definition.omit(keys, this));
|
|
142
134
|
}
|
|
143
135
|
|
|
144
136
|
static rename(mapping: Record<string, string>) {
|
|
145
|
-
|
|
146
|
-
const renamed: Fields = {};
|
|
147
|
-
for (const [key, field] of Object.entries(this.fields))
|
|
148
|
-
renamed[mapping[key] ?? key] = field;
|
|
149
|
-
return this.derive(renamed, (k) => mapping[k] ?? k);
|
|
137
|
+
return Schema.subclass(this.definition.rename(mapping, this));
|
|
150
138
|
}
|
|
151
139
|
|
|
152
|
-
/**
|
|
153
|
-
* Everything a schema states about ITSELF, available wherever a schema is. `entity(fields, …)`
|
|
154
|
-
* is this same gesture at the declaration site; the fields do not move, so neither does the type.
|
|
155
|
-
*/
|
|
156
140
|
static declares(declarations: EntityDeclarations<Fields>) {
|
|
157
|
-
const addressed = EntityAdapterSet.of(declarations.adapters)?.fieldNames ?? [];
|
|
158
|
-
assertKnownKeys(
|
|
159
|
-
'declares',
|
|
160
|
-
[...addressed, ...Object.keys(declarations.previous ?? {})],
|
|
161
|
-
this.fields,
|
|
162
|
-
);
|
|
163
|
-
|
|
164
141
|
return Schema.subclass(this.definition.declaring(declarations));
|
|
165
142
|
}
|
|
166
143
|
|
|
167
|
-
/**
|
|
168
|
-
* This schema holds rows of its own — every entity is one, and a derivation says so.
|
|
169
|
-
*
|
|
170
|
-
* An anchor is where a walk STOPS: `derivation.anchor` climbs to the nearest one, and what
|
|
171
|
-
* is cut from an anchor roots on it. Two anchors are two entities that happen to share a
|
|
172
|
-
* shape, never a hierarchy — nothing here subtypes, so a relation between them is `ref()`.
|
|
173
|
-
*/
|
|
174
144
|
static anchor() {
|
|
175
145
|
return Schema.subclass(this.definition.anchoring());
|
|
176
146
|
}
|
|
@@ -202,20 +172,20 @@ export class Schema {
|
|
|
202
172
|
) as unknown as SchemaConstructor<Merged<T>>;
|
|
203
173
|
}
|
|
204
174
|
|
|
205
|
-
static of<TFields extends Fields>(
|
|
175
|
+
static of<TFields extends Fields>(declaration: {
|
|
206
176
|
fields: TFields;
|
|
207
177
|
derivation?: SchemaDerivation;
|
|
208
178
|
adapters?: EntityAdapters<TFields>;
|
|
209
179
|
opts?: ValidateOptions;
|
|
210
180
|
previous?: PreviousNames<TFields>;
|
|
211
181
|
anchored?: boolean;
|
|
182
|
+
constraints?: SchemaConstraints;
|
|
212
183
|
}): SchemaConstructor<TFields> {
|
|
213
184
|
return Schema.subclass(
|
|
214
|
-
SchemaDefinition.
|
|
185
|
+
SchemaDefinition.of(declaration),
|
|
215
186
|
) as unknown as SchemaConstructor<TFields>;
|
|
216
187
|
}
|
|
217
188
|
|
|
218
|
-
/** The class a definition becomes. The one place a Schema subclass is born. */
|
|
219
189
|
private static subclass(definition: SchemaDefinition): SchemaConstructor<Fields> {
|
|
220
190
|
class Derived extends Schema {}
|
|
221
191
|
Derived.definition = definition;
|
|
@@ -225,19 +195,6 @@ export class Schema {
|
|
|
225
195
|
});
|
|
226
196
|
return Derived as unknown as SchemaConstructor<Fields>;
|
|
227
197
|
}
|
|
228
|
-
|
|
229
|
-
private static derive(fields: Fields, survives: (key: string) => string | undefined) {
|
|
230
|
-
return Schema.subclass(this.definition.cut(fields, survives, this));
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function assertKnownKeys(operation: string, keys: string[], fields: Fields): void {
|
|
235
|
-
const strangers = keys.filter((key) => !(key in fields));
|
|
236
|
-
if (strangers.length === 0) return;
|
|
237
|
-
throw new Error(
|
|
238
|
-
`${operation}(): unknown field ${strangers.map((s) => `\`${s}\``).join(', ')}. ` +
|
|
239
|
-
`This schema carries ${Object.keys(fields).join(', ')}.`,
|
|
240
|
-
);
|
|
241
198
|
}
|
|
242
199
|
|
|
243
200
|
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { type Fields } from './field/Field.js';
|
|
2
|
+
import { FieldSet, deduplicated } from './field/FieldSet.js';
|
|
3
|
+
import {
|
|
4
|
+
type CompositeUnique,
|
|
5
|
+
type EntityDeclarations,
|
|
6
|
+
type PreviousNames,
|
|
7
|
+
} from './entity/EntityDeclarations.js';
|
|
8
|
+
import { type EntityAdapters } from './entity/EntityAdapters.js';
|
|
9
|
+
import { EntityAdapterSet } from './entity/EntityAdapterSet.js';
|
|
10
|
+
import { SchemaDerivation } from './SchemaDerivation.js';
|
|
11
|
+
import { type ValidateOptions } from './validator/InputValidator.js';
|
|
12
|
+
import type { SchemaView } from './SchemaView.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* What a schema constrains beyond any single field.
|
|
16
|
+
*
|
|
17
|
+
* `unique` is the one member today. It sits under an owner rather than beside `fields`
|
|
18
|
+
* and `opts` because the next rule spanning two fields — a check, an exclusion — is a
|
|
19
|
+
* member here, not an eighth positional argument in a list that has already lost one.
|
|
20
|
+
*/
|
|
21
|
+
export interface SchemaConstraints<TFields extends Fields = Fields> {
|
|
22
|
+
readonly unique?: CompositeUnique<TFields>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Everything a definition is made of, every member required.
|
|
27
|
+
*
|
|
28
|
+
* A transformation states what it keeps AND what it clears — `previous: undefined` and
|
|
29
|
+
* `anchored: false` are the two a derivation decides, and positionally they were an
|
|
30
|
+
* `undefined` and a `false` a reader had to count arguments to name.
|
|
31
|
+
*/
|
|
32
|
+
interface SchemaState {
|
|
33
|
+
fields: Fields;
|
|
34
|
+
adapterSet: EntityAdapterSet;
|
|
35
|
+
opts: ValidateOptions;
|
|
36
|
+
previous: PreviousNames<Fields> | undefined;
|
|
37
|
+
derivation: SchemaDerivation | undefined;
|
|
38
|
+
anchored: boolean;
|
|
39
|
+
constraints: SchemaConstraints;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** The keys a derivation keeps, in the order it keeps them, under the names they take. */
|
|
43
|
+
type Renaming = ReadonlyMap<string, string>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Everything a schema IS, apart from being a class whose instances are rows.
|
|
47
|
+
*
|
|
48
|
+
* The members used to be that many statics assigned side by side, and every derivation
|
|
49
|
+
* re-threaded them by hand — which is how one of them came to be dropped from a list
|
|
50
|
+
* without anyone noticing. A transformation here returns a COMPLETE definition or it does
|
|
51
|
+
* not compile, so no gesture can mix the fields of one with the options of another.
|
|
52
|
+
*
|
|
53
|
+
* Internal: it is not exported from the package and never appears on `SchemaConstructor`.
|
|
54
|
+
* A user derives with `Order.pick(…)`, never `Order.definition.pick(…)`.
|
|
55
|
+
*/
|
|
56
|
+
export class SchemaDefinition {
|
|
57
|
+
readonly fields: Fields;
|
|
58
|
+
readonly adapterSet: EntityAdapterSet;
|
|
59
|
+
readonly opts: ValidateOptions;
|
|
60
|
+
readonly previous: PreviousNames<Fields> | undefined;
|
|
61
|
+
readonly derivation: SchemaDerivation | undefined;
|
|
62
|
+
readonly anchored: boolean;
|
|
63
|
+
readonly constraints: SchemaConstraints;
|
|
64
|
+
|
|
65
|
+
private constructor(state: SchemaState) {
|
|
66
|
+
this.fields = state.fields;
|
|
67
|
+
this.adapterSet = state.adapterSet;
|
|
68
|
+
this.opts = state.opts;
|
|
69
|
+
this.previous = state.previous;
|
|
70
|
+
this.derivation = state.derivation;
|
|
71
|
+
this.anchored = state.anchored;
|
|
72
|
+
this.constraints = state.constraints;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Built complete or not at all — no static assigned on the side. */
|
|
76
|
+
static of(declaration: {
|
|
77
|
+
fields: Fields;
|
|
78
|
+
adapters?: EntityAdapters<Fields>;
|
|
79
|
+
opts?: ValidateOptions;
|
|
80
|
+
previous?: PreviousNames<Fields>;
|
|
81
|
+
derivation?: SchemaDerivation;
|
|
82
|
+
anchored?: boolean;
|
|
83
|
+
constraints?: SchemaConstraints;
|
|
84
|
+
}): SchemaDefinition {
|
|
85
|
+
return new SchemaDefinition({
|
|
86
|
+
fields: declaration.fields,
|
|
87
|
+
adapterSet: EntityAdapterSet.of(declaration.adapters),
|
|
88
|
+
opts: declaration.opts ?? {},
|
|
89
|
+
previous: declaration.previous,
|
|
90
|
+
derivation: declaration.derivation,
|
|
91
|
+
anchored: declaration.anchored ?? false,
|
|
92
|
+
constraints: declaration.constraints ?? {},
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
declaring(declarations: EntityDeclarations<Fields>): SchemaDefinition {
|
|
97
|
+
const addressed = EntityAdapterSet.of(declarations.adapters).fieldNames;
|
|
98
|
+
this.assertKnown('declares', [
|
|
99
|
+
...addressed,
|
|
100
|
+
...Object.keys(declarations.previous ?? {}),
|
|
101
|
+
]);
|
|
102
|
+
const declared = FieldSet.declaring(this.fields, declarations.unique);
|
|
103
|
+
|
|
104
|
+
return new SchemaDefinition({
|
|
105
|
+
fields: declared.fields,
|
|
106
|
+
adapterSet: EntityAdapterSet.merged([
|
|
107
|
+
this.adapterSet,
|
|
108
|
+
EntityAdapterSet.of(declarations.adapters),
|
|
109
|
+
]),
|
|
110
|
+
opts: this.opts,
|
|
111
|
+
previous: declarations.previous ?? this.previous,
|
|
112
|
+
derivation: this.derivation,
|
|
113
|
+
anchored: this.anchored,
|
|
114
|
+
constraints:
|
|
115
|
+
declarations.unique === undefined ? this.constraints : { unique: declared.unique },
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
anchoring(): SchemaDefinition {
|
|
120
|
+
return new SchemaDefinition({
|
|
121
|
+
fields: this.fields,
|
|
122
|
+
adapterSet: this.adapterSet,
|
|
123
|
+
opts: this.opts,
|
|
124
|
+
previous: this.previous,
|
|
125
|
+
derivation: this.derivation,
|
|
126
|
+
anchored: true,
|
|
127
|
+
constraints: this.constraints,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
pick(keys: readonly string[], root: SchemaView): SchemaDefinition {
|
|
132
|
+
this.assertKnown('pick', keys);
|
|
133
|
+
|
|
134
|
+
return this.renaming(new Map(keys.map((key) => [key, key])), root);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
omit(keys: readonly string[], root: SchemaView): SchemaDefinition {
|
|
138
|
+
this.assertKnown('omit', keys);
|
|
139
|
+
const kept = Object.keys(this.fields).filter((key) => !keys.includes(key));
|
|
140
|
+
|
|
141
|
+
return this.renaming(new Map(kept.map((key) => [key, key])), root);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
rename(mapping: Record<string, string>, root: SchemaView): SchemaDefinition {
|
|
145
|
+
this.assertKnown('rename', Object.keys(mapping));
|
|
146
|
+
const here = Object.keys(this.fields).map((key) => [key, mapping[key] ?? key] as const);
|
|
147
|
+
|
|
148
|
+
return this.renaming(new Map(here), root);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* `pick`, `omit` and `rename` are one gesture, and the renaming IS that gesture: the
|
|
153
|
+
* fields it keeps and everything else addressed by field name are both read from it.
|
|
154
|
+
*/
|
|
155
|
+
private renaming(kept: Renaming, root: SchemaView): SchemaDefinition {
|
|
156
|
+
const fields: Fields = {};
|
|
157
|
+
for (const [from, to] of kept) {
|
|
158
|
+
const field = this.fields[from];
|
|
159
|
+
if (field) fields[to] = field;
|
|
160
|
+
}
|
|
161
|
+
const nameOf = (key: string) => kept.get(key);
|
|
162
|
+
|
|
163
|
+
return new SchemaDefinition({
|
|
164
|
+
fields,
|
|
165
|
+
adapterSet: this.adapterSet.rename(nameOf),
|
|
166
|
+
opts: this.opts,
|
|
167
|
+
previous: undefined,
|
|
168
|
+
derivation: this.origin(root).rename(nameOf),
|
|
169
|
+
anchored: false,
|
|
170
|
+
constraints: this.constraintsRenamed(nameOf),
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** One member gone and the group is gone: it constrained a pair that no longer exists. */
|
|
175
|
+
private constraintsRenamed(
|
|
176
|
+
transform: (key: string) => string | undefined,
|
|
177
|
+
): SchemaConstraints {
|
|
178
|
+
if (!this.constraints.unique) return this.constraints;
|
|
179
|
+
const kept: string[][] = [];
|
|
180
|
+
for (const group of this.constraints.unique) {
|
|
181
|
+
const renamed = group.map(transform);
|
|
182
|
+
if (renamed.every((key): key is string => key !== undefined)) kept.push(renamed);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return { unique: deduplicated(kept) as CompositeUnique<Fields> | undefined };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
patched(root: SchemaView): SchemaDefinition {
|
|
189
|
+
return new SchemaDefinition({
|
|
190
|
+
fields: { ...this.fields },
|
|
191
|
+
adapterSet: this.adapterSet,
|
|
192
|
+
opts: { ...this.opts, patch: true },
|
|
193
|
+
previous: undefined,
|
|
194
|
+
derivation: this.origin(root),
|
|
195
|
+
anchored: false,
|
|
196
|
+
constraints: this.constraints,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** An added field does not pretend to come from the root, which never declared it. */
|
|
201
|
+
extended(extra: Fields, root: SchemaView): SchemaDefinition {
|
|
202
|
+
return new SchemaDefinition({
|
|
203
|
+
fields: { ...this.fields, ...extra },
|
|
204
|
+
adapterSet: this.adapterSet,
|
|
205
|
+
opts: this.opts,
|
|
206
|
+
previous: undefined,
|
|
207
|
+
derivation: this.origin(root),
|
|
208
|
+
anchored: false,
|
|
209
|
+
constraints: this.constraints,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Several schemas fold into one, which has no single origin to point at. */
|
|
214
|
+
static merged(views: readonly SchemaView[]): SchemaDefinition {
|
|
215
|
+
const fields: Fields = {};
|
|
216
|
+
let opts: ValidateOptions = {};
|
|
217
|
+
const groups: (readonly string[])[] = [];
|
|
218
|
+
for (const view of views) {
|
|
219
|
+
Object.assign(fields, view.getFields());
|
|
220
|
+
opts = { ...opts, ...view.getOpts() };
|
|
221
|
+
groups.push(...(view.getUnique() ?? []));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return new SchemaDefinition({
|
|
225
|
+
fields,
|
|
226
|
+
adapterSet: EntityAdapterSet.merged(
|
|
227
|
+
views.map((view) => EntityAdapterSet.of(view.getAdapters())),
|
|
228
|
+
),
|
|
229
|
+
opts,
|
|
230
|
+
previous: undefined,
|
|
231
|
+
derivation: undefined,
|
|
232
|
+
anchored: false,
|
|
233
|
+
constraints: { unique: deduplicated(groups) as CompositeUnique<Fields> | undefined },
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* So a gesture naming a field that does not exist says so, and lists what there is.
|
|
239
|
+
* FR : pour qu'un geste nommant un champ inexistant le dise, et énumère ce qui existe.
|
|
240
|
+
* `pick('titel')` → `pick(): unknown field \`titel\`. This schema carries id, title, body.`
|
|
241
|
+
*/
|
|
242
|
+
private assertKnown(operation: string, keys: readonly string[]): void {
|
|
243
|
+
const strangers = keys.filter((key) => !(key in this.fields));
|
|
244
|
+
if (strangers.length === 0) return;
|
|
245
|
+
|
|
246
|
+
throw new Error(
|
|
247
|
+
`${operation}(): unknown field ${strangers.map((s) => `\`${s}\``).join(', ')}. ` +
|
|
248
|
+
`This schema carries ${Object.keys(this.fields).join(', ')}.`,
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
private origin(root: SchemaView): SchemaDerivation {
|
|
253
|
+
if (!this.anchored && this.derivation) return this.derivation;
|
|
254
|
+
|
|
255
|
+
return SchemaDerivation.first(root, this.fields);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type Fields } from './field/Field.js';
|
|
2
|
+
import type { SchemaView } from './SchemaView.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The origin is the ROOT: `Post.pick(a, b).omit(b)` answers `Post`, never the intermediate.
|
|
6
|
+
*/
|
|
7
|
+
export class SchemaDerivation {
|
|
8
|
+
private constructor(
|
|
9
|
+
readonly source: SchemaView,
|
|
10
|
+
readonly nameOf: Readonly<Record<string, string | undefined>>,
|
|
11
|
+
) {}
|
|
12
|
+
|
|
13
|
+
static first(source: SchemaView, fields: Fields): SchemaDerivation {
|
|
14
|
+
return new SchemaDerivation(
|
|
15
|
+
source,
|
|
16
|
+
Object.fromEntries(Object.keys(fields).map((key) => [key, key])),
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
rename(transform: (key: string) => string | undefined): SchemaDerivation {
|
|
21
|
+
return new SchemaDerivation(
|
|
22
|
+
this.source,
|
|
23
|
+
Object.fromEntries(
|
|
24
|
+
Object.entries(this.nameOf).map(([origin, here]) => [
|
|
25
|
+
origin,
|
|
26
|
+
here === undefined ? undefined : transform(here),
|
|
27
|
+
]),
|
|
28
|
+
),
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get sourceName(): string {
|
|
33
|
+
return this.source.name;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Whose rows this one borrows, however many cuts away: `Post.pick('t').omit('t')` → `Post`. */
|
|
37
|
+
get anchor(): SchemaView {
|
|
38
|
+
const source = this.source;
|
|
39
|
+
|
|
40
|
+
return source.anchored !== undefined || !source.derivation
|
|
41
|
+
? source
|
|
42
|
+
: source.derivation.anchor;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type { Field, Fields } from './
|
|
2
|
-
import type { CompositeUnique, PreviousNames } from '
|
|
3
|
-
import type { EntityAdapters } from '
|
|
4
|
-
import type { ValidationResult } from '
|
|
5
|
-
import type { ValidateOptions } from '
|
|
1
|
+
import type { Field, Fields } from './field/Field.js';
|
|
2
|
+
import type { CompositeUnique, PreviousNames } from './entity/EntityDeclarations.js';
|
|
3
|
+
import type { EntityAdapters } from './entity/EntityAdapters.js';
|
|
4
|
+
import type { ValidationResult } from './validation.js';
|
|
5
|
+
import type { ValidateOptions } from './validator/InputValidator.js';
|
|
6
6
|
import type { SchemaDerivation } from './SchemaDerivation.js';
|
|
7
7
|
|
|
8
|
-
export type
|
|
8
|
+
export type Values<TFields extends Fields> = {
|
|
9
9
|
[K in keyof TFields]: TFields[K] extends Field<infer T> ? T : never;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
export type
|
|
12
|
+
export type PartialValues<TFields extends Fields> = Partial<Values<TFields>>;
|
|
13
13
|
|
|
14
14
|
export interface SchemaView<TFields extends Fields = Fields> {
|
|
15
15
|
readonly name: string;
|
|
@@ -20,8 +20,8 @@ export interface SchemaView<TFields extends Fields = Fields> {
|
|
|
20
20
|
/** Does it hold rows of its own? False on a derivation means an answer. */
|
|
21
21
|
readonly anchored?: boolean;
|
|
22
22
|
getFields(): TFields;
|
|
23
|
-
getAdapters(): EntityAdapters<TFields
|
|
23
|
+
getAdapters(): EntityAdapters<TFields>;
|
|
24
24
|
getUnique(): CompositeUnique<TFields> | undefined;
|
|
25
25
|
getOpts(): ValidateOptions;
|
|
26
|
-
validate(input: unknown): ValidationResult<
|
|
26
|
+
validate(input: unknown): ValidationResult<Values<TFields>>;
|
|
27
27
|
}
|