@5minds/processcube_engine
Version:
The ProcessCube Engine. Stores and executes BPMNs.
72 lines • 3.71 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = ensureDatabaseIntegrity;
const Configurator_1 = __importDefault(require("../../Configurator"));
const SequelizeConnectionManager_1 = __importDefault(require("./SequelizeConnectionManager"));
async function ensureDatabaseIntegrity() {
const sequelizeInstance = await (0, SequelizeConnectionManager_1.default)();
const registeredModels = Object.keys(sequelizeInstance.models);
const validationErrors = {};
for (const modelName of registeredModels) {
const model = sequelizeInstance.models[modelName];
const table = (await getTableInfo(sequelizeInstance, model.tableName));
if (!table) {
validationErrors[model.tableName] = 'Table does not exist.';
continue;
}
const tableValidationErrors = compareModelAgainstTable(model, table);
if (tableValidationErrors.length > 0) {
validationErrors[model.tableName] = tableValidationErrors;
}
}
return validationErrors;
}
/**
* The following conditions need to be met, in order for a table to be recognized as compatible:
* - Each attribute on the model must exist as table-column
* - Each extraneous table-column must allow null values, or supply a default value (because the model won't access it)
* - If a model's attribute allows null values, the corresponding table column must allow null values as well
*/
function compareModelAgainstTable(model, tableColumnCollection) {
const modelAttributeNames = Object.keys(model.getAttributes());
const tableColumnNames = Object.keys(tableColumnCollection);
const validationErrors = [];
for (const attributeName of modelAttributeNames) {
if (!tableColumnNames.includes(attributeName)) {
validationErrors.push(`Required column \`${attributeName}\` is missing.`);
}
}
for (const tableColumnName of tableColumnNames) {
const columnInfo = tableColumnCollection[tableColumnName];
const modelHasNoMatchingAttribute = !modelAttributeNames.includes(tableColumnName);
if (modelHasNoMatchingAttribute && !columnInfo.allowNull && !columnInfo.defaultValue) {
validationErrors.push(`Extraneous Column \`${tableColumnName}\` must be nullable or supply a default value, because it is not used by the engine.`);
continue;
}
const modelAttributeInfo = model.getAttributes()[tableColumnName];
if (modelAttributeInfo != null && modelAttributeInfo.allowNull && modelAttributeInfo.defaultValue == null && !columnInfo.allowNull) {
validationErrors.push(`Column \`${tableColumnName}\` is expected to be nullable.`);
}
}
return validationErrors;
}
async function getTableInfo(sequelizeInstance, tableName) {
try {
const dbConfig = Configurator_1.default.database();
const queryInterface = sequelizeInstance.getQueryInterface();
const schema = !dbConfig.schema && dbConfig.dialect === 'mssql' ? 'dbo' : dbConfig.schema;
if (dbConfig.dialect === 'sqlite') {
const tableNamePrefix = schema ? `${schema}.` : '';
const tableInfoQuery = `PRAGMA TABLE_INFO(\`${tableNamePrefix}${tableName}\`);`;
return queryInterface.sequelize.query(tableInfoQuery);
}
return queryInterface.describeTable({ tableName: tableName, schema: schema }, { schema: schema });
}
catch (error) {
return undefined;
}
}
//# sourceMappingURL=DatabaseIntegrityChecker.js.map