@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,90 +0,0 @@
|
|
|
1
|
-
import { upperFirst } from '../../utils.js';
|
|
2
|
-
import type { FieldDescriptor, SchemaDescriptor } from './Descriptor.js';
|
|
3
|
-
|
|
4
|
-
function typeOf(field: FieldDescriptor): string {
|
|
5
|
-
const types = Array.isArray(field.type) ? field.type : field.type ? [field.type] : [];
|
|
6
|
-
const nullable = types.includes('null');
|
|
7
|
-
const base = types.find((t) => t !== 'null');
|
|
8
|
-
const inner = baseTypeOf(base, field);
|
|
9
|
-
return nullable ? `${inner} | null` : inner;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function baseTypeOf(base: string | undefined, field: FieldDescriptor): string {
|
|
13
|
-
if (field.enum?.length) {
|
|
14
|
-
return field.enum.map((v) => (v === null ? 'null' : JSON.stringify(v))).join(' | ');
|
|
15
|
-
}
|
|
16
|
-
switch (base) {
|
|
17
|
-
case 'string':
|
|
18
|
-
return field.format === 'date-time' ? 'Date' : 'string';
|
|
19
|
-
case 'number':
|
|
20
|
-
case 'integer':
|
|
21
|
-
return 'number';
|
|
22
|
-
case 'boolean':
|
|
23
|
-
return 'boolean';
|
|
24
|
-
case 'array':
|
|
25
|
-
return field.items ? `${typeOf(field.items)}[]` : 'string[]';
|
|
26
|
-
case 'object':
|
|
27
|
-
return field.properties ? objectTypeOf(field.properties, field.required ?? []) : 'Record<string, unknown>';
|
|
28
|
-
default:
|
|
29
|
-
return 'unknown';
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function objectTypeOf(properties: Record<string, FieldDescriptor>, required: readonly string[]): string {
|
|
34
|
-
const members = Object.entries(properties).map(([name, field]) => {
|
|
35
|
-
const optional = required.includes(name) ? '' : '?';
|
|
36
|
-
return `${propertyKey(name)}${optional}: ${typeOf(field)}`;
|
|
37
|
-
});
|
|
38
|
-
return `{ ${members.join('; ')} }`;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function propertyKey(name: string): string {
|
|
42
|
-
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function docCommentOf(text: string | undefined, indent: string): string {
|
|
46
|
-
if (!text) return '';
|
|
47
|
-
return `${indent}/** ${text.replace(/\*\//g, '*\\/')} */\n`;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface EntityTypeSourceOptions {
|
|
51
|
-
name?: string;
|
|
52
|
-
exported?: boolean;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function shapeTypeOf(descriptor: SchemaDescriptor, indent = ''): string {
|
|
56
|
-
const entries = Object.entries(descriptor.properties ?? {});
|
|
57
|
-
if (entries.length === 0) return '{}';
|
|
58
|
-
|
|
59
|
-
const lines = entries.map(([key, field]) => {
|
|
60
|
-
const doc = docCommentOf(field.description, `${indent} `);
|
|
61
|
-
return `${doc}${indent} ${propertyKey(key)}: ${typeOf(field)};`;
|
|
62
|
-
});
|
|
63
|
-
return `{\n${lines.join('\n')}\n${indent}}`;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export class EntityTypeSource {
|
|
67
|
-
private constructor(private readonly descriptor: SchemaDescriptor) {}
|
|
68
|
-
|
|
69
|
-
static of(descriptor: SchemaDescriptor): EntityTypeSource {
|
|
70
|
-
return new EntityTypeSource(descriptor);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
render(options: EntityTypeSourceOptions = {}): string {
|
|
74
|
-
const name = identifierOf(options.name ?? upperFirst(this.descriptor.title ?? 'Schema'));
|
|
75
|
-
const exported = options.exported === false ? '' : 'export ';
|
|
76
|
-
const card = JSON.stringify(this.descriptor, null, 2)
|
|
77
|
-
.split('\n')
|
|
78
|
-
.map((line, i) => (i === 0 ? line : ` ${line}`))
|
|
79
|
-
.join('\n');
|
|
80
|
-
|
|
81
|
-
return `${exported}class ${name} extends Card.fromDescriptor<${shapeTypeOf(this.descriptor)}>(${card}).toSchema() {}`;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function identifierOf(name: string): string {
|
|
86
|
-
if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name)) {
|
|
87
|
-
throw new Error(`'${name}' is not a TypeScript identifier — it cannot name a generated declaration`);
|
|
88
|
-
}
|
|
89
|
-
return name;
|
|
90
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type { SchemaDescriptor } from './Descriptor.js';
|
|
2
|
-
|
|
3
|
-
export interface FacadeTypeSourceOptions {
|
|
4
|
-
name?: string;
|
|
5
|
-
exported?: boolean;
|
|
6
|
-
rowType?: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface OpDescriptor {
|
|
10
|
-
name: string;
|
|
11
|
-
description?: string;
|
|
12
|
-
output?: SchemaDescriptor;
|
|
13
|
-
cardinality?: 'one' | 'maybe' | 'many' | 'page' | 'none';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function propertyKey(name: string): string {
|
|
17
|
-
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function docCommentOf(text: string | undefined, indent: string): string {
|
|
21
|
-
if (!text) return '';
|
|
22
|
-
return `${indent}/** ${text.replace(/\*\//g, '*\\/')} */\n`;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function returnTypeOf(op: OpDescriptor, rowType: string): string {
|
|
26
|
-
switch (op.cardinality) {
|
|
27
|
-
case 'many': return `${rowType}[]`;
|
|
28
|
-
case 'page': return `${rowType}[] & { total?: number; endCursor?: string; hasMore?: boolean }`;
|
|
29
|
-
case 'maybe': return `${rowType} | undefined`;
|
|
30
|
-
case 'one': return rowType;
|
|
31
|
-
case 'none': return 'unknown';
|
|
32
|
-
default: return 'unknown';
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export class FacadeTypeSource {
|
|
37
|
-
private constructor(private readonly operations: readonly OpDescriptor[]) {}
|
|
38
|
-
|
|
39
|
-
static of(operations: readonly OpDescriptor[]): FacadeTypeSource {
|
|
40
|
-
return new FacadeTypeSource(operations);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
render(options: FacadeTypeSourceOptions = {}): string {
|
|
44
|
-
const name = options.name ?? 'Facade';
|
|
45
|
-
const exported = options.exported === false ? '' : 'export ';
|
|
46
|
-
const rowType = options.rowType ?? 'unknown';
|
|
47
|
-
const members = this.operations.map((operation) => {
|
|
48
|
-
const doc = docCommentOf(operation.description, ' ');
|
|
49
|
-
return `${doc} ${propertyKey(operation.name)}(invocation?: Invocation): Promise<${returnTypeOf(operation, rowType)}>;`;
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
if (members.length === 0) return `${exported}interface ${name} {}`;
|
|
53
|
-
return `${exported}interface ${name} {\n${members.join('\n')}\n}`;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import { type Fields } from './fields/Field.js';
|
|
2
|
-
import { FieldSet } from './fields/FieldSet.js';
|
|
3
|
-
import {
|
|
4
|
-
type EntityDeclarations,
|
|
5
|
-
type PreviousNames,
|
|
6
|
-
} from '../entity/EntityDeclarations.js';
|
|
7
|
-
import { EntityAdapterSet, type EntityAdapters } from '../entity/EntityAdapters.js';
|
|
8
|
-
import { SchemaDerivation } from './SchemaDerivation.js';
|
|
9
|
-
import { type ValidateOptions } from '../judge/options.js';
|
|
10
|
-
import type { SchemaView } from './SchemaView.js';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Everything a schema IS, apart from being a class whose instances are rows.
|
|
14
|
-
*
|
|
15
|
-
* The members used to be that many statics assigned side by side, and every derivation
|
|
16
|
-
* re-threaded them by hand — which is how one of them came to be dropped from a list
|
|
17
|
-
* without anyone noticing. A transformation here returns a COMPLETE definition or it does
|
|
18
|
-
* not compile, so no gesture can mix the fields of one with the options of another.
|
|
19
|
-
*
|
|
20
|
-
* Internal: it is not exported from the package and never appears on `SchemaConstructor`.
|
|
21
|
-
* A user derives with `Order.pick(…)`, never `Order.definition.pick(…)`.
|
|
22
|
-
*/
|
|
23
|
-
export class SchemaDefinition {
|
|
24
|
-
private constructor(
|
|
25
|
-
readonly fields: Fields,
|
|
26
|
-
readonly adapters: EntityAdapters<Fields> | undefined,
|
|
27
|
-
readonly opts: ValidateOptions,
|
|
28
|
-
readonly previous: PreviousNames<Fields> | undefined,
|
|
29
|
-
readonly derivation: SchemaDerivation | undefined,
|
|
30
|
-
readonly anchored: boolean,
|
|
31
|
-
) {}
|
|
32
|
-
|
|
33
|
-
static stated(said: {
|
|
34
|
-
fields: Fields;
|
|
35
|
-
adapters?: EntityAdapters<Fields>;
|
|
36
|
-
opts?: ValidateOptions;
|
|
37
|
-
previous?: PreviousNames<Fields>;
|
|
38
|
-
derivation?: SchemaDerivation;
|
|
39
|
-
anchored?: boolean;
|
|
40
|
-
}): SchemaDefinition {
|
|
41
|
-
return new SchemaDefinition(
|
|
42
|
-
said.fields,
|
|
43
|
-
EntityAdapterSet.of(said.adapters)?.stated,
|
|
44
|
-
said.opts ?? {},
|
|
45
|
-
said.previous,
|
|
46
|
-
said.derivation,
|
|
47
|
-
said.anchored ?? false,
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* What a schema states about ITSELF, folded into what it already states — one adapter
|
|
53
|
-
* entry per field wins the later spelling, and a unique group is stamped on its members.
|
|
54
|
-
*/
|
|
55
|
-
declaring(said: EntityDeclarations<Fields>): SchemaDefinition {
|
|
56
|
-
return new SchemaDefinition(
|
|
57
|
-
FieldSet.declared(this.fields, said.unique),
|
|
58
|
-
EntityAdapterSet.merged([this.adapters, said.adapters])?.stated,
|
|
59
|
-
this.opts,
|
|
60
|
-
said.previous ?? this.previous,
|
|
61
|
-
this.derivation,
|
|
62
|
-
this.anchored,
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* The same schema, holding rows of its own. A derivation is an answer until it says this.
|
|
68
|
-
*/
|
|
69
|
-
anchoring(): SchemaDefinition {
|
|
70
|
-
return new SchemaDefinition(
|
|
71
|
-
this.fields,
|
|
72
|
-
this.adapters,
|
|
73
|
-
this.opts,
|
|
74
|
-
this.previous,
|
|
75
|
-
this.derivation,
|
|
76
|
-
true,
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* `pick`, `omit` and `rename` are one gesture: the fields that remain, and what became
|
|
82
|
-
* of each name. What each adapter was handed follows the same correspondence, and so does the origin.
|
|
83
|
-
*/
|
|
84
|
-
cut(
|
|
85
|
-
fields: Fields,
|
|
86
|
-
survives: (key: string) => string | undefined,
|
|
87
|
-
root: SchemaView,
|
|
88
|
-
): SchemaDefinition {
|
|
89
|
-
const renamed: Fields = {};
|
|
90
|
-
for (const [key, field] of Object.entries(fields))
|
|
91
|
-
renamed[key] = field.rename(survives);
|
|
92
|
-
return new SchemaDefinition(
|
|
93
|
-
renamed,
|
|
94
|
-
EntityAdapterSet.of(this.adapters)?.cut(survives)?.stated,
|
|
95
|
-
this.opts,
|
|
96
|
-
undefined,
|
|
97
|
-
this.origin(root).compose(survives),
|
|
98
|
-
false,
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/** The same fields, judged as an update. */
|
|
103
|
-
patched(root: SchemaView): SchemaDefinition {
|
|
104
|
-
return new SchemaDefinition(
|
|
105
|
-
{ ...this.fields },
|
|
106
|
-
this.adapters,
|
|
107
|
-
{ ...this.opts, patch: true },
|
|
108
|
-
undefined,
|
|
109
|
-
this.origin(root),
|
|
110
|
-
false,
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/** The added fields have no origin, so the derivation is unchanged: it speaks of the root. */
|
|
115
|
-
extended(extra: Fields, root: SchemaView): SchemaDefinition {
|
|
116
|
-
return new SchemaDefinition(
|
|
117
|
-
{ ...this.fields, ...extra },
|
|
118
|
-
this.adapters,
|
|
119
|
-
this.opts,
|
|
120
|
-
undefined,
|
|
121
|
-
this.origin(root),
|
|
122
|
-
false,
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/** Several views folded into one definition, which therefore has no single origin. */
|
|
127
|
-
static merged(views: readonly SchemaView[]): SchemaDefinition {
|
|
128
|
-
const fields: Fields = {};
|
|
129
|
-
let opts: ValidateOptions = {};
|
|
130
|
-
for (const view of views) {
|
|
131
|
-
Object.assign(fields, view.getFields());
|
|
132
|
-
opts = { ...opts, ...view.getOpts() };
|
|
133
|
-
}
|
|
134
|
-
const adapters = EntityAdapterSet.merged(
|
|
135
|
-
views.map((view) => view.getAdapters()),
|
|
136
|
-
)?.stated;
|
|
137
|
-
|
|
138
|
-
return new SchemaDefinition(fields, adapters, opts, undefined, undefined, false);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* The origin this definition already carries, or the one `root` becomes. A schema that
|
|
143
|
-
* is an ANCHOR holds rows of its own, so what is cut from it roots on IT and not on its own origin.
|
|
144
|
-
*/
|
|
145
|
-
private origin(root: SchemaView): SchemaDerivation {
|
|
146
|
-
if (!this.anchored && this.derivation) return this.derivation;
|
|
147
|
-
|
|
148
|
-
return SchemaDerivation.first(root, this.fields);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
@@ -1,65 +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(
|
|
22
|
-
source,
|
|
23
|
-
Object.fromEntries(Object.keys(fields).map((key) => [key, key])),
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/** The same origin, seen through one more cut. */
|
|
28
|
-
compose(survives: (key: string) => string | undefined): SchemaDerivation {
|
|
29
|
-
return new SchemaDerivation(
|
|
30
|
-
this.source,
|
|
31
|
-
Object.fromEntries(
|
|
32
|
-
Object.entries(this.survived).map(([origin, here]) => [
|
|
33
|
-
origin,
|
|
34
|
-
here === undefined ? undefined : survives(here),
|
|
35
|
-
]),
|
|
36
|
-
),
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
get sourceName(): string {
|
|
41
|
-
return this.source.name;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* The anchor whose rows this describes — the nearest one going up, and a schema with no
|
|
46
|
-
* origin of its own is one. An answer borrows its rows; this says from whom. Whether
|
|
47
|
-
* those rows carry a key is a separate question: an anchor may have none.
|
|
48
|
-
*/
|
|
49
|
-
get anchor(): SchemaView {
|
|
50
|
-
const source = this.source;
|
|
51
|
-
|
|
52
|
-
return source.anchored !== undefined || !source.derivation
|
|
53
|
-
? source
|
|
54
|
-
: source.derivation.anchor;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* What the ROOT calls `key`, translated to the name it carries here — `undefined` when a
|
|
59
|
-
* cut dropped it. A reader that needs something the root declared about a field asks the
|
|
60
|
-
* root and comes back through this; it does not keep a copy of the answer.
|
|
61
|
-
*/
|
|
62
|
-
hereFor(key: string): string | undefined {
|
|
63
|
-
return this.survived[key];
|
|
64
|
-
}
|
|
65
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { BoundaryRules } from './Boundary.js';
|
|
2
|
-
|
|
3
|
-
export type Decoder = (value: unknown) => { value: unknown } | { error: string };
|
|
4
|
-
export type Encoder = (value: unknown) => unknown;
|
|
5
|
-
|
|
6
|
-
export class Boundaries {
|
|
7
|
-
private static readonly decoders = new Map<string, Decoder>();
|
|
8
|
-
private static readonly encoders = new Map<string, Encoder>();
|
|
9
|
-
private static readonly aliases = new Map<string, BoundaryRules>();
|
|
10
|
-
|
|
11
|
-
static registerDecoder(name: string, fn: Decoder): void { this.decoders.set(name, fn); }
|
|
12
|
-
static registerEncoder(name: string, fn: Encoder): void { this.encoders.set(name, fn); }
|
|
13
|
-
|
|
14
|
-
static registerAlias(name: string, boundary: BoundaryRules): void { this.aliases.set(name, boundary); }
|
|
15
|
-
|
|
16
|
-
static alias(name: string): BoundaryRules | undefined { return this.aliases.get(name); }
|
|
17
|
-
|
|
18
|
-
static decoder(name: string): Decoder { return this.named(this.decoders, name, 'decoder'); }
|
|
19
|
-
static encoder(name: string): Encoder { return this.named(this.encoders, name, 'encoder'); }
|
|
20
|
-
|
|
21
|
-
private static named<T>(registry: Map<string, T>, name: string, kind: string): T {
|
|
22
|
-
const fn = registry.get(name);
|
|
23
|
-
if (!fn) {
|
|
24
|
-
throw new Error(
|
|
25
|
-
`Unknown boundary ${kind}: '${name}'. Register it with ` +
|
|
26
|
-
`Boundaries.register${kind[0].toUpperCase()}${kind.slice(1)}('${name}', …).`,
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
return fn;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
Boundaries.registerDecoder('isoDate', (value) => {
|
|
34
|
-
if (value instanceof Date) return { value };
|
|
35
|
-
if (typeof value === 'string') {
|
|
36
|
-
const d = new Date(value);
|
|
37
|
-
return Number.isNaN(d.getTime()) ? { error: 'Invalid date' } : { value: d };
|
|
38
|
-
}
|
|
39
|
-
return { error: 'Expected a date' };
|
|
40
|
-
});
|
|
41
|
-
Boundaries.registerEncoder('isoDate', (value) =>
|
|
42
|
-
value instanceof Date ? value.toISOString() : value,
|
|
43
|
-
);
|
|
44
|
-
Boundaries.registerAlias('isoDate', { in: { decode: 'isoDate' }, out: { encode: 'isoDate' } });
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { createId } from '@paralleldrive/cuid2';
|
|
2
|
-
|
|
3
|
-
export type GeneratorRef = 'cuid2' | 'uuid' | 'nanoid' | (string & {});
|
|
4
|
-
|
|
5
|
-
const NANOID_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
|
6
|
-
|
|
7
|
-
function nanoid(): string {
|
|
8
|
-
const bytes = new Uint8Array(21);
|
|
9
|
-
globalThis.crypto.getRandomValues(bytes);
|
|
10
|
-
return Array.from(bytes, (byte) => NANOID_ALPHABET[byte & 63]).join('');
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Who answers a `generate` by name — one registry per process, like `Formats` and
|
|
15
|
-
* `Boundaries`.
|
|
16
|
-
*
|
|
17
|
-
* The three builtins are REGISTERED rather than switched on, which is what brings the
|
|
18
|
-
* refusal back inside: a registry whose unknown name is refused by a `default:` branch in
|
|
19
|
-
* its caller does not know what it holds, so it cannot say so.
|
|
20
|
-
*/
|
|
21
|
-
export class Generators {
|
|
22
|
-
private static readonly registry = new Map<string, () => string>([
|
|
23
|
-
['cuid2', createId],
|
|
24
|
-
['uuid', () => globalThis.crypto.randomUUID()],
|
|
25
|
-
['nanoid', nanoid],
|
|
26
|
-
]);
|
|
27
|
-
|
|
28
|
-
static register(name: string, fn: () => string): void {
|
|
29
|
-
this.registry.set(name, fn);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** The generator this name stands for, refused by name when nothing does. */
|
|
33
|
-
static resolve(ref: GeneratorRef): () => string {
|
|
34
|
-
const found = this.registry.get(ref);
|
|
35
|
-
if (found) return found;
|
|
36
|
-
throw new Error(
|
|
37
|
-
`Unknown generator '${ref}' — register it with Generators.register('${ref}', fn). ` +
|
|
38
|
-
`This process answers ${[...this.registry.keys()].join(', ')}.`,
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** Whether a name is answered, for a caller that must not throw to find out. */
|
|
43
|
-
static answers(ref: GeneratorRef): boolean {
|
|
44
|
-
return this.registry.has(ref);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Lifecycle } from './Lifecycle.js';
|
|
2
|
-
import { Generators } from './Generators.js';
|
|
3
|
-
import { Clock } from './Clock.js';
|
|
4
|
-
import { type Field, type Fields } from '../../fields/Field.js';
|
|
5
|
-
|
|
6
|
-
type Row = Record<string, unknown>;
|
|
7
|
-
|
|
8
|
-
export function applyCreate(fields: Fields, input: Row): Row {
|
|
9
|
-
const out: Row = { ...input };
|
|
10
|
-
const instant = Clock.now();
|
|
11
|
-
|
|
12
|
-
for (const [name, field] of Object.entries(fields) as [string, Field][]) {
|
|
13
|
-
if (name in out) continue;
|
|
14
|
-
const rule = Lifecycle.of(field);
|
|
15
|
-
|
|
16
|
-
if (rule.create === 'now') out[name] = new Date(instant);
|
|
17
|
-
else if (rule.literal) out[name] = freshValue(rule.literal.value);
|
|
18
|
-
else if (rule.generator) out[name] = Generators.resolve(rule.generator)();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return out;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function freshValue(value: unknown): unknown {
|
|
25
|
-
if (value === null || typeof value !== 'object') return value;
|
|
26
|
-
return structuredClone(value);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function applyUpdate(fields: Fields, patch: Row): Row {
|
|
30
|
-
const out: Row = { ...patch };
|
|
31
|
-
const instant = Clock.now();
|
|
32
|
-
|
|
33
|
-
for (const [name, field] of Object.entries(fields) as [string, Field][]) {
|
|
34
|
-
if (Lifecycle.of(field).stampedOnUpdate && !(name in out))
|
|
35
|
-
out[name] = new Date(instant);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return out;
|
|
39
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { FieldGroup } from "../../fields/constraint/FieldGroup.js";
|
|
2
|
-
import { Unique } from "../../fields/constraint/Unique.js";
|
|
3
|
-
import type { EntityConstructor, Relation } from "./Relation.js";
|
|
4
|
-
|
|
5
|
-
export interface RoleRules {
|
|
6
|
-
primary?: boolean;
|
|
7
|
-
index?: boolean;
|
|
8
|
-
relation?: Relation;
|
|
9
|
-
rules?: readonly FieldGroup[];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export class Role implements RoleRules {
|
|
13
|
-
readonly primary?: boolean;
|
|
14
|
-
readonly index?: boolean;
|
|
15
|
-
readonly relation?: Relation;
|
|
16
|
-
readonly rules?: readonly FieldGroup[];
|
|
17
|
-
|
|
18
|
-
private constructor(declared: RoleRules = {}) {
|
|
19
|
-
this.primary = declared.primary;
|
|
20
|
-
this.index = declared.index;
|
|
21
|
-
this.relation = declared.relation;
|
|
22
|
-
this.rules = declared.rules;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
static of(field: { role?: RoleRules }): Role {
|
|
26
|
-
return new Role(field.role);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/** A group written with no members means "this field": only the key it is declared under resolves it. */
|
|
30
|
-
static resolvedOn(role: RoleRules | undefined, key?: string): RoleRules | undefined {
|
|
31
|
-
let rules = FieldGroup.normalize(role?.rules, (members) => new Unique(members));
|
|
32
|
-
if (rules && key !== undefined && rules.some((group) => group.isSelf))
|
|
33
|
-
rules = rules.map((group) => group.resolvedOn(key));
|
|
34
|
-
return rules === role?.rules ? role : { ...role, rules };
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
get isPrimary(): boolean {
|
|
38
|
-
return this.primary === true;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
get isIndexed(): boolean {
|
|
42
|
-
return this.index === true;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
get isCollection(): boolean {
|
|
46
|
-
return this.relation?.kind === "many";
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
get isReference(): boolean {
|
|
50
|
-
return this.relation?.kind === "one";
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
get target(): EntityConstructor | undefined {
|
|
54
|
-
return this.relation?.to();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export type StringFormat =
|
|
2
|
-
| 'date-time'
|
|
3
|
-
| 'date'
|
|
4
|
-
| 'time'
|
|
5
|
-
| 'email'
|
|
6
|
-
| 'uuid'
|
|
7
|
-
| 'uri'
|
|
8
|
-
| (string & {});
|
|
9
|
-
|
|
10
|
-
export type FormatPredicate = (value: string) => boolean;
|
|
11
|
-
|
|
12
|
-
export class Formats {
|
|
13
|
-
private static readonly registry = new Map<string, FormatPredicate>();
|
|
14
|
-
|
|
15
|
-
static register(name: string, predicate: FormatPredicate): void {
|
|
16
|
-
this.registry.set(name, predicate);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
static resolve(name: string): FormatPredicate | undefined {
|
|
20
|
-
return this.registry.get(name);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { Role } from '../axis/role/Role.js';
|
|
2
|
-
import { FieldGroup } from './constraint/FieldGroup.js';
|
|
3
|
-
import { Unique } from './constraint/Unique.js';
|
|
4
|
-
import type { CompositeUnique } from '../../entity/EntityDeclarations.js';
|
|
5
|
-
import { Field, type FieldName, type Fields } from './Field.js';
|
|
6
|
-
|
|
7
|
-
export class FieldSet<TFields extends Fields = Fields> {
|
|
8
|
-
private constructor(private readonly fields: TFields) {}
|
|
9
|
-
|
|
10
|
-
static of<TFields extends Fields>(fields: TFields): FieldSet<TFields> {
|
|
11
|
-
return new FieldSet(fields);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Every entry through the field door, then the groups declared over several of them.
|
|
16
|
-
* A group written here names its members; one written on a field named itself, and the
|
|
17
|
-
* key it sat under resolved it.
|
|
18
|
-
*/
|
|
19
|
-
static declared<TFields extends Fields>(
|
|
20
|
-
declared: TFields,
|
|
21
|
-
unique?: CompositeUnique<TFields>,
|
|
22
|
-
): TFields {
|
|
23
|
-
let fields: Fields = {};
|
|
24
|
-
for (const [key, field] of Object.entries(declared))
|
|
25
|
-
fields[key] = new Field(field, key);
|
|
26
|
-
for (const group of unique ?? []) fields = new Unique(group).onto(fields);
|
|
27
|
-
return fields as TFields;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* The name of the field that carries `primary`, or `undefined` when none does.
|
|
32
|
-
*
|
|
33
|
-
* `Role.of(field).isPrimary` answers about ONE field; this answers about a shape, which
|
|
34
|
-
* is the question every reader actually had. It was the same three lines spelled five
|
|
35
|
-
* times — a mirror's key, a form's row identity, GraphQL's node id, the DDL's primary
|
|
36
|
-
* key and the storage's `findById` column — so a shape with two primaries meant whichever
|
|
37
|
-
* one that loop happened to see first, five times over.
|
|
38
|
-
*
|
|
39
|
-
* The absence is answered and not defaulted: `'id'` is a fine fallback for a form and a
|
|
40
|
-
* lie for a DDL, so the caller decides.
|
|
41
|
-
*/
|
|
42
|
-
get primary(): FieldName<TFields> | undefined {
|
|
43
|
-
const primaries = Object.entries(this.fields)
|
|
44
|
-
.filter(([, field]) => Role.of(field).isPrimary)
|
|
45
|
-
.map(([name]) => name);
|
|
46
|
-
|
|
47
|
-
if (primaries.length > 1) {
|
|
48
|
-
throw new Error(
|
|
49
|
-
`FieldSet.primary: ${primaries.map((name) => JSON.stringify(name)).join(', ')} all declare ` +
|
|
50
|
-
'`primary`; a field set can have only one primary field.',
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return primaries[0] as FieldName<TFields> | undefined;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
get uniqueGroups(): CompositeUnique<TFields> | undefined {
|
|
58
|
-
const groups = FieldGroup.groupsOf(this.fields, Unique);
|
|
59
|
-
return groups.length
|
|
60
|
-
? (groups.map((group) => [...group.members]) as unknown as CompositeUnique<TFields>)
|
|
61
|
-
: undefined;
|
|
62
|
-
}
|
|
63
|
-
}
|