miniorm
Version:
A lightweight, minimal TypeScript ORM & query‑builder for MySQL, PostgreSQL and SQLite
236 lines (235 loc) • 11.2 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());
});
};
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;