You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
2.5 KiB
JavaScript
119 lines
2.5 KiB
JavaScript
"use strict";
|
|
|
|
const errorChain = require("error-chain");
|
|
|
|
let ValidationError = errorChain("ValidationError");
|
|
|
|
function isPresent(value) {
|
|
if (value == null) {
|
|
throw new ValidationError("Required value is missing", { errorType: "isPresent" });
|
|
}
|
|
}
|
|
|
|
function isString(value) {
|
|
if (value != null && typeof value !== "string") {
|
|
throw new ValidationError("Value is not a string", { errorType: "isString" });
|
|
}
|
|
}
|
|
|
|
function isOneOf(...acceptableValues) {
|
|
let valueSet = new Set(acceptableValues);
|
|
|
|
return function (value) {
|
|
if (value != null && !valueSet.has(value)) {
|
|
throw new ValidationError("Value is not one of the specified acceptable values", {
|
|
errorType: "isOneOf",
|
|
acceptableValues: acceptableValues
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
/* NOTE: Extremely sketchy way of tracking validation state via a module-global object, but we can get away with this because validation is completely synchronous */
|
|
let context;
|
|
|
|
function assertProperties(object, properties) {
|
|
for (let [property, assertions] of Object.entries(properties)) {
|
|
context.path.push(property);
|
|
|
|
let value = object[property];
|
|
|
|
try {
|
|
for (let assertion of assertions) {
|
|
assertion(value);
|
|
}
|
|
} catch (error) {
|
|
if (error.input == null) {
|
|
error.input = value;
|
|
}
|
|
|
|
throw error;
|
|
}
|
|
|
|
context.path.pop();
|
|
}
|
|
}
|
|
|
|
function arrayOf(assertions) {
|
|
return function (value) {
|
|
if (value != null) {
|
|
if (!Array.isArray(value)) {
|
|
throw new ValidationError("Value is not an array", { errorType: "arrayOf" });
|
|
} else {
|
|
for (let [i, item] of value.entries()) {
|
|
context.path.push(i);
|
|
|
|
try {
|
|
for (let assertion of assertions) {
|
|
assertion(item);
|
|
}
|
|
} catch (error) {
|
|
if (error.input == null) {
|
|
error.input = value;
|
|
}
|
|
|
|
throw error;
|
|
}
|
|
|
|
context.path.pop();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
function validate(validator, value) {
|
|
context = {
|
|
path: []
|
|
};
|
|
|
|
try {
|
|
validator(value);
|
|
} catch (error) {
|
|
if (error.path == null) {
|
|
error.path = context.path;
|
|
}
|
|
|
|
throw error;
|
|
}
|
|
|
|
context = undefined;
|
|
}
|
|
|
|
module.exports = {
|
|
validate, assertProperties, ValidationError,
|
|
isPresent, isString, isOneOf, arrayOf
|
|
};
|
|
|
|
// try {
|
|
// validate(validateLoginPayload, {
|
|
// type: 'm.login.password',
|
|
// password: 'test',
|
|
// identifier: { type: 'm.id.user', user: 'joepie91' },
|
|
// initial_device_display_name: 'http://localhost:3001/index.html via Firefox on Linux',
|
|
// user: 'joepie91',
|
|
// arrayStuff: [ 42 ]
|
|
// });
|
|
// } catch (error) {
|
|
// console.log(require("util").inspect(error, {colors: true, depth: null}));
|
|
// }
|