@versionzero/schema 1.0.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/LICENSE +177 -0
- package/README.md +246 -0
- package/package.json +84 -0
- package/src/compilation/handler-compilation.js +28 -0
- package/src/compilation/metadata-compilation.js +35 -0
- package/src/compilation/schema-compilation.js +142 -0
- package/src/compilation/selection-compilation.js +84 -0
- package/src/compilation/union-compilation.js +510 -0
- package/src/compilation/values-compilation.js +35 -0
- package/src/compiled-schema.js +1709 -0
- package/src/constants.js +1 -0
- package/src/core-library/index.js +32 -0
- package/src/core-library/processors/aggregation-operators.js +75 -0
- package/src/core-library/processors/alpha-constraint.js +20 -0
- package/src/core-library/processors/alphanum-constraint.js +20 -0
- package/src/core-library/processors/array-operator.js +51 -0
- package/src/core-library/processors/assert-constraint.js +75 -0
- package/src/core-library/processors/base64-constraint.js +26 -0
- package/src/core-library/processors/camel-case-operator.js +24 -0
- package/src/core-library/processors/capitalize-operator.js +16 -0
- package/src/core-library/processors/cardnum-constraint.js +193 -0
- package/src/core-library/processors/ceil-operator.js +44 -0
- package/src/core-library/processors/collapse-operator.js +29 -0
- package/src/core-library/processors/compact-operator.js +34 -0
- package/src/core-library/processors/compile-operator.js +65 -0
- package/src/core-library/processors/concat-operator.js +51 -0
- package/src/core-library/processors/conditional-operators.js +301 -0
- package/src/core-library/processors/constant-case-operator.js +16 -0
- package/src/core-library/processors/data-size-operator.js +86 -0
- package/src/core-library/processors/date-object-operator.js +54 -0
- package/src/core-library/processors/date-operator.js +67 -0
- package/src/core-library/processors/date-range-constraint.js +76 -0
- package/src/core-library/processors/defined-constraint.js +30 -0
- package/src/core-library/processors/each-operator.js +57 -0
- package/src/core-library/processors/email-constraint.js +112 -0
- package/src/core-library/processors/entries-operator.js +25 -0
- package/src/core-library/processors/eq-constraint.js +37 -0
- package/src/core-library/processors/filter-operator.js +74 -0
- package/src/core-library/processors/find-schema-operator.js +45 -0
- package/src/core-library/processors/flatten-operator.js +40 -0
- package/src/core-library/processors/floor-operator.js +47 -0
- package/src/core-library/processors/get-operator.js +44 -0
- package/src/core-library/processors/group-by-operator.js +84 -0
- package/src/core-library/processors/has-prefix-constraint.js +37 -0
- package/src/core-library/processors/has-suffix-constraint.js +35 -0
- package/src/core-library/processors/hex-constraint.js +20 -0
- package/src/core-library/processors/hostname-constraint.js +22 -0
- package/src/core-library/processors/http-url-constraint.js +27 -0
- package/src/core-library/processors/in-constraint.js +66 -0
- package/src/core-library/processors/index-by-operator.js +98 -0
- package/src/core-library/processors/index.js +131 -0
- package/src/core-library/processors/input-operator.js +23 -0
- package/src/core-library/processors/instanceof-constraint.js +38 -0
- package/src/core-library/processors/integer-constraint.js +22 -0
- package/src/core-library/processors/invoke-operator.js +33 -0
- package/src/core-library/processors/ipv4-constraint.js +188 -0
- package/src/core-library/processors/ipv6-constraint.js +205 -0
- package/src/core-library/processors/is-array-constraint.js +21 -0
- package/src/core-library/processors/is-date-constraint.js +22 -0
- package/src/core-library/processors/is-number-constraint.js +21 -0
- package/src/core-library/processors/is-object-constraint.js +21 -0
- package/src/core-library/processors/is-string-constraint.js +21 -0
- package/src/core-library/processors/join-operator.js +41 -0
- package/src/core-library/processors/json-constraint.js +22 -0
- package/src/core-library/processors/json-decode-operator.js +25 -0
- package/src/core-library/processors/json-encode-operator.js +35 -0
- package/src/core-library/processors/kebab-case-operator.js +23 -0
- package/src/core-library/processors/keys-operator.js +20 -0
- package/src/core-library/processors/length-constraint.js +85 -0
- package/src/core-library/processors/lookup-operator.js +84 -0
- package/src/core-library/processors/lowercase-operator.js +14 -0
- package/src/core-library/processors/map-operator.js +84 -0
- package/src/core-library/processors/match-operator.js +64 -0
- package/src/core-library/processors/matches-constraint.js +54 -0
- package/src/core-library/processors/math-operators.js +151 -0
- package/src/core-library/processors/merge-deep-operator.js +61 -0
- package/src/core-library/processors/merge-operator.js +54 -0
- package/src/core-library/processors/metadata-operator.js +100 -0
- package/src/core-library/processors/negative-constraint.js +23 -0
- package/src/core-library/processors/never-constraint.js +69 -0
- package/src/core-library/processors/non-empty-constraint.js +59 -0
- package/src/core-library/processors/not-constraint.js +71 -0
- package/src/core-library/processors/number-operator.js +24 -0
- package/src/core-library/processors/numeric-constraint.js +22 -0
- package/src/core-library/processors/object-operator.js +38 -0
- package/src/core-library/processors/omit-operator.js +57 -0
- package/src/core-library/processors/parallel-operator.js +64 -0
- package/src/core-library/processors/pascal-case-operator.js +16 -0
- package/src/core-library/processors/phone-constraint.js +235 -0
- package/src/core-library/processors/pick-operator.js +62 -0
- package/src/core-library/processors/pipeline-operator.js +63 -0
- package/src/core-library/processors/port-constraint.js +22 -0
- package/src/core-library/processors/positive-constraint.js +23 -0
- package/src/core-library/processors/process-operator.js +55 -0
- package/src/core-library/processors/property-operator.js +49 -0
- package/src/core-library/processors/range-constraint.js +72 -0
- package/src/core-library/processors/reference-operator.js +79 -0
- package/src/core-library/processors/require-constraint.js +74 -0
- package/src/core-library/processors/reverse-operator.js +20 -0
- package/src/core-library/processors/round-operator.js +53 -0
- package/src/core-library/processors/schema-handler-operators.js +54 -0
- package/src/core-library/processors/semver-constraint.js +282 -0
- package/src/core-library/processors/sequence-processors.js +406 -0
- package/src/core-library/processors/sort-operator.js +52 -0
- package/src/core-library/processors/split-operator.js +43 -0
- package/src/core-library/processors/string-extra-operators.js +141 -0
- package/src/core-library/processors/string-operator.js +34 -0
- package/src/core-library/processors/target-operator.js +30 -0
- package/src/core-library/processors/template-operator.js +60 -0
- package/src/core-library/processors/title-case-operator.js +17 -0
- package/src/core-library/processors/trim-operator.js +14 -0
- package/src/core-library/processors/truthy-constraint.js +35 -0
- package/src/core-library/processors/type-operator.js +24 -0
- package/src/core-library/processors/unique-operator.js +21 -0
- package/src/core-library/processors/uppercase-operator.js +14 -0
- package/src/core-library/processors/url-constraint.js +31 -0
- package/src/core-library/processors/url-decode-operator.js +50 -0
- package/src/core-library/processors/url-encode-operator.js +44 -0
- package/src/core-library/processors/uuid-constraint.js +31 -0
- package/src/core-library/processors/values-operator.js +20 -0
- package/src/core-library/schemas/any-schema.js +23 -0
- package/src/core-library/schemas/array-schema.js +8 -0
- package/src/core-library/schemas/boolean-schema.js +10 -0
- package/src/core-library/schemas/date-schema.js +12 -0
- package/src/core-library/schemas/function-schema.js +40 -0
- package/src/core-library/schemas/number-schema.js +9 -0
- package/src/core-library/schemas/object-schema.js +10 -0
- package/src/core-library/schemas/root-schema.js +21 -0
- package/src/core-library/schemas/string-schema.js +9 -0
- package/src/core-library-node/index.js +47 -0
- package/src/core-library-node/processors/base64-decode-operator.js +20 -0
- package/src/core-library-node/processors/base64-encode-operator.js +20 -0
- package/src/core-library-node/processors/buffer-operator.js +39 -0
- package/src/core-library-node/processors/directory-constraint.js +35 -0
- package/src/core-library-node/processors/executable-constraint.js +34 -0
- package/src/core-library-node/processors/file-constraint.js +34 -0
- package/src/core-library-node/processors/file-size-constraint.js +94 -0
- package/src/core-library-node/processors/is-buffer-constraint.js +21 -0
- package/src/core-library-node/processors/reachable-constraint.js +28 -0
- package/src/core-library-node/processors/readable-constraint.js +34 -0
- package/src/core-library-node/processors/writable-constraint.js +59 -0
- package/src/core-library-node/schemas/buffer-schema.js +10 -0
- package/src/errors.js +209 -0
- package/src/executor/array-executor.js +78 -0
- package/src/executor/conditional-executor.js +134 -0
- package/src/executor/each-executor.js +68 -0
- package/src/executor/executor.js +123 -0
- package/src/executor/object-executor.js +98 -0
- package/src/executor/parallel-executor.js +43 -0
- package/src/executor/pipeline-executor.js +65 -0
- package/src/executor/sequence-executor.js +206 -0
- package/src/executor/serial-executor.js +24 -0
- package/src/executor/step-executor.js +68 -0
- package/src/helpers/case.js +124 -0
- package/src/helpers/data-size.js +144 -0
- package/src/helpers/debug-sink.js +15 -0
- package/src/helpers/deep.js +280 -0
- package/src/helpers/format.js +121 -0
- package/src/helpers/has-string-properties.js +30 -0
- package/src/helpers/index.js +16 -0
- package/src/helpers/object.js +115 -0
- package/src/helpers/parse-date.js +75 -0
- package/src/helpers/path.js +28 -0
- package/src/helpers/regex.js +18 -0
- package/src/helpers/stringify.js +309 -0
- package/src/helpers/to-data.js +64 -0
- package/src/helpers/truthy.js +55 -0
- package/src/index.js +29 -0
- package/src/schema-compiler.js +531 -0
- package/src/schema-location.js +200 -0
- package/src/schema-resolver.js +546 -0
- package/src/schema.js +1182 -0
- package/src/traversal/executors/check-condition.js +42 -0
- package/src/traversal/executors/check-input.js +27 -0
- package/src/traversal/executors/check-required.js +19 -0
- package/src/traversal/executors/check-schema.js +45 -0
- package/src/traversal/executors/defaults.js +21 -0
- package/src/traversal/executors/enter-existing.js +25 -0
- package/src/traversal/executors/enter-input.js +25 -0
- package/src/traversal/executors/enter.js +37 -0
- package/src/traversal/executors/exit.js +74 -0
- package/src/traversal/executors/finalize.js +64 -0
- package/src/traversal/executors/index.js +42 -0
- package/src/traversal/executors/normalize.js +38 -0
- package/src/traversal/executors/prepare-existing.js +27 -0
- package/src/traversal/executors/prepare-pending.js +54 -0
- package/src/traversal/executors/resolve-union.js +50 -0
- package/src/traversal/executors/serialize.js +48 -0
- package/src/traversal/executors/transform-early.js +51 -0
- package/src/traversal/executors/transform.js +68 -0
- package/src/traversal/executors/traversal-state-executor.js +46 -0
- package/src/traversal/executors/validate.js +63 -0
- package/src/traversal/traversal-context.js +231 -0
- package/src/traversal/traversal-state.js +809 -0
- package/src/types.js +102 -0
- package/src/value-processor/composed-value-processor.js +43 -0
- package/src/value-processor/defined-value-processor.js +72 -0
- package/src/value-processor/function-value-processor.js +68 -0
- package/src/value-processor/parameterized-value-processor.js +45 -0
- package/src/value-processor/parameters-value-processor.js +178 -0
- package/src/value-processor/spec.js +89 -0
- package/src/value-processor/value-processor.js +105 -0
- package/types/compilation/handler-compilation.d.ts +13 -0
- package/types/compilation/metadata-compilation.d.ts +6 -0
- package/types/compilation/schema-compilation.d.ts +32 -0
- package/types/compilation/selection-compilation.d.ts +9 -0
- package/types/compilation/union-compilation.d.ts +42 -0
- package/types/compilation/values-compilation.d.ts +12 -0
- package/types/compiled-schema.d.ts +883 -0
- package/types/constants.d.ts +1 -0
- package/types/core-library/index.d.ts +7 -0
- package/types/core-library/processors/aggregation-operators.d.ts +24 -0
- package/types/core-library/processors/alpha-constraint.d.ts +9 -0
- package/types/core-library/processors/alphanum-constraint.d.ts +9 -0
- package/types/core-library/processors/array-operator.d.ts +12 -0
- package/types/core-library/processors/assert-constraint.d.ts +30 -0
- package/types/core-library/processors/base64-constraint.d.ts +11 -0
- package/types/core-library/processors/camel-case-operator.d.ts +17 -0
- package/types/core-library/processors/capitalize-operator.d.ts +11 -0
- package/types/core-library/processors/cardnum-constraint.d.ts +51 -0
- package/types/core-library/processors/ceil-operator.d.ts +30 -0
- package/types/core-library/processors/collapse-operator.d.ts +24 -0
- package/types/core-library/processors/compact-operator.d.ts +29 -0
- package/types/core-library/processors/compile-operator.d.ts +34 -0
- package/types/core-library/processors/concat-operator.d.ts +23 -0
- package/types/core-library/processors/conditional-operators.d.ts +219 -0
- package/types/core-library/processors/constant-case-operator.d.ts +9 -0
- package/types/core-library/processors/data-size-operator.d.ts +31 -0
- package/types/core-library/processors/date-object-operator.d.ts +16 -0
- package/types/core-library/processors/date-operator.d.ts +21 -0
- package/types/core-library/processors/date-range-constraint.d.ts +26 -0
- package/types/core-library/processors/defined-constraint.d.ts +20 -0
- package/types/core-library/processors/each-operator.d.ts +34 -0
- package/types/core-library/processors/email-constraint.d.ts +54 -0
- package/types/core-library/processors/entries-operator.d.ts +13 -0
- package/types/core-library/processors/eq-constraint.d.ts +20 -0
- package/types/core-library/processors/filter-operator.d.ts +35 -0
- package/types/core-library/processors/find-schema-operator.d.ts +28 -0
- package/types/core-library/processors/flatten-operator.d.ts +26 -0
- package/types/core-library/processors/floor-operator.d.ts +33 -0
- package/types/core-library/processors/get-operator.d.ts +31 -0
- package/types/core-library/processors/group-by-operator.d.ts +36 -0
- package/types/core-library/processors/has-prefix-constraint.d.ts +22 -0
- package/types/core-library/processors/has-suffix-constraint.d.ts +20 -0
- package/types/core-library/processors/hex-constraint.d.ts +9 -0
- package/types/core-library/processors/hostname-constraint.d.ts +11 -0
- package/types/core-library/processors/http-url-constraint.d.ts +9 -0
- package/types/core-library/processors/in-constraint.d.ts +27 -0
- package/types/core-library/processors/index-by-operator.d.ts +26 -0
- package/types/core-library/processors/index.d.ts +8 -0
- package/types/core-library/processors/input-operator.d.ts +20 -0
- package/types/core-library/processors/instanceof-constraint.d.ts +23 -0
- package/types/core-library/processors/integer-constraint.d.ts +9 -0
- package/types/core-library/processors/invoke-operator.d.ts +12 -0
- package/types/core-library/processors/ipv4-constraint.d.ts +37 -0
- package/types/core-library/processors/ipv6-constraint.d.ts +34 -0
- package/types/core-library/processors/is-array-constraint.d.ts +10 -0
- package/types/core-library/processors/is-date-constraint.d.ts +10 -0
- package/types/core-library/processors/is-number-constraint.d.ts +10 -0
- package/types/core-library/processors/is-object-constraint.d.ts +10 -0
- package/types/core-library/processors/is-string-constraint.d.ts +10 -0
- package/types/core-library/processors/join-operator.d.ts +29 -0
- package/types/core-library/processors/json-constraint.d.ts +10 -0
- package/types/core-library/processors/json-decode-operator.d.ts +9 -0
- package/types/core-library/processors/json-encode-operator.d.ts +27 -0
- package/types/core-library/processors/kebab-case-operator.d.ts +16 -0
- package/types/core-library/processors/keys-operator.d.ts +9 -0
- package/types/core-library/processors/length-constraint.d.ts +34 -0
- package/types/core-library/processors/lookup-operator.d.ts +36 -0
- package/types/core-library/processors/lowercase-operator.d.ts +9 -0
- package/types/core-library/processors/map-operator.d.ts +38 -0
- package/types/core-library/processors/match-operator.d.ts +34 -0
- package/types/core-library/processors/matches-constraint.d.ts +29 -0
- package/types/core-library/processors/math-operators.d.ts +91 -0
- package/types/core-library/processors/merge-deep-operator.d.ts +32 -0
- package/types/core-library/processors/merge-operator.d.ts +26 -0
- package/types/core-library/processors/metadata-operator.d.ts +56 -0
- package/types/core-library/processors/negative-constraint.d.ts +13 -0
- package/types/core-library/processors/never-constraint.d.ts +26 -0
- package/types/core-library/processors/non-empty-constraint.d.ts +28 -0
- package/types/core-library/processors/not-constraint.d.ts +28 -0
- package/types/core-library/processors/number-operator.d.ts +9 -0
- package/types/core-library/processors/numeric-constraint.d.ts +10 -0
- package/types/core-library/processors/object-operator.d.ts +10 -0
- package/types/core-library/processors/omit-operator.d.ts +24 -0
- package/types/core-library/processors/parallel-operator.d.ts +41 -0
- package/types/core-library/processors/pascal-case-operator.d.ts +9 -0
- package/types/core-library/processors/phone-constraint.d.ts +65 -0
- package/types/core-library/processors/pick-operator.d.ts +27 -0
- package/types/core-library/processors/pipeline-operator.d.ts +40 -0
- package/types/core-library/processors/port-constraint.d.ts +11 -0
- package/types/core-library/processors/positive-constraint.d.ts +13 -0
- package/types/core-library/processors/process-operator.d.ts +37 -0
- package/types/core-library/processors/property-operator.d.ts +34 -0
- package/types/core-library/processors/range-constraint.d.ts +30 -0
- package/types/core-library/processors/reference-operator.d.ts +38 -0
- package/types/core-library/processors/require-constraint.d.ts +29 -0
- package/types/core-library/processors/reverse-operator.d.ts +9 -0
- package/types/core-library/processors/round-operator.d.ts +34 -0
- package/types/core-library/processors/schema-handler-operators.d.ts +28 -0
- package/types/core-library/processors/semver-constraint.d.ts +43 -0
- package/types/core-library/processors/sequence-processors.d.ts +213 -0
- package/types/core-library/processors/sort-operator.d.ts +31 -0
- package/types/core-library/processors/split-operator.d.ts +33 -0
- package/types/core-library/processors/string-extra-operators.d.ts +83 -0
- package/types/core-library/processors/string-operator.d.ts +10 -0
- package/types/core-library/processors/target-operator.d.ts +27 -0
- package/types/core-library/processors/template-operator.d.ts +31 -0
- package/types/core-library/processors/title-case-operator.d.ts +12 -0
- package/types/core-library/processors/trim-operator.d.ts +9 -0
- package/types/core-library/processors/truthy-constraint.d.ts +23 -0
- package/types/core-library/processors/type-operator.d.ts +11 -0
- package/types/core-library/processors/unique-operator.d.ts +10 -0
- package/types/core-library/processors/uppercase-operator.d.ts +9 -0
- package/types/core-library/processors/url-constraint.d.ts +20 -0
- package/types/core-library/processors/url-decode-operator.d.ts +31 -0
- package/types/core-library/processors/url-encode-operator.d.ts +36 -0
- package/types/core-library/processors/uuid-constraint.d.ts +20 -0
- package/types/core-library/processors/values-operator.d.ts +9 -0
- package/types/core-library/schemas/any-schema.d.ts +2 -0
- package/types/core-library/schemas/array-schema.d.ts +2 -0
- package/types/core-library/schemas/boolean-schema.d.ts +2 -0
- package/types/core-library/schemas/date-schema.d.ts +2 -0
- package/types/core-library/schemas/function-schema.d.ts +2 -0
- package/types/core-library/schemas/number-schema.d.ts +2 -0
- package/types/core-library/schemas/object-schema.d.ts +2 -0
- package/types/core-library/schemas/root-schema.d.ts +2 -0
- package/types/core-library/schemas/string-schema.d.ts +2 -0
- package/types/core-library-node/index.d.ts +12 -0
- package/types/core-library-node/processors/base64-decode-operator.d.ts +9 -0
- package/types/core-library-node/processors/base64-encode-operator.d.ts +9 -0
- package/types/core-library-node/processors/buffer-operator.d.ts +15 -0
- package/types/core-library-node/processors/directory-constraint.d.ts +14 -0
- package/types/core-library-node/processors/executable-constraint.d.ts +17 -0
- package/types/core-library-node/processors/file-constraint.d.ts +13 -0
- package/types/core-library-node/processors/file-size-constraint.d.ts +43 -0
- package/types/core-library-node/processors/is-buffer-constraint.d.ts +10 -0
- package/types/core-library-node/processors/reachable-constraint.d.ts +13 -0
- package/types/core-library-node/processors/readable-constraint.d.ts +17 -0
- package/types/core-library-node/processors/writable-constraint.d.ts +18 -0
- package/types/core-library-node/schemas/buffer-schema.d.ts +2 -0
- package/types/errors.d.ts +58 -0
- package/types/executor/array-executor.d.ts +17 -0
- package/types/executor/conditional-executor.d.ts +45 -0
- package/types/executor/each-executor.d.ts +15 -0
- package/types/executor/executor.d.ts +84 -0
- package/types/executor/object-executor.d.ts +14 -0
- package/types/executor/parallel-executor.d.ts +27 -0
- package/types/executor/pipeline-executor.d.ts +11 -0
- package/types/executor/sequence-executor.d.ts +32 -0
- package/types/executor/serial-executor.d.ts +16 -0
- package/types/executor/step-executor.d.ts +14 -0
- package/types/helpers/case.d.ts +30 -0
- package/types/helpers/data-size.d.ts +25 -0
- package/types/helpers/debug-sink.d.ts +9 -0
- package/types/helpers/deep.d.ts +33 -0
- package/types/helpers/format.d.ts +14 -0
- package/types/helpers/has-string-properties.d.ts +5 -0
- package/types/helpers/index.d.ts +13 -0
- package/types/helpers/object.d.ts +46 -0
- package/types/helpers/parse-date.d.ts +6 -0
- package/types/helpers/path.d.ts +13 -0
- package/types/helpers/regex.d.ts +7 -0
- package/types/helpers/stringify.d.ts +33 -0
- package/types/helpers/to-data.d.ts +13 -0
- package/types/helpers/truthy.d.ts +26 -0
- package/types/index.d.ts +6 -0
- package/types/schema-compiler.d.ts +49 -0
- package/types/schema-location.d.ts +64 -0
- package/types/schema-resolver.d.ts +145 -0
- package/types/schema.d.ts +586 -0
- package/types/traversal/executors/check-condition.d.ts +8 -0
- package/types/traversal/executors/check-input.d.ts +6 -0
- package/types/traversal/executors/check-required.d.ts +6 -0
- package/types/traversal/executors/check-schema.d.ts +7 -0
- package/types/traversal/executors/defaults.d.ts +8 -0
- package/types/traversal/executors/enter-existing.d.ts +6 -0
- package/types/traversal/executors/enter-input.d.ts +8 -0
- package/types/traversal/executors/enter.d.ts +7 -0
- package/types/traversal/executors/exit.d.ts +6 -0
- package/types/traversal/executors/finalize.d.ts +6 -0
- package/types/traversal/executors/index.d.ts +15 -0
- package/types/traversal/executors/normalize.d.ts +7 -0
- package/types/traversal/executors/prepare-existing.d.ts +6 -0
- package/types/traversal/executors/prepare-pending.d.ts +6 -0
- package/types/traversal/executors/resolve-union.d.ts +6 -0
- package/types/traversal/executors/serialize.d.ts +11 -0
- package/types/traversal/executors/transform-early.d.ts +6 -0
- package/types/traversal/executors/transform.d.ts +6 -0
- package/types/traversal/executors/traversal-state-executor.d.ts +19 -0
- package/types/traversal/executors/validate.d.ts +6 -0
- package/types/traversal/traversal-context.d.ts +67 -0
- package/types/traversal/traversal-state.d.ts +97 -0
- package/types/types.d.ts +218 -0
- package/types/value-processor/composed-value-processor.d.ts +17 -0
- package/types/value-processor/defined-value-processor.d.ts +16 -0
- package/types/value-processor/function-value-processor.d.ts +15 -0
- package/types/value-processor/parameterized-value-processor.d.ts +14 -0
- package/types/value-processor/parameters-value-processor.d.ts +28 -0
- package/types/value-processor/spec.d.ts +22 -0
- package/types/value-processor/value-processor.d.ts +92 -0
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
import { CompiledSchema } from '../compiled-schema.js';
|
|
2
|
+
import { SchemaCompiler } from '../schema-compiler.js';
|
|
3
|
+
import { SchemaLocation } from '../schema-location.js';
|
|
4
|
+
import { Schema } from '../schema.js';
|
|
5
|
+
import { SchemaCompilationError, SchemaError, UnionResolutionError } from '../errors.js';
|
|
6
|
+
import { deepEquals } from '../helpers/deep.js';
|
|
7
|
+
import { formatValue } from '../helpers/format.js';
|
|
8
|
+
|
|
9
|
+
/** @import {ValueProcessorFunction} from '../value-processor/value-processor.js' */
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {CompiledSchema} inputSchema
|
|
13
|
+
* @param {any} _
|
|
14
|
+
* @param {SchemaLocation} location
|
|
15
|
+
* @returns {CompiledSchema}
|
|
16
|
+
* @this {SchemaCompiler}
|
|
17
|
+
*/
|
|
18
|
+
export function synthesizeKeyDiscrimination(inputSchema, _, location) {
|
|
19
|
+
if (!inputSchema.isUnion) {
|
|
20
|
+
return inputSchema;
|
|
21
|
+
}
|
|
22
|
+
const unionKeyProperties = Array.from(inputSchema.propertyEntries).filter(e => e[1].isUnionKey);
|
|
23
|
+
|
|
24
|
+
if (unionKeyProperties.length === 0) {
|
|
25
|
+
return inputSchema;
|
|
26
|
+
}
|
|
27
|
+
if (unionKeyProperties.length > 1) {
|
|
28
|
+
throw new SchemaCompilationError(`Union schema has multiple properties marked as union keys: ${unionKeyProperties.map(p => p[0]).join(', ')}`, {location});
|
|
29
|
+
}
|
|
30
|
+
const unionKeyPropertyName = unionKeyProperties[0][0];
|
|
31
|
+
const unionKeyPropertySchema = unionKeyProperties[0][1];
|
|
32
|
+
const unionKeyPropertyLocation = location.relative(unionKeyPropertyName);
|
|
33
|
+
|
|
34
|
+
const unionSchemaEntries = [...inputSchema.unionSchemaEntries];
|
|
35
|
+
|
|
36
|
+
const unionKeySet = new Set(); // it's possible that keys may normalize to the same value :-/
|
|
37
|
+
for (const [unionKey] of unionSchemaEntries) {
|
|
38
|
+
unionKeySet.add(unionKeyPropertySchema._normalizeValue(unionKey, undefined, undefined, {sync:true}));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (unionKeySet.size !== unionSchemaEntries.length) {
|
|
42
|
+
throw new SchemaCompilationError('Union keys must not collide after normalization with the unionKey property schema', {location});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const v = (unionKeyPropertySchema.values ?? []).sort();
|
|
46
|
+
const uksv = [...unionKeySet].sort();
|
|
47
|
+
|
|
48
|
+
if (v.length > 0) {
|
|
49
|
+
if (!deepEquals(v, uksv)) {
|
|
50
|
+
throw new SchemaCompilationError(
|
|
51
|
+
`Union key schema values {${v.join('|')}} do not include all possible union keys {${uksv.join('|')}}`,
|
|
52
|
+
{location: unionKeyPropertyLocation});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
if (unionKeyPropertySchema.isSelector) {
|
|
57
|
+
throw new SchemaCompilationError(
|
|
58
|
+
'Cannot populate values for a schema that is both a selector and a union key', {location: unionKeyPropertyLocation}
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
unionKeyPropertySchema.options.values = uksv;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (Array.isArray(inputSchema.handlers.discriminators) && inputSchema.handlers.discriminators.length > 0) {
|
|
65
|
+
return inputSchema;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const compiler = this;
|
|
69
|
+
|
|
70
|
+
// Note: it's ok to use a custom discriminator (above) even if there is a union key option,
|
|
71
|
+
// as it also triggers population of allowed values for the property in _finalizeValues.
|
|
72
|
+
inputSchema.handlers.discriminators = [
|
|
73
|
+
compiler.resolver.compileValueProcessorSpec(
|
|
74
|
+
compiler,
|
|
75
|
+
generatePropertyValueDiscriminatorFunction(inputSchema, unionKeyPropertyName))
|
|
76
|
+
];
|
|
77
|
+
return inputSchema;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @param {CompiledSchema} inputSchema
|
|
82
|
+
* @param {any} _target
|
|
83
|
+
* @param {SchemaLocation} _location
|
|
84
|
+
* @param {object} options
|
|
85
|
+
* @returns {CompiledSchema}
|
|
86
|
+
* @this {SchemaCompiler}
|
|
87
|
+
*/
|
|
88
|
+
export function synthesizeAutoDiscrimination(inputSchema, _target, _location, options) {
|
|
89
|
+
if (!inputSchema.isUnion) {
|
|
90
|
+
return inputSchema;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (Array.isArray(inputSchema.handlers.discriminators) && inputSchema.handlers.discriminators.length > 0) {
|
|
94
|
+
return inputSchema;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (inputSchema.hasValues) {
|
|
98
|
+
return inputSchema;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// the compiler is bound to the helper functions
|
|
102
|
+
const compiler = this;
|
|
103
|
+
|
|
104
|
+
const discriminatorPropertyMap = findDiscriminatorProperties(inputSchema);
|
|
105
|
+
|
|
106
|
+
for (const [property, schemaSet] of discriminatorPropertyMap) {
|
|
107
|
+
if (inputSchema.getPropertySchema(property)) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (schemaSet.size === 1) {
|
|
112
|
+
const [unionSchema] = schemaSet;
|
|
113
|
+
const propertySchema = unionSchema.getPropertySchema(property);
|
|
114
|
+
if (propertySchema && !propertySchema.hasConditions && !propertySchema.required && propertySchema.default === undefined) {
|
|
115
|
+
// this feels dangerous... because it is. can't copy required
|
|
116
|
+
inputSchema._setPropertySchema(property, propertySchema);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
let base;
|
|
122
|
+
const values = new Set();
|
|
123
|
+
|
|
124
|
+
let normalizerCompatible = true;
|
|
125
|
+
let firstNormalizers;
|
|
126
|
+
|
|
127
|
+
let allHaveValues = true;
|
|
128
|
+
|
|
129
|
+
for (const unionSchema of schemaSet) {
|
|
130
|
+
const propertySchema = unionSchema.getPropertySchema(property);
|
|
131
|
+
if (!propertySchema) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (!firstNormalizers) {
|
|
135
|
+
firstNormalizers = propertySchema.handlers.normalizers;
|
|
136
|
+
}
|
|
137
|
+
if (propertySchema.metadata.parserTypeHint) {
|
|
138
|
+
if (base === undefined) {
|
|
139
|
+
base = propertySchema.metadata.parserTypeHint;
|
|
140
|
+
}
|
|
141
|
+
else if (base && base !== propertySchema.metadata.parserTypeHint) {
|
|
142
|
+
base = 'any';
|
|
143
|
+
normalizerCompatible = false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!propertySchema.hasValues) {
|
|
147
|
+
allHaveValues = false;
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
for (const v of propertySchema.values ?? []) {
|
|
151
|
+
const normalized = propertySchema._normalizeValue(v, undefined, undefined, {sync:true});
|
|
152
|
+
if (normalizerCompatible && normalized !== v) {
|
|
153
|
+
normalizerCompatible = false;
|
|
154
|
+
}
|
|
155
|
+
values.add(normalized);
|
|
156
|
+
if (base === undefined) {
|
|
157
|
+
if (compiler.resolver.hasSchema(typeof v)) {
|
|
158
|
+
base = typeof v;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const useNormalizer = normalizerCompatible && firstNormalizers;
|
|
165
|
+
|
|
166
|
+
// TODO - Now that we support reusing schema instances throughout the hierarchy, is there a way
|
|
167
|
+
// that we can detect "basically identical schemas differing only in constrained values"?
|
|
168
|
+
// It feels like it would be far safer to check "is the schema the same" rather than
|
|
169
|
+
// "probe the schema's normalizers to see if they are compatible".
|
|
170
|
+
|
|
171
|
+
const hoisted = new Schema(base ?? 'any');
|
|
172
|
+
if (useNormalizer && firstNormalizers) {
|
|
173
|
+
for (const normalizer of firstNormalizers) {
|
|
174
|
+
hoisted.normalizer(normalizer);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (values.size > 0) {
|
|
178
|
+
hoisted.values(Array.from(values));
|
|
179
|
+
if (!allHaveValues) {
|
|
180
|
+
hoisted.option('allowUnknownValues', true);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
inputSchema._setPropertySchema(property, this.compile(hoisted));
|
|
184
|
+
}
|
|
185
|
+
inputSchema.handlers.discriminators = [
|
|
186
|
+
compiler.resolver.compileValueProcessorSpec(compiler, generateAutomaticDiscriminatorFunction(inputSchema))
|
|
187
|
+
];
|
|
188
|
+
|
|
189
|
+
return inputSchema;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Collect values from union members onto the union schema itself.
|
|
195
|
+
* When all members define values, the union gets the full set (strict).
|
|
196
|
+
* When only some members define values, the union gets the known subset
|
|
197
|
+
* and `allowUnknownValues` is set so that `ensureAccepts` does not gate.
|
|
198
|
+
*
|
|
199
|
+
* Skips unions that already have values defined, or that have no members
|
|
200
|
+
* with values.
|
|
201
|
+
*
|
|
202
|
+
* @param {CompiledSchema} inputSchema
|
|
203
|
+
* @returns {CompiledSchema}
|
|
204
|
+
* @package
|
|
205
|
+
*/
|
|
206
|
+
export function synthesizeUnionValues(inputSchema) {
|
|
207
|
+
if (!inputSchema.isUnion || inputSchema.hasValues) {
|
|
208
|
+
return inputSchema;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const values = new Set();
|
|
212
|
+
let allHaveValues = true;
|
|
213
|
+
|
|
214
|
+
for (const [, unionSchema] of inputSchema.unionSchemaEntries) {
|
|
215
|
+
if (!unionSchema.hasValues) {
|
|
216
|
+
allHaveValues = false;
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
// @ts-ignore
|
|
220
|
+
for (const v of unionSchema.values) {
|
|
221
|
+
values.add(v);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (values.size === 0) {
|
|
226
|
+
return inputSchema;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
inputSchema.options.values = [...values];
|
|
230
|
+
|
|
231
|
+
if (!allHaveValues) {
|
|
232
|
+
inputSchema.options.allowUnknownValues = true;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return inputSchema;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* @param {CompiledSchema} inputSchema
|
|
240
|
+
* @returns {CompiledSchema}
|
|
241
|
+
*/
|
|
242
|
+
export function copyUnionOptions(inputSchema) {
|
|
243
|
+
if (!inputSchema.isUnion) {
|
|
244
|
+
return inputSchema;
|
|
245
|
+
}
|
|
246
|
+
for (const [unionSchemaKey, unionSchema] of inputSchema.unionSchemaEntries) {
|
|
247
|
+
const skipOptions = ['values', 'type', 'default'];
|
|
248
|
+
|
|
249
|
+
for (const [optionName, optionValue] of Object.entries(inputSchema.options ?? {})) {
|
|
250
|
+
if (skipOptions.includes(optionName)) {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
// todo - detect if a union schema is a shared instance!
|
|
254
|
+
//
|
|
255
|
+
// If the union schema was separately compiled, this will throw a TypeError because it is frozen.
|
|
256
|
+
|
|
257
|
+
if (optionValue !== undefined && unionSchema.options[optionName] === undefined) {
|
|
258
|
+
// union schemas "inherit" options from their parent
|
|
259
|
+
unionSchema.options[optionName] = optionValue;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return inputSchema;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
/** @typedef {Set<CompiledSchema>} SchemaSet */
|
|
269
|
+
/** @typedef {Map<string,SchemaSet>} DiscriminatorPropertyMap */
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* @package
|
|
273
|
+
* @param {CompiledSchema} schema
|
|
274
|
+
* @returns {DiscriminatorPropertyMap}
|
|
275
|
+
*/
|
|
276
|
+
function findDiscriminatorProperties(schema) {
|
|
277
|
+
|
|
278
|
+
const schemas = Array.from(schema.unionSchemaEntries).map(e => e[1]);
|
|
279
|
+
|
|
280
|
+
const discriminatorPropertyMap = new Map();
|
|
281
|
+
for (const unionSchema of schemas) {
|
|
282
|
+
let found = false;
|
|
283
|
+
for (const [property, propertySchema] of unionSchema.propertyEntries) {
|
|
284
|
+
if (Array.isArray(propertySchema.values) && (propertySchema.values.length > 0)) {
|
|
285
|
+
if (!discriminatorPropertyMap.has(property)) {
|
|
286
|
+
discriminatorPropertyMap.set(property, new Set());
|
|
287
|
+
}
|
|
288
|
+
const schemaSet = discriminatorPropertyMap.get(property);
|
|
289
|
+
schemaSet.add(unionSchema);
|
|
290
|
+
found = true;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (!found) {
|
|
294
|
+
// fixme - shouldn't we wait until we see if we can add anything from the unique property set below?
|
|
295
|
+
const key = schema.findUnionKey(unionSchema); // this is silly, we had the key already
|
|
296
|
+
// throw new SchemaCompilationError(`Union schema ${key} needs at least one property with constrained values`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Augment list with unique properties
|
|
301
|
+
const eliminated = new Set();
|
|
302
|
+
const multiple = new Set();
|
|
303
|
+
for (let i = 0; i < schemas.length; i++) {
|
|
304
|
+
const schema1 = schemas[i];
|
|
305
|
+
for (const [property, propertySchema] of schema1.propertyEntries) {
|
|
306
|
+
if (discriminatorPropertyMap.has(property) || multiple.has(property) || eliminated.has(property)) {
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
if (propertySchema.default !== undefined) {
|
|
310
|
+
eliminated.add(property);
|
|
311
|
+
// a default would cause it to self-discriminate!
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
let canDistinguish = true;
|
|
315
|
+
for (let j = i + 1; j < schemas.length; j++) {
|
|
316
|
+
const schema2 = schemas[j];
|
|
317
|
+
if (schema2.getPropertySchema(property)) {
|
|
318
|
+
multiple.add(property)
|
|
319
|
+
canDistinguish = false;
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (canDistinguish) {
|
|
324
|
+
discriminatorPropertyMap.set(property, new Set([schema1]))
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
for (const p of discriminatorPropertyMap.keys()) {
|
|
329
|
+
if (eliminated.has(p)) {
|
|
330
|
+
discriminatorPropertyMap.delete(p);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
const encountered = new Set();
|
|
334
|
+
// After the main loop, check if all schemas are distinguishable
|
|
335
|
+
for (let i = 0; i < schemas.length; i++) {
|
|
336
|
+
for (let j = i + 1; j < schemas.length; j++) {
|
|
337
|
+
const schema1 = schemas[i];
|
|
338
|
+
const schema2 = schemas[j];
|
|
339
|
+
|
|
340
|
+
let canDistinguish = false;
|
|
341
|
+
let uniqueProperty = true;
|
|
342
|
+
|
|
343
|
+
for (const [property, schemaSet] of discriminatorPropertyMap) {
|
|
344
|
+
schemaSet.forEach(schema => encountered.add(schema))
|
|
345
|
+
// Check if both schemas have this discriminator property
|
|
346
|
+
if (!schemaSet.has(schema1) || !schemaSet.has(schema2)) {
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
uniqueProperty = false;
|
|
350
|
+
|
|
351
|
+
const prop1 = schema1.getPropertySchema(property);
|
|
352
|
+
const prop2 = schema2.getPropertySchema(property);
|
|
353
|
+
|
|
354
|
+
const values1 = prop1?.values ?? []; // should always be set, but fallback for typecheck nanny
|
|
355
|
+
const values2 = prop2?.values ?? [];
|
|
356
|
+
|
|
357
|
+
// TODO - consider...?
|
|
358
|
+
//const otherOverlap = values1.some(v => prop2.checkInput(v));
|
|
359
|
+
|
|
360
|
+
// If the value sets are disjoint, we can distinguish them
|
|
361
|
+
const hasOverlap = values1.some(v => values2.includes(v));
|
|
362
|
+
if (!hasOverlap) {
|
|
363
|
+
canDistinguish = true;
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (!canDistinguish && !uniqueProperty) {
|
|
369
|
+
throw new SchemaCompilationError(
|
|
370
|
+
`Union members are indistinguishable (cannot discriminate between schemas)`
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (schemas.length > 1 && encountered.size !== schemas.length) {
|
|
377
|
+
for (const s of schemas) {
|
|
378
|
+
if (!encountered.has(s)) {
|
|
379
|
+
throw new SchemaCompilationError(`Union member ${formatValue(schema.findUnionKey(s))} cannot be uniquely discriminated`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return discriminatorPropertyMap;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* @package
|
|
390
|
+
* @param {CompiledSchema} schema
|
|
391
|
+
* @returns {ValueProcessorFunction}
|
|
392
|
+
*/
|
|
393
|
+
function generateAutomaticDiscriminatorFunction(schema) {
|
|
394
|
+
if (!schema.isUnion) {
|
|
395
|
+
throw new SchemaCompilationError('Can only generate a discriminator for a union')
|
|
396
|
+
}
|
|
397
|
+
const unionSchemas = Array.from(schema.unionSchemaEntries).map(e => e[1]);
|
|
398
|
+
const discriminatorProps = findDiscriminatorProperties(schema);
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* @param {any} inputObject
|
|
402
|
+
* @param {any} target
|
|
403
|
+
* @param {SchemaLocation} location
|
|
404
|
+
* @param {object} [options]
|
|
405
|
+
* @returns {CompiledSchema|undefined}
|
|
406
|
+
*/
|
|
407
|
+
function discriminator(inputObject, target, location, options) {
|
|
408
|
+
|
|
409
|
+
let candidates = new Set(unionSchemas)
|
|
410
|
+
let matched = false;
|
|
411
|
+
|
|
412
|
+
for (const [property, schemaSet] of discriminatorProps) {
|
|
413
|
+
const propertyValue = inputObject?.[property];
|
|
414
|
+
|
|
415
|
+
if (propertyValue === undefined) {
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (schemaSet.size === 1) {
|
|
420
|
+
const [single] = schemaSet;
|
|
421
|
+
if (candidates.has(single)) {
|
|
422
|
+
candidates = new Set([single])
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
candidates = new Set();
|
|
426
|
+
if (candidates.size === 0) {
|
|
427
|
+
throw new UnionResolutionError('Union resolution conflict with', {property, location, value: propertyValue});
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
for (const schema of schemaSet) {
|
|
432
|
+
if (!candidates.has(schema)) {
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
const propertyLocation = location.union(schema)?.relative(property);
|
|
436
|
+
|
|
437
|
+
if (propertyLocation === undefined) {
|
|
438
|
+
// should never happen!
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// const propertySchema = schema.properties[property];
|
|
443
|
+
// if (!propertySchema) {
|
|
444
|
+
// continue;
|
|
445
|
+
// }
|
|
446
|
+
|
|
447
|
+
if (propertyLocation.schema.checkAccepts(propertyValue)) {
|
|
448
|
+
matched = true;
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
candidates.delete(schema);
|
|
452
|
+
|
|
453
|
+
if (candidates.size === 0) {
|
|
454
|
+
throw new UnionResolutionError(`Union resolution conflict with`, {property, value: propertyValue, location});
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (candidates.size === 1 && matched) {
|
|
461
|
+
return Array.from(candidates)[0];
|
|
462
|
+
}
|
|
463
|
+
else if (candidates.size <= 1) {
|
|
464
|
+
// if only one candidate but didn't actually match, just accidentally ended up here (only one option?)
|
|
465
|
+
if (options?.strict || options?.context?.final) {
|
|
466
|
+
throw new UnionResolutionError('Union resolution failure (no matches)', {location});
|
|
467
|
+
}
|
|
468
|
+
return undefined;
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
471
|
+
if (options?.strict || options?.context?.final) {
|
|
472
|
+
const keys = Array.from(candidates).map(s => schema.findUnionKey(s)).join('|')
|
|
473
|
+
|
|
474
|
+
throw new UnionResolutionError(`Union resolution ambiguity (could be ${keys})`, {location});
|
|
475
|
+
}
|
|
476
|
+
return undefined;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
return discriminator;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* @param {CompiledSchema} schema
|
|
486
|
+
* @param {string} propertyName
|
|
487
|
+
* @returns {ValueProcessorFunction}
|
|
488
|
+
*/
|
|
489
|
+
function generatePropertyValueDiscriminatorFunction(schema, propertyName) {
|
|
490
|
+
|
|
491
|
+
const ref = schema.getPropertySchema(propertyName);
|
|
492
|
+
if (!ref) {
|
|
493
|
+
throw new SchemaError(`Discriminator property ${propertyName} not found`);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* @param {any} input
|
|
498
|
+
* @param {any} target
|
|
499
|
+
* @param {SchemaLocation} location
|
|
500
|
+
* @returns {CompiledSchema|string|undefined}
|
|
501
|
+
*/
|
|
502
|
+
function discriminator(input, target, location) {
|
|
503
|
+
// we could just look at location, but the union knows its own properties
|
|
504
|
+
return input?.[propertyName];
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
return discriminator;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { CompiledSchema } from '../compiled-schema.js';
|
|
2
|
+
import { SchemaCompiler } from '../schema-compiler.js';
|
|
3
|
+
import { SchemaLocation } from '../schema-location.js';
|
|
4
|
+
import { SchemaCompilationError } from '../errors.js';
|
|
5
|
+
import { isEmpty } from '../helpers/object.js';
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param {CompiledSchema} cs
|
|
9
|
+
* @param {any} _
|
|
10
|
+
* @param {SchemaLocation} location
|
|
11
|
+
* @returns {CompiledSchema|Promise<CompiledSchema>}
|
|
12
|
+
* @this {SchemaCompiler}
|
|
13
|
+
*/
|
|
14
|
+
export function normalizeValues(cs, _, location) {
|
|
15
|
+
const values = cs.options.values ?? [];
|
|
16
|
+
if (isEmpty(cs.options.values)) {
|
|
17
|
+
return cs;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const valueSet = new Set();
|
|
21
|
+
|
|
22
|
+
let vi = 0;
|
|
23
|
+
|
|
24
|
+
while (vi < values.length) {
|
|
25
|
+
const value = cs._normalizeValue(values[vi++], undefined, undefined, {sync:true});
|
|
26
|
+
if (value === undefined) {
|
|
27
|
+
throw new SchemaCompilationError(`Undefined after normalizing`, {value, location});
|
|
28
|
+
}
|
|
29
|
+
valueSet.add(value);
|
|
30
|
+
}
|
|
31
|
+
if (valueSet.size) {
|
|
32
|
+
cs.options.values = [...valueSet];
|
|
33
|
+
}
|
|
34
|
+
return cs;
|
|
35
|
+
}
|