diff --git a/packages/api/src/controllers/databaseConnections.js b/packages/api/src/controllers/databaseConnections.js index be16f7e95..37a5a0a9b 100644 --- a/packages/api/src/controllers/databaseConnections.js +++ b/packages/api/src/controllers/databaseConnections.js @@ -2,7 +2,7 @@ const uuidv1 = require('uuid/v1'); const connections = require('./connections'); const socket = require('../utility/socket'); const { fork } = require('child_process'); -const DatabaseAnalyser = require('dbgate-engines/default/DatabaseAnalyser'); +const { DatabaseAnalyser } = require('dbgate-tools'); module.exports = { /** @type {import('dbgate-types').OpenedDatabaseConnection[]} */ diff --git a/packages/engines/mssql/MsSqlAnalyser.js b/packages/engines/mssql/MsSqlAnalyser.js index 8a272a3c8..7804a4c69 100644 --- a/packages/engines/mssql/MsSqlAnalyser.js +++ b/packages/engines/mssql/MsSqlAnalyser.js @@ -2,7 +2,7 @@ const fp = require('lodash/fp'); const _ = require('lodash'); const sql = require('./sql'); -const DatabaseAnalyser = require('../default/DatabaseAnalyser'); +const { DatabaseAnalyser } = require('dbgate-tools'); const { filter } = require('lodash'); const { isTypeString, isTypeNumeric } = require('dbgate-tools'); diff --git a/packages/engines/mssql/MsSqlDumper.js b/packages/engines/mssql/MsSqlDumper.js index ba5bf0b8a..652fc5016 100644 --- a/packages/engines/mssql/MsSqlDumper.js +++ b/packages/engines/mssql/MsSqlDumper.js @@ -1,4 +1,4 @@ -const SqlDumper = require('../default/SqlDumper'); +const { SqlDumper } = require('dbgate-tools'); class MsSqlDumper extends SqlDumper { autoIncrement() { diff --git a/packages/engines/mssql/createBulkInsertStream.js b/packages/engines/mssql/createBulkInsertStream.js index b3f345102..991783b84 100644 --- a/packages/engines/mssql/createBulkInsertStream.js +++ b/packages/engines/mssql/createBulkInsertStream.js @@ -1,4 +1,4 @@ -const createBulkInsertStreamBase = require('../default/createBulkInsertStreamBase'); +const { createBulkInsertStreamBase } = require('dbgate-tools'); /** * diff --git a/packages/engines/mssql/index.js b/packages/engines/mssql/index.js index 2eda2cde9..f09eec170 100644 --- a/packages/engines/mssql/index.js +++ b/packages/engines/mssql/index.js @@ -1,8 +1,8 @@ const _ = require('lodash'); +const { driverBase } = require('dbgate-tools'); const MsSqlAnalyser = require('./MsSqlAnalyser'); const MsSqlDumper = require('./MsSqlDumper'); const createBulkInsertStream = require('./createBulkInsertStream'); -const driverBase = require('../default/driverBase'); /** @type {import('dbgate-types').SqlDialect} */ const dialect = { diff --git a/packages/engines/mysql/MySqlAnalyser.js b/packages/engines/mysql/MySqlAnalyser.js index 64de86467..4ce5aa1a8 100644 --- a/packages/engines/mysql/MySqlAnalyser.js +++ b/packages/engines/mysql/MySqlAnalyser.js @@ -2,7 +2,7 @@ const fp = require('lodash/fp'); const _ = require('lodash'); const sql = require('./sql'); -const DatabaseAnalayser = require('../default/DatabaseAnalyser'); +const { DatabaseAnalyser } = require('dbgate-tools'); const { isTypeString, isTypeNumeric } = require('dbgate-tools'); const { rangeStep } = require('lodash/fp'); @@ -35,7 +35,7 @@ function objectTypeToField(type) { return null; } -class MySqlAnalyser extends DatabaseAnalayser { +class MySqlAnalyser extends DatabaseAnalyser { constructor(pool, driver) { super(pool, driver); } @@ -103,8 +103,8 @@ class MySqlAnalyser extends DatabaseAnalayser { tables: tables.rows.map((table) => ({ ...table, columns: columns.rows.filter((col) => col.pureName == table.pureName).map(getColumnInfo), - primaryKey: DatabaseAnalayser.extractPrimaryKeys(table, pkColumns.rows), - foreignKeys: DatabaseAnalayser.extractForeignKeys(table, fkColumns.rows), + primaryKey: DatabaseAnalyser.extractPrimaryKeys(table, pkColumns.rows), + foreignKeys: DatabaseAnalyser.extractForeignKeys(table, fkColumns.rows), })), views: views.rows.map((view) => ({ ...view, diff --git a/packages/engines/mysql/MySqlDumper.js b/packages/engines/mysql/MySqlDumper.js index 3b778de0c..0a5e6922d 100644 --- a/packages/engines/mysql/MySqlDumper.js +++ b/packages/engines/mysql/MySqlDumper.js @@ -1,4 +1,4 @@ -const SqlDumper = require('../default/SqlDumper'); +const { SqlDumper } = require('dbgate-tools'); class MySqlDumper extends SqlDumper { /** @param type {import('dbgate-types').TransformType} */ diff --git a/packages/engines/mysql/index.js b/packages/engines/mysql/index.js index 5aee7c46d..010e7a461 100644 --- a/packages/engines/mysql/index.js +++ b/packages/engines/mysql/index.js @@ -1,4 +1,4 @@ -const driverBase = require('../default/driverBase'); +const { driverBase } = require('dbgate-tools'); const MySqlAnalyser = require('./MySqlAnalyser'); const MySqlDumper = require('./MySqlDumper'); @@ -143,6 +143,12 @@ const driver = { const { rows } = await this.query(connection, 'show databases'); return rows.map((x) => ({ name: x.Database })); }, + async writeTable(pool, name, options) { + const { stream } = pool._nativeModules; + // @ts-ignore + return createBulkInsertStreamBase(this, stream, pool, name, options); + }, + // createDumper() { // return new MySqlDumper(this); // }, diff --git a/packages/engines/postgres/PostgreAnalyser.js b/packages/engines/postgres/PostgreAnalyser.js index 16ed42b5d..79a4a32a1 100644 --- a/packages/engines/postgres/PostgreAnalyser.js +++ b/packages/engines/postgres/PostgreAnalyser.js @@ -2,7 +2,7 @@ const fp = require('lodash/fp'); const _ = require('lodash'); const sql = require('./sql'); -const DatabaseAnalayser = require('../default/DatabaseAnalyser'); +const { DatabaseAnalyser } = require('dbgate-tools'); const { isTypeString, isTypeNumeric } = require('dbgate-tools'); function normalizeTypeName(dataType) { @@ -35,7 +35,7 @@ function getColumnInfo({ }; } -class PostgreAnalyser extends DatabaseAnalayser { +class PostgreAnalyser extends DatabaseAnalyser { constructor(pool, driver) { super(pool, driver); } @@ -84,8 +84,8 @@ class PostgreAnalyser extends DatabaseAnalayser { columns: columns.rows .filter((col) => col.pureName == table.pureName && col.schemaName == table.schemaName) .map(getColumnInfo), - primaryKey: DatabaseAnalayser.extractPrimaryKeys(table, pkColumns.rows), - foreignKeys: DatabaseAnalayser.extractForeignKeys(table, fkColumns.rows), + primaryKey: DatabaseAnalyser.extractPrimaryKeys(table, pkColumns.rows), + foreignKeys: DatabaseAnalyser.extractForeignKeys(table, fkColumns.rows), })), views: views.rows.map((view) => ({ ...view, diff --git a/packages/engines/postgres/PostgreDumper.js b/packages/engines/postgres/PostgreDumper.js index 12582b547..2fe0bf076 100644 --- a/packages/engines/postgres/PostgreDumper.js +++ b/packages/engines/postgres/PostgreDumper.js @@ -1,4 +1,4 @@ -const SqlDumper = require('../default/SqlDumper'); +const { SqlDumper } = require('dbgate-tools'); class PostgreDumper extends SqlDumper { /** @param type {import('dbgate-types').TransformType} */ diff --git a/packages/engines/postgres/index.js b/packages/engines/postgres/index.js index bc09995b4..9aad592cf 100644 --- a/packages/engines/postgres/index.js +++ b/packages/engines/postgres/index.js @@ -1,5 +1,5 @@ const _ = require('lodash'); -const driverBase = require('../default/driverBase'); +const { driverBase } = require('dbgate-tools'); const PostgreAnalyser = require('./PostgreAnalyser'); const PostgreDumper = require('./PostgreDumper'); @@ -174,6 +174,11 @@ const driver = { // createDumper() { // return new PostgreDumper(this); // }, + async writeTable(pool, name, options) { + const { stream } = pool._nativeModules; + // @ts-ignore + return createBulkInsertStreamBase(this, stream, pool, name, options); + }, async listDatabases(client) { const { rows } = await this.query(client, 'SELECT datname AS name FROM pg_database WHERE datistemplate = false'); return rows; diff --git a/packages/engines/default/DatabaseAnalyser.js b/packages/tools/src/DatabaseAnalyser.ts similarity index 51% rename from packages/engines/default/DatabaseAnalyser.js rename to packages/tools/src/DatabaseAnalyser.ts index 8874a725e..47360ecca 100644 --- a/packages/engines/default/DatabaseAnalyser.js +++ b/packages/tools/src/DatabaseAnalyser.ts @@ -1,21 +1,13 @@ -const _ = require('lodash'); -const fp = require('lodash/fp'); +import { DatabaseInfo, DatabaseModification, EngineDriver } from 'dbgate-types'; +import _ from 'lodash'; +import fp from 'lodash/fp'; -class DatabaseAnalyser { - /** - * - * @param {import('dbgate-types').EngineDriver} driver - */ - constructor(pool, driver) { - this.pool = pool; - this.driver = driver; - // this.result = DatabaseAnalyser.createEmptyStructure(); - /** @type {import('dbgate-types').DatabaseInfo} */ - this.structure = null; - /** import('dbgate-types').DatabaseModification[]) */ - this.modifications = null; - this.singleObjectFilter = null; - } +export class DatabaseAnalyser { + structure: DatabaseInfo; + modifications: DatabaseModification[]; + singleObjectFilter: any; + + constructor(public pool, public driver: EngineDriver) {} async _runAnalysis() { return DatabaseAnalyser.createEmptyStructure(); @@ -80,46 +72,46 @@ class DatabaseAnalyser { // findObjectById(id) { // return this.structure.tables.find((x) => x.objectId == id); // } + + static createEmptyStructure(): DatabaseInfo { + return { + tables: [], + views: [], + functions: [], + procedures: [], + triggers: [], + schemas: [], + }; + } + + static byTableFilter(table) { + return (x) => x.pureName == table.pureName && x.schemaName == x.schemaName; + } + + static extractPrimaryKeys(table, pkColumns) { + const filtered = pkColumns.filter(DatabaseAnalyser.byTableFilter(table)); + if (filtered.length == 0) return undefined; + return { + ..._.pick(filtered[0], ['constraintName', 'schemaName', 'pureName']), + constraintType: 'primaryKey', + columns: filtered.map(fp.pick('columnName')), + }; + } + static extractForeignKeys(table, fkColumns) { + const grouped = _.groupBy(fkColumns.filter(DatabaseAnalyser.byTableFilter(table)), 'constraintName'); + return _.keys(grouped).map((constraintName) => ({ + constraintName, + constraintType: 'foreignKey', + ..._.pick(grouped[constraintName][0], [ + 'constraintName', + 'schemaName', + 'pureName', + 'refSchemaName', + 'refTableName', + 'updateAction', + 'deleteAction', + ]), + columns: grouped[constraintName].map(fp.pick(['columnName', 'refColumnName'])), + })); + } } - -/** @returns {import('dbgate-types').DatabaseInfo} */ -DatabaseAnalyser.createEmptyStructure = () => ({ - tables: [], - views: [], - functions: [], - procedures: [], - triggers: [], - schemas: [], -}); - -DatabaseAnalyser.byTableFilter = (table) => (x) => x.pureName == table.pureName && x.schemaName == x.schemaName; - -DatabaseAnalyser.extractPrimaryKeys = (table, pkColumns) => { - const filtered = pkColumns.filter(DatabaseAnalyser.byTableFilter(table)); - if (filtered.length == 0) return undefined; - return { - ..._.pick(filtered[0], ['constraintName', 'schemaName', 'pureName']), - constraintType: 'primaryKey', - columns: filtered.map(fp.pick('columnName')), - }; -}; - -DatabaseAnalyser.extractForeignKeys = (table, fkColumns) => { - const grouped = _.groupBy(fkColumns.filter(DatabaseAnalyser.byTableFilter(table)), 'constraintName'); - return _.keys(grouped).map((constraintName) => ({ - constraintName, - constraintType: 'foreignKey', - ..._.pick(grouped[constraintName][0], [ - 'constraintName', - 'schemaName', - 'pureName', - 'refSchemaName', - 'refTableName', - 'updateAction', - 'deleteAction', - ]), - columns: grouped[constraintName].map(fp.pick(['columnName', 'refColumnName'])), - })); -}; - -module.exports = DatabaseAnalyser; diff --git a/packages/engines/default/SqlDumper.js b/packages/tools/src/SqlDumper.ts similarity index 83% rename from packages/engines/default/SqlDumper.js rename to packages/tools/src/SqlDumper.ts index e00b96ca1..2e9c51ba5 100644 --- a/packages/engines/default/SqlDumper.js +++ b/packages/tools/src/SqlDumper.ts @@ -1,13 +1,24 @@ -const _ = require('lodash'); -const moment = require('moment'); +import { + ColumnInfo, + EngineDriver, + ForeignKeyInfo, + NamedObjectInfo, + SqlDialect, + TableInfo, + TransformType, +} from 'dbgate-types'; +import _ from 'lodash'; +import moment from 'moment'; -class SqlDumper { - /** @param driver {import('dbgate-types').EngineDriver} */ - constructor(driver) { - this.s = ''; +export class SqlDumper { + s = ''; + driver: EngineDriver; + dialect: SqlDialect; + indentLevel = 0; + + constructor(driver: EngineDriver) { this.driver = driver; this.dialect = driver.dialect; - this.indentLevel = 0; } endCommand() { this.putRaw(';\n'); @@ -85,8 +96,7 @@ class SqlDumper { if (!collection) return; this.putCollection(', ', collection, (item) => this.putFormattedValue(c, item)); } - /** @param format {string} */ - put(format, ...args) { + put(format: string, ...args) { let i = 0; let argIndex = 0; const length = format.length; @@ -149,10 +159,7 @@ class SqlDumper { this.put(' ^auto_increment'); } - /** - * @param column {import('dbgate-types').ColumnInfo} - */ - columnDefinition(column, { includeDefault = true, includeNullable = true, includeCollate = true } = {}) { + columnDefinition(column: ColumnInfo, { includeDefault = true, includeNullable = true, includeCollate = true } = {}) { if (column.computedExpression) { this.put('^as %s', column.computedExpression); if (column.isPersisted) this.put(' ^persisted'); @@ -175,10 +182,7 @@ class SqlDumper { } } - /** - * @param column {import('dbgate-types').ColumnInfo} - */ - columnDefault(column) { + columnDefault(column: ColumnInfo) { if (column.defaultConstraint != null) { this.put(' ^constraint %i ^default %s ', column.defaultConstraint, column.defaultValue); } else { @@ -186,13 +190,7 @@ class SqlDumper { } } - /** - * @template T - * @param {string} delimiter - * @param {T[]} collection - * @param {(col: T) => void} lambda - */ - putCollection(delimiter, collection, lambda) { + putCollection(delimiter: string, collection: T[], lambda: (col: T) => void) { if (!collection) return; let first = true; for (const item of collection) { @@ -202,8 +200,7 @@ class SqlDumper { } } - /** @param table {import('dbgate-types').TableInfo} */ - createTable(table) { + createTable(table: TableInfo) { this.put('^create ^table %f ( &>&n', table); this.putCollection(',&n', table.columns, (col) => { this.put('%i ', col.columnName); @@ -245,8 +242,7 @@ class SqlDumper { // } } - /** @param fk {import('dbgate-types').ForeignKeyInfo} */ - createForeignKeyFore(fk) { + createForeignKeyFore(fk: ForeignKeyInfo) { if (fk.constraintName != null) this.put('^constraint %i ', fk.constraintName); this.put( '^foreign ^key (%,i) ^references %f (%,i)', @@ -258,16 +254,9 @@ class SqlDumper { if (fk.updateAction) this.put(' ^on ^update %k', fk.updateAction); } - /** @param type {import('dbgate-types').TransformType} */ - transform(type, dumpExpr) { + transform(type: TransformType, dumpExpr) { dumpExpr(); } - /** - * @param table {import('dbgate-types').NamedObjectInfo} - * @param allow {boolean} - */ - allowIdentityInsert(table, allow) {} + allowIdentityInsert(table: NamedObjectInfo, allow: boolean) {} } - -module.exports = SqlDumper; diff --git a/packages/engines/default/createBulkInsertStreamBase.js b/packages/tools/src/createBulkInsertStreamBase.ts similarity index 90% rename from packages/engines/default/createBulkInsertStreamBase.js rename to packages/tools/src/createBulkInsertStreamBase.ts index 12550104b..1d02c9eb6 100644 --- a/packages/engines/default/createBulkInsertStreamBase.js +++ b/packages/tools/src/createBulkInsertStreamBase.ts @@ -1,11 +1,8 @@ -const { prepareTableForImport } = require('dbgate-tools'); -const _ = require('lodash'); +import { EngineDriver } from 'dbgate-types'; +import _ from 'lodash'; +import { prepareTableForImport } from './tableTransforms'; -/** - * - * @param {import('dbgate-types').EngineDriver} driver - */ -function createBulkInsertStreamBase(driver, stream, pool, name, options) { +export function createBulkInsertStreamBase(driver, stream, pool, name, options): any { const fullNameQuoted = name.schemaName ? `${driver.dialect.quoteIdentifier(name.schemaName)}.${driver.dialect.quoteIdentifier(name.pureName)}` : driver.dialect.quoteIdentifier(name.pureName); @@ -94,5 +91,3 @@ function createBulkInsertStreamBase(driver, stream, pool, name, options) { return writable; } - -module.exports = createBulkInsertStreamBase; diff --git a/packages/engines/default/driverBase.js b/packages/tools/src/driverBase.ts similarity index 70% rename from packages/engines/default/driverBase.js rename to packages/tools/src/driverBase.ts index 38c6a9599..6adf8bdec 100644 --- a/packages/engines/default/driverBase.js +++ b/packages/tools/src/driverBase.ts @@ -1,6 +1,6 @@ -const createBulkInsertStreamBase = require('./createBulkInsertStreamBase'); +import { createBulkInsertStreamBase } from './createBulkInsertStreamBase'; -const driverBase = { +export const driverBase = { analyserClass: null, dumperClass: null, @@ -24,11 +24,4 @@ const driverBase = { createDumper() { return new this.dumperClass(this); }, - async writeTable(pool, name, options) { - const { stream, mssql } = pool._nativeModules; - // @ts-ignore - return createBulkInsertStreamBase(this, stream, pool, name, options); - }, }; - -module.exports = driverBase; diff --git a/packages/tools/src/index.ts b/packages/tools/src/index.ts index 9518e5b90..857fa0aec 100644 --- a/packages/tools/src/index.ts +++ b/packages/tools/src/index.ts @@ -2,3 +2,7 @@ export * from './commonTypeParser'; export * from './nameTools'; export * from './tableTransforms'; export * from './packageTools'; +export * from './createBulkInsertStreamBase'; +export * from './DatabaseAnalyser'; +export * from './driverBase'; +export * from './SqlDumper';