@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
JavaScript
;
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