UNPKG

miniorm

Version:

A lightweight, minimal TypeScript ORM & query‑builder for MySQL, PostgreSQL and SQLite

236 lines (235 loc) 11.2 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()); }); }; var __asyncValues = (this && this.__asyncValues) || function (o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FluentTableBuilder = void 0; const core_1 = require("../core"); var STATIC; (function (STATIC) { STATIC["NOT_NULL"] = "NOT NULL"; STATIC["AUTO_INCREMENT"] = "AUTO_INCREMENT"; })(STATIC || (STATIC = {})); class FluentTableBuilder { constructor(tableName, dbName) { this.sql = ``; this.queryies = {}; this.columns = {}; this.column = ''; this.engineType = null; this.charsetType = null; this.dbName = ''; this.dbType = 'mysql'; this.tableName = ''; this.dbName = dbName; this.dbType = core_1.MiniOrm.dbs[dbName].config.type; this.tableName = tableName; this.sql = `CREATE TABLE IF NOT EXISTS ${tableName} ( COLUMNS_PLACEHOLDER )`; } set(opt = { db: this.dbName, table: this.tableName }) { var _a, _b, _c; if (!this.queryies[this.dbName]) this.queryies[this.dbName] = []; this.queryies[this.dbName].push(this.toSQL()); this.sql = ''; this.dbName = (_a = opt.db) !== null && _a !== void 0 ? _a : this.dbName; this.dbType = core_1.MiniOrm.dbs[(_b = opt.db) !== null && _b !== void 0 ? _b : this.dbName].config.type; this.tableName = (_c = opt.table) !== null && _c !== void 0 ? _c : this.tableName; this.sql = `CREATE TABLE IF NOT EXISTS ${this.tableName} ( COLUMNS_PLACEHOLDER )`; this.charset(''); this.column = ''; this.columns = {}; return this; } engine(engine) { this.engineType = engine; return this; } charset(charset) { this.charsetType = charset; return this; } id(nameOrLength, length = 11) { length = typeof nameOrLength == 'number' ? nameOrLength : length; const name = typeof nameOrLength == 'string' ? nameOrLength : 'id'; this.integer(name, length); this.notNULL(); this.auto_increment(); this.primary(); this.columns[name] = Object.assign(Object.assign({}, this.columns[this.column]), { length }); return this; } string(name, length) { this.column = name; this.columns[name] = Object.assign(Object.assign({}, this.columns[this.column]), { type: 'varchar', length }); return this; } integer(name, length) { this.column = name; this.columns[name] = Object.assign(Object.assign({}, this.columns[this.column]), { type: 'integer', length }); return this; } bool(name) { this.column = name; this.columns[name] = Object.assign(Object.assign({}, this.columns[this.column]), { type: 'boolean' }); return this; } enum(name, values) { this.column = name; this.columns[name] = Object.assign(Object.assign({}, this.columns[this.column]), { type: 'enum', enum: values }); return this; } timestamps() { this.columns['created_at'] = { type: 'timestamp', default: 'CURRENT_TIMESTAMP', notNull: STATIC.NOT_NULL }; this.columns['updated_at'] = { type: 'timestamp', default: 'CURRENT_TIMESTAMP', notNull: STATIC.NOT_NULL }; return this; } primary() { this.columns[this.column] = Object.assign(Object.assign({}, this.columns[this.column]), { primary: 'PRIMARY KEY' }); this.auto_increment(); return this; } unique() { this.columns[this.column] = Object.assign(Object.assign({}, this.columns[this.column]), { unique: 'UNIQUE' }); return this; } notNULL() { this.columns[this.column] = Object.assign(Object.assign({}, this.columns[this.column]), { notNull: STATIC.NOT_NULL }); return this; } nullable() { delete this.columns[this.column].notNull; return this; } auto_increment() { this.columns[this.column] = Object.assign(Object.assign({}, this.columns[this.column]), { autoIncrement: STATIC.AUTO_INCREMENT }); return this; } default(value) { this.columns[this.column] = Object.assign(Object.assign({}, this.columns[this.column]), { default: value }); return this; } toSQL() { var _a, _b, _c; const lines = []; for (const [key, values] of Object.entries(this.columns)) { let type = values.type.toUpperCase(); if (values.enum) { const enumValues = values.enum.map(val => typeof val === 'string' ? `'${val}'` : val).join(', '); type = `ENUM(${enumValues})`; if (this.dbType == 'sqlite') type = `TEXT CHECK(${key} IN(${enumValues}))`; } else if ((values.length && values.type != 'integer') || this.dbType != 'sqlite' && !(['boolean', 'timestamp'].includes(values.type))) type += `(${values.length})`; const notNull = values.notNull ? ` ${STATIC.NOT_NULL}` : '', autoInc = values.autoIncrement ? this.dbType == 'sqlite' ? ' AUTOINCREMENT' : this.dbType == 'mysql' ? 'AUTO_INCREMENT' : ' GENERATED ALWAYS AS IDENTITY' : '', primaryKey = ` ${(_a = values.primary) !== null && _a !== void 0 ? _a : ''}`, uniqueKey = ` ${(_b = values.unique) !== null && _b !== void 0 ? _b : ''}`, defaultVal = Object.prototype.hasOwnProperty.call(values, 'default') ? (() => { if (values.default === null) return ' DEFAULT NULL'; if (typeof values.default === 'string') { return values.default.toUpperCase() === 'CURRENT_TIMESTAMP' ? ' DEFAULT CURRENT_TIMESTAMP' : ` DEFAULT '${values.default}'`; } return ` DEFAULT ${values.default}`; })() : ''; lines.push(` ${key} ${type} ${primaryKey.trim()} ${uniqueKey.trim()} ${autoInc.trim()} ${notNull.trim()} ${defaultVal.trim()} `.trimRight()); } let sql = `CREATE TABLE IF NOT EXISTS ${this.tableName} (\n${lines.join(',\n')}\n)`.trim(); if (this.dbType == 'mysql') sql += ` ENGINE=${(_c = this.engineType) !== null && _c !== void 0 ? _c : 'InnoDB'} ${this.charsetType ? `DEFAULT CHARSET=${this.charsetType}` : ''}`; return sql; } build() { return __awaiter(this, void 0, void 0, function* () { var _a, e_1, _b, _c, _d, e_2, _e, _f; if (this.sql == '') this.sql = `CREATE TABLE IF NOT EXISTS ${this.tableName} ( COLUMNS_PLACEHOLDER )`; this.set(); if (Object.keys(this.queryies).length > 0) try { for (var _g = true, _h = __asyncValues(Object.entries(this.queryies)), _j; _j = yield _h.next(), _a = _j.done, !_a; _g = true) { _c = _j.value; _g = false; const [dbName, sqls] = _c; try { for (var _k = true, sqls_1 = (e_2 = void 0, __asyncValues(sqls)), sqls_1_1; sqls_1_1 = yield sqls_1.next(), _d = sqls_1_1.done, !_d; _k = true) { _f = sqls_1_1.value; _k = false; const sql = _f; yield core_1.MiniOrm.runQuery(dbName, sql, []); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (!_k && !_d && (_e = sqls_1.return)) yield _e.call(sqls_1); } finally { if (e_2) throw e_2.error; } } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (!_g && !_a && (_b = _h.return)) yield _b.call(_h); } finally { if (e_1) throw e_1.error; } } else yield core_1.MiniOrm.runQuery(this.dbName, this.toSQL(), []); this.engineType = null; this.sql = ''; this.column = ''; this.columns = {}; }); } static checkTableExists(db, dbType, tableName) { return new Promise((resolve, reject) => { if (dbType === 'mysql') { db.query(`SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ?`, [tableName], (err, results) => { if (err) return reject(err); resolve(results.length >= 1); }); } else if (dbType === 'sqlite') { db.get(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`, [tableName], (err, row) => { if (err) return reject(err); resolve(!!row); }); } else if (dbType === 'postgresql') { db.query(`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name = $1`, [tableName], (err, results) => { if (err) return reject(err); resolve(results.rows.length >= 1); }); } else { reject(new Error('Unsupported DB type')); } }); } } exports.FluentTableBuilder = FluentTableBuilder;