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
JavaScript
"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