@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,188 @@
|
|
|
1
|
+
import { ConstraintError, ResolverError } from '../../errors.js';
|
|
2
|
+
|
|
3
|
+
const IPV4_REGEX = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parse a dotted-decimal IPv4 string into a 32-bit unsigned integer.
|
|
7
|
+
* @param {string} ip
|
|
8
|
+
* @returns {number}
|
|
9
|
+
*/
|
|
10
|
+
function ipToUint32(ip) {
|
|
11
|
+
const [a, b, c, d] = ip.split('.').map(Number);
|
|
12
|
+
return ((a << 24) | (b << 16) | (c << 8) | d) >>> 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Parse a CIDR string (e.g. '192.168.1.0/24') into network and mask as uint32.
|
|
17
|
+
* @param {string} cidr
|
|
18
|
+
* @returns {{ network: number, mask: number }}
|
|
19
|
+
*/
|
|
20
|
+
function parseCIDR(cidr) {
|
|
21
|
+
const [ip, bitsStr] = cidr.split('/');
|
|
22
|
+
const bits = Number(bitsStr);
|
|
23
|
+
if (!IPV4_REGEX.test(ip) || !Number.isInteger(bits) || bits < 0 || bits > 32) {
|
|
24
|
+
throw new ResolverError(`Invalid CIDR notation: ${cidr}`);
|
|
25
|
+
}
|
|
26
|
+
const mask = bits === 0 ? 0 : (~0 << (32 - bits)) >>> 0;
|
|
27
|
+
const network = ipToUint32(ip) & mask;
|
|
28
|
+
return { network, mask };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Check whether an IPv4 uint32 falls within a CIDR range.
|
|
33
|
+
* @param {number} ip
|
|
34
|
+
* @param {{ network: number, mask: number }} cidr
|
|
35
|
+
* @returns {boolean}
|
|
36
|
+
*/
|
|
37
|
+
function isInCIDR(ip, cidr) {
|
|
38
|
+
return (ip & cidr.mask) === cidr.network;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** @type {Record<string, { network: number, mask: number }[]>} */
|
|
42
|
+
const NAMED_RANGES = {
|
|
43
|
+
rfc1918: [
|
|
44
|
+
parseCIDR('10.0.0.0/8'),
|
|
45
|
+
parseCIDR('172.16.0.0/12'),
|
|
46
|
+
parseCIDR('192.168.0.0/16'),
|
|
47
|
+
],
|
|
48
|
+
loopback: [
|
|
49
|
+
parseCIDR('127.0.0.0/8'),
|
|
50
|
+
],
|
|
51
|
+
'link-local': [
|
|
52
|
+
parseCIDR('169.254.0.0/16'),
|
|
53
|
+
],
|
|
54
|
+
rfc6598: [
|
|
55
|
+
parseCIDR('100.64.0.0/10'),
|
|
56
|
+
],
|
|
57
|
+
multicast: [
|
|
58
|
+
parseCIDR('224.0.0.0/4'),
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
NAMED_RANGES['non-routable'] = [
|
|
63
|
+
...NAMED_RANGES.rfc1918,
|
|
64
|
+
...NAMED_RANGES.loopback,
|
|
65
|
+
...NAMED_RANGES['link-local'],
|
|
66
|
+
...NAMED_RANGES.rfc6598,
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Resolve an `in` parameter value to an array of CIDR ranges.
|
|
71
|
+
* Accepts a named range (e.g. 'rfc1918') or a CIDR string (e.g. '10.0.0.0/8').
|
|
72
|
+
* @param {string} spec
|
|
73
|
+
* @returns {{ network: number, mask: number }[]}
|
|
74
|
+
*/
|
|
75
|
+
function resolveRange(spec) {
|
|
76
|
+
const named = NAMED_RANGES[spec.toLowerCase()];
|
|
77
|
+
if (named) return named;
|
|
78
|
+
if (spec.includes('/')) return [parseCIDR(spec)];
|
|
79
|
+
throw new ResolverError(`Unknown IPv4 range: "${spec}" (expected CIDR or one of: ${Object.keys(NAMED_RANGES).join(', ')})`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* ## $ipv4
|
|
84
|
+
*
|
|
85
|
+
* Validates that a string is a valid IPv4 address in dotted-decimal notation.
|
|
86
|
+
*
|
|
87
|
+
* ### Parameters
|
|
88
|
+
* - `in` (string, optional): Network range to validate against. Accepts CIDR
|
|
89
|
+
* notation (e.g. `'192.168.1.0/24'`) or a named range: `rfc1918`, `loopback`,
|
|
90
|
+
* `link-local`, `rfc6598`, `multicast`, `non-routable`.
|
|
91
|
+
* - `min` (string, optional): Minimum IPv4 address (inclusive).
|
|
92
|
+
* - `max` (string, optional): Maximum IPv4 address (inclusive).
|
|
93
|
+
* - `format` (string, optional): Output format — `'integer'` emits the address
|
|
94
|
+
* as a uint32. Default passes through the original dotted-decimal string.
|
|
95
|
+
*
|
|
96
|
+
* Use either `in` OR `min`/`max`, not both.
|
|
97
|
+
*
|
|
98
|
+
* ### Example
|
|
99
|
+
* ```js
|
|
100
|
+
* // Format-only validation
|
|
101
|
+
* new Schema('string').validator('$ipv4')
|
|
102
|
+
*
|
|
103
|
+
* // CIDR range (positional `in`)
|
|
104
|
+
* new Schema('string').validator({$ipv4: '192.168.1.0/24'})
|
|
105
|
+
*
|
|
106
|
+
* // Named range
|
|
107
|
+
* new Schema('string').validator({$ipv4: 'rfc1918'})
|
|
108
|
+
*
|
|
109
|
+
* // Explicit min/max
|
|
110
|
+
* new Schema('string').validator({$ipv4: {min: '192.168.1.1', max: '192.168.1.254'}})
|
|
111
|
+
*
|
|
112
|
+
* // Output as uint32
|
|
113
|
+
* new Schema('string').validator({$ipv4: {in: 'rfc1918', format: 'integer'}})
|
|
114
|
+
* ```
|
|
115
|
+
*
|
|
116
|
+
* @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
|
|
117
|
+
*/
|
|
118
|
+
export const IPV4_CONSTRAINT = {
|
|
119
|
+
keyword: 'ipv4',
|
|
120
|
+
|
|
121
|
+
parameters: [
|
|
122
|
+
{ parameter: 'in', default: undefined, type: 'string' },
|
|
123
|
+
{ parameter: 'min', default: undefined, type: 'string' },
|
|
124
|
+
{ parameter: 'max', default: undefined, type: 'string' },
|
|
125
|
+
{ parameter: 'format', default: undefined, type: 'string' },
|
|
126
|
+
],
|
|
127
|
+
|
|
128
|
+
process: (value, _target, _location, options) => {
|
|
129
|
+
if (!IPV4_REGEX.test(value)) {
|
|
130
|
+
throw new ConstraintError('Invalid IPv4 address');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const { in: inRange, min, max, format } = options?.args ?? {};
|
|
134
|
+
|
|
135
|
+
// mutual exclusivity check
|
|
136
|
+
if (inRange !== undefined && (min !== undefined || max !== undefined)) {
|
|
137
|
+
throw new ResolverError('$ipv4: "in" and "min"/"max" are mutually exclusive');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// validate min/max are valid IPv4 if provided
|
|
141
|
+
if (min !== undefined && !IPV4_REGEX.test(min)) {
|
|
142
|
+
throw new ResolverError(`$ipv4: invalid "min" address: ${min}`);
|
|
143
|
+
}
|
|
144
|
+
if (max !== undefined && !IPV4_REGEX.test(max)) {
|
|
145
|
+
throw new ResolverError(`$ipv4: invalid "max" address: ${max}`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const ip = ipToUint32(value);
|
|
149
|
+
|
|
150
|
+
if (inRange !== undefined) {
|
|
151
|
+
const ranges = resolveRange(inRange);
|
|
152
|
+
if (!ranges.some(cidr => isInCIDR(ip, cidr))) {
|
|
153
|
+
throw new ConstraintError(`IPv4 address not in range "${inRange}"`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (min !== undefined && ip < ipToUint32(min)) {
|
|
158
|
+
throw new ConstraintError(`IPv4 address below minimum ${min}`);
|
|
159
|
+
}
|
|
160
|
+
if (max !== undefined && ip > ipToUint32(max)) {
|
|
161
|
+
throw new ConstraintError(`IPv4 address above maximum ${max}`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (format === 'integer') {
|
|
165
|
+
return ip;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return value;
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
describe: (args) => {
|
|
172
|
+
if (!args) return undefined;
|
|
173
|
+
|
|
174
|
+
const inProcessor = (Array.isArray(args) ? args[0] : args.in);
|
|
175
|
+
const minProcessor = (Array.isArray(args) ? args[1] : args.min);
|
|
176
|
+
const maxProcessor = (Array.isArray(args) ? args[2] : args.max);
|
|
177
|
+
|
|
178
|
+
const inVal = inProcessor?.description;
|
|
179
|
+
const min = minProcessor?.description;
|
|
180
|
+
const max = maxProcessor?.description;
|
|
181
|
+
|
|
182
|
+
if (inVal !== undefined) return `in ${inVal}`;
|
|
183
|
+
if (min !== undefined && max !== undefined) return `${min}–${max}`;
|
|
184
|
+
if (min !== undefined) return `≥${min}`;
|
|
185
|
+
if (max !== undefined) return `≤${max}`;
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { ConstraintError, ResolverError } from '../../errors.js';
|
|
2
|
+
|
|
3
|
+
const IPV6_REGEX = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
|
|
4
|
+
|
|
5
|
+
const IPV4_TAIL_REGEX = /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Expand an IPv6 string (possibly compressed, possibly with zone id or IPv4 tail)
|
|
9
|
+
* into exactly 8 16-bit groups as a BigInt.
|
|
10
|
+
* @param {string} ip
|
|
11
|
+
* @returns {bigint}
|
|
12
|
+
*/
|
|
13
|
+
function ipv6ToBigInt(ip) {
|
|
14
|
+
// strip zone identifier (e.g. %eth0)
|
|
15
|
+
let addr = ip.replace(/%.*$/, '');
|
|
16
|
+
|
|
17
|
+
// handle IPv4-mapped tail: convert dotted-decimal to two hex groups
|
|
18
|
+
const v4Match = IPV4_TAIL_REGEX.exec(addr);
|
|
19
|
+
if (v4Match) {
|
|
20
|
+
const [a, b, c, d] = [v4Match[1], v4Match[2], v4Match[3], v4Match[4]].map(Number);
|
|
21
|
+
const hi = ((a << 8) | b).toString(16);
|
|
22
|
+
const lo = ((c << 8) | d).toString(16);
|
|
23
|
+
addr = addr.slice(0, v4Match.index) + `${hi}:${lo}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// expand :: shorthand
|
|
27
|
+
if (addr.includes('::')) {
|
|
28
|
+
const [left, right] = addr.split('::');
|
|
29
|
+
const leftGroups = left ? left.split(':') : [];
|
|
30
|
+
const rightGroups = right ? right.split(':') : [];
|
|
31
|
+
const missing = 8 - leftGroups.length - rightGroups.length;
|
|
32
|
+
const fill = Array(missing).fill('0');
|
|
33
|
+
addr = [...leftGroups, ...fill, ...rightGroups].join(':');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const groups = addr.split(':');
|
|
37
|
+
let result = 0n;
|
|
38
|
+
for (const group of groups) {
|
|
39
|
+
result = (result << 16n) | BigInt(parseInt(group, 16));
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Parse an IPv6 CIDR string into network and mask as BigInt.
|
|
46
|
+
* @param {string} cidr
|
|
47
|
+
* @returns {{ network: bigint, mask: bigint }}
|
|
48
|
+
*/
|
|
49
|
+
function parseCIDR(cidr) {
|
|
50
|
+
const slashIdx = cidr.lastIndexOf('/');
|
|
51
|
+
if (slashIdx === -1) {
|
|
52
|
+
throw new ResolverError(`Invalid IPv6 CIDR notation: ${cidr}`);
|
|
53
|
+
}
|
|
54
|
+
const ip = cidr.slice(0, slashIdx);
|
|
55
|
+
const bits = Number(cidr.slice(slashIdx + 1));
|
|
56
|
+
if (!IPV6_REGEX.test(ip) || !Number.isInteger(bits) || bits < 0 || bits > 128) {
|
|
57
|
+
throw new ResolverError(`Invalid IPv6 CIDR notation: ${cidr}`);
|
|
58
|
+
}
|
|
59
|
+
const mask = bits === 0 ? 0n : ((1n << 128n) - 1n) << BigInt(128 - bits);
|
|
60
|
+
const network = ipv6ToBigInt(ip) & mask;
|
|
61
|
+
return { network, mask };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Check whether an IPv6 BigInt falls within a CIDR range.
|
|
66
|
+
* @param {bigint} ip
|
|
67
|
+
* @param {{ network: bigint, mask: bigint }} cidr
|
|
68
|
+
* @returns {boolean}
|
|
69
|
+
*/
|
|
70
|
+
function isInCIDR(ip, cidr) {
|
|
71
|
+
return (ip & cidr.mask) === cidr.network;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** @type {Record<string, { network: bigint, mask: bigint }[]>} */
|
|
75
|
+
const NAMED_RANGES = {
|
|
76
|
+
loopback: [
|
|
77
|
+
parseCIDR('::1/128'),
|
|
78
|
+
],
|
|
79
|
+
'link-local': [
|
|
80
|
+
parseCIDR('fe80::/10'),
|
|
81
|
+
],
|
|
82
|
+
'unique-local': [
|
|
83
|
+
parseCIDR('fc00::/7'),
|
|
84
|
+
],
|
|
85
|
+
multicast: [
|
|
86
|
+
parseCIDR('ff00::/8'),
|
|
87
|
+
],
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
NAMED_RANGES['non-routable'] = [
|
|
91
|
+
...NAMED_RANGES.loopback,
|
|
92
|
+
...NAMED_RANGES['link-local'],
|
|
93
|
+
...NAMED_RANGES['unique-local'],
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Resolve an `in` parameter value to an array of CIDR ranges.
|
|
98
|
+
* Accepts a named range or a CIDR string.
|
|
99
|
+
* @param {string} spec
|
|
100
|
+
* @returns {{ network: bigint, mask: bigint }[]}
|
|
101
|
+
*/
|
|
102
|
+
function resolveRange(spec) {
|
|
103
|
+
const named = NAMED_RANGES[spec.toLowerCase()];
|
|
104
|
+
if (named) return named;
|
|
105
|
+
if (spec.includes('/')) return [parseCIDR(spec)];
|
|
106
|
+
throw new ResolverError(`Unknown IPv6 range: "${spec}" (expected CIDR or one of: ${Object.keys(NAMED_RANGES).join(', ')})`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* ## $ipv6
|
|
111
|
+
*
|
|
112
|
+
* Validates that a string is a properly formatted IPv6 address. Supports all standard
|
|
113
|
+
* notation formats including full, compressed (::), link-local with zone identifiers,
|
|
114
|
+
* and IPv4-mapped addresses.
|
|
115
|
+
*
|
|
116
|
+
* ### Parameters
|
|
117
|
+
* - `in` (string, optional): Network range to validate against. Accepts CIDR
|
|
118
|
+
* notation (e.g. `'fe80::/10'`) or a named range: `loopback`, `link-local`,
|
|
119
|
+
* `unique-local`, `multicast`, `non-routable`.
|
|
120
|
+
* - `min` (string, optional): Minimum IPv6 address (inclusive).
|
|
121
|
+
* - `max` (string, optional): Maximum IPv6 address (inclusive).
|
|
122
|
+
*
|
|
123
|
+
* Use either `in` OR `min`/`max`, not both.
|
|
124
|
+
*
|
|
125
|
+
* ### Example
|
|
126
|
+
* ```js
|
|
127
|
+
* // Format-only validation
|
|
128
|
+
* new Schema('string').validator('$ipv6')
|
|
129
|
+
*
|
|
130
|
+
* // CIDR range (positional `in`)
|
|
131
|
+
* new Schema('string').validator({$ipv6: '2001:db8::/32'})
|
|
132
|
+
*
|
|
133
|
+
* // Named range
|
|
134
|
+
* new Schema('string').validator({$ipv6: 'unique-local'})
|
|
135
|
+
*
|
|
136
|
+
* // Explicit min/max
|
|
137
|
+
* new Schema('string').validator({$ipv6: {min: '2001:db8::1', max: '2001:db8::ffff'}})
|
|
138
|
+
* ```
|
|
139
|
+
*
|
|
140
|
+
* @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
|
|
141
|
+
*/
|
|
142
|
+
export const IPV6_CONSTRAINT = {
|
|
143
|
+
keyword: 'ipv6',
|
|
144
|
+
|
|
145
|
+
parameters: [
|
|
146
|
+
{ parameter: 'in', default: undefined, type: 'string' },
|
|
147
|
+
{ parameter: 'min', default: undefined, type: 'string' },
|
|
148
|
+
{ parameter: 'max', default: undefined, type: 'string' },
|
|
149
|
+
],
|
|
150
|
+
|
|
151
|
+
process: (value, _target, _location, options) => {
|
|
152
|
+
if (!IPV6_REGEX.test(value)) {
|
|
153
|
+
throw new ConstraintError('Invalid IPv6 address');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const { in: inRange, min, max } = options?.args ?? {};
|
|
157
|
+
|
|
158
|
+
if (inRange !== undefined && (min !== undefined || max !== undefined)) {
|
|
159
|
+
throw new ResolverError('$ipv6: "in" and "min"/"max" are mutually exclusive');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (min !== undefined && !IPV6_REGEX.test(min)) {
|
|
163
|
+
throw new ResolverError(`$ipv6: invalid "min" address: ${min}`);
|
|
164
|
+
}
|
|
165
|
+
if (max !== undefined && !IPV6_REGEX.test(max)) {
|
|
166
|
+
throw new ResolverError(`$ipv6: invalid "max" address: ${max}`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const ip = ipv6ToBigInt(value);
|
|
170
|
+
|
|
171
|
+
if (inRange !== undefined) {
|
|
172
|
+
const ranges = resolveRange(inRange);
|
|
173
|
+
if (!ranges.some(cidr => isInCIDR(ip, cidr))) {
|
|
174
|
+
throw new ConstraintError(`IPv6 address not in range "${inRange}"`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (min !== undefined && ip < ipv6ToBigInt(min)) {
|
|
179
|
+
throw new ConstraintError(`IPv6 address below minimum ${min}`);
|
|
180
|
+
}
|
|
181
|
+
if (max !== undefined && ip > ipv6ToBigInt(max)) {
|
|
182
|
+
throw new ConstraintError(`IPv6 address above maximum ${max}`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return value;
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
describe: (args) => {
|
|
189
|
+
if (!args) return undefined;
|
|
190
|
+
|
|
191
|
+
const inProcessor = (Array.isArray(args) ? args[0] : args.in);
|
|
192
|
+
const minProcessor = (Array.isArray(args) ? args[1] : args.min);
|
|
193
|
+
const maxProcessor = (Array.isArray(args) ? args[2] : args.max);
|
|
194
|
+
|
|
195
|
+
const inVal = inProcessor?.description;
|
|
196
|
+
const min = minProcessor?.description;
|
|
197
|
+
const max = maxProcessor?.description;
|
|
198
|
+
|
|
199
|
+
if (inVal !== undefined) return `in ${inVal}`;
|
|
200
|
+
if (min !== undefined && max !== undefined) return `${min}–${max}`;
|
|
201
|
+
if (min !== undefined) return `≥${min}`;
|
|
202
|
+
if (max !== undefined) return `≤${max}`;
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ConstraintError } from '../../errors.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ## $is-array
|
|
5
|
+
*
|
|
6
|
+
* Validates that the input is a valid array.
|
|
7
|
+
*
|
|
8
|
+
* See `$array` for looser array handling that accepts values that can be normalized as arrays.
|
|
9
|
+
*
|
|
10
|
+
* @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
|
|
11
|
+
*/
|
|
12
|
+
export const IS_ARRAY_CONSTRAINT = {
|
|
13
|
+
keyword: 'is-array',
|
|
14
|
+
process: (value, _, location) => {
|
|
15
|
+
if (!Array.isArray(value)) {
|
|
16
|
+
throw new ConstraintError('Must be an array');
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
},
|
|
20
|
+
description: ''
|
|
21
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ConstraintError } from '../../errors.js';
|
|
2
|
+
import { formatValue } from '../../helpers/format.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ## $is-date
|
|
6
|
+
*
|
|
7
|
+
* Validates that the input is a valid date.
|
|
8
|
+
*
|
|
9
|
+
* See `$date` for looser date handling that accepts values that can be normalized as dates.
|
|
10
|
+
*
|
|
11
|
+
* @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
|
|
12
|
+
*/
|
|
13
|
+
export const IS_DATE_CONSTRAINT = {
|
|
14
|
+
keyword: 'is-date',
|
|
15
|
+
process: (value) => {
|
|
16
|
+
if (value instanceof Date && !isNaN(value.getTime())) {
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
throw new ConstraintError(`Invalid date: ${formatValue(value)}`)
|
|
20
|
+
},
|
|
21
|
+
description: ''
|
|
22
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ConstraintError } from '../../errors.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ## $is-number
|
|
5
|
+
*
|
|
6
|
+
* Validates that the input is a valid number.
|
|
7
|
+
*
|
|
8
|
+
* See `$number` for looser number validation that accepts values that can be normalized as numbers.
|
|
9
|
+
*
|
|
10
|
+
* @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
|
|
11
|
+
*/
|
|
12
|
+
export const IS_NUMBER_CONSTRAINT = {
|
|
13
|
+
keyword: 'is-number',
|
|
14
|
+
process: (value) => {
|
|
15
|
+
if (typeof value !== 'number' || Number.isNaN(value) || !Number.isFinite(value)) {
|
|
16
|
+
throw new ConstraintError('Must be a number');
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
},
|
|
20
|
+
description: ''
|
|
21
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ConstraintError } from '../../errors.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ## $is-object
|
|
5
|
+
*
|
|
6
|
+
* Validates that the input is a valid object (and not null!)
|
|
7
|
+
*
|
|
8
|
+
* See `$object` for looser object handling that accepts values that can be normalized as objects.
|
|
9
|
+
*
|
|
10
|
+
* @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
|
|
11
|
+
*/
|
|
12
|
+
export const IS_OBJECT_CONSTRAINT = {
|
|
13
|
+
keyword: 'is-object',
|
|
14
|
+
process: (value, _, location) => {
|
|
15
|
+
if (typeof value === 'object' && value !== null) {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
throw new ConstraintError('Must be an object');
|
|
19
|
+
},
|
|
20
|
+
description: ''
|
|
21
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ConstraintError } from '../../errors.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ## $is-string
|
|
5
|
+
*
|
|
6
|
+
* Validates that the input is a valid string.
|
|
7
|
+
*
|
|
8
|
+
* See `$string` for looser validation that accepts values that can be normalized as strings.
|
|
9
|
+
*
|
|
10
|
+
* @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
|
|
11
|
+
*/
|
|
12
|
+
export const IS_STRING_CONSTRAINT = {
|
|
13
|
+
keyword: 'is-string',
|
|
14
|
+
process: (value) => {
|
|
15
|
+
if (typeof value === 'string') {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
throw new ConstraintError('Must be a string');
|
|
19
|
+
},
|
|
20
|
+
description: ''
|
|
21
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ## $join
|
|
3
|
+
*
|
|
4
|
+
* Join the input array elements into a string using the provided separator.
|
|
5
|
+
*
|
|
6
|
+
* ### Parameters
|
|
7
|
+
* - `separator` (string, required): The value to use for joining
|
|
8
|
+
*
|
|
9
|
+
* If the input is not an array, it is treated as a single element.
|
|
10
|
+
* Follows the behavior of JavaScript's Array.prototype.join()
|
|
11
|
+
*
|
|
12
|
+
* ### Example
|
|
13
|
+
* ```js
|
|
14
|
+
* // Join array elements with a comma (default)
|
|
15
|
+
* new Schema('array').transformer('$join')
|
|
16
|
+
* // ['a', 'b', 'c'] → 'a,b,c'
|
|
17
|
+
*
|
|
18
|
+
* // Join with a custom separator
|
|
19
|
+
* new Schema('array').transformer({$join: {separator: ' | '}})
|
|
20
|
+
* // ['admin', 'read', 'write'] → 'admin | read | write'
|
|
21
|
+
*
|
|
22
|
+
* // Split then rejoin with normalized separators
|
|
23
|
+
* new Schema('string').normalizer([{$split: {separator: /[,;]/}}, {$each: '$trim'}])
|
|
24
|
+
* .transformer({$join: {separator: ', '}})
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}*
|
|
28
|
+
*/
|
|
29
|
+
export const JOIN_OPERATOR = {
|
|
30
|
+
keyword: 'join',
|
|
31
|
+
parameters: [ { parameter: 'separator', default: ',' } ],
|
|
32
|
+
|
|
33
|
+
process: (value, _target, _location, options) => {
|
|
34
|
+
const separator = options.args?.['separator'];
|
|
35
|
+
|
|
36
|
+
if (!Array.isArray(value)) {
|
|
37
|
+
return `${value}`;
|
|
38
|
+
}
|
|
39
|
+
return value.join(separator);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ConstraintError } from '../../errors.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ## $json
|
|
5
|
+
*
|
|
6
|
+
* Validates that a string contains valid JSON that can be parsed by `JSON.parse()`.
|
|
7
|
+
* The processor does not modify the input - it only validates that the string is
|
|
8
|
+
* syntactically correct JSON.
|
|
9
|
+
*
|
|
10
|
+
* @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
|
|
11
|
+
*/
|
|
12
|
+
export const JSON_CONSTRAINT = {
|
|
13
|
+
keyword: 'json',
|
|
14
|
+
process: (value) => {
|
|
15
|
+
try {
|
|
16
|
+
JSON.parse(value);
|
|
17
|
+
return value;
|
|
18
|
+
} catch {
|
|
19
|
+
throw new ConstraintError('Invalid JSON format');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ConstraintError } from '../../errors.js';
|
|
2
|
+
import { formatValue } from '../../helpers/format.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ## $json-decode
|
|
6
|
+
*
|
|
7
|
+
* Parses a JSON string into a value.
|
|
8
|
+
* Throws if the input is not a string or is not valid JSON.
|
|
9
|
+
*
|
|
10
|
+
* @type {import('../../value-processor/value-processor.js').ValueProcessorDefinition}
|
|
11
|
+
*/
|
|
12
|
+
export const JSON_DECODE_OPERATOR = {
|
|
13
|
+
keyword: 'json-decode',
|
|
14
|
+
process: (value, _target, location) => {
|
|
15
|
+
if (typeof value !== 'string') {
|
|
16
|
+
throw new ConstraintError(`$json-decode requires a string, got ${formatValue(value)}`, {location});
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(value);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
throw new ConstraintError(`$json-decode: invalid JSON — ${error.message}`, {location, cause: error});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ## $json-encode
|
|
3
|
+
*
|
|
4
|
+
* Serializes any value to a JSON string.
|
|
5
|
+
*
|
|
6
|
+
* ### Parameters
|
|
7
|
+
* - `indent` (number, optional, default `0`): Indentation spaces for pretty-printing. `0` produces compact output.
|
|
8
|
+
*
|
|
9
|
+
* ### Example
|
|
10
|
+
* ```js
|
|
11
|
+
* // Serialize an object to a compact JSON string
|
|
12
|
+
* new Schema('object').transformer('$json-encode')
|
|
13
|
+
* // {a: 1} → '{"a":1}'
|
|
14
|
+
*
|
|
15
|
+
* // Pretty-print with 2-space indentation
|
|
16
|
+
* new Schema('object').transformer({'$json-encode': {indent: 2}})
|
|
17
|
+
* // {a: 1} → '{\n "a": 1\n}'
|
|
18
|
+
*
|
|
19
|
+
* // Encode a nested payload field for storage
|
|
20
|
+
* new Schema('object', {
|
|
21
|
+
* payload: new Schema('object').transformer('$json-encode'),
|
|
22
|
+
* })
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @type {import('../../value-processor/value-processor.js').ValueProcessorDefinition}
|
|
26
|
+
*/
|
|
27
|
+
export const JSON_ENCODE_OPERATOR = {
|
|
28
|
+
keyword: 'json-encode',
|
|
29
|
+
parameters: [ { parameter: 'indent', default: 0 } ],
|
|
30
|
+
|
|
31
|
+
process: (value, _target, _location, options) => {
|
|
32
|
+
const indent = options.args?.['indent'] || 0;
|
|
33
|
+
return JSON.stringify(value, null, indent || undefined);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { toKebabCase } from '../../helpers/case.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ## $kebab-case
|
|
5
|
+
*
|
|
6
|
+
* Converts a string to kebab-case format (lowercase words separated by hyphens).
|
|
7
|
+
* Safe to use in normalize phase (non-throwing).
|
|
8
|
+
*
|
|
9
|
+
* **Input/Output Examples**:
|
|
10
|
+
* - `"HelloWorld"` → `"hello-world"`
|
|
11
|
+
* - `"API_KEY_NAME"` → `"api-key-name"`
|
|
12
|
+
* - `"some text here"` → `"some-text-here"`
|
|
13
|
+
* - `"camelCase"` → `"camel-case"`
|
|
14
|
+
* - `"already-kebab"` → `"already-kebab"`
|
|
15
|
+
*
|
|
16
|
+
* @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
|
|
17
|
+
*/
|
|
18
|
+
export const KEBAB_CASE_OPERATOR = {
|
|
19
|
+
keyword: 'kebab-case',
|
|
20
|
+
process: (value) => {
|
|
21
|
+
return toKebabCase(String(value));
|
|
22
|
+
}
|
|
23
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ConstraintError } from '../../errors.js';
|
|
2
|
+
import { formatValue } from '../../helpers/format.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ## $keys
|
|
6
|
+
*
|
|
7
|
+
* Returns the enumerable own property keys of an object as an array of strings.
|
|
8
|
+
* Throws if the input is not a plain object.
|
|
9
|
+
*
|
|
10
|
+
* @type {import('../../value-processor/value-processor.js').ValueProcessorDefinition}
|
|
11
|
+
*/
|
|
12
|
+
export const KEYS_OPERATOR = {
|
|
13
|
+
keyword: 'keys',
|
|
14
|
+
process: (value, _target, location) => {
|
|
15
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
16
|
+
throw new ConstraintError(`$keys requires a plain object, got ${formatValue(value)}`, {location});
|
|
17
|
+
}
|
|
18
|
+
return Object.keys(value);
|
|
19
|
+
}
|
|
20
|
+
};
|