From c84798e8bf65a316a970ec918413aedf637fa361 Mon Sep 17 00:00:00 2001 From: Kononnable Date: Sun, 15 Mar 2020 00:41:35 +0100 Subject: [PATCH] load db drivers on demand --- package.json | 2 +- src/drivers/MssqlDriver.ts | 33 +++++++++---- src/drivers/MysqlDriver.ts | 17 ++++++- src/drivers/OracleDriver.ts | 89 ++++++++++++++++++----------------- src/drivers/PostgresDriver.ts | 18 ++++++- src/drivers/SqliteDriver.ts | 22 +++++++-- src/index.ts | 2 + 7 files changed, 120 insertions(+), 63 deletions(-) diff --git a/package.json b/package.json index d6156ea..0fa8b09 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test": "nyc --reporter=lcov ts-node ./node_modules/mocha/bin/_mocha test/**/*.test.ts -- --bail", "posttest": "eslint ./src/**/*.ts ./test/**/*.ts", "clean": "rimraf coverage output dist", - "prettier": "prettier --write ./src/*.ts ./src/**/*.ts" + "prettier": "echo Disabled until import type syntax is supported. || prettier --write ./src/*.ts ./src/**/*.ts" }, "repository": { "type": "git", diff --git a/src/drivers/MssqlDriver.ts b/src/drivers/MssqlDriver.ts index 23eb1ff..c4a104e 100644 --- a/src/drivers/MssqlDriver.ts +++ b/src/drivers/MssqlDriver.ts @@ -1,4 +1,4 @@ -import * as MSSQL from "mssql"; +import type * as MSSQL from "mssql"; import { ConnectionOptions } from "typeorm"; import * as TypeormDriver from "typeorm/driver/sqlserver/SqlServerDriver"; import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; @@ -22,14 +22,27 @@ export default class MssqlDriver extends AbstractDriver { public readonly standardUser = "sa"; + private MSSQL: typeof MSSQL; + private Connection: MSSQL.ConnectionPool; + public constructor() { + super(); + try { + // eslint-disable-next-line import/no-extraneous-dependencies, global-require, import/no-unresolved + this.MSSQL = require("mssql"); + } catch (error) { + TomgUtils.LogError("", false, error); + throw error; + } + } + public GetAllTablesQuery = async ( schema: string, dbNames: string, tableNames: string[] ) => { - const request = new MSSQL.Request(this.Connection); + const request = new this.MSSQL.Request(this.Connection); const tableCondition = tableNames.length > 0 ? ` AND NOT TABLE_NAME IN ('${tableNames.join("','")}')` @@ -54,7 +67,7 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG schema: string, dbNames: string ): Promise { - const request = new MSSQL.Request(this.Connection); + const request = new this.MSSQL.Request(this.Connection); const response: { TABLE_NAME: string; COLUMN_NAME: string; @@ -253,7 +266,7 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG schema: string, dbNames: string ): Promise { - const request = new MSSQL.Request(this.Connection); + const request = new this.MSSQL.Request(this.Connection); const response: { TableName: string; TableSchema: string; @@ -333,7 +346,7 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG dbNames: string, generationOptions: IGenerationOptions ): Promise { - const request = new MSSQL.Request(this.Connection); + const request = new this.MSSQL.Request(this.Connection); const response: { TableWithForeignKey: string; FK_PartNo: number; @@ -469,7 +482,7 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG }; const promise = new Promise((resolve, reject) => { - this.Connection = new MSSQL.ConnectionPool(config, err => { + this.Connection = new this.MSSQL.ConnectionPool(config, err => { if (!err) { resolve(true); } else { @@ -487,22 +500,22 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG } public async CreateDB(dbName: string) { - const request = new MSSQL.Request(this.Connection); + const request = new this.MSSQL.Request(this.Connection); await request.query(`CREATE DATABASE ${dbName}; `); } public async UseDB(dbName: string) { - const request = new MSSQL.Request(this.Connection); + const request = new this.MSSQL.Request(this.Connection); await request.query(`USE ${dbName}; `); } public async DropDB(dbName: string) { - const request = new MSSQL.Request(this.Connection); + const request = new this.MSSQL.Request(this.Connection); await request.query(`DROP DATABASE ${dbName}; `); } public async CheckIfDBExists(dbName: string): Promise { - const request = new MSSQL.Request(this.Connection); + const request = new this.MSSQL.Request(this.Connection); const resp = await request.query( `SELECT name FROM master.sys.databases WHERE name = N'${dbName}' ` ); diff --git a/src/drivers/MysqlDriver.ts b/src/drivers/MysqlDriver.ts index 59a5e33..a21df74 100644 --- a/src/drivers/MysqlDriver.ts +++ b/src/drivers/MysqlDriver.ts @@ -1,4 +1,4 @@ -import * as MYSQL from "mysql"; +import type * as MYSQL from "mysql"; import { ConnectionOptions } from "typeorm"; import * as TypeormDriver from "typeorm/driver/mysql/MysqlDriver"; import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; @@ -24,8 +24,21 @@ export default class MysqlDriver extends AbstractDriver { public readonly standardSchema = ""; + private MYSQL: typeof MYSQL; + private Connection: MYSQL.Connection; + public constructor() { + super(); + try { + // eslint-disable-next-line import/no-extraneous-dependencies, global-require, import/no-unresolved + this.MYSQL = require("mysql"); + } catch (error) { + TomgUtils.LogError("", false, error); + throw error; + } + } + public GetAllTablesQuery = async ( schema: string, dbNames: string, @@ -458,7 +471,7 @@ export default class MysqlDriver extends AbstractDriver { } const promise = new Promise((resolve, reject) => { - this.Connection = MYSQL.createConnection(config); + this.Connection = this.MYSQL.createConnection(config); this.Connection.connect(err => { if (!err) { diff --git a/src/drivers/OracleDriver.ts b/src/drivers/OracleDriver.ts index 81d4ad2..9411762 100644 --- a/src/drivers/OracleDriver.ts +++ b/src/drivers/OracleDriver.ts @@ -1,3 +1,5 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import type * as Oracle from "oracledb" import * as TypeormDriver from "typeorm/driver/oracle/OracleDriver"; import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; import * as TomgUtils from "../Utils"; @@ -20,16 +22,16 @@ export default class OracleDriver extends AbstractDriver { public readonly standardSchema = ""; - public Oracle: any; + private Oracle: typeof Oracle; - private Connection: any /* Oracle.IConnection */; + private Connection: Oracle.Connection; public constructor() { super(); try { // eslint-disable-next-line import/no-extraneous-dependencies, global-require, import/no-unresolved this.Oracle = require("oracledb"); - this.Oracle.outFormat = this.Oracle.OBJECT; + this.Oracle.outFormat = (this.Oracle as any).OBJECT; } catch (error) { TomgUtils.LogError("", false, error); throw error; @@ -45,12 +47,11 @@ export default class OracleDriver extends AbstractDriver { tableNames.length > 0 ? ` AND NOT TABLE_NAME IN ('${tableNames.join("','")}')` : ""; - const response: { - TABLE_SCHEMA: string; + const response= ( + await this.Connection.execute<{ + TABLE_SCHEMA: string; TABLE_NAME: string; - DB_NAME: string; - }[] = ( - await this.Connection.execute( + DB_NAME: string;}>( `SELECT NULL AS TABLE_SCHEMA, TABLE_NAME, NULL AS DB_NAME FROM all_tables WHERE owner = (select user from dual) ${tableCondition}` ) ).rows!; @@ -58,20 +59,20 @@ export default class OracleDriver extends AbstractDriver { }; public async GetCoulmnsFromEntity(entities: Entity[]): Promise { - const response: { - TABLE_NAME: string; - COLUMN_NAME: string; - DATA_DEFAULT: string; - NULLABLE: string; - DATA_TYPE: string; - DATA_LENGTH: number; - DATA_PRECISION: number; - DATA_SCALE: number; - IDENTITY_COLUMN: string; // doesn't exist in old oracle versions (#195) - IS_UNIQUE: number; - }[] = ( + const response = ( await this.Connection - .execute(`SELECT utc.*, (select count(*) from USER_CONS_COLUMNS ucc + .execute<{ + TABLE_NAME: string; + COLUMN_NAME: string; + DATA_DEFAULT: string; + NULLABLE: string; + DATA_TYPE: string; + DATA_LENGTH: number; + DATA_PRECISION: number; + DATA_SCALE: number; + IDENTITY_COLUMN: string; // doesn't exist in old oracle versions (#195) + IS_UNIQUE: number; + }>(`SELECT utc.*, (select count(*) from USER_CONS_COLUMNS ucc JOIN USER_CONSTRAINTS uc ON uc.CONSTRAINT_NAME = ucc.CONSTRAINT_NAME and uc.CONSTRAINT_TYPE='U' where ucc.column_name = utc.COLUMN_NAME AND ucc.table_name = utc.TABLE_NAME) IS_UNIQUE FROM USER_TAB_COLUMNS utc`) @@ -226,15 +227,15 @@ export default class OracleDriver extends AbstractDriver { } public async GetIndexesFromEntity(entities: Entity[]): Promise { - const response: { - COLUMN_NAME: string; - TABLE_NAME: string; - INDEX_NAME: string; - UNIQUENESS: string; - ISPRIMARYKEY: number; - }[] = ( + const response = ( await this.Connection - .execute(`SELECT ind.TABLE_NAME, ind.INDEX_NAME, col.COLUMN_NAME,ind.UNIQUENESS, CASE WHEN uc.CONSTRAINT_NAME IS NULL THEN 0 ELSE 1 END ISPRIMARYKEY + .execute<{ + COLUMN_NAME: string; + TABLE_NAME: string; + INDEX_NAME: string; + UNIQUENESS: string; + ISPRIMARYKEY: number; + }>(`SELECT ind.TABLE_NAME, ind.INDEX_NAME, col.COLUMN_NAME,ind.UNIQUENESS, CASE WHEN uc.CONSTRAINT_NAME IS NULL THEN 0 ELSE 1 END ISPRIMARYKEY FROM USER_INDEXES ind JOIN USER_IND_COLUMNS col ON ind.INDEX_NAME=col.INDEX_NAME LEFT JOIN USER_CONSTRAINTS uc ON uc.INDEX_NAME = ind.INDEX_NAME @@ -274,17 +275,17 @@ export default class OracleDriver extends AbstractDriver { dbNames: string, generationOptions: IGenerationOptions ): Promise { - const response: { - OWNER_TABLE_NAME: string; - OWNER_POSITION: string; - OWNER_COLUMN_NAME: string; - CHILD_TABLE_NAME: string; - CHILD_COLUMN_NAME: string; - DELETE_RULE: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION"; - CONSTRAINT_NAME: string; - }[] = ( + const response = ( await this.Connection - .execute(`select owner.TABLE_NAME OWNER_TABLE_NAME,ownCol.POSITION OWNER_POSITION,ownCol.COLUMN_NAME OWNER_COLUMN_NAME, + .execute<{ + OWNER_TABLE_NAME: string; + OWNER_POSITION: string; + OWNER_COLUMN_NAME: string; + CHILD_TABLE_NAME: string; + CHILD_COLUMN_NAME: string; + DELETE_RULE: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION"; + CONSTRAINT_NAME: string; + }>(`select owner.TABLE_NAME OWNER_TABLE_NAME,ownCol.POSITION OWNER_POSITION,ownCol.COLUMN_NAME OWNER_COLUMN_NAME, child.TABLE_NAME CHILD_TABLE_NAME ,childCol.COLUMN_NAME CHILD_COLUMN_NAME, owner.DELETE_RULE, owner.CONSTRAINT_NAME @@ -345,9 +346,9 @@ export default class OracleDriver extends AbstractDriver { } public async ConnectToServer(connectionOptions: IConnectionOptions) { - let config: any; + let config: Oracle.ConnectionAttributes; if (connectionOptions.user === String(process.env.ORACLE_UsernameSys)) { - config /* Oracle.IConnectionAttributes */ = { + config = { connectString: `${connectionOptions.host}:${connectionOptions.port}/${connectionOptions.databaseName}`, externalAuth: connectionOptions.ssl, password: connectionOptions.password, @@ -355,7 +356,7 @@ export default class OracleDriver extends AbstractDriver { user: connectionOptions.user }; } else { - config /* Oracle.IConnectionAttributes */ = { + config = { connectString: `${connectionOptions.host}:${connectionOptions.port}/${connectionOptions.databaseName}`, externalAuth: connectionOptions.ssl, password: connectionOptions.password, @@ -400,10 +401,10 @@ export default class OracleDriver extends AbstractDriver { } public async CheckIfDBExists(dbName: string): Promise { - const x = await this.Connection.execute( + const {rows} = await this.Connection.execute( `select count(*) as CNT from dba_users where username='${dbName.toUpperCase()}'` ); - return x.rows[0][0] > 0 || x.rows[0].CNT; + return rows![0][0] > 0 || rows![0].CNT; } private static ReturnDefaultValueFunction( diff --git a/src/drivers/PostgresDriver.ts b/src/drivers/PostgresDriver.ts index 174becb..a7bcc36 100644 --- a/src/drivers/PostgresDriver.ts +++ b/src/drivers/PostgresDriver.ts @@ -1,4 +1,4 @@ -import * as PG from "pg"; +import type * as PG from "pg"; import { ConnectionOptions } from "typeorm"; import * as TypeormDriver from "typeorm/driver/postgres/PostgresDriver"; import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; @@ -22,8 +22,22 @@ export default class PostgresDriver extends AbstractDriver { public readonly standardSchema = "public"; + private PG: typeof PG; + private Connection: PG.Client; + public constructor() { + super(); + try { + // eslint-disable-next-line import/no-extraneous-dependencies, global-require, import/no-unresolved + this.PG = require("pg"); + } catch (error) { + TomgUtils.LogError("", false, error); + throw error; + } + } + + public GetAllTablesQuery = async ( schema: string, dbNames: string, @@ -599,7 +613,7 @@ export default class PostgresDriver extends AbstractDriver { } public async ConnectToServer(connectionOptons: IConnectionOptions) { - this.Connection = new PG.Client({ + this.Connection = new this.PG.Client({ database: connectionOptons.databaseName, host: connectionOptons.host, password: connectionOptons.password, diff --git a/src/drivers/SqliteDriver.ts b/src/drivers/SqliteDriver.ts index 2eee238..e429a0f 100644 --- a/src/drivers/SqliteDriver.ts +++ b/src/drivers/SqliteDriver.ts @@ -1,7 +1,7 @@ import { ConnectionOptions } from "typeorm"; import * as TypeormDriver from "typeorm/driver/sqlite/SqliteDriver"; import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; -import * as sqliteLib from "sqlite3"; +import type * as sqliteLib from "sqlite3"; import * as TomgUtils from "../Utils"; import AbstractDriver from "./AbstractDriver"; import IConnectionOptions from "../IConnectionOptions"; @@ -22,14 +22,28 @@ export default class SqliteDriver extends AbstractDriver { public readonly standardSchema = ""; - public sqlite = sqliteLib.verbose(); + private sqliteLib:typeof sqliteLib; - public db: sqliteLib.Database; + private sqlite:sqliteLib.sqlite3; - public tablesWithGeneratedPrimaryKey: string[] = new Array(); + private db: sqliteLib.Database; + + private tablesWithGeneratedPrimaryKey: string[] = new Array(); public GetAllTablesQuery: any; + public constructor() { + super(); + try { + // eslint-disable-next-line import/no-extraneous-dependencies, global-require, import/no-unresolved + this.sqliteLib = require("sqlite3"); + this.sqlite= this.sqliteLib.verbose() + } catch (error) { + TomgUtils.LogError("", false, error); + throw error; + } + } + public async GetAllTables( schema: string, dbNames: string, diff --git a/src/index.ts b/src/index.ts index 2ac00ef..e42802f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ +// TODO: Enable prettier once import type syntax is supported import * as Yargs from "yargs"; import { createDriver, createModelFromDatabase } from "./Engine"; import * as TomgUtils from "./Utils"; @@ -11,6 +12,7 @@ import IGenerationOptions, { import fs = require("fs-extra"); import inquirer = require("inquirer"); import path = require("path"); + // eslint-disable-next-line @typescript-eslint/no-floating-promises CliLogic();