UNPKG

@onn-software/ddl-to-gql

Version:

Convert a SQL DDL to a GraphQL implementation with all relations.

117 lines (116 loc) 5.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HeuristicEngine = void 0; class HeuristicEngine { execute(tableDefs, options) { const flatTableDefs = this.flattenNames(tableDefs); const suffixes = options.suffixes.map(s => s.toUpperCase()); const res = []; const heuristics = {}; flatTableDefs.forEach((t) => (heuristics[t.tableName] = { tableName: t.tableName, columns: [], relations: [] })); this.crossAllTableAndColumnDefinitions(flatTableDefs, (leftTable, leftCol, rightTable, rightCol) => { const relationsByNameMatch = this.missingRelationByNameMatch(leftTable, leftCol, rightTable, rightCol, suffixes, options.heurEnableAll ?? false); if (relationsByNameMatch) { heuristics[leftTable.tableName].relations.push(relationsByNameMatch); } const relationsBySuffix = this.missingRelationBySuffix(leftTable, leftCol, rightTable, rightCol, suffixes, options.heurEnableAll ?? false); if (relationsBySuffix) { heuristics[leftTable.tableName].relations.push(relationsBySuffix); } }); return Object.values(heuristics); } flattenNames(tableDefs) { const res = JSON.parse(JSON.stringify(tableDefs)); res.forEach((table) => { table.flatTableName = table.tableName.replaceAll(/[^a-zA-Z0-9]/g, '').toUpperCase(); table.columns.forEach((col) => { col.flatKeyName = col.key.replaceAll(/[^a-zA-Z0-9]/g, '').toUpperCase(); }); }); return res; } missingRelationByNameMatch(leftTableDef, leftCol, rightTableDef, rightCol, suffixes, heurEnableAll) { const nameMatch = leftCol.flatKeyName === rightCol.flatKeyName; const typeMatch = leftCol.type === rightCol.type; const isSuffix = suffixes.indexOf(leftCol.flatKeyName) >= 0; if (nameMatch && typeMatch && !isSuffix) { return this.buildRelation(leftTableDef, leftCol, rightTableDef, rightCol, true, 'nameMatch', heurEnableAll); } return null; } missingRelationBySuffix(leftTableDef, leftCol, rightTableDef, rightCol, suffixes, heurEnableAll) { if (leftCol.type !== rightCol.type) { return null; } const leftSuffix = suffixes.find((suf) => leftCol.flatKeyName.endsWith(suf)); const rightSuffix = suffixes.find((suf) => rightCol.flatKeyName.endsWith(suf)); if (!leftSuffix || !rightSuffix) { return null; } if (leftSuffix !== rightSuffix) { return null; } const leftSuffixIndex = leftCol.flatKeyName.indexOf(leftSuffix); const rightSuffixIndex = rightCol.flatKeyName.indexOf(rightSuffix); const leftEndsWithSuffix = leftSuffixIndex > 0; const leftIsSuffix = leftSuffixIndex == 0; const rightEndsWithSuffix = rightSuffixIndex > 0; const rightIsSuffix = rightSuffixIndex == 0; if (!((leftEndsWithSuffix && rightIsSuffix) || (rightEndsWithSuffix && leftIsSuffix))) { return null; } const leftFlatKey = leftCol.flatKeyName.substring(0, leftSuffixIndex) || leftCol.flatKeyName; const rightFlatKey = rightCol.flatKeyName.substring(0, rightSuffixIndex) || rightCol.flatKeyName; if (leftTableDef.flatTableName !== rightFlatKey && leftTableDef.flatTableName !== `${rightFlatKey}S` && rightTableDef.flatTableName !== leftFlatKey && rightTableDef.flatTableName !== `${leftFlatKey}S`) { return null; } return this.buildRelation(leftTableDef, leftCol, rightTableDef, rightCol, leftIsSuffix, 'suffixMatch', heurEnableAll); } buildRelation(leftTableDef, leftCol, rightTableDef, rightCol, many, type, heurEnableAll) { const relationsAlreadyExists = leftTableDef.relations.findIndex((value) => { return ((value.from.table === leftTableDef.tableName && value.from.key === leftCol.key && value.to.table === rightTableDef.tableName && value.to.key === rightCol.key) || (value.to.table === leftTableDef.tableName && value.to.key === leftCol.key && value.from.table === rightTableDef.tableName && value.from.key === rightCol.key)); }) >= 0; if (!relationsAlreadyExists) { return { from: { table: leftTableDef.tableName, key: leftCol.key, }, to: { table: rightTableDef.tableName, key: rightCol.key, }, many, type, enabled: heurEnableAll, nullable: !many, }; } return null; } crossAllTableAndColumnDefinitions(flatTableDefs, block) { flatTableDefs.forEach((leftTableDef) => { leftTableDef.columns.forEach((leftCol) => { flatTableDefs.forEach((rightTableDef) => { if (rightTableDef.flatTableName !== leftTableDef.flatTableName) { rightTableDef.columns.forEach((rightCol) => { block(leftTableDef, leftCol, rightTableDef, rightCol); }); } }); }); }); } } exports.HeuristicEngine = HeuristicEngine;