mirror of
https://github.com/swc-project/swc.git
synced 2024-12-18 19:21:33 +03:00
241 lines
7.2 KiB
JavaScript
241 lines
7.2 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
|
|
});
|