Add error code support

master
Sven Slootweg 4 years ago
parent f3c007ace5
commit a668faefa3

@ -6,7 +6,7 @@ const wrapError = require("./");
/*** Simple rules ***/ /*** Simple rules ***/
let rule = wrapError("This is a custom error message complaining that the value must be a string!", [ isString ]); let rule = wrapError("wrap-error.custom", "This is a custom error message complaining that the value must be a string!", [ isString ]);
console.log(validateValue("hello world", [ rule ])); // hello world console.log(validateValue("hello world", [ rule ])); // hello world
@ -21,7 +21,7 @@ try {
/*** Combinators with properties, and preserving the original errors as well ***/ /*** Combinators with properties, and preserving the original errors as well ***/
let objectRule = wrapError("Must be a valid thingem", { let objectRule = wrapError("wrap-error.thingem", "Must be a valid thingem", {
a: [ isString ], a: [ isString ],
b: [ isString ] b: [ isString ]
}, { preserveOriginalErrors: true }); }, { preserveOriginalErrors: true });
@ -35,5 +35,5 @@ let objectB = { a: "hello", b: 42 };
console.log(validateValue(objectB, [ objectRule ])); /* console.log(validateValue(objectB, [ objectRule ])); /*
AggregrateValidationError: One or more validation errors occurred: AggregrateValidationError: One or more validation errors occurred:
- At (root): Must be a valid thingem - At (root): Must be a valid thingem
- At b: Must be a string b: Must be a string
*/ */

@ -17,68 +17,76 @@ function concat(arrays) {
}, arrays[0]); }, arrays[0]);
} }
module.exports = function wrapError(message, rules, options = {}) { module.exports = function wrapError(code, message, rules, options = {}) {
let preserveOriginalErrors = defaultValue(options.preserveOriginalErrors, false); if (typeof code !== "string") {
throw new Error(`'code' argument must be a string`);
} else if (typeof message !== "string") {
throw new Error(`'message' argument must be a string`);
} else if (rules == null) {
throw new Error(`'rules' argument is required`);
} else {
let preserveOriginalErrors = defaultValue(options.preserveOriginalErrors, false);
return combinator((value, applyValidators, context) => { return combinator((value, applyValidators, context) => {
let result = applyValidators(value, rules, context); let result = applyValidators(value, rules, context);
if (result.errors.length > 0) { if (result.errors.length > 0) {
let { errors, newValue } = result; let { errors, newValue } = result;
let errorsByType = splitFilterN(errors, [ "validationRoot", "validationPath", "other" ], (error) => { let errorsByType = splitFilterN(errors, [ "validationRoot", "validationPath", "other" ], (error) => {
if (matchValidationError(error)) { if (matchValidationError(error)) {
if (error.path.length === 0) { if (error.path.length === 0) {
return "validationRoot"; return "validationRoot";
} else {
return "validationPath";
}
} else { } else {
return "validationPath"; return "other";
} }
} else { });
return "other";
}
});
let hasRootValidationErrors = errorsByType.validationRoot.length > 0; let hasRootValidationErrors = errorsByType.validationRoot.length > 0;
let hasPathValidationErrors = errorsByType.validationPath.length > 0; let hasPathValidationErrors = errorsByType.validationPath.length > 0;
let hasValidationErrors = hasRootValidationErrors || hasPathValidationErrors; let hasValidationErrors = hasRootValidationErrors || hasPathValidationErrors;
let transformedValidationErrors = asExpression(() => { let transformedValidationErrors = asExpression(() => {
if (hasValidationErrors) { if (hasValidationErrors) {
if (!preserveOriginalErrors) { if (!preserveOriginalErrors) {
return [ new ValidationError(message) ]; return [ new ValidationError(message, { code: code }) ];
} else {
// If possible, we try to move any subpath errors into the subErrors of an (optionally newly-created) root error. Otherwise, it can become difficult for the user to correlate together the root and subpath errors that are related, when we start changing the messages of the root errors.
if (errorsByType.validationRoot.length === 0) {
return [ new ValidationError(message, { subErrors: errorsByType.validationPath }) ];
} else if (errorsByType.validationRoot.length === 1) {
let error = errorsByType.validationRoot[0];
// TODO: Currently we cannot set `originalError` due to a bug in `create-error`; switch to a better error implementation
return [ new ValidationError(`${message} (${error.message})`, { subErrors: errorsByType.validationPath }) ];
} else { } else {
// If there are multiple root errors, we cannot determine which root error the subpath errors belong to, so we'll just provide them as a flat list // If possible, we try to move any subpath errors into the subErrors of an (optionally newly-created) root error. Otherwise, it can become difficult for the user to correlate together the root and subpath errors that are related, when we start changing the messages of the root errors.
return concat([ if (errorsByType.validationRoot.length === 0) {
errorsByType.validationRoot.map((error) => { return [ new ValidationError(message, { code: code, subErrors: errorsByType.validationPath }) ];
return new ValidationError(`${message} (${error.message})`) } else if (errorsByType.validationRoot.length === 1) {
}), let error = errorsByType.validationRoot[0];
errorsByType.validationPath
]); // TODO: Currently we cannot set `originalError` due to a bug in `create-error`; switch to a better error implementation
return [ new ValidationError(`${message} (${error.message})`, { code: code, subErrors: errorsByType.validationPath }) ];
} else {
// If there are multiple root errors, we cannot determine which root error the subpath errors belong to, so we'll just provide them as a flat list
return concat([
errorsByType.validationRoot.map((error) => {
return new ValidationError(`${message} (${error.message})`, { code: code })
}),
errorsByType.validationPath
]);
}
} }
} else {
return [];
} }
} else { });
return [];
} return validationResult({
}); newValue: newValue,
errors: concat([
return validationResult({ transformedValidationErrors,
newValue: newValue, errorsByType.other
errors: concat([ ])
transformedValidationErrors, });
errorsByType.other } else {
]) return result;
}); }
} else { });
return result; }
}
});
}; };

@ -10,9 +10,9 @@
"@validatem/match-validation-error" "^0.1.0" "@validatem/match-validation-error" "^0.1.0"
"@validatem/any-property@^0.1.0": "@validatem/any-property@^0.1.0":
version "0.1.2" version "0.1.3"
resolved "https://registry.yarnpkg.com/@validatem/any-property/-/any-property-0.1.2.tgz#e6cced130ced057ab185d1a61034b77cb277a5ad" resolved "https://registry.yarnpkg.com/@validatem/any-property/-/any-property-0.1.3.tgz#fc7768c1922a8bacff9369ae48913672e5350f52"
integrity sha512-WHiUM9oKTVc3w1ZWXb2c09yx6pT65Z9oPJC6/rEJtygtsL+H5B8PlAAH16BllPxLF1ebeLlEhXs3qwau5I0USQ== integrity sha512-jYWxif5ff9pccu7566LIQ/4+snlApXEJUimBywzAriBgS3r4eDBbz3oZFHuiPmhxNK/NNof5YUS+L6Sk3zaMfg==
dependencies: dependencies:
"@validatem/annotate-errors" "^0.1.2" "@validatem/annotate-errors" "^0.1.2"
"@validatem/combinator" "^0.1.0" "@validatem/combinator" "^0.1.0"
@ -22,47 +22,51 @@
default-value "^1.0.0" default-value "^1.0.0"
"@validatem/combinator@^0.1.0", "@validatem/combinator@^0.1.1": "@validatem/combinator@^0.1.0", "@validatem/combinator@^0.1.1":
version "0.1.1" version "0.1.2"
resolved "https://registry.yarnpkg.com/@validatem/combinator/-/combinator-0.1.1.tgz#202f31243f8d57cf87f1b449405b134e2fa40c5a" resolved "https://registry.yarnpkg.com/@validatem/combinator/-/combinator-0.1.2.tgz#eab893d55f1643b9c6857eaf6ff7ed2a728e89ff"
integrity sha512-crzAYCmKUcb1DC5sSpdof4gWHX81VRmm+REWflhFuRlKH6JHRV5RcBCxEjlDfRrxW2yF6s9i0rQAOyVVE+GGAg== integrity sha512-vE8t1tNXknmN62FlN6LxQmA2c6TwVKZ+fl/Wit3H2unFdOhu7SZj2kRPGjAXdK/ARh/3svYfUBeD75pea0j1Sw==
"@validatem/core@^0.3.1": "@validatem/core@^0.3.1":
version "0.3.1" version "0.3.12"
resolved "https://registry.yarnpkg.com/@validatem/core/-/core-0.3.1.tgz#33ea24ba4d4c516b5836703aea7e7da0afb6c227" resolved "https://registry.yarnpkg.com/@validatem/core/-/core-0.3.12.tgz#e4e8a566850571bf55412862e88a3b06e75c8072"
integrity sha512-k9OgvVqxX6rKmnkEQGi14pBqsilXu8pIVelaQsI/3tI5xVDDE5podpuPAJVrIsepy2berCtN9KSD/NCDhX1wLg== integrity sha512-ngrFk6PT/pPZntpleG6q55SByongNxRk7wJhUiCihyv4yqIqqG+bNGH4wb6yW33IHefreWxkkJ53yM1Yj9srNA==
dependencies: dependencies:
"@validatem/annotate-errors" "^0.1.2" "@validatem/annotate-errors" "^0.1.2"
"@validatem/any-property" "^0.1.0" "@validatem/any-property" "^0.1.0"
"@validatem/error" "^1.0.0" "@validatem/error" "^1.0.0"
"@validatem/is-plain-object" "^0.1.0"
"@validatem/match-validation-error" "^0.1.0" "@validatem/match-validation-error" "^0.1.0"
"@validatem/match-versioned-special" "^0.1.0" "@validatem/match-versioned-special" "^0.1.0"
"@validatem/match-virtual-property" "^0.1.0" "@validatem/match-virtual-property" "^0.1.0"
"@validatem/normalize-rules" "^0.1.0" "@validatem/normalize-rules" "^0.1.0"
"@validatem/required" "^0.1.0" "@validatem/required" "^0.1.0"
"@validatem/validation-result" "^0.1.1" "@validatem/validation-result" "^0.1.1"
"@validatem/virtual-property" "^0.1.0"
as-expression "^1.0.0"
assure-array "^1.0.0" assure-array "^1.0.0"
create-error "^0.3.1" create-error "^0.3.1"
default-value "^1.0.0" default-value "^1.0.0"
execall "^2.0.0"
flatten "^1.0.3" flatten "^1.0.3"
indent-string "^4.0.0"
is-arguments "^1.0.4" is-arguments "^1.0.4"
supports-color "^7.1.0"
syncpipe "^1.0.0"
"@validatem/error@^1.0.0": "@validatem/error@^1.0.0":
version "1.0.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/@validatem/error/-/error-1.0.0.tgz#a975904aa4c3e7618d89088a393567a5e1778340" resolved "https://registry.yarnpkg.com/@validatem/error/-/error-1.1.0.tgz#bef46e7066c39761b494ebe3eec2ecdc7348f4ed"
integrity sha512-7M3tV4DhCuimuCRdC2L/topBByDjhzspzeQGNU0S4/mdn2aDNtESYE43K/2Kh/utCAhqXh2gyw89WYxy//t3fQ== integrity sha512-gZJEoZq1COi/8/5v0fVKQ9uX54x5lb5HbV7mzIOhY6dqjmLNfxdQmpECZPQrCAOpcRkRMJ7zaFhq4UTslpY9yA==
dependencies:
create-error "^0.3.1"
"@validatem/has-shape@^0.1.0": "@validatem/has-shape@^0.1.0":
version "0.1.4" version "0.1.8"
resolved "https://registry.yarnpkg.com/@validatem/has-shape/-/has-shape-0.1.4.tgz#678ebcd2864628515531d75e1b5491387a97bfd9" resolved "https://registry.yarnpkg.com/@validatem/has-shape/-/has-shape-0.1.8.tgz#dff0f0449c12b96d150091b7a980154d810ae63d"
integrity sha512-MVN4BOxRfsa2D95Lwp8Dh9I8paAhTYgBpZbDAFnyEv51qlGTQPeAnunnslFS+K38QLa9E96Dk5Vs8Pn7F5XH9g== integrity sha512-x2i8toW1uraFF2Vl6WBl4CScbBeg5alrtoCKMyXbJkHf2B5QxL/ftUh2RQRcBzx6U0i7KUb8vdShcWAa+fehRQ==
dependencies: dependencies:
"@validatem/annotate-errors" "^0.1.2" "@validatem/annotate-errors" "^0.1.2"
"@validatem/combinator" "^0.1.0" "@validatem/combinator" "^0.1.0"
"@validatem/error" "^1.0.0" "@validatem/error" "^1.0.0"
"@validatem/validation-result" "^0.1.1" "@validatem/validation-result" "^0.1.1"
array-union "^2.1.0"
as-expression "^1.0.0" as-expression "^1.0.0"
assure-array "^1.0.0" assure-array "^1.0.0"
default-value "^1.0.0" default-value "^1.0.0"
@ -107,9 +111,9 @@
integrity sha512-ssd3coFgwbLuqvZftLZTy3eHN0TFST8oTS2XTViQdXJPXVoJmwEKBpFhXgwnb5Ly1CE037R/KWpjhd1TP/56kQ== integrity sha512-ssd3coFgwbLuqvZftLZTy3eHN0TFST8oTS2XTViQdXJPXVoJmwEKBpFhXgwnb5Ly1CE037R/KWpjhd1TP/56kQ==
"@validatem/normalize-rules@^0.1.0": "@validatem/normalize-rules@^0.1.0":
version "0.1.2" version "0.1.3"
resolved "https://registry.yarnpkg.com/@validatem/normalize-rules/-/normalize-rules-0.1.2.tgz#6529f17a6f36c6e2ae3ef285c59347c2ea208aa1" resolved "https://registry.yarnpkg.com/@validatem/normalize-rules/-/normalize-rules-0.1.3.tgz#59fd6193b1091ff97b5c723b32c9bb1fe2a9dc9c"
integrity sha512-IHc81Sy/W0OiCbmvE3kTB+5OPVJnXWHP2tTXvKO6hVH0qykclMvIPRGgZf1s4dLaeOLKdkkfKyO/pLTVyNCIbA== integrity sha512-HHPceAP2ce9NWymIZrgLCTzpdwXNRBCCB5H6ZPc5ggOrbmh4STpT83fLazleHtvYNlqgXZ4GjQOvCwrjaM+qEA==
dependencies: dependencies:
"@validatem/has-shape" "^0.1.0" "@validatem/has-shape" "^0.1.0"
"@validatem/is-plain-object" "^0.1.0" "@validatem/is-plain-object" "^0.1.0"
@ -136,6 +140,11 @@
resolved "https://registry.yarnpkg.com/@validatem/virtual-property/-/virtual-property-0.1.0.tgz#880540dfd149f98ecf1095d93912e34443381fe4" resolved "https://registry.yarnpkg.com/@validatem/virtual-property/-/virtual-property-0.1.0.tgz#880540dfd149f98ecf1095d93912e34443381fe4"
integrity sha512-JUUvWtdqoSkOwlsl20oB3qFHYIL05a/TAfdY4AJcs55QeVTiX5iI1b8IoQW644sIWWooBuLv+XwoxjRsQFczlQ== integrity sha512-JUUvWtdqoSkOwlsl20oB3qFHYIL05a/TAfdY4AJcs55QeVTiX5iI1b8IoQW644sIWWooBuLv+XwoxjRsQFczlQ==
array-union@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
as-expression@^1.0.0: as-expression@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/as-expression/-/as-expression-1.0.0.tgz#7bc620ca4cb2fe0ee90d86729bd6add33b8fd831" resolved "https://registry.yarnpkg.com/as-expression/-/as-expression-1.0.0.tgz#7bc620ca4cb2fe0ee90d86729bd6add33b8fd831"
@ -146,6 +155,13 @@ assure-array@^1.0.0:
resolved "https://registry.yarnpkg.com/assure-array/-/assure-array-1.0.0.tgz#4f4ad16a87659d6200a4fb7103462033d216ec1f" resolved "https://registry.yarnpkg.com/assure-array/-/assure-array-1.0.0.tgz#4f4ad16a87659d6200a4fb7103462033d216ec1f"
integrity sha1-T0rRaodlnWIApPtxA0YgM9IW7B8= integrity sha1-T0rRaodlnWIApPtxA0YgM9IW7B8=
clone-regexp@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f"
integrity sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==
dependencies:
is-regexp "^2.0.0"
create-error@^0.3.1: create-error@^0.3.1:
version "0.3.1" version "0.3.1"
resolved "https://registry.yarnpkg.com/create-error/-/create-error-0.3.1.tgz#69810245a629e654432bf04377360003a5351a23" resolved "https://registry.yarnpkg.com/create-error/-/create-error-0.3.1.tgz#69810245a629e654432bf04377360003a5351a23"
@ -163,11 +179,28 @@ es6-promise-try@0.0.1:
resolved "https://registry.yarnpkg.com/es6-promise-try/-/es6-promise-try-0.0.1.tgz#10f140dad27459cef949973e5d21a087f7274b20" resolved "https://registry.yarnpkg.com/es6-promise-try/-/es6-promise-try-0.0.1.tgz#10f140dad27459cef949973e5d21a087f7274b20"
integrity sha1-EPFA2tJ0Wc75SZc+XSGgh/cnSyA= integrity sha1-EPFA2tJ0Wc75SZc+XSGgh/cnSyA=
execall@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/execall/-/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45"
integrity sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==
dependencies:
clone-regexp "^2.1.0"
flatten@^1.0.3: flatten@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b"
integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==
has-flag@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
indent-string@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
is-arguments@^1.0.4: is-arguments@^1.0.4:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3"
@ -178,6 +211,11 @@ is-plain-obj@^2.1.0:
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
is-regexp@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-2.1.0.tgz#cd734a56864e23b956bf4e7c66c396a4c0b22c2d"
integrity sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==
is-string@^1.0.5: is-string@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6"
@ -187,3 +225,17 @@ split-filter-n@^1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/split-filter-n/-/split-filter-n-1.1.2.tgz#268be1ec9c4d93dfb27b030c06165ac1b6f70f66" resolved "https://registry.yarnpkg.com/split-filter-n/-/split-filter-n-1.1.2.tgz#268be1ec9c4d93dfb27b030c06165ac1b6f70f66"
integrity sha512-+hXSQYpKe1uyXPXI4zQtAJAlaF2EzEc+BaF2goMeNL5oUD5YLqrVcpjxELJxpomXfwMCUaYLAszEbdY9gKVdHQ== integrity sha512-+hXSQYpKe1uyXPXI4zQtAJAlaF2EzEc+BaF2goMeNL5oUD5YLqrVcpjxELJxpomXfwMCUaYLAszEbdY9gKVdHQ==
supports-color@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1"
integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==
dependencies:
has-flag "^4.0.0"
syncpipe@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/syncpipe/-/syncpipe-1.0.0.tgz#170340f813150bc8fcb8878b1b9c71ea0ccd3727"
integrity sha512-cdiAFTnFJRvUaNPDc2n9CqoFvtIL3+JUMJZrC3kA3FzpugHOqu0TvkgNwmnxPZ5/WjAzMcfMS3xm+AO7rg/j/w==
dependencies:
assure-array "^1.0.0"

Loading…
Cancel
Save