UNPKG

typescript-mysql-model

Version:

{ "version": "1.2.46", "name": "typescript-mysql-model", "description": "", "main": "index.js", "types": "index.d.ts", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url":

187 lines 7.58 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const change_case = require("change-case"); const LIST_TYPE_VIEW = "VIEW"; const LIST_TYPE_TABLE = "BASE TABLE"; class ModelBuilder { constructor(knex, databaseName) { this.knex = knex; this.databaseName = databaseName; } static init(knex) { return new ModelBuilder(knex).renderDatabaseSchema(); } /** * Return a copy of an object but with all keys lower case */ static keysToLower(obj) { const newobj = {}; Object.keys(obj).forEach(key => newobj[key.toLowerCase()] = obj[key]); return newobj; } /** * Return the length of a type, eg varchar(255)=>255 * 0 if not parsable * @param type */ static getMysqlLength(strType) { const strip = strType.replace(/\D/g, ""); return strip.length === 0 ? 0 : parseInt(strip, undefined); } /** * Return the length of a type, eg varchar(255)=>varchar * @param type */ static stripMysqlLength(type) { const pos = type.indexOf("("); if (pos > -1) { return type.substr(0, pos); } return type; } static getEnumValues(type) { if (type.startsWith("enum")) { const strList = type.replace("enum(", "").replace(")", ""); const list = strList.split(",").map(s => s.replace("'", "").replace("'", "")); return list; } return null; } renderDatabaseSchema() { return __awaiter(this, void 0, void 0, function* () { if (!this.databaseName) { this.databaseName = yield this.getDatabaseName(); } const schema = { storedProcedures: yield this.renderStoredProcedures(), tables: yield this.renderTableModel(), views: yield this.renderViewModel() }; return schema; }); } getDatabaseName() { return __awaiter(this, void 0, void 0, function* () { const resp = yield this.knex.raw("SELECT DATABASE() as db"); return resp[0][0].db; }); } /** * return a select query to list all tables or views from a database */ listFromDatabase(listType) { if (listType !== "BASE TABLE" && listType !== "VIEW") { throw new Error("Illegal listtype"); } const select = "`information_schema`.`TABLES`.`TABLE_NAME` AS `tname`"; const from = "`information_schema`.`TABLES`"; const dbClause = "`information_schema`.`TABLES`.`TABLE_SCHEMA` = '" + this.databaseName + "'"; const baseTable = "`information_schema`.`TABLES`.`TABLE_TYPE` = '" + listType + "'"; return `SELECT ${select} FROM ${from} WHERE ${dbClause} AND ${baseTable} `; } listViews() { return __awaiter(this, void 0, void 0, function* () { const rows = yield this.knex.raw(this.listFromDatabase(LIST_TYPE_VIEW)); return rows[0].map(item => item.tname); }); } /** * Lists all the tables in current database */ listTables() { return __awaiter(this, void 0, void 0, function* () { const rows = yield this.knex.raw(this.listFromDatabase(LIST_TYPE_TABLE)); return rows[0].map(item => item.tname); }); } columnArrayToDatabaseSchema(colArrMap) { const schema = {}; for (const tableName in colArrMap) { colArrMap[tableName] = colArrMap[tableName].map((col, i) => { col = ModelBuilder.keysToLower(col); col.length = ModelBuilder.getMysqlLength(col.type); col.enumValues = ModelBuilder.getEnumValues(col.type); col.isPrimary = col.key === "PRI"; col.index = i; col.type = ModelBuilder.stripMysqlLength(col.type); return col; }); const newTable = {}; colArrMap[tableName].forEach(col => newTable[col.field] = col); schema[tableName] = newTable; } return schema; } /** * List all columns for a table given table name */ listColumns(tableName) { return __awaiter(this, void 0, void 0, function* () { return yield this.knex.raw("SHOW COLUMNS FROM " + tableName).then(colData => colData[0]); }); } renderModel(tables) { return __awaiter(this, void 0, void 0, function* () { // TODO list all in one query instead of one query per table const columnArrayMap = {}; const promises = tables.map((tableName) => __awaiter(this, void 0, void 0, function* () { columnArrayMap[tableName] = yield this.listColumns(tableName); })); yield Promise.all(promises); return this.columnArrayToDatabaseSchema(columnArrayMap); }); } listStoredProcedures() { return __awaiter(this, void 0, void 0, function* () { const SHOW_DB_QUERY = `SHOW PROCEDURE STATUS WHERE Db = ?`; const sps = yield this.knex.raw(SHOW_DB_QUERY, [this.databaseName]); return sps[0].map(sp => sp.Name); }); } listStoredProcedureParams() { return __awaiter(this, void 0, void 0, function* () { const LIST_PARAM_QUERY = `SELECT * FROM information_schema.parameters WHERE specific_schema = ?`; const params = yield this.knex.raw(LIST_PARAM_QUERY, [this.databaseName]); return params[0].map(item => { const copy = {}; for (const key in item) { copy[change_case.camelCase(key)] = item[key]; } return copy; }); }); } renderStoredProcedures() { return __awaiter(this, void 0, void 0, function* () { const storedProcedures = yield this.listStoredProcedures(); const mapped = yield this.listStoredProcedureParams(); const storedProcedureDictionary = {}; storedProcedures.forEach(spName => storedProcedureDictionary[spName] = { name: spName, parameters: {} }); mapped.forEach(item => storedProcedureDictionary[item.specificName].parameters[item.parameterName] = item); return storedProcedureDictionary; }); } renderViewModel() { return __awaiter(this, void 0, void 0, function* () { const tables = yield this.listViews(); return yield this.renderModel(tables); }); } renderTableModel() { return __awaiter(this, void 0, void 0, function* () { const tables = yield this.listTables(); return this.renderModel(tables); }); } } exports.default = ModelBuilder; //# sourceMappingURL=model-builder.js.map