UNPKG

jeep-sqlite

Version:
1,304 lines 122 kB
import { Database } from "../../utils/database"; import localForage from "localforage"; import { UtilsJSON } from "../../utils/utils-json"; import { UtilsStore } from "../../utils/utils-store"; import * as JSZip from "jszip"; import { fileOpen, fileSave, supported } from "browser-fs-access"; export class JeepSqlite { constructor() { this.isStore = false; this._dbDict = {}; this.databaseList = {}; this._versionUpgrades = {}; this._overwrite = true; this.autoSave = false; this.typeOrm = false; this.wasmPath = undefined; this.pickText = undefined; this.saveText = undefined; this.buttonOptions = undefined; this.innerAutoSave = undefined; this.innerTypeOrm = undefined; this.innerWasmPath = undefined; this.innerPickText = undefined; this.innerSaveText = undefined; this.innerButtonOptions = undefined; } //***************************** //* Watch on Property Changes * //***************************** parseAutoSave(newValue) { this.innerAutoSave = newValue; } parseTypeOrm(newValue) { this.innerTypeOrm = newValue; } parseWasmPath(newValue) { this.innerWasmPath = newValue; } parsePickText(newValue) { this.innerPickText = newValue; } parseSaveText(newValue) { this.innerSaveText = newValue; } parseButtonOptions(newValue) { this.innerButtonOptions = JSON.parse(newValue); const keys = Object.keys(this.innerButtonOptions); for (const key of keys) { switch (key) { case "top": { this.el.style.setProperty('--jeep-sqlite-top', this.innerButtonOptions[key]); break; } case "right": { this.el.style.setProperty('--jeep-sqlite-right', this.innerButtonOptions[key]); break; } case "fontSize": { this.el.style.setProperty('--jeep-sqlite-font-size', this.innerButtonOptions[key]); break; } case "padding": { this.el.style.setProperty('--jeep-sqlite-padding', this.innerButtonOptions[key]); break; } case "backgroundColor": { this.el.style.setProperty('--jeep-sqlite-background-color', this.innerButtonOptions[key]); break; } case "color": { this.el.style.setProperty('--jeep-sqlite-color', this.innerButtonOptions[key]); break; } } } } //********************** //* Method Definitions * //********************** async echo(options) { return options; } async createConnection(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const version = options.version ? options.version : 1; const readonly = options.readonly ? options.readonly : false; try { await this._createConnection(dbName, version, readonly); return Promise.resolve(); } catch (err) { return Promise.reject(err); } } async isConnection(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; const ret = await this._isConnection(dbName, readonly); return Promise.resolve(ret); } async closeConnection(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; try { await this._closeConnection(dbName, readonly); return Promise.resolve(); } catch (err) { return Promise.reject(err); } } async open(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; try { await this._open(dbName, readonly); return Promise.resolve(); } catch (err) { return Promise.reject(err); } } async close(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; try { await this._close(dbName, readonly); return Promise.resolve(); } catch (err) { return Promise.reject(err); } } async getVersion(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; try { const res = await this._getVersion(dbName, readonly); return Promise.resolve(res); } catch (err) { return Promise.reject(err); } } async beginTransaction(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; if (readonly) { return Promise.reject(`BeginTransaction: not allowed in read-only mode`); } try { const changes = await this._beginTransaction(dbName); return Promise.resolve(changes); } catch (err) { return Promise.reject(err); } } async commitTransaction(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; if (readonly) { return Promise.reject(`CommitTransaction: not allowed in read-only mode`); } try { const changes = await this._commitTransaction(dbName); return Promise.resolve(changes); } catch (err) { return Promise.reject(err); } } async rollbackTransaction(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; if (readonly) { return Promise.reject(`BeginTransaction: not allowed in read-only mode`); } try { const changes = await this._rollbackTransaction(dbName); return Promise.resolve(changes); } catch (err) { return Promise.reject(err); } } async isTransactionActive(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; if (readonly) { return Promise.reject(`isTransactionActive: not allowed in read-only mode`); } try { const res = await this._isTransactionActive(dbName); return Promise.resolve(res); } catch (err) { return Promise.reject(err); } } async execute(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } if (!keys.includes('statements') || options.statements.length === 0) { return Promise.reject('Must provide raw SQL statements'); } const dbName = options.database; const statements = options.statements; let transaction = true; const readonly = options.readonly ? options.readonly : false; if (keys.includes('transaction')) transaction = options.transaction; try { const changes = await this._execute(dbName, statements, transaction, readonly); return Promise.resolve(changes); } catch (err) { return Promise.reject(err); } } async executeSet(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } if (!keys.includes('set') || options.set.length === 0) { return Promise.reject('Must provide a non-empty set of SQL statements'); } const dbName = options.database; const setOfStatements = options.set; let transaction = true; if (keys.includes('transaction')) transaction = options.transaction; const readonly = options.readonly ? options.readonly : false; const returnMode = options.returnMode ? options.returnMode : 'no'; try { const changes = await this._executeSet(dbName, setOfStatements, transaction, readonly, returnMode); return Promise.resolve(changes); } catch (err) { return Promise.reject(err); } } async run(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } if (!keys.includes('statement') || options.statement.length === 0) { return Promise.reject('Must provide a run statement'); } const dbName = options.database; const statement = options.statement; let values = []; if (keys.includes('values')) { values = options.values.length > 0 ? options.values : []; } let transaction = true; if (keys.includes('transaction')) transaction = options.transaction; const readonly = options.readonly ? options.readonly : false; const returnMode = options.returnMode ? options.returnMode : 'no'; try { const retChanges = await this._run(dbName, statement, values, transaction, readonly, returnMode); return Promise.resolve(retChanges); } catch (err) { return Promise.reject(err); } } async query(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } if (!keys.includes('statement') || options.statement.length === 0) { return Promise.reject('Must provide a query statement'); } let values = []; if (keys.includes('values')) { values = options.values.length > 0 ? options.values : []; } const dbName = options.database; const statement = options.statement; const readonly = options.readonly ? options.readonly : false; try { const retValues = await this._query(dbName, statement, values, readonly); return Promise.resolve(retValues); } catch (err) { return Promise.reject(err); } } async getTableList(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; try { const retValues = await this._getTableList(dbName, readonly); return Promise.resolve(retValues); } catch (err) { return Promise.reject(err); } } async isDBExists(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; try { const ret = await this._isDBExists(dbName, readonly); return Promise.resolve(ret); } catch (err) { return Promise.reject(err); } } async isDBOpen(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; try { const ret = await this._isDBOpen(dbName, readonly); return Promise.resolve(ret); } catch (err) { return Promise.reject(err); } } async deleteDatabase(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; try { return await this._deleteDatabase(dbName, readonly); } catch (err) { return Promise.reject(err); } } async isStoreOpen() { return Promise.resolve(this.isStore); } async copyFromAssets(options) { let overwrite; if (options != null) { const keys = Object.keys(options); overwrite = keys.includes('overwrite') ? options.overwrite : true; } else { overwrite = true; } if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } try { await this._copyFromAssets(overwrite); return Promise.resolve(); } catch (err) { return Promise.reject(err); } } async isTableExists(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; if (!keys.includes('table')) { return Promise.reject('Must provide a table name'); } const tableName = options.table; const readonly = options.readonly ? options.readonly : false; try { const ret = await this._isTableExists(dbName, tableName, readonly); return Promise.resolve(ret); } catch (err) { return Promise.reject(err); } } async createSyncTable(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; try { const ret = await this._createSyncTable(dbName, readonly); return Promise.resolve(ret); } catch (err) { return Promise.reject(err); } } async getSyncDate(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; try { const ret = await this._getSyncDate(dbName, readonly); return Promise.resolve(ret); } catch (err) { return Promise.reject(err); } } async setSyncDate(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } if (!keys.includes('syncdate')) { return Promise.reject('Must provide a synchronization date'); } const dbName = options.database; const syncDate = options.syncdate; const readonly = options.readonly ? options.readonly : false; try { await this._setSyncDate(dbName, syncDate, readonly); return Promise.resolve(); } catch (err) { return Promise.reject(err); } } async isJsonValid(options) { const keys = Object.keys(options); if (!keys.includes('jsonstring')) { return Promise.reject('Must provide a json object'); } const jsonStrObj = options.jsonstring; try { const ret = await this._isJsonValid(jsonStrObj); return Promise.resolve(ret); } catch (err) { return Promise.reject(err); } } async importFromJson(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('jsonstring')) { return Promise.reject('Must provide a json object'); } const jsonStrObj = options.jsonstring; try { const ret = await this._importFromJson(jsonStrObj); return Promise.resolve(ret); } catch (err) { return Promise.reject(err); } } async exportToJson(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } if (!keys.includes('jsonexportmode')) { return Promise.reject('Must provide a json export mode'); } const dbName = options.database; const exportMode = options.jsonexportmode; const readonly = options.readonly ? options.readonly : false; try { const ret = await this._exportToJson(dbName, exportMode, readonly); return Promise.resolve(ret); } catch (err) { return Promise.reject(err); } } async deleteExportedRows(options) { const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; try { await this._deleteExportedRows(dbName, readonly); return Promise.resolve(); } catch (err) { return Promise.reject(err); } } async addUpgradeStatement(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } if (!keys.includes('upgrade')) { return Promise.reject('Must provide an upgrade capSQLiteVersionUpgrade Object'); } const dbName = options.database; const upgrades = options.upgrade; for (const upgrade of upgrades) { const versionUpgradeKeys = Object.keys(upgrade); if (!versionUpgradeKeys.includes('toVersion') || !versionUpgradeKeys.includes('statements')) { return Promise.reject('Must provide an upgrade capSQLiteVersionUpgrade Object'); } if (typeof upgrade.toVersion != 'number') { return Promise.reject('upgrade.toVersion must be a number'); } if (this._versionUpgrades[dbName]) { this._versionUpgrades[dbName][upgrade.toVersion] = upgrade; } else { const upgVDict = {}; upgVDict[upgrade.toVersion] = upgrade; this._versionUpgrades[dbName] = upgVDict; } } return Promise.resolve(); } async isDatabase(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; try { const ret = await this._isDatabase(dbName); return Promise.resolve(ret); } catch (err) { return Promise.reject(err); } } async getDatabaseList() { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } try { const ret = await this._getDatabaseList(); return Promise.resolve(ret); } catch (err) { return Promise.reject(err); } } async checkConnectionsConsistency(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('dbNames')) { return Promise.reject(`Must provide a list of connection's name`); } const dbNames = options.dbNames; if (!keys.includes('openModes')) { return Promise.reject(`Must provide a list of connection's open mode`); } const openModes = options.openModes; try { const ret = await this._checkConnectionsConsistency(dbNames, openModes); return Promise.resolve(ret); } catch (err) { return Promise.reject(err); } } async saveToStore(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; const readonly = options.readonly ? options.readonly : false; try { await this._saveToStore(dbName, readonly); return Promise.resolve(); } catch (err) { return Promise.reject(err); } } async saveToLocalDisk(options) { const keys = Object.keys(options); if (!keys.includes('database')) { return Promise.reject('Must provide a database name'); } const dbName = options.database; try { await this._saveToLocalDisk(dbName); return Promise.resolve(); } catch (err) { return Promise.reject(err); } } async getFromLocalDiskToStore(options) { const overwrite = options.overwrite ? options.overwrite : true; if (supported) { console.log('Using the File System Access API.'); } else { console.log('Using the fallback implementation.'); } try { await this._getFromLocalDiskToStore(overwrite); return Promise.resolve(); } catch (err) { return Promise.reject(err); } } async getFromHTTPRequest(options) { if (!this.isStore) { return Promise.reject(`>>> jeep-sqlite StoreName: ${this.storeName} is not opened`); } let keys = Object.keys(options); if (!keys.includes('url')) { return Promise.reject('Must provide an url'); } const url = options.url; const overwrite = options.overwrite ? options.overwrite : true; try { await this._getFromHTTPRequest(url, overwrite); return Promise.resolve(); } catch (err) { return Promise.reject(err); } } //******************************* //* Component Lifecycle Methods * //******************************* connectedCallback() { this.parseAutoSave(this.autoSave !== undefined ? this.autoSave : false); this.parseTypeOrm(this.typeOrm !== undefined ? this.typeOrm : false); this.parseWasmPath(this.wasmPath !== undefined ? this.wasmPath : '/assets'); this.parseSaveText(this.saveText !== undefined ? this.saveText : 'Save'); this.parsePickText(this.pickText !== undefined ? this.pickText : 'Pick a database'); if (this.buttonOptions !== undefined) { this.parseButtonOptions(this.buttonOptions); } this.openStore("jeepSqliteStore", "databases").then((mStore) => { this.isStore = mStore; }); } componentWillLoad() { } async componentDidLoad() { this._element = this.el.shadowRoot; if (!this.isStore) { console.log('jeep-sqlite isStore = false'); } } //****************************** //* Private Method Definitions * //****************************** async _createConnection(database, version, readonly) { let upgDict = {}; const vUpgKeys = Object.keys(this._versionUpgrades); if (vUpgKeys.length !== 0 && vUpgKeys.includes(database)) { upgDict = this._versionUpgrades[database]; } const dbDictKeys = Object.keys(this._dbDict); let mDB; try { if (dbDictKeys.length > 0 && (dbDictKeys.includes("RW_" + database) || dbDictKeys.includes("RO_" + database))) { mDB = dbDictKeys.includes("RW_" + database) ? this._dbDict["RW_" + database] : this._dbDict["RO_" + database]; } else { mDB = new Database(database + 'SQLite.db', version, upgDict, this.store, this.innerAutoSave, this.innerWasmPath); } const connName = readonly ? "RO_" + database : "RW_" + database; this._dbDict[connName] = mDB; return Promise.resolve(); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(msg); } } async _isConnection(database, readonly) { const keys = Object.keys(this._dbDict); const connName = readonly ? "RO_" + database : "RW_" + database; if (keys.includes(connName)) { return { result: true }; } else { return { result: false }; } } async _closeConnection(database, readonly) { const keys = Object.keys(this._dbDict); const connName = readonly ? "RO_" + database : "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`CloseConnection: No available connection for ${database}`); } const mDB = this._dbDict[connName]; try { if (mDB.isDBOpen()) { await mDB.close(); } // remove the connection from dictionary delete this._dbDict[connName]; return Promise.resolve(); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`CloseConnection: ${msg}`); } } async _open(database, readonly) { const keys = Object.keys(this._dbDict); const connName = readonly ? "RO_" + database : "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`Open: No available connection for ${database}`); } const mDB = this._dbDict[connName]; try { await mDB.open(); return Promise.resolve(); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`Open: ${msg}`); } } async _close(database, readonly) { const keys = Object.keys(this._dbDict); const connName = readonly ? "RO_" + database : "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`Close: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`Close: ${database} database not opened`); } try { await mDB.close(); return Promise.resolve(); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`Close: ${msg}`); } } async _saveToStore(database, readonly) { const keys = Object.keys(this._dbDict); const connName = readonly ? "RO_" + database : "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`SaveToStore: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`SaveToStore: ${database} database not opened`); } try { await mDB.saveToStore(); return Promise.resolve(); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`SaveToStore: ${msg}`); } } async _saveToLocalDisk(database) { try { const keys = Object.keys(this._dbDict); const connName = "RW_" + database; if (!keys.includes(connName)) { return Promise.reject('SaveToLocalDisk: No available connection for ' + `${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`SaveToLocalDisk: ${database} database not opened`); } const uint = await mDB.exportDB(); this._blob = await this.uint2blob(uint); const dbName = `${database}SQLite.db`; this._opts = { fileName: dbName, extensions: ['.db'], startIn: 'documents', }; this._buttonSaveEl = document.createElement('button'); // const baseName = this._opts.fileName.split('.db')[0]; this._buttonSaveEl.setAttribute("id", `saveButton`); this._buttonSaveEl.innerHTML = `${this.innerSaveText} ${dbName}`; this._element.appendChild(this._buttonSaveEl); this._buttonSaveEl.addEventListener("click", this.saveFile.bind(this)); return Promise.resolve(); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`SaveToLocalDisk: ${msg}`); } } async _getFromLocalDiskToStore(overwrite) { this._buttonPickEl = document.createElement('button'); this._buttonPickEl.setAttribute("id", "pickButton"); this._buttonPickEl.innerHTML = `${this.innerPickText}`; this._element.appendChild(this._buttonPickEl); this._buttonPickEl.addEventListener("click", this.pickDatabase.bind(this)); this._overwrite = overwrite; return Promise.resolve(); } async pickDatabase() { try { const blob = await fileOpen({ extensions: ['.db'] }); let uInt8Array = await this.blob2uint(blob); const databaseName = this.removePathSuffix(blob.name); const dbName = this.setPathSuffix(blob.name); // check if dbName exists const isExist = await UtilsStore.isDBInStore(dbName, this.store); if (!isExist) { await UtilsStore.saveDBToStore(dbName, uInt8Array, this.store); } else { if (this._overwrite) { await UtilsStore.removeDBFromStore(dbName, this.store); await UtilsStore.saveDBToStore(dbName, uInt8Array, this.store); } else { this.PickDatabaseEnded.emit({ message: `Error: cannot overwrite ${dbName}` }); } } this._element.removeChild(this._buttonPickEl); this.PickDatabaseEnded.emit({ db_name: databaseName }); } catch (err) { const msg = err.message ? err.message : err; this.PickDatabaseEnded.emit({ message: msg }); } } async saveFile() { try { await fileSave(this._blob, [this._opts]); const databaseName = this._opts.fileName; this._element.removeChild(this._buttonSaveEl); this.SaveDatabaseEnded.emit({ db_name: databaseName }); } catch (err) { const msg = err.message ? err.message : err; this.SaveDatabaseEnded.emit({ message: msg }); } } async _getVersion(database, readonly) { const keys = Object.keys(this._dbDict); const connName = readonly ? "RO_" + database : "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`Open: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`GetVersion: ${database} database not opened`); } try { const version = await mDB.getVersion(); const ret = {}; ret.version = version; return Promise.resolve(ret); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`Open: ${msg}`); } } async _beginTransaction(database) { const keys = Object.keys(this._dbDict); const connName = "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`BeginTransaction: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`BeginTransaction: ${database} database not opened`); } let changes = {}; const ret = await mDB.beginTransaction(); changes = { changes: { changes: ret } }; return Promise.resolve(changes); } async _commitTransaction(database) { const keys = Object.keys(this._dbDict); const connName = "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`CommitTransaction: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`CommitTransaction: ${database} database not opened`); } let changes = {}; const ret = await mDB.commitTransaction(); changes = { changes: { changes: ret } }; return Promise.resolve(changes); } async _rollbackTransaction(database) { const keys = Object.keys(this._dbDict); const connName = "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`RollbackTransaction: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`RollbackTransaction: ${database} database not opened`); } let changes = {}; const ret = await mDB.rollbackTransaction(); changes = { changes: { changes: ret } }; return Promise.resolve(changes); } async _isTransactionActive(database) { const keys = Object.keys(this._dbDict); const connName = "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`IsTransactionActive: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`IsTransactionActive: ${database} database not opened`); } let result = {}; const res = mDB.isTransActive(); result = { result: res }; return Promise.resolve(result); } async _execute(database, statements, transaction, readonly) { const keys = Object.keys(this._dbDict); const connName = "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`Execute: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`Execute: ${database} database not opened`); } if (readonly) { return Promise.reject(`Execute: not allowed in read-only mode`); } let changes = {}; const command = statements.substring(0, 6); if (this.innerAutoSave && command === "COMMIT" && this.innerTypeOrm) { // fix issue for typeORM with autosave changes = { changes: { changes: 0 } }; return Promise.resolve(changes); } try { const ret = await mDB.executeSQL(statements, transaction); changes = { changes: { changes: ret } }; return Promise.resolve(changes); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`Execute: ${msg}`); } } async _executeSet(database, setOfStatements, transaction, readonly, returnMode) { const keys = Object.keys(this._dbDict); const connName = "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`ExecuteSet: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`ExecuteSet: ${database} database not opened`); } if (readonly) { return Promise.reject(`ExecuteSet: not allowed in read-only mode`); } for (const sStmt of setOfStatements) { if (!('statement' in sStmt) || !('values' in sStmt)) { return Promise.reject('ExecuteSet: Must provide a set as ' + 'Array of {statement,values}'); } } try { const ret = await mDB.execSet(setOfStatements, transaction, returnMode); const changes = { changes: { changes: ret.changes, lastId: ret.lastId, values: ret.values } }; return Promise.resolve(changes); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`ExecuteSet: ${msg}`); } } async _run(database, statement, values, transaction, readonly, returnMode) { const keys = Object.keys(this._dbDict); const connName = "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`Run: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`Run: ${database} database not opened`); } if (readonly) { return Promise.reject(`Run: not allowed in read-only mode`); } let changes = {}; const command = statement.substring(0, 6); if (this.innerAutoSave && command === "COMMIT") { // fix issue for typeORM with autosave changes = { changes: { changes: 0 } }; return Promise.resolve(changes); } try { const ret = await mDB.runSQL(statement, values, transaction, returnMode); changes = { changes: { changes: ret.changes, lastId: ret.lastId, values: ret.values } }; return Promise.resolve(changes); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`Run: ${msg}`); } } async _query(database, statement, values, readonly) { const keys = Object.keys(this._dbDict); const connName = readonly ? "RO_" + database : "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`Query: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`Query: ${database} database not opened`); } let ret = []; const command = statement.substring(0, 6); if (this.innerAutoSave && command === "COMMIT") { // fix issue for typeORM with autosave return Promise.resolve({ values: ret }); } try { ret = await mDB.selectSQL(statement, values); return Promise.resolve({ values: ret }); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`Query failed: ${msg}`); } } async _getTableList(database, readonly) { const keys = Object.keys(this._dbDict); const connName = readonly ? "RO_" + database : "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`GetTableList: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`GetTableList: ${database} database not opened`); } let ret = []; try { ret = await mDB.getTableNames(); return Promise.resolve({ values: ret }); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`GetTableList failed: ${msg}`); } } async _isDBExists(database, readonly) { const keys = Object.keys(this._dbDict); const connName = readonly ? "RO_" + database : "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`IsDBExists: No available connection for ${database}`); } const mDB = this._dbDict[connName]; /* if (!mDB.isDBOpen()) { return Promise.reject( `IsDBExists: ${database} database not opened`); } */ try { const ret = await mDB.isDBExists(database + 'SQLite.db'); const result = { result: ret }; return Promise.resolve(result); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`IsDBExists: ${msg}`); } } async _isDBOpen(database, readonly) { const keys = Object.keys(this._dbDict); const connName = readonly ? "RO_" + database : "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`IsDBOpen: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { const result = { result: false }; return Promise.resolve(result); } try { const ret = await mDB.isDBOpen(database + 'SQLite.db'); const result = { result: ret }; return Promise.resolve(result); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`IsDBOpen: ${msg}`); } } async _deleteDatabase(database, readonly) { const keys = Object.keys(this._dbDict); const connName = "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`DeleteDatabase: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (readonly) { return Promise.reject(`DeleteDatabase: not allowed in read-only mode`); } try { await mDB.deleteDB(database + 'SQLite.db'); return Promise.resolve(); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`DeleteDatabase: ${msg}`); } } async _isTableExists(database, table, readonly) { const keys = Object.keys(this._dbDict); const connName = readonly ? "RO_" + database : "RW_" + database; if (!keys.includes(connName)) { return Promise.reject(`IsTableExists: No available connection for ${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`IsTableExists: ${database} database not opened`); } try { const ret = await mDB.isTable(table); const result = { result: ret }; return Promise.resolve(result); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`IsTableExists: ${msg}`); } } async _createSyncTable(database, readonly) { const keys = Object.keys(this._dbDict); const connName = "RW_" + database; if (!keys.includes(connName)) { return Promise.reject('CreateSyncTable: No available connection for ' + `${database}`); } const mDB = this._dbDict[connName]; if (!mDB.isDBOpen()) { return Promise.reject(`CreateSyncTable: ${database} database not opened`); } if (readonly) { return Promise.reject(`CreateSyncTable: not allowed in read-only mode`); } try { const ret = await mDB.createSyncTable(); return Promise.resolve({ changes: { changes: ret } }); } catch (err) { const msg = err.message ? err.message : err; return Promise.reject(`CreateSyncTable: ${msg}`); } } async _getSyncDate(database, readonly) { const keys = Object.keys(this._dbDict); const connName = readonly ? "RO_" + database : "RW_" + d