UNPKG

@grandlinex/bundle-sqlight

Version:

> SQLight support GrandlineX using better-sqlite3

295 lines (294 loc) 9.66 kB
import Path from 'path'; import { CoreDBCon, getColumnMeta, } from '@grandlinex/core'; import Database from 'better-sqlite3'; import { buildSearchQ, mappingWithDataType, objToTable, rowToObj, tableToObj, } from '../util/index.js'; export default class SQLCon extends CoreDBCon { constructor(module, dbversion, printLog = false) { super(dbversion, 'main', module); const store = module.getKernel().getConfigStore(); const path = store.get('GLOBAL_PATH_DB'); if (!path) { this.error('Cant get db path from store'); throw new Error('Cant get db path from store'); } this.path = Path.join(path, `${module.getName()}.db`); this.db = null; this.printLog = printLog; } async createEntity(config, entity) { const [keys, values, params] = objToTable(entity, config); const query = { exec: `INSERT INTO ${this.schemaName}.${config.className}(${keys.join(', ')}) VALUES (${values.join(', ')})`, param: params, }; const res = await this.execScripts([query]); if (!res || !res[0]) { throw this.lError('Cant Create entity'); } return entity; } async updateEntity(config, e_id, entity) { const [, values, params] = objToTable(entity, config, true); const result = await this.execScripts([ { exec: `UPDATE ${this.schemaName}.${config.className} SET ${values.join(', ')} WHERE e_id = ?;`, param: [...params, e_id], }, ]); return result[0] !== null; } async updateBulkEntity(config, e_id, entity) { if (e_id.length === 0) { return false; } const [, values, params] = objToTable(entity, config, true); const result = await this.execScripts([ { exec: `UPDATE ${this.schemaName}.${config.className} SET ${values.join(', ')} WHERE e_id in (${e_id.map(() => '?').join(',')});`, param: [...params, ...e_id], }, ]); return result[0] !== null; } async getEntityById(config, id) { const query = this.db?.prepare(`SELECT * FROM ${this.schemaName}.${config.className} WHERE e_id = ?;`); const res = query?.get([id]); if (res) { return rowToObj(config, res); } return null; } async getEntityBulkById(config, e_id) { if (e_id.length === 0) { return []; } const query = this.db?.prepare(`SELECT * FROM ${this.schemaName}.${config.className} WHERE e_id in (${e_id.map(() => '?').join(',')});`); const res = query?.all(e_id); if (res) { return tableToObj(config, res); } return []; } async findEntity(config, search) { let searchQ = ''; const param = []; searchQ = buildSearchQ(config, search, param, searchQ); const query = this.db?.prepare(`SELECT * FROM ${this.schemaName}.${config.className} ${searchQ};`); const res = query?.get(param); if (res) { return rowToObj(config, res); } return null; } async deleteEntityById(className, id) { const query = this.db?.prepare(`DELETE FROM ${this.schemaName}.${className} WHERE e_id = ?;`); return query?.run([id]).changes === 1; } async deleteEntityBulkById(className, e_id) { if (e_id.length === 0) { return false; } const query = this.db?.prepare(`DELETE FROM ${this.schemaName}.${className} WHERE e_id in (${e_id.map(() => '?').join(',')});`); return (query?.run([...e_id]).changes ?? 0) > 1; } async getEntityList(q) { const { limit, search, config, order, offset } = q; if (limit === 0) { return []; } let searchQ = ''; const orderBy = []; let orderByQ = ''; const off = offset !== undefined ? ` OFFSET ${offset}` : ''; const range = limit ? `LIMIT ${limit}${off}` : ''; const param = []; if (search) { searchQ = buildSearchQ(config, search, param, searchQ); } if (order && order.length > 0) { order.forEach((val) => { orderBy.push(`${String(val.key)} ${val.order}`); }); orderByQ = `ORDER BY ${orderBy.join(',\n')}`; } const query = this.db?.prepare(`SELECT * FROM ${this.schemaName}.${config.className} ${searchQ} ${orderByQ} ${range};`); const res = query?.all(param); if (res) { return tableToObj(config, res); } return []; } async initEntity(className, entity) { await this.execScripts([ { exec: `CREATE TABLE ${this.schemaName}.${className} ( ${this.transformEntityKeys(entity)} );`, param: [], }, ]); return true; } transformEntityKeys(entity) { const keys = Object.keys(entity); const out = []; keys.forEach((key) => { const meta = getColumnMeta(entity, key); if (key === 'e_id') { out.push(`e_id TEXT PRIMARY KEY`); } else if (meta?.dataType) { mappingWithDataType(meta, out, key); } else { const type = typeof entity[key]; switch (type) { case 'bigint': case 'number': out.push(`${String(key)} INTEGER NOT NULL`); break; case 'string': out.push(`${String(key)} TEXT NOT NULL`); break; default: throw Error('TypeNotSupported'); } } }); return out.join(',\n'); } async removeConfig(key) { try { const query = await this.execScripts([ { exec: `DELETE FROM ${this.schemaName}.config WHERE c_key = ?;`, param: [key], }, ]); this.log(query); if (query.length !== 1) { this.error('invalid result'); } } catch (e) { this.error(e); } } async initNewDB() { this.debug('no init '); } async connect() { try { this.db = new Database(this.path, { verbose: (message, additionalArgs) => { if (this.printLog) { this.verbose(message, additionalArgs); } }, }); } catch (e) { this.error(e); return false; } try { const query = this.db.prepare(`SELECT * FROM ${this.schemaName}.config;`); const result = query.all(); const version = result.find((el) => { return el.c_key === 'dbversion'; }); return !!version; } catch (e) { this.warn(e); this.log('Create new Database'); await this.execScripts([ { exec: `CREATE TABLE ${this.schemaName}.config ( c_key text not null, c_value text, PRIMARY KEY (c_key) );`, param: [], }, { exec: `INSERT INTO ${this.schemaName}.config (c_key, c_value) VALUES ('dbversion', '${this.dbVersion}');`, param: [], }, ]); this.setNew(true); return true; } } getRawDBObject() { return this.db; } async configExist(key) { const query = this.db?.prepare(`SELECT * FROM ${this.schemaName}.config WHERE c_key = '${key}'`); const exist = query?.get(); return !!exist && exist.c_key !== undefined && exist.c_value !== undefined; } async setConfig(key, value) { const query = this.db?.prepare(`REPLACE INTO ${this.schemaName} . config ( c_key, c_value ) VALUES ('${key}', '${value}');`); if (query === undefined) { return false; } query.run(); return true; } async getConfig(key) { const query = this.db?.prepare(`SELECT * FROM ${this.schemaName}.config WHERE c_key = '${key}'`); return query?.get(); } async execScripts(list) { const result = []; list.forEach((el) => { const prep = this.db?.prepare(el.exec); const res = prep?.run(el.param); if (res) { result.push(res); } }); return result; } async disconnect() { this.db?.close(); return true; } }