UNPKG

@resin/pinejs

Version:

Pine.js is a sophisticated rules-driven API engine that enables you to define rules in a structured subset of English. Those rules are used in order for Pine.js to generate a database schema and the associated [OData](http://www.odata.org/) API. This make

141 lines 5.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isRuleAffected = exports.getAndCheckBindValues = exports.resolveOdataBind = exports.compileRequest = void 0; const Bluebird = require("bluebird"); const _ = require("lodash"); const AbstractSQLCompiler = require("@resin/abstract-sql-compiler"); const odata_to_abstract_sql_1 = require("@resin/odata-to-abstract-sql"); const deepFreeze = require("deep-freeze"); const memoize = require("memoizee"); const memoizeWeak = require("memoizee/weak"); const env = require("../config-loader/env"); const errors_1 = require("./errors"); const sbvrUtils = require("./sbvr-utils"); const getMemoizedCompileRule = memoize((engine) => memoizeWeak((abstractSqlQuery) => { const sqlQuery = AbstractSQLCompiler[engine].compileRule(abstractSqlQuery); const modifiedFields = AbstractSQLCompiler[engine].getModifiedFields(abstractSqlQuery); if (modifiedFields != null) { deepFreeze(modifiedFields); } return { sqlQuery, modifiedFields, }; }, { max: env.cache.abstractSqlCompiler.max }), { primitive: true }); exports.compileRequest = (request) => { if (request.abstractSqlQuery != null) { const { engine } = request; if (engine == null) { throw new errors_1.SqlCompilationError('No database engine specified'); } try { const { sqlQuery, modifiedFields } = getMemoizedCompileRule(engine)(request.abstractSqlQuery); request.sqlQuery = sqlQuery; request.modifiedFields = modifiedFields; } catch (err) { sbvrUtils.api[request.vocabulary].logger.error('Failed to compile abstract sql: ', request.abstractSqlQuery, err); throw new errors_1.SqlCompilationError(err); } } return request; }; exports.resolveOdataBind = (odataBinds, value) => { if (typeof value === 'object' && value != null && value.bind != null) { [, value] = odataBinds[value.bind]; } return value; }; exports.getAndCheckBindValues = (request, bindings) => { const { odataBinds, values, engine } = request; const sqlModelTables = sbvrUtils.getAbstractSqlModel(request).tables; return Bluebird.map(bindings, async (binding) => { let fieldName = ''; let field; let value; if (binding[0] === 'Bind') { const bindValue = binding[1]; if (Array.isArray(bindValue)) { let tableName; [tableName, fieldName] = bindValue; const referencedName = tableName + '.' + fieldName; value = values[referencedName]; if (value === undefined) { value = values[fieldName]; } value = exports.resolveOdataBind(odataBinds, value); const sqlTableName = odata_to_abstract_sql_1.odataNameToSqlName(tableName); const sqlFieldName = odata_to_abstract_sql_1.odataNameToSqlName(fieldName); const maybeField = sqlModelTables[sqlTableName].fields.find((f) => f.fieldName === sqlFieldName); if (maybeField == null) { throw new Error(`Could not find field '${fieldName}'`); } field = maybeField; } else if (Number.isInteger(bindValue)) { if (bindValue >= odataBinds.length) { console.error(`Invalid binding number '${bindValue}' for binds: `, odataBinds); throw new Error('Invalid binding'); } let dataType; [dataType, value] = odataBinds[bindValue]; field = { dataType }; } else if (typeof bindValue === 'string') { if (!odataBinds.hasOwnProperty(bindValue)) { console.error(`Invalid binding '${bindValue}' for binds: `, odataBinds); throw new Error('Invalid binding'); } let dataType; [dataType, value] = odataBinds[bindValue]; field = { dataType }; } else { throw new Error(`Unknown binding: ${binding}`); } } else { let dataType; [dataType, value] = binding; field = { dataType }; } if (value === undefined) { throw new Error(`Bind value cannot be undefined: ${binding}`); } try { return await AbstractSQLCompiler[engine].dataTypeValidate(value, field); } catch (err) { err.message = `"${fieldName}" ${err.message}`; throw err; } }); }; const checkModifiedFields = (referencedFields, modifiedFields) => { const refs = referencedFields[modifiedFields.table]; if (refs == null) { return false; } if (modifiedFields.fields == null) { return true; } return _.intersection(refs, modifiedFields.fields).length > 0; }; exports.isRuleAffected = (rule, request) => { if (request == null || request.abstractSqlQuery == null) { return false; } if (rule.referencedFields == null) { return true; } const { modifiedFields } = request; if (modifiedFields == null) { console.warn(`Could not determine the modified table/fields info for '${request.method}' to ${request.vocabulary}`, request.abstractSqlQuery); return true; } if (Array.isArray(modifiedFields)) { return modifiedFields.some(_.partial(checkModifiedFields, rule.referencedFields)); } return checkModifiedFields(rule.referencedFields, modifiedFields); }; //# sourceMappingURL=abstract-sql.js.map