mirror of
https://github.com/swc-project/swc.git
synced 2024-12-20 12:12:16 +03:00
266 lines
7.7 KiB
JavaScript
266 lines
7.7 KiB
JavaScript
function invalid(rule, params = {}, implicit = false) {
|
|
return {
|
|
rule,
|
|
params,
|
|
implicit,
|
|
};
|
|
}
|
|
function nullable(value) {
|
|
if (typeof value === "undefined") {
|
|
return invalid(
|
|
"nullable",
|
|
{
|
|
value,
|
|
},
|
|
true
|
|
);
|
|
}
|
|
}
|
|
function isNullable(rules) {
|
|
return rules.find((rule) => rule === nullable) ? true : false;
|
|
}
|
|
function isOptionalValue(value) {
|
|
return value === undefined || value === null || value === "";
|
|
}
|
|
function required(value) {
|
|
return isOptionalValue(value)
|
|
? invalid(
|
|
"required",
|
|
{
|
|
value,
|
|
},
|
|
true
|
|
)
|
|
: undefined;
|
|
}
|
|
function isOptional(rules) {
|
|
return rules.find((rule) => rule === required) ? false : true;
|
|
}
|
|
const resolveErrorMessage = (msg, params, attr, checkType) => {
|
|
params.attr = attr;
|
|
if (typeof msg === "function") {
|
|
return msg(params, checkType || "");
|
|
} else {
|
|
for (let key in params) {
|
|
msg = msg.replace(`:${key}`, params[key]);
|
|
}
|
|
return msg;
|
|
}
|
|
};
|
|
const getCheckType = (rule) => {
|
|
const split = rule.split(":");
|
|
split.shift();
|
|
return split.join(":");
|
|
};
|
|
const findBestMessage = (messages, key, ruleName, ruleKey, defaultMessage) => {
|
|
return (
|
|
messages[`${key}.${ruleName}`] ||
|
|
messages[`${key}.${ruleKey}`] ||
|
|
messages[key] ||
|
|
messages[ruleName] ||
|
|
messages[ruleKey] ||
|
|
defaultMessage
|
|
);
|
|
};
|
|
const resolveErrorMessages = (rawErrors, { messages, attributes }) => {
|
|
const errorMessages = {};
|
|
const defaultMessage = (messages || {})["default"] || ":attr is invalid";
|
|
for (let key in rawErrors) {
|
|
const errs = rawErrors[key];
|
|
const attr = (attributes || {})[key] || key;
|
|
errorMessages[key] = {};
|
|
for (let err of errs) {
|
|
const checkType = getCheckType(err.rule);
|
|
const ruleKey = checkType
|
|
? err.rule.substr(0, err.rule.length - checkType.length - 1)
|
|
: err.rule;
|
|
if (err.rule === "validateObject" && err.params.errors) {
|
|
errorMessages[key][ruleKey] = resolveErrorMessages(
|
|
err.params.errors,
|
|
{
|
|
messages,
|
|
attributes,
|
|
}
|
|
);
|
|
} else if (err.rule === "validateArray" && err.params.errors) {
|
|
errorMessages[key][ruleKey] = resolveErrorMessages(
|
|
err.params.errors,
|
|
{
|
|
messages,
|
|
attributes,
|
|
}
|
|
);
|
|
} else {
|
|
const msg = findBestMessage(
|
|
messages || {},
|
|
key,
|
|
err.rule,
|
|
ruleKey,
|
|
defaultMessage
|
|
);
|
|
errorMessages[key][ruleKey] = resolveErrorMessage(
|
|
msg,
|
|
err.params,
|
|
attr,
|
|
checkType
|
|
);
|
|
}
|
|
}
|
|
}
|
|
return errorMessages;
|
|
};
|
|
const isStringInt = (value) => {
|
|
return value.match(/^\d+$/) ? true : false;
|
|
};
|
|
const getValue = (input, key) => {
|
|
if (typeof input[key] !== "undefined") {
|
|
return input[key];
|
|
}
|
|
const paths = key.split(".");
|
|
const value = paths.reduce(
|
|
(data, path) => {
|
|
if (data && typeof data === "object") {
|
|
return data[path];
|
|
} else if (data instanceof Array && isStringInt(path)) {
|
|
const index = parseInt(path);
|
|
return data[index];
|
|
}
|
|
},
|
|
{
|
|
...input,
|
|
}
|
|
);
|
|
return value;
|
|
};
|
|
const hasValue = (input, key) => {
|
|
const value = getValue(input, key);
|
|
return typeof value !== "undefined";
|
|
};
|
|
const makeValidationUtils = (input) => {
|
|
return {
|
|
getValue: (key) => getValue(input, key),
|
|
hasValue: (key) => hasValue(input, key),
|
|
};
|
|
};
|
|
const defaultMessages = {
|
|
"fileExists:pathCheck": "file :value doesn't exists",
|
|
"fileExists:stringCheck": "file path must be a string",
|
|
isArray: ":attr must be an array",
|
|
isBool: ":attr must be a boolean",
|
|
isEmail: ":attr is not a valid email address",
|
|
isFloat: ":attr must be a float number",
|
|
isIn: ":value is not allowed",
|
|
isInt: ":attr must be an integer",
|
|
isNumber: ":attr must be a number",
|
|
isNumeric: ":attr must be numeric",
|
|
isString: ":attr must be a string",
|
|
lengthBetween:
|
|
":attr characters length must be between :minLength-:maxLength",
|
|
match: ":attr format is incorrect",
|
|
maxLength: ":attr cannot be higher than :maxValue characters",
|
|
maxNumber: ":attr cannot be higher than :maxValue",
|
|
minLength: ":attr cannot be lower than :minValue characters",
|
|
minNumber: ":attr cannot be lower than :minValue",
|
|
notIn: ":value is not allowed",
|
|
notNull: ":value cannot be null",
|
|
numberBetween: ":value must be between :minValue - :maxValue",
|
|
required: ":attr is required",
|
|
default: ":attr is invalid",
|
|
};
|
|
const getValue1 = (input, key) => {
|
|
return input[key];
|
|
};
|
|
const optionallyRequired = new Set([
|
|
"requiredWhenRule",
|
|
"requiredIfRule",
|
|
"requiredUnlessRule",
|
|
]);
|
|
const validateValue = async (value, rules, utils) => {
|
|
const results = [];
|
|
if (isOptionalValue(value) && isOptional(rules)) {
|
|
const optionallyRequiredRules = rules.filter((r) =>
|
|
optionallyRequired.has(r.name)
|
|
);
|
|
if (optionallyRequiredRules.length === 0) {
|
|
return [];
|
|
}
|
|
for (let rule of rules.filter((r) => optionallyRequired.has(r.name))) {
|
|
let res = rule(value, utils);
|
|
if (res instanceof Promise) {
|
|
res = await res;
|
|
}
|
|
if (res !== undefined && res.noContext) {
|
|
return [];
|
|
}
|
|
if (res !== undefined) {
|
|
results.push(res);
|
|
if (res.implicit) {
|
|
return results;
|
|
}
|
|
}
|
|
}
|
|
rules = rules.filter((r) => !optionallyRequired.has(r.name));
|
|
}
|
|
if (typeof value === "object" && value === null && isNullable(rules)) {
|
|
return [];
|
|
}
|
|
for (let rule of rules) {
|
|
let res = rule(value, utils);
|
|
if (res instanceof Promise) {
|
|
res = await res;
|
|
}
|
|
if (res !== undefined && !res.noContext) {
|
|
results.push(res);
|
|
if (res.implicit === true) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return results;
|
|
};
|
|
const validateData = async (input, rules) => {
|
|
const results = {};
|
|
const utils = makeValidationUtils(input);
|
|
for (let key in rules) {
|
|
const keyRules =
|
|
rules[key] instanceof Array ? rules[key] : [rules[key]];
|
|
const value = getValue1(input, key);
|
|
const errors = await validateValue(value, keyRules, utils);
|
|
if (errors.length) {
|
|
results[key] = errors;
|
|
}
|
|
}
|
|
return results;
|
|
};
|
|
const validate = async (
|
|
input,
|
|
rules,
|
|
options = {
|
|
messages: defaultMessages,
|
|
}
|
|
) => {
|
|
const rawErrors = await validateData(input, rules);
|
|
const passes = Object.keys(rawErrors).length === 0;
|
|
const errors = passes ? {} : resolveErrorMessages(rawErrors, options);
|
|
return [passes, errors];
|
|
};
|
|
function isNumber(value) {
|
|
if (typeof value !== "number") {
|
|
return invalid("isNumber", {
|
|
value,
|
|
});
|
|
}
|
|
}
|
|
const inputs = {
|
|
name: "",
|
|
age: "20",
|
|
};
|
|
const [passes1, errors1] = await validate(inputs, {
|
|
name: required,
|
|
age: [required, isNumber],
|
|
});
|
|
console.log({
|
|
passes: passes1,
|
|
errors: errors1,
|
|
});
|