commit 47d147852b8bb50df2d841b2e41bd108f79873fd Author: Sven Slootweg Date: Tue May 26 04:01:24 2020 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/README.md b/README.md new file mode 100644 index 0000000..c801d45 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# @validatem/array-of + +Documentation for this module has not been fully written yet. By the time it reaches 1.0.0, it will have full documentation. + +In the meantime, check out the `example.js` file in the repository for a usage demonstration. diff --git a/example.js b/example.js new file mode 100644 index 0000000..4724459 --- /dev/null +++ b/example.js @@ -0,0 +1,38 @@ +"use strict"; + +const anyProperty = require("./"); +const { validateValue } = require("@validatem/core"); /* FIXME: Add this as a devDep */ +const isString = require("@validatem/is-string"); + +let validator = anyProperty({ + key: [ isString ], + value: [ isString ] +}); + +let objectA = { + foo: "bar", + baz: "qux" +}; + +console.log(validateValue(objectA, validator)); // { foo: 'bar', baz: 'qux' } + +let objectB = { + foo: "bar", + baz: 42 +}; + +console.log(validateValue(objectB, validator)); /* + AggregrateValidationError: One or more validation errors occurred: + - At baz -> (value): Must be a string +*/ + +let SomeSymbol = Symbol("SomeSymbol"); +let objectC = { + foo: "bar", + [SomeSymbol]: "qux" +}; + +console.log(validateValue(objectC, validator)); /* + AggregrateValidationError: One or more validation errors occurred: + - At Symbol(SomeSymbol) -> (key): Must be a string +*/ diff --git a/index.js b/index.js new file mode 100644 index 0000000..170c0e0 --- /dev/null +++ b/index.js @@ -0,0 +1,54 @@ +"use strict"; + +const defaultValue = require("default-value"); + +const ValidationError = require("@validatem/error"); +const combinator = require("@validatem/combinator"); +const annotateErrors = require("@validatem/annotate-errors"); +const virtualProperty = require("@validatem/virtual-property"); +const validationResult = require("@validatem/validation-result"); + +module.exports = function (rules) { + if (rules.key == null && rules.value == null) { + throw new Error(`Must specify either a 'key' or 'value' property in the ruleset`); + } else { + let keyRules = defaultValue(rules.key, []); + let valueRules = defaultValue(rules.value, []); + + return combinator((object, applyValidators) => { + let newObject = {}; + let allErrors = []; + + if (typeof object !== "object" || Array.isArray(object)) { + throw new ValidationError("Must be an object"); + } else { + // NOTE: Reflect.ownEntries is used here to ensure we capture the Symbol-typed keys as well + for (let key of Reflect.ownKeys(object)) { + let value = object[key]; + let keyAsString = key.toString(); // Again, to deal with Symbol-typed keys. + + let { errors: keyErrors, newValue: newKey } = applyValidators(key, keyRules); + let { errors: valueErrors, newValue } = applyValidators(value, valueRules); + + let annotatedKeyErrors = annotateErrors({ + pathSegments: [ keyAsString, virtualProperty("key") ], + errors: keyErrors + }); + + let annotatedValueErrors = annotateErrors({ + pathSegments: [ keyAsString, virtualProperty("value") ], + errors: valueErrors + }); + + newObject[newKey] = newValue; + allErrors.push(...annotatedKeyErrors, ...annotatedValueErrors); + } + + return validationResult({ + errors: allErrors, + newValue: newObject + }); + } + }); + } +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..7ce6349 --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "@validatem/any-property", + "description": "Validatem combinator for validating that a value is an array of items meeting certain rules", + "keywords": [ + "validatem", + "validator", + "combinator" + ], + "version": "0.1.0", + "main": "index.js", + "repository": "http://git.cryto.net/validatem/any-property.git", + "author": "Sven Slootweg ", + "license": "WTFPL OR CC0-1.0", + "dependencies": { + "@validatem/annotate-errors": "^0.1.2", + "@validatem/combinator": "^0.1.0", + "@validatem/error": "^1.0.0", + "@validatem/validation-result": "^0.1.1", + "@validatem/virtual-property": "^0.1.0", + "default-value": "^1.0.0" + }, + "devDependencies": { + "@validatem/is-string": "^0.1.0" + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..6e62b64 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,76 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@validatem/annotate-errors@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@validatem/annotate-errors/-/annotate-errors-0.1.2.tgz#fa9152bb30f4f42b69496b527e38f0c31ff605a9" + integrity sha512-EuX7pzdYI/YpTmZcgdPG481Oi3elAg8JWh/LYXuE1h6MaZk3A8eP5DD33/l7EoKzrysn6y8nCsqNa1ngei562w== + dependencies: + "@validatem/match-validation-error" "^0.1.0" + +"@validatem/combinator@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@validatem/combinator/-/combinator-0.1.0.tgz#d07f49b7c519d7bc0d1060f68ffe162cd80ac6e9" + integrity sha512-dW0zCHmeCiZhXjX4A6Til4X4XEcFHclQQ5mDehwRPJwh8rgY/fwuPbUIbuKM0Vgz49KnVxIcCl4xc7p4h6AVRg== + +"@validatem/error@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@validatem/error/-/error-1.0.0.tgz#a975904aa4c3e7618d89088a393567a5e1778340" + integrity sha512-7M3tV4DhCuimuCRdC2L/topBByDjhzspzeQGNU0S4/mdn2aDNtESYE43K/2Kh/utCAhqXh2gyw89WYxy//t3fQ== + dependencies: + create-error "^0.3.1" + +"@validatem/is-string@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@validatem/is-string/-/is-string-0.1.0.tgz#0ef6bc7a0111dafa9da277c7316c18d35c295f69" + integrity sha512-DoTf4FFgVjX8Bup5qLUIxTMqnf+NQOSPicHLfMsIQMx63+RHUe1JS2f1ih6kKTo/2nqLQndO0ir4FTghqgJFdw== + dependencies: + "@validatem/error" "^1.0.0" + is-string "^1.0.5" + +"@validatem/match-validation-error@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@validatem/match-validation-error/-/match-validation-error-0.1.0.tgz#fa87f5f1836e7c1d9bf6b75b2addf0a5b21e4c1e" + integrity sha512-6akGTk7DdulOreyqDiGdikwRSixQz/AlvARSX18dcWaTFc79KxCLouL2hyoFcor9IIUhu5RTY4/i756y4T1yxA== + dependencies: + "@validatem/match-versioned-special" "^0.1.0" + +"@validatem/match-versioned-special@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@validatem/match-versioned-special/-/match-versioned-special-0.1.0.tgz#2eacc48debecdbbe7e3d02f0c0a665afaea9bedf" + integrity sha512-xoOTY0bdA2ELj+ntcDVJ8YyMEFIJpjZ4HNPL9lGcbnRFwJBhQcHUAhUpZwkMxu02zH9wkNM1FvYGHxPz40745Q== + +"@validatem/validation-result@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@validatem/validation-result/-/validation-result-0.1.1.tgz#4ea37a6028d2ccc4f9f4be91f3c36c90ebc1ed04" + integrity sha512-EeN1iO6yhr50DfWUoQzhBjeZcrbq4B2xqNJgN+W6JhwMFHXMxDTSQOXwX+oijSwRpXBcBe3KSCv9T+NuvHmeEw== + dependencies: + default-value "^1.0.0" + +"@validatem/virtual-property@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@validatem/virtual-property/-/virtual-property-0.1.0.tgz#880540dfd149f98ecf1095d93912e34443381fe4" + integrity sha512-JUUvWtdqoSkOwlsl20oB3qFHYIL05a/TAfdY4AJcs55QeVTiX5iI1b8IoQW644sIWWooBuLv+XwoxjRsQFczlQ== + +create-error@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/create-error/-/create-error-0.3.1.tgz#69810245a629e654432bf04377360003a5351a23" + integrity sha1-aYECRaYp5lRDK/BDdzYAA6U1GiM= + +default-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/default-value/-/default-value-1.0.0.tgz#8c6f52a5a1193fe78fdc9f86eb71d16c9757c83a" + integrity sha1-jG9SpaEZP+eP3J+G63HRbJdXyDo= + dependencies: + es6-promise-try "0.0.1" + +es6-promise-try@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/es6-promise-try/-/es6-promise-try-0.0.1.tgz#10f140dad27459cef949973e5d21a087f7274b20" + integrity sha1-EPFA2tJ0Wc75SZc+XSGgh/cnSyA= + +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==