moleculer-api
Version:
A dynamic API Gateway for MoleculerJS which updates REST endpoints and aggregated GraphQL schema, access control policy for each action calls from metadata of remote services schema without restart or deployment.
159 lines • 5.94 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateInlineFunction = exports.validateValue = exports.compileValidationRule = exports.validateObject = exports.compileValidationSchema = exports.normalizeValidationSchema = void 0;
const tslib_1 = require("tslib");
/*
extends validation type definition and normalize validation schema for catalog document
ref: https://github.com/icebob/fastest-validator
*/
const _ = tslib_1.__importStar(require("lodash"));
const fastest_validator_1 = tslib_1.__importDefault(require("fastest-validator"));
const vm = tslib_1.__importStar(require("vm"));
/*
oneOf.items: Array<NormalizedValidationSchema>
object.props NormalizedValidationSchema
array.items: NormalizedValidationSchema[string]
*/
function normalizeValidationSchema(schema) {
const normalizedSchema = {};
for (const [paramName, paramSchema] of Object.entries(schema)) {
normalizedSchema[paramName] = recNormalizeValidationSchema(paramSchema);
}
return normalizedSchema;
}
exports.normalizeValidationSchema = normalizeValidationSchema;
function recNormalizeValidationSchema(paramSchema) {
let schema;
if (typeof paramSchema === "string") {
// normalize sugar syntax
// like "string", "number|optional|integer|positive|min:0|max:99", ...
// ref: https://github.com/icebob/fastest-validator/releases/tag/v1.0.0-beta1
schema = {
type: paramSchema,
deprecated: false,
description: null,
};
const tokens = paramSchema.split("|").filter(t => t);
if (tokens.length > 1) {
for (let i = 1; i < tokens.length; i++) {
const token = tokens[i];
const subTokens = token.split(":").filter(t => t);
if (subTokens.length === 1) {
schema[token] = true;
}
else if (subTokens.length === 2) {
const asNum = parseInt(subTokens[1], 10);
schema[token] = isNaN(asNum) ? subTokens[1] : asNum;
}
}
}
}
else if (Array.isArray(paramSchema)) {
// normalize array syntax
const items = paramSchema.map(s => recNormalizeValidationSchema(s));
schema = {
type: "oneOf",
deprecated: false,
description: null,
optional: items.every(item => item.optional),
items: paramSchema.map(s => recNormalizeValidationSchema(s)),
};
}
else if (paramSchema && typeof paramSchema === "object") {
// normalize recursive rules
schema = _.cloneDeep(paramSchema);
if (schema.type === "object") {
if (schema.props) {
schema.props = normalizeValidationSchema(schema.props);
}
}
else if (schema.type === "array") {
if (schema.items) {
schema.items = recNormalizeValidationSchema(schema.items);
}
}
}
else {
// normalize unknown syntax
schema = {
type: "any",
description: null,
deprecated: false,
schema: paramSchema,
};
}
// normalize optional props
if (!schema.description)
schema.description = null;
schema.deprecated = !!schema.deprecated;
schema.optional = !!schema.optional || typeof schema.default !== "undefined";
return schema;
}
function compileValidationSchema(schema, opts) {
const options = _.defaultsDeep(opts || {}, { strict: true, field: "", messages: {} });
// apply messages option
const validator = new fastest_validator_1.default({ messages: options.messages });
// prepare field (prefix) option
const prefix = options.field.trim();
if (prefix) {
const prefixedSchema = {};
for (const [k, v] of Object.entries(schema)) {
prefixedSchema[`${prefix}.${k}`] = v;
}
schema = prefixedSchema;
}
// apply strict option
schema.$$strict = !options.strict;
// create checker
const check = validator.compile(schema);
if (prefix) {
return (value) => {
let prefixedValue = value;
if (typeof value === "object" && value !== null) {
prefixedValue = {};
for (const [k, v] of Object.entries(value)) {
prefixedValue[`${prefix}.${k}`] = v;
}
}
return check(prefixedValue);
};
}
return check;
}
exports.compileValidationSchema = compileValidationSchema;
function validateObject(obj, schema, opts) {
const result = compileValidationSchema(schema, opts)(obj);
return result === true ? [] : result;
}
exports.validateObject = validateObject;
function compileValidationRule(rule, opts) {
const options = _.defaultsDeep(opts || {}, { strict: true, field: "value", messages: {} });
// apply messages option
const validator = new fastest_validator_1.default({ messages: options.messages });
// apply field option
const schema = { [options.field]: rule };
// apply strict option
schema.$$strict = !options.strict;
// create checker
const check = validator.compile(schema);
return (value) => check({ [options.field]: value });
}
exports.compileValidationRule = compileValidationRule;
function validateValue(value, rule, opts) {
const result = compileValidationRule(rule, opts)(value);
return result === true ? [] : result;
}
exports.validateValue = validateValue;
function validateInlineFunction(fnString) {
try {
return vm.runInNewContext(`typeof (${fnString}) === "function"`, {}, {
displayErrors: true,
timeout: 100,
});
}
catch (_a) {
return false;
}
}
exports.validateInlineFunction = validateInlineFunction;
//# sourceMappingURL=validation.js.map