UNPKG

@vulcan-sql/core

Version:
184 lines 8.52 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ParametersChecker = void 0; const tslib_1 = require("tslib"); const models_1 = require("../../../../models/index"); const lodash_1 = require("lodash"); const nunjucks = require("nunjucks"); const utils_1 = require("../../../utils/index"); const constants_1 = require("./constants"); const inversify_1 = require("inversify"); const types_1 = require("../../../../containers/types"); const extension_utils_1 = require("../../extension-utils"); // Validation filters (VF) which meet the following requirements can be PreCheck Validation Filters (PCVF) // 1. All arguments should be static. (O) context.params.id | number(max=20) , (X) context.params.id | number(max=var) // 2. Filters should be applied right after the parameters. (O) context.params.id | number(max=20), (X) context.params.id | upper | number(max=20) // 3. Filters should not be applied on the children of parameters. (O) context.params.id | number(max=20), (X) context.params.id.account | number(max=20) let ParametersChecker = class ParametersChecker extends models_1.CompileTimeExtension { constructor(config, moduleName, validatorLoader) { super(config, moduleName); this.metadataName = constants_1.PARAMETER_METADATA_NAME; this.parameters = new Map(); this.validationFilterNames = new Set(); validatorLoader .getValidators() .forEach((validator) => this.validationFilterNames.add((0, extension_utils_1.getValidationFilterName)(validator))); } onVisit(node) { // Clear parameters at the begin if (node instanceof nunjucks.nodes.Root) this.parameters.clear(); // Extract parameter from lookupVal node: {{ context.params.xxx }} if (node instanceof nunjucks.nodes.LookupVal) { const parameter = this.getParametersOfLookupNode(node); this.addParameter(parameter); return; } // Visit the children and replace the preCheck validation filters. {{ context.params.xxx | xxx() }} (0, extension_utils_1.visitChildren)(node, (child, replace) => { if (!this.isPreCheckValidationFilterNode(child)) return; const parameter = this.getParametersOfPCVFNode(child); if (!parameter) return; replace(parameter.nodes[0]); this.addParameter(parameter); }); } getMetadata() { return (0, lodash_1.chain)(Array.from(this.parameters.values())) .map((parameter) => ({ name: parameter.name, locations: parameter.nodes.map((node) => ({ lineNo: node.lineno, columnNo: node.colno, })), validators: parameter.validators, })) .value(); } /** Get parameters from PreCheck Validation Filter node */ getParametersOfPCVFNode(node) { const target = node.args.children[0]; let parameter = null; if (target instanceof nunjucks.nodes.LookupVal) { // Get the parameter if our target is a lookup node parameter = this.getParametersOfLookupNode(target); } else if (this.isPreCheckValidationFilterNode(target)) { // Get its parameter if our target is still a PreCheck node parameter = this.getParametersOfPCVFNode(target); } // Check args const args = {}; const argsNode = node.args.children[1]; if (argsNode) { // (max=10, min=0) --> KeywordArgs if (!(argsNode instanceof nunjucks.nodes.KeywordArgs)) { throw new utils_1.TemplateError(`The arguments of validation filter ${node.name.value} is invalid`, { node: argsNode, }); } for (const arg of argsNode.children) { // max=10 --> Pair if (!(arg instanceof nunjucks.nodes.Pair)) { throw new utils_1.TemplateError(`The arguments of validation filter ${node.name.value} is invalid`, { node: arg, }); } if (arg.value instanceof nunjucks.nodes.Literal) { // Static value, set the value. e.g. a=1, a="s", a=true ... args[arg.key.value] = arg.value.value; } else if (arg.value instanceof nunjucks.nodes.Array && arg.value.children.every((child) => child instanceof nunjucks.nodes.Literal)) { // Static array value, set the value. e.g. a=[1,2,3] args[arg.key.value] = arg.value.children.map((child) => child.value); } else { // Dynamic value, set to null because we know the value only when executing. args[arg.key.value] = null; } } } // 1. All arguments should be static. (O) context.params.id | number(max=20) , (X) context.params.id | number(max=var) if ((0, lodash_1.values)(args).some((value) => value === null)) return null; // 3. Filters should not be applied on the children of parameters. (O) context.params.id | number(max=20), (X) context.params.id.account | number(max=20) if (parameter === null || parameter === void 0 ? void 0 : parameter.name.includes('.')) return null; parameter === null || parameter === void 0 ? void 0 : parameter.validators.push({ name: (0, extension_utils_1.getValidatorName)(node.name.value), args, }); return parameter; } /** Return the name and position of parameters if found */ getParametersOfLookupNode(node) { let name = node.val.value; let target = node.target; let depth = 0; while (target) { depth++; if (depth > constants_1.REFERENCE_SEARCH_MAX_DEPTH) { throw new utils_1.InternalError('Max depth reached'); } if (target instanceof nunjucks.nodes.LookupVal) { name = target.val.value + '.' + name; target = target.target; } else if (target instanceof nunjucks.nodes.FunCall) { target = target.name; } else { name = target.value + '.' + name; const lookUp = constants_1.LOOK_UP_PARAMETER + '.'; if (name.startsWith(lookUp)) { return { name: name.replace(lookUp, ''), validators: [], nodes: [node], }; } break; } } return null; } isValidationFilterNode(node) { return (node instanceof nunjucks.nodes.Filter && node.name instanceof nunjucks.nodes.Symbol && this.validationFilterNames.has(node.name.value)); } isPreCheckValidationFilterNode(node) { return (this.isValidationFilterNode(node) && // 1. All arguments should be static. node.args.children .slice(1) // The first argument is the target of the filter .every((arg) => !(arg instanceof nunjucks.nodes.LookupVal))); } addParameter(parameter) { if (!parameter) return; if (!this.parameters.has(parameter.name)) { this.parameters.set(parameter.name, parameter); } else { const existedParam = this.parameters.get(parameter.name); // If node is already in our collection, ignore it. if (existedParam.nodes.includes(parameter.nodes[0])) return; existedParam.validators.push(...parameter.validators); existedParam.nodes.push(...parameter.nodes); } } }; ParametersChecker = tslib_1.__decorate([ (0, models_1.VulcanInternalExtension)(), tslib_1.__param(0, (0, inversify_1.inject)(types_1.TYPES.ExtensionConfig)), tslib_1.__param(1, (0, inversify_1.inject)(types_1.TYPES.ExtensionName)), tslib_1.__param(2, (0, inversify_1.inject)(types_1.TYPES.ValidatorLoader)), tslib_1.__metadata("design:paramtypes", [Object, String, Object]) ], ParametersChecker); exports.ParametersChecker = ParametersChecker; //# sourceMappingURL=parametersChecker.js.map