@egi/smart-db 2.6.2 → 2.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- import BetterSqlite3 from"better-sqlite3";import _ from"lodash";import{SqliteMasterModel}from"../models/sqlite-master-model";import{SmartDb}from"../smart-db";export class SmartDbBetterSqlite3 extends SmartDb{constructor(t,e){_.isString(t)?(super(t),this.db=new BetterSqlite3(t,e)):(super(null),this.db=t,this.db.inTransaction),this.isReady=!0}aggregate(t,e){return!!this.saveExecute((()=>this.db.aggregate(t,e)))}backup(t,e){return new Promise(((s,r)=>{const n=this.saveExecute((()=>this.db.backup(t,e)));0==n?r(this.getLastError()):s(n)}))}closeSync(){return this.smartDbLog.setDb(null),!!this.db.close()}commitSync(){this.db.inTransaction&&this.db.exec("commit")}defaultSafeIntegers(t){return!!this.saveExecute((()=>this.db.defaultSafeIntegers(t)))}execSync(t){return!!this.saveExecute((()=>this.db.exec(t)))}existsSync(t,e,s){let r=!1;const n=_.isString(t)?t:t.getTableName(),a=this.getFirstSync(SqliteMasterModel,{name:n,type:e,tblName:s});if(!1===a)throw this.getLastError();return r=!!a,r}func(t,e,s){return this.saveExecute((()=>{let r;return r=_.isFunction(e)?this.db.function(t,e):this.db.function(t,e,s),r}))}getDatabaseType(){return"sqlite3"}getTableInfo(t){return new Promise((e=>{const s=this.pragma(`table_info(${t})`);let r=[];s&&(r=s.map((t=>({cid:t.cid,name:t.name,type:t.type,notNull:0!==t.notnull,defaultValue:t.dflt_value,isPk:0!==t.pk}))),e({name:t,fields:r}))}))}hasTransaction(){return this.db.inTransaction}loadExtension(t){return!!this.saveExecute((()=>this.db.loadExtension(t)))}pragma(t,e){return this.saveExecute((()=>this.db.pragma(t,e)))}rollbackSync(){this.db.inTransaction&&this.db.exec("rollback")}transaction(t){return!!this.saveExecute((()=>this.db.transaction(t)))}statementRun(t,e=0){return new Promise(((s,r)=>{try{s(this.statementRunSync(t))}catch(n){"SQLITE_BUSY"==n.code&&e<10?setTimeout((()=>{this.statementRun(t,e+1).then((t=>{s(t)})).catch((t=>{r(t)}))}),100):(this.lastError=n,r(n))}}))}statementRunSync(t){const e=this.db.prepare(t.sql),s=e&&e.run(t.values);return s&&{changes:s.changes,affected:s.changes,lastId:s.lastInsertRowid}}statementGetSync(t){const e=this.db.prepare(t.sql);return e&&e.get(t.values)}statementGetAllSync(t){const e=this.db.prepare(t.sql);return e&&e.all(t.values)}get supportSyncCalls(){return!0}}
1
+ import BetterSqlite3 from"better-sqlite3";import _ from"lodash";import{SqliteMasterModel}from"../models/sqlite-master-model";import{SmartDb}from"../smart-db";export class SmartDbBetterSqlite3 extends SmartDb{constructor(t,e){_.isString(t)?(super(t),this.db=new BetterSqlite3(t,e)):(super(null),this.db=t,this.db.inTransaction),this.isReady=!0}aggregate(t,e){return!!this.saveExecute((()=>this.db.aggregate(t,e)))}backup(t,e){return new Promise(((s,r)=>{const n=this.saveExecute((()=>this.db.backup(t,e)));0==n?r(this.getLastError()):s(n)}))}closeSync(){return this.smartDbLog.setDb(null),this.isReady=!1,!!this.db.close()}commitSync(){this.db.inTransaction&&this.db.exec("commit")}defaultSafeIntegers(t){return!!this.saveExecute((()=>this.db.defaultSafeIntegers(t)))}execSync(t){return!!this.saveExecute((()=>this.db.exec(t)))}existsSync(t,e,s){let r=!1;const n=_.isString(t)?t:t.getTableName(),a=this.getFirstSync(SqliteMasterModel,{name:n,type:e,tblName:s});if(!1===a)throw this.getLastError();return r=!!a,r}func(t,e,s){return this.saveExecute((()=>{let r;return r=_.isFunction(e)?this.db.function(t,e):this.db.function(t,e,s),r}))}getDatabaseType(){return"sqlite3"}getTableInfo(t){return new Promise((e=>{const s=this.pragma(`table_info(${t})`);let r=[];s&&(r=s.map((t=>({cid:t.cid,name:t.name,type:t.type,notNull:0!==t.notnull,defaultValue:t.dflt_value,isPk:0!==t.pk}))),e({name:t,fields:r}))}))}hasTransaction(){return this.db.inTransaction}loadExtension(t){return!!this.saveExecute((()=>this.db.loadExtension(t)))}pragma(t,e){return this.saveExecute((()=>this.db.pragma(t,e)))}rollbackSync(){this.db.inTransaction&&this.db.exec("rollback")}transaction(t){return!!this.saveExecute((()=>this.db.transaction(t)))}statementRun(t,e=0){return new Promise(((s,r)=>{try{s(this.statementRunSync(t))}catch(n){"SQLITE_BUSY"==n.code&&e<10?setTimeout((()=>{this.statementRun(t,e+1).then((t=>{s(t)})).catch((t=>{r(t)}))}),100):(this.lastError=n,r(n))}}))}statementRunSync(t){const e=this.db.prepare(t.sql),s=e&&e.run(t.values);return s&&{changes:s.changes,affected:s.changes,lastId:s.lastInsertRowid}}statementGetSync(t){const e=this.db.prepare(t.sql);return e&&e.get(t.values)}statementGetAllSync(t){const e=this.db.prepare(t.sql);return e&&e.all(t.values)}get supportSyncCalls(){return!0}}
@@ -1 +1 @@
1
- import _ from"lodash";import Mysql from"mysql";import{SmartDb}from"../smart-db";export class SmartDbMysql extends SmartDb{constructor(t){t.config&&t.connect?(super(t.config),this.db=t):(super(t),this.db=Mysql.createConnection(t))}close(){return new Promise((t=>{this.db.end((r=>{r?(this.lastError=r,t(!1)):t(!0)}))}))}commit(){return new Promise(((t,r)=>{this.db.commit((e=>{e?(this.lastError=e,r(e)):t()}))}))}exec(t){return new Promise(((r,e)=>{try{this.db.query(t,((t,s,o)=>{t?(this.lastError=t,e(t)):r()}))}catch(t){this.lastError=t,e(t)}}))}exists(t,r,e){return new Promise(((r,e)=>{const s=_.isString(t)?t:t.getTableName();this.db.query(`show tables like '${s}'`,((t,s,o)=>{t?(this.lastError=t,e(t)):r(s&&s.length>0)}))}))}getDatabaseType(){return"mysql"}getDbQuote(){return"`"}getTableInfo(t){throw new Error("Method not implemented (getTableInfo)")}rollback(){return new Promise(((t,r)=>{this.db.rollback((e=>{e?(this.lastError=e,r(e)):t()}))}))}statementRun(t){return new Promise(((r,e)=>{this.db.query(t.sql,t.values,((t,s,o)=>{if(t)this.lastError=t,e(t);else{const t={changes:s.changedRows,affected:s.affectedRows,lastId:s.insertId};r(t)}}))}))}statementGet(t){return new Promise(((r,e)=>{try{this.db.query(t.sql,t.values,((t,s,o)=>{t?(this.lastError=t,e(t)):r(s&&s[0])}))}catch(t){this.lastError=t,e(t)}}))}statementGetAll(t){return new Promise(((r,e)=>{this.db.query(t.sql,t.values,((t,s,o)=>{t?(this.lastError=t,e(t)):r(s&&s)}))}))}}
1
+ import _ from"lodash";import Mysql from"mysql";import{SmartDb}from"../smart-db";export class SmartDbMysql extends SmartDb{constructor(t){t.config&&t.connect?(super(t.config),this.db=t):(super(t),this.db=Mysql.createConnection(t))}close(){return new Promise((t=>{this.db.end((r=>{this.isReady=!1,r?(this.lastError=r,t(!1)):t(!0)}))}))}commit(){return new Promise(((t,r)=>{this.db.commit((e=>{e?(this.lastError=e,r(e)):t()}))}))}exec(t){return new Promise(((r,e)=>{try{this.db.query(t,((t,s,o)=>{t?(this.lastError=t,e(t)):r()}))}catch(t){this.lastError=t,e(t)}}))}exists(t,r,e){return new Promise(((r,e)=>{const s=_.isString(t)?t:t.getTableName();this.db.query(`show tables like '${s}'`,((t,s,o)=>{t?(this.lastError=t,e(t)):r(s&&s.length>0)}))}))}getDatabaseType(){return"mysql"}getDbQuote(){return"`"}getTableInfo(t){throw new Error("Method not implemented (getTableInfo)")}rollback(){return new Promise(((t,r)=>{this.db.rollback((e=>{e?(this.lastError=e,r(e)):t()}))}))}statementRun(t){return new Promise(((r,e)=>{this.db.query(t.sql,t.values,((t,s,o)=>{if(t)this.lastError=t,e(t);else{const t={changes:s.changedRows,affected:s.affectedRows,lastId:s.insertId};r(t)}}))}))}statementGet(t){return new Promise(((r,e)=>{try{this.db.query(t.sql,t.values,((t,s,o)=>{t?(this.lastError=t,e(t)):r(s&&s[0])}))}catch(t){this.lastError=t,e(t)}}))}statementGetAll(t){return new Promise(((r,e)=>{this.db.query(t.sql,t.values,((t,s,o)=>{t?(this.lastError=t,e(t)):r(s&&s)}))}))}}
@@ -1 +1 @@
1
- import _ from"lodash";import Mysql from"mysql";import{SmartDb}from"../smart-db";export class SmartDbMysql2 extends SmartDb{constructor(t){t.config&&t.connect?(super(t.config),this.db=t):(super(t),this.db=Mysql.createConnection(t))}close(){return new Promise(((t,e)=>{this.db.end((e=>{e?(this.lastError=e,t(!1)):t(!0)}))}))}commit(){return new Promise(((t,e)=>{this.db.commit((r=>{r?(this.lastError=r,e(r)):t()}))}))}exec(t){return new Promise(((e,r)=>{try{this.db.query(t,((t,s,o)=>{t?(this.lastError=t,r(t)):e()}))}catch(t){r(t)}}))}exists(t,e,r){return new Promise(((e,r)=>{const s=_.isString(t)?t:t.getTableName();this.db.query(`show tables like '${s}'`,((t,s,o)=>{t?(this.lastError=t,r(t)):e(s&&s.length>0)}))}))}getDatabaseType(){return"mysql"}getDbQuote(){return"`"}getTableInfo(t){throw new Error("Method not implemented (getTableInfo)")}rollback(){return new Promise(((t,e)=>{this.db.rollback((r=>{r?(this.lastError=r,e(r)):t()}))}))}statementRun(t){return new Promise(((e,r)=>{this.db.query(t.sql,t.values,((t,s,o)=>{if(t)this.lastError=t,r(t);else{const t={changes:s.changedRows,affected:s.affectedRows,lastId:s.insertId};e(t)}}))}))}statementGet(t){return new Promise(((e,r)=>{try{this.db.query(t.sql,t.values,((t,s,o)=>{t?(this.lastError=t,r(t)):e(s&&s[0])}))}catch(t){this.lastError=t,r(t)}}))}statementGetAll(t){return new Promise(((e,r)=>{this.db.query(t.sql,t.values,((t,s,o)=>{t?(this.lastError=t,r(t)):(console.log(o),e(s&&s))}))}))}}
1
+ import _ from"lodash";import Mysql from"mysql";import{SmartDb}from"../smart-db";export class SmartDbMysql2 extends SmartDb{constructor(t){t.config&&t.connect?(super(t.config),this.db=t):(super(t),this.db=Mysql.createConnection(t))}close(){return new Promise(((t,e)=>{this.db.end((e=>{this.isReady=!1,e?(this.lastError=e,t(!1)):t(!0)}))}))}commit(){return new Promise(((t,e)=>{this.db.commit((r=>{r?(this.lastError=r,e(r)):t()}))}))}exec(t){return new Promise(((e,r)=>{try{this.db.query(t,((t,s,o)=>{t?(this.lastError=t,r(t)):e()}))}catch(t){r(t)}}))}exists(t,e,r){return new Promise(((e,r)=>{const s=_.isString(t)?t:t.getTableName();this.db.query(`show tables like '${s}'`,((t,s,o)=>{t?(this.lastError=t,r(t)):e(s&&s.length>0)}))}))}getDatabaseType(){return"mysql"}getDbQuote(){return"`"}getTableInfo(t){throw new Error("Method not implemented (getTableInfo)")}rollback(){return new Promise(((t,e)=>{this.db.rollback((r=>{r?(this.lastError=r,e(r)):t()}))}))}statementRun(t){return new Promise(((e,r)=>{this.db.query(t.sql,t.values,((t,s,o)=>{if(t)this.lastError=t,r(t);else{const t={changes:s.changedRows,affected:s.affectedRows,lastId:s.insertId};e(t)}}))}))}statementGet(t){return new Promise(((e,r)=>{try{this.db.query(t.sql,t.values,((t,s,o)=>{t?(this.lastError=t,r(t)):e(s&&s[0])}))}catch(t){this.lastError=t,r(t)}}))}statementGetAll(t){return new Promise(((e,r)=>{this.db.query(t.sql,t.values,((t,s,o)=>{t?(this.lastError=t,r(t)):(console.log(o),e(s&&s))}))}))}}
@@ -1 +1 @@
1
- import fs from"fs";import process from"node:process";import oracleDb from"oracledb";import{take}from"rxjs";import{OracleCatModel}from"../models/oracle-cat-model";import{OracleUserTabColumnsViewModel}from"../models/oracle-user-tab-columns-view-model";import{SmartDb}from"../smart-db";export class SmartDbOracle extends SmartDb{constructor(e,t){if(!SmartDbOracle.libInit){let e;"darwin"===process.platform&&(e=process.env.ORACLE_HOME),e&&fs.existsSync(e)&&oracleDb.initOracleClient({libDir:e}),SmartDbOracle.libInit=!0}"string"==typeof e?super(e,t?.noDbLogging):super(null),this.reconnect(e,t)}close(){return new Promise(((e,t)=>{try{this.smartDbLog.setDb(null),this.db.close((t=>{t?(this.lastError=t,e(!1)):(this._onReady.next(!1),e(!0))}))}catch(e){this.lastError=e,t(e)}}))}commit(){return this.db.commit()}exec(e){return new Promise(((t,r)=>{try{this.db.execute(e,(e=>{e?(this.lastError=e,r(e)):t()}))}catch(e){this.lastError=e,r(e)}}))}exists(e,t,r){return new Promise(((r,s)=>{try{const o="string"==typeof e?e:e.getTableName();this.getFirst(OracleCatModel,{name:o.toUpperCase(),type:t?t.toUpperCase():void 0}).then((e=>{r(!!e)})).catch((e=>{s(e)}))}catch(e){this.lastError=e,s(e)}}))}getDatabaseType(){return"oracle"}getTableInfo(e){return new Promise((async(t,r)=>{await this.getAll(OracleUserTabColumnsViewModel,{tableName:e.toUpperCase()}).then((s=>{if(!1!==s){let r=[];r=s.map((e=>({cid:e.columnId,name:e.columnName,type:e.dataType,notNull:"Y"!=e.nullable,defaultValue:e.defaultValue,isPk:"P"==e.constraintType}))),t({name:e,fields:r})}else r(this.getLastError())})).catch((e=>{this.lastError=e,r(e)}))}))}hasConcurrentTransactions(){return!0}reconnect(e,t){e?this.connectorOrDb=e:e=this.connectorOrDb,t?this.options=t:t=this.options,"string"==typeof e?oracleDb.getConnection(Object.assign({connectString:e},t??this.options)).then((e=>{this.db=e,t&&t.onReady&&this.onReady().pipe(take(1)).subscribe((r=>{r&&t.onReady(e)})),this.exec("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'").then((e=>{this.exec("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY:MM:DD HH24:MI:SS.FF'").then((e=>{this.isReady=!0})).catch((e=>{throw e}))})).catch((e=>{throw e}))})).catch((e=>{t&&t.onReady&&t.onReady(null,e),t.silent||console.log("unable prepare session database connection",e),this.isReady=null})):this.db=e}rollback(){return this.db.rollback()}statementRun(e){return new Promise(((t,r)=>{try{this.db.execute(this.replacePlaceholders(e.sql),e.values,((e,s)=>{e?(this.lastError=e,r(e)):this.commit().then((()=>{t({changes:s.rowsAffected,affected:s.rowsAffected,lastId:null})})).catch((e=>{r(e)}))}))}catch(e){this.lastError=e,r(e)}}))}statementGet(e){return new Promise(((t,r)=>{try{this.db.execute(this.replacePlaceholders(this.replacePlaceholders(e.sql)),e.values,{maxRows:1,outFormat:oracleDb.OUT_FORMAT_OBJECT},((e,s)=>{if(e)this.lastError=e,r(e);else{const e=s.rows[0];let r=null;if(e){r={};Object.keys(e).forEach((t=>{r[t.toLowerCase()]=e[t]}))}t(r)}}))}catch(e){this.lastError=e,r(e)}}))}statementGetAll(e){return new Promise(((t,r)=>{try{this.db.execute(this.replacePlaceholders(e.sql),e.values,{maxRows:0,outFormat:oracleDb.OUT_FORMAT_OBJECT}).then((e=>{t(e.rows)})).catch((e=>{this.lastError=e,r(e)}))}catch(e){this.lastError=e,r(e)}}))}replacePlaceholders(e){let t=1,r=!1;for(let s=0;s<e.length;s++)"'"==e[s]?r=!r:r||"?"!=e[s]||(e=e.substring(0,s)+":"+t+++e.substring(s+1));return e}}SmartDbOracle.libInit=!1;
1
+ import fs from"fs";import process from"node:process";import oracleDb from"oracledb";import{take}from"rxjs";import{OracleCatModel}from"../models/oracle-cat-model";import{OracleUserTabColumnsViewModel}from"../models/oracle-user-tab-columns-view-model";import{SmartDb}from"../smart-db";import{SmartErrorLocation}from"../smart-error";export class SmartDbOracle extends SmartDb{constructor(e,t){if(!SmartDbOracle.libInit){let e;"darwin"===process.platform&&(e=process.env.ORACLE_HOME),e&&fs.existsSync(e)&&oracleDb.initOracleClient({libDir:e}),SmartDbOracle.libInit=!0}"string"==typeof e?super(e,t?.noDbLogging):super(null),this.reconnect(e,t)}close(){return new Promise(((e,t)=>{try{this.smartDbLog.setDb(null),this.db.close((t=>{this.isReady=!1,t?(this.lastError=t,e(!1)):(this._onReady.next(!1),e(!0))}))}catch(e){this.lastError=e,t(e)}}))}commit(){return this.db.commit()}exec(e){return new Promise(((t,r)=>{try{this.db.execute(e,(e=>{e?(this.lastError=e,r(e)):t()}))}catch(e){this.lastError=e,r(e)}}))}exists(e,t,r){return new Promise(((r,s)=>{try{const o="string"==typeof e?e:e.getTableName();this.getFirst(OracleCatModel,{name:o.toUpperCase(),type:t?t.toUpperCase():void 0}).then((e=>{r(!!e)})).catch((e=>{s(e)}))}catch(e){this.lastError=e,s(e)}}))}getDatabaseType(){return"oracle"}getTableInfo(e){return new Promise((async(t,r)=>{await this.getAll(OracleUserTabColumnsViewModel,{tableName:e.toUpperCase()}).then((s=>{if(!1!==s){let r=[];r=s.map((e=>({cid:e.columnId,name:e.columnName,type:e.dataType,notNull:"Y"!=e.nullable,defaultValue:e.defaultValue,isPk:"P"==e.constraintType}))),t({name:e,fields:r})}else r(this.getLastError())})).catch((e=>{this.lastError=e,r(e)}))}))}hasConcurrentTransactions(){return!0}reconnect(e,t){e?this.connectorOrDb=e:e=this.connectorOrDb,t?this.options=t:t=this.options,"string"==typeof e?oracleDb.getConnection(Object.assign({connectString:e},t??this.options)).then((e=>{this.db=e,t&&t.onReady&&this.onReady().pipe(take(1)).subscribe((r=>{r&&t.onReady(e)})),this.exec("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'").then((e=>{this.exec("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY:MM:DD HH24:MI:SS.FF'").then((e=>{this.isReady=!0})).catch((e=>{throw e}))})).catch((e=>{throw e}))})).catch((e=>{t&&t.onReady&&t.onReady(null,e),this.smartDbLog.logError(SmartErrorLocation.Database,"reconnect","unable prepare session database connection",e),this.isReady=null})):this.db=e}rollback(){return this.db.rollback()}statementRun(e){return new Promise(((t,r)=>{try{this.db.execute(this.replacePlaceholders(e.sql),e.values,((e,s)=>{e?(this.lastError=e,r(e)):this.commit().then((()=>{t({changes:s.rowsAffected,affected:s.rowsAffected,lastId:null})})).catch((e=>{r(e)}))}))}catch(e){this.lastError=e,r(e)}}))}statementGet(e){return new Promise(((t,r)=>{try{this.db.execute(this.replacePlaceholders(this.replacePlaceholders(e.sql)),e.values,{maxRows:1,outFormat:oracleDb.OUT_FORMAT_OBJECT},((e,s)=>{if(e)this.lastError=e,r(e);else{const e=s.rows[0];let r=null;if(e){r={};Object.keys(e).forEach((t=>{r[t.toLowerCase()]=e[t]}))}t(r)}}))}catch(e){this.lastError=e,r(e)}}))}statementGetAll(e){return new Promise(((t,r)=>{try{this.db.execute(this.replacePlaceholders(e.sql),e.values,{maxRows:0,outFormat:oracleDb.OUT_FORMAT_OBJECT}).then((e=>{t(e.rows)})).catch((e=>{this.lastError=e,r(e)}))}catch(e){this.lastError=e,r(e)}}))}replacePlaceholders(e){let t=1,r=!1;for(let s=0;s<e.length;s++)"'"==e[s]?r=!r:r||"?"!=e[s]||(e=e.substring(0,s)+":"+t+++e.substring(s+1));return e}}SmartDbOracle.libInit=!1;
@@ -1 +1 @@
1
- import _ from"lodash";import Sqlite3 from"sqlite3";import{SqliteMasterModel}from"../models/sqlite-master-model";import{SmartDb}from"../smart-db";export class SmartDbSqlite3 extends SmartDb{constructor(t,r){_.isString(t)?(super(t),this.db=new Sqlite3.Database(t,r&&r.mode,r&&r.callback)):(super(null),this.db=t)}close(){return new Promise(((t,r)=>{try{this.smartDbLog.setDb(null),this.db.close((r=>{r?(this.lastError=r,t(!1)):t(!0)}))}catch(t){this.lastError=t,r(t)}}))}commit(){return this.exec("commit")}exec(t){return new Promise(((r,e)=>{try{this.db.exec(t,(t=>{t?(this.lastError=t,e(t)):r()}))}catch(t){this.lastError=t,e(t)}}))}exists(t,r,e){return new Promise(((s,a)=>{try{const i=_.isString(t)?t:t.getTableName();this.getFirst(SqliteMasterModel,{name:i,type:r,tblName:e}).then((t=>{s(!!t)})).catch((t=>{a(t)}))}catch(t){this.lastError=t,a(t)}}))}getDatabaseType(){return"sqlite3"}getTableInfo(t){throw new Error("Method not implemented (getTableInfo)")}rollback(){return this.exec("rollback")}statementRun(t){return new Promise(((r,e)=>{try{const s=this;this.db.run(t.sql,t.values,(function(t){t?(s.lastError=t,e(t)):r({changes:this.changes,affected:this.changes,lastId:this.lastID})}))}catch(t){this.lastError=t,e(t)}}))}statementGet(t){return new Promise(((r,e)=>{try{const s=this;this.db.prepare(t.sql,(function(a){a?e(a):this.get(t.values,(function(t,a){t?(s.lastError=t,e(t)):r(a)}))}))}catch(t){this.lastError=t,e(t)}}))}statementGetAll(t){return new Promise(((r,e)=>{try{const s=this;this.db.prepare(t.sql,(function(a){a?(s.lastError=a,e(a)):this.all(t.values,(function(t,a){t?(s.lastError=t,e(t)):r(a)}))}))}catch(t){this.lastError=t,e(t)}}))}}
1
+ import _ from"lodash";import Sqlite3 from"sqlite3";import{SqliteMasterModel}from"../models/sqlite-master-model";import{SmartDb}from"../smart-db";export class SmartDbSqlite3 extends SmartDb{constructor(t,r){_.isString(t)?(super(t),this.db=new Sqlite3.Database(t,r&&r.mode,r&&r.callback)):(super(null),this.db=t)}close(){return new Promise(((t,r)=>{try{this.smartDbLog.setDb(null),this.db.close((r=>{this.isReady=!1,r?(this.lastError=r,t(!1)):t(!0)}))}catch(t){this.lastError=t,r(t)}}))}commit(){return this.exec("commit")}exec(t){return new Promise(((r,e)=>{try{this.db.exec(t,(t=>{t?(this.lastError=t,e(t)):r()}))}catch(t){this.lastError=t,e(t)}}))}exists(t,r,e){return new Promise(((s,a)=>{try{const i=_.isString(t)?t:t.getTableName();this.getFirst(SqliteMasterModel,{name:i,type:r,tblName:e}).then((t=>{s(!!t)})).catch((t=>{a(t)}))}catch(t){this.lastError=t,a(t)}}))}getDatabaseType(){return"sqlite3"}getTableInfo(t){throw new Error("Method not implemented (getTableInfo)")}rollback(){return this.exec("rollback")}statementRun(t){return new Promise(((r,e)=>{try{const s=this;this.db.run(t.sql,t.values,(function(t){t?(s.lastError=t,e(t)):r({changes:this.changes,affected:this.changes,lastId:this.lastID})}))}catch(t){this.lastError=t,e(t)}}))}statementGet(t){return new Promise(((r,e)=>{try{const s=this;this.db.prepare(t.sql,(function(a){a?e(a):this.get(t.values,(function(t,a){t?(s.lastError=t,e(t)):r(a)}))}))}catch(t){this.lastError=t,e(t)}}))}statementGetAll(t){return new Promise(((r,e)=>{try{const s=this;this.db.prepare(t.sql,(function(a){a?(s.lastError=a,e(a)):this.all(t.values,(function(t,a){t?(s.lastError=t,e(t)):r(a)}))}))}catch(t){this.lastError=t,e(t)}}))}}
@@ -1 +1 @@
1
- import fs from"fs";import _ from"lodash";import process from"process";import{SmartDbBetterSqlite3}from"../drivers/smart-db-better-sqlite3";import{SmartDbOracle}from"../drivers/smart-db-oracle";import{OracleCatModel}from"../models/oracle-cat-model";import{SmartDbCoreTableModel}from"../models/smart-db-core-table-model";import{SqliteMasterModel}from"../models/sqlite-master-model";import{IN,NE,NOT_LIKE}from"../smart-db-globals";function getType(e){let t;return t=e?e.match(/varchar/i)||e.match(/text/i)?"string":e.match(/integer\(1\)/i)?"boolean":e.match(/date/i)?"Date":e.match(/integer/i)||e.match(/number/i)?"number":e.match(/long/i)||e.match(/raw/i)?"any":"SqlValueType":"SqlValueType",t}function getRelations(e){return new Promise((async(t,r)=>{e instanceof SmartDbOracle?e.getAll(OracleCatModel,{type:IN(["TABLE","VIEW"]),name:NOT_LIKE("BIN$%")}).then((a=>{a?t(a.map((e=>e.name.toLowerCase()))):r(e.getLastError())})).catch((e=>{r(e)})):e instanceof SmartDbBetterSqlite3?e.getAll(SqliteMasterModel,{type:IN(["table","view"]),name:NE("sqlite_sequence")}).then((a=>{a?t(a.map((e=>e.name))):r(e.getLastError())})).catch((e=>{r(e)})):r("unimplemented database type")}))}async function extractDbApi(e){console.log(`extract interface from '${e.db.getDbConnector()}' to '${e.modelDirectory}'`);const t=["break","case","catch","class","const","continue","debugger","default","delete","do","else","enum","export","extends","false","finally","for","function","If","import","in","instanceOf","interface","new","null","return","super","switch","this","throw","true","try","typeOf","var","void","while","with"];fs.existsSync(e.modelDirectory)||fs.mkdirSync(e.modelDirectory,{recursive:!0}),getRelations(e.db).then((async r=>{let a=[];if((e.skipCoreTables||e.justCoreTables)&&await e.db.exists(SmartDbCoreTableModel)){const t=await e.db.getAll(SmartDbCoreTableModel);if(!1===t)throw e.db.getLastError();t.forEach((e=>{a.push(e.name)}))}const n=[];for(const s of r){let r=!0;if(e.justCoreTables?r=a.includes(s):e.skipCoreTables&&(r=!a.includes(s)),r){const r=s[0].toUpperCase()+_.camelCase(s.substring(1))+"Model",a=[];console.log("working on",s),await e.db.getTableInfo(s).then((o=>{const i=o.fields;let l=!1,c="",m="",p="",d="",b="";const u=s.toLowerCase().replace(/[^[a-z0-9]/g,"-")+"-model";if(n.push({className:r,fileName:u}),c+="/* eslint-disable @typescript-eslint/member-ordering */\n",c+="// noinspection JSUnusedGlobalSymbols\n",i){e.abstractModelModule==e.smartDbInterfaces?e.separateApi?(p+=`import {GenericModelData} from "${e.abstractModelModule}";\n`,b+=`import {AbstractModel, ModelAttributeMap} from "${e.abstractModelModule}";\n`,b+=`import {${r}Data} from "./${u}-api";\n`):b+=`import {AbstractModel, GenericModelData, ModelAttributeMap} from "${e.abstractModelModule}";\n`:e.separateApi?(p+=`import {GenericModelData} from "${e.smartDbInterfaces}";\n`,b+=`import {ModelAttributeMap} from "${e.smartDbInterfaces}";\n`,b+=`import {AbstractModel} from "${e.abstractModelModule}";\n`,b+=`import {${r}Data} from "./${u}-api";\n`):(b+=`import {GenericModelData, ModelAttributeMap} from "${e.smartDbInterfaces}";\n`,b+=`import {AbstractModel} from "${e.abstractModelModule}";\n`),m+=`export interface ${r}Data extends GenericModelData {\n`;let n,o="",f="",h=!1;const g=[];i.forEach((e=>{const t=e.name.match(/([a-z0-9]{1,4})_/i);e.isPk&&(o=e.name,t&&(f=t[1])),t?g.includes(t[1])||g.push(t[1]):h=!0})),f||h||1!=g.length||(f=g[0]),f&&(n=new RegExp(`^${f}_(.*)$`));const y={};i.forEach((t=>{const r=getType(t.type);let o;l||"SqlValueType"!=r||(p+=`import {SqlValueType} from "${e.smartDbInterfaces}";\n`,b+=`import {SqlValueType} from "${e.smartDbInterfaces}";\n`,l=!0);const i=n&&t.name.match(n);o=i?_.camelCase(i[1]):_.camelCase(t.name);let c=!0;if(o!=t.name&&(a.push({name:o,attribute:o,type:r,typeScriptStyle:c,alias:t.name}),c=!1),o!=t.name.toLowerCase()&&(a.push({name:t.name.toLowerCase(),attribute:o,type:r,physical:void 0!==t.cid&&t.name==t.name.toLowerCase(),typeScriptStyle:c}),c=!1),o!=t.name.toUpperCase()&&a.push({name:t.name.toUpperCase(),attribute:o,type:r,physical:void 0!==t.cid&&t.name==t.name.toUpperCase(),typeScriptStyle:c}),t.cid){const e=a.find((e=>e.physical&&e.name.toLowerCase()==t.name.toLowerCase()));e||a.push({name:t.name,attribute:o,type:r,physical:!0,typeScriptStyle:c})}y[o]=r,"user"==s&&"name"==o&&(m+=" // @ts-ignore"),m+=` ${o}?: ${r};\n`})),m+="}\n",d+=`export class ${r} extends AbstractModel<${r}, ${r}Data> {\n`,_.forEach(y,((e,t)=>{d+=` private _${t}?: ${e};\n`})),"user"==s&&(d+=" private _hash?: string;\n",d+=" private _privileges?: string[];\n"),d+="\n",d+=" static readonly attributeMap: ModelAttributeMap = {\n",a.forEach(((e,t)=>{t>0&&(d+=",\n"),d+=` ${e.name}: {\n`,e.physical&&(d+=" physical: true,\n"),e.alias&&(d+=` alias: "${e.alias}",\n`),e.virtual&&(d+=" virtual: true,\n"),e.typeScriptStyle&&(d+=" typeScriptStyle: true,\n"),d+=` type: "${e.type}",\n`,d+=` attribute: "_${e.attribute}"\n`,d+=" }"})),d+="\n",d+=" };\n",d+="\n",d+=" static getClassName(): string {\n",d+=` return "${r}";\n`,d+=" }\n",d+="\n",d+=" static getTableName(): string {\n",d+=` return "${s}";\n`,d+=" }\n",d+="\n",d+=" static getPrimaryKey(): string {\n",d+=` return "${o}";\n`,d+=" }\n",d+="\n",d+=` static from(other: ${r} | ${r}Data): ${r} {\n`,d+=` let value: ${r} = null;\n`,d+=" if (other) {\n",d+=` value = new ${r}();\n`,d+=` if (other instanceof ${r}) {\n`,d+=" Object.assign(value, other);\n",d+=" } else {\n",d+=" value.assign(other);\n",d+=" }\n",d+=" }\n",d+=" return value;\n",d+=" }\n",d+="\n",d+=` constructor(data?: ${r} | ${r}Data) {\n`,d+=" super();\n",d+=" if (data) {\n",d+=" this.assign(data);\n",d+=" }\n",d+=" }\n",d+="\n",d+=` public clone(): ${r} {\n`,d+=` return ${r}.from(this);\n`,d+=" }\n",d+="\n",d+=" public getClassName(): string {\n",d+=` return "${r}";\n`,d+=" }\n",d+="\n",d+=" public getTableName(): string {\n",d+=` return "${s}";\n`,d+=" }\n",d+="\n",d+=" public getPrimaryKey(): string {\n",d+=` return "${o}";\n`,d+=" }\n",d+="\n",d+=" public getAttributeMap(): ModelAttributeMap {\n",d+=` return ${r}.attributeMap;\n`,d+=" }\n",a.forEach((e=>{let r;d+="\n",r=e.name.length<3||e.name.match(/_/)?"FunctionNamingConventionJS":"",""!==r&&(d+=` // noinspection ${r}\n`),d+=` get ${e.name}(): ${e.type} {\n`,d+=` return this._${e.attribute};\n`,d+=" }\n\n",""!==r&&(d+=` // noinspection ${r}\n`);let a=e.attribute;t.includes(a)&&(a="value"),d+=` set ${e.name}(${a}: ${e.type}) {\n`,d+=` this._${e.attribute} = ${a};\n`,d+=" }\n"})),"user"==s&&(d+="\n",d+=" get hash(): string {\n",d+=" return this._hash;\n",d+=" }\n\n",d+=" set hash(hash: string) {\n",d+=" this._hash = hash;\n",d+=" }\n",d+="\n",d+=" get privileges(): string[] {\n",d+=" return this._privileges;\n",d+=" }\n\n",d+=" set privileges(p: string[]) {\n",d+=" this._privileges = p;\n",d+=" }\n"),d+="}\n",e.separateApi?(m=c+"\n"+p+"\n"+m,fs.writeFileSync(`${e.modelDirectory}/${u+"-api.ts"}`,m),d=c+"\n"+b+"\n"+d):d=c+"\n"+b+"\n"+m+"\n"+d,fs.writeFileSync(`${e.modelDirectory}/${u+".ts"}`,d)}else console.log("error: table has no fields")})).catch((e=>{console.error(e),process.abort()}))}}let s=`import {AbstractModel} from "${e.abstractModelModule}";\n`;_.forEach(n,(e=>{s+=`import {${e.className}} from "./${e.fileName}";\n`})),s+="\n",s+="interface SmartDbDictionaryEntry {\n",s+=" cls: "+n.map((e=>"typeof "+e.className)).join(" |\n "),s+=";\n",s+="}\n\n",s+="export class SmartDbDictionary {\n",s+=" static models: { [relation: string]: SmartDbDictionaryEntry; } = {\n",_.forEach(n,(e=>{s+=` ${e.className}: {\n`,s+=` cls: ${e.className}\n`,s+=" },\n"})),s=s.substring(0,s.length-2)+"\n",s+=" };\n",s+="}\n",fs.writeFileSync(`${e.modelDirectory}/smart-db-dictionary.ts`,s)})).catch((e=>{console.error("extraction error",e)}))}(async()=>{let e=!1;const t=Array.from(process.argv);let r,a,n,s=!1;for(t.shift(),t.shift();t[0]&&"--"==t[0].substring(0,2);)"--separate-api"==t[0]?(e=!0,t.shift()):"--database"==t[0]?(r=t[1],t.shift(),t.shift()):"--username"==t[0]?(a=t[1],t.shift(),t.shift()):"--password"==t[0]?(n=t[1],t.shift(),t.shift()):"--create"==t[0]?(s=!0,t.shift()):(console.error(`unknown option '${t[2]}'`),process.exit(-1));if(r||(r=process.env.ORACLE_SID),fs.existsSync(r)||(a||(a=process.env.ORA_USER),n||(n=process.env.ORA_PASS)),r&&t.length<=1){let o;a&&n?o=new SmartDbOracle(r,{user:a,password:n,noDbLogging:!0}):s||fs.existsSync(r)?o=new SmartDbBetterSqlite3(r,{}):(console.error(`ERROR: missing sqlite3 database file ${r}`),process.exit(-1)),1==t.length?o.onReady().subscribe((async r=>{if(r){o.getLogger().setDbLogging(!1);const r={skipCoreTables:!0,modelDirectory:t[0],smartDbInterfaces:"@egi/smart-db",abstractModelModule:"@egi/smart-db",separateApi:e,db:o};await extractDbApi(r)}})):fs.existsSync("src/helpers/extract-db-api.ts")?o.onReady().subscribe((t=>{if(t){const t={justCoreTables:!0,modelDirectory:"src/models/generated",smartDbInterfaces:"../smart-db-interfaces",abstractModelModule:"./abstract-model",separateApi:e,db:o};t.db.initDb({module:"smart-db-core",sqlFilesDirectory:"assets/sqlite3"}).then((async()=>{await extractDbApi(t)}))}else console.error("unable to connect to database")})):console.log("command must be run at the root directory of the smart-db project")}else console.log("USAGE: extract-db-api --database {db-connector|path-to-db} [{options}] {target-models-directory}\n"),console.log("Options are: [--username {username}]"),console.log(" [--password {password}]"),console.log(" [--create"),console.log(" [--separate-api]")})();
1
+ import fs from"fs";import _ from"lodash";import process from"process";import{SmartDbBetterSqlite3}from"../drivers/smart-db-better-sqlite3";import{SmartDbOracle}from"../drivers/smart-db-oracle";import{OracleCatModel}from"../models/oracle-cat-model";import{SmartDbCoreTableModel}from"../models/smart-db-core-table-model";import{SqliteMasterModel}from"../models/sqlite-master-model";import{IN,NE,NOT_LIKE}from"../smart-db-globals";function getType(e){let t;return t=e?e.match(/varchar/i)||e.match(/text/i)?"string":e.match(/integer\(1\)/i)?"boolean":e.match(/date/i)?"Date":e.match(/integer/i)||e.match(/number/i)?"number":e.match(/long/i)||e.match(/raw/i)?"any":"SqlValueType":"SqlValueType",t}function getRelations(e){return new Promise((async(t,r)=>{e instanceof SmartDbOracle?e.getAll(OracleCatModel,{type:IN(["TABLE","VIEW"]),name:NOT_LIKE("BIN$%")}).then((a=>{a?t(a.map((e=>e.name.toLowerCase()))):r(e.getLastError())})).catch((e=>{r(e)})):e instanceof SmartDbBetterSqlite3?e.getAll(SqliteMasterModel,{type:IN(["table","view"]),name:NE("sqlite_sequence")}).then((a=>{a?t(a.map((e=>e.name))):r(e.getLastError())})).catch((e=>{r(e)})):r("unimplemented database type")}))}async function extractDbApi(e){console.log(`extract interface from '${e.db.getDbConnector()}' to '${e.modelDirectory}'`);const t=["break","case","catch","class","const","continue","debugger","default","delete","do","else","enum","export","extends","false","finally","for","function","If","import","in","instanceOf","interface","new","null","return","super","switch","this","throw","true","try","typeOf","var","void","while","with"];fs.existsSync(e.modelDirectory)||fs.mkdirSync(e.modelDirectory,{recursive:!0}),getRelations(e.db).then((async r=>{let a=[];if((e.skipCoreTables||e.justCoreTables)&&await e.db.exists(SmartDbCoreTableModel)){const t=await e.db.getAll(SmartDbCoreTableModel);if(!1===t)throw e.db.getLastError();t.forEach((e=>{a.push(e.name)}))}const n=[];for(const s of r){let r=!0;if(e.justCoreTables?r=a.includes(s):e.skipCoreTables&&(r=!a.includes(s)),r){const r=s[0].toUpperCase()+_.camelCase(s.substring(1))+"Model",a=[];console.log("working on",s),await e.db.getTableInfo(s).then((o=>{const i=o.fields;let l=!1,c="",m="",p="",d="",b="";const u=s.toLowerCase().replace(/[^[a-z0-9]/g,"-")+"-model";if(n.push({className:r,fileName:u}),c+="/* eslint-disable @typescript-eslint/member-ordering */\n",c+="// noinspection JSUnusedGlobalSymbols\n",i){e.abstractModelModule==e.smartDbInterfaces?e.separateApi?(p+=`import {GenericModelData} from "${e.abstractModelModule}";\n`,b+=`import {AbstractModel, ModelAttributeMap} from "${e.abstractModelModule}";\n`,b+=`import {${r}Data} from "./${u}-api";\n`):b+=`import {AbstractModel, GenericModelData, ModelAttributeMap} from "${e.abstractModelModule}";\n`:e.separateApi?(p+=`import {GenericModelData} from "${e.smartDbInterfaces}";\n`,b+=`import {ModelAttributeMap} from "${e.smartDbInterfaces}";\n`,b+=`import {AbstractModel} from "${e.abstractModelModule}";\n`,b+=`import {${r}Data} from "./${u}-api";\n`):(b+=`import {GenericModelData, ModelAttributeMap} from "${e.smartDbInterfaces}";\n`,b+=`import {AbstractModel} from "${e.abstractModelModule}";\n`),m+=`export interface ${r}Data extends GenericModelData {\n`;let n,o="",f="",h=!1;const g=[];i.forEach((e=>{const t=e.name.match(/([a-z0-9]{1,4})_/i);e.isPk&&(o=e.name,t&&(f=t[1])),t?g.includes(t[1])||g.push(t[1]):h=!0})),f||h||1!=g.length||(f=g[0]),f&&(n=new RegExp(`^${f}_(.*)$`));const y={};i.forEach((t=>{const r=getType(t.type);let o;l||"SqlValueType"!=r||(p+=`import {SqlValueType} from "${e.smartDbInterfaces}";\n`,b+=`import {SqlValueType} from "${e.smartDbInterfaces}";\n`,l=!0);const i=n&&t.name.match(n);o=i?_.camelCase(i[1]):_.camelCase(t.name);let c=!0;if(o!=t.name&&(a.push({name:o,attribute:o,type:r,typeScriptStyle:c,alias:t.name}),c=!1),o!=t.name.toLowerCase()&&(a.push({name:t.name.toLowerCase(),attribute:o,type:r,physical:void 0!==t.cid&&t.name==t.name.toLowerCase(),typeScriptStyle:c}),c=!1),o!=t.name.toUpperCase()&&a.push({name:t.name.toUpperCase(),attribute:o,type:r,physical:void 0!==t.cid&&t.name==t.name.toUpperCase(),typeScriptStyle:c}),t.cid){const e=a.find((e=>e.physical&&e.name.toLowerCase()==t.name.toLowerCase()));e||a.push({name:t.name,attribute:o,type:r,physical:!0,typeScriptStyle:c})}y[o]=r,"user"==s&&"name"==o&&(m+=" // @ts-ignore"),m+=` ${o}?: ${r};\n`})),m+="}\n",d+=`export class ${r} extends AbstractModel<${r}, ${r}Data> {\n`,_.forEach(y,((e,t)=>{d+=` private _${t}?: ${e};\n`})),"user"==s&&(d+=" private _hash?: string;\n",d+=" private _privileges?: string[];\n"),d+="\n",d+=" static readonly attributeMap: ModelAttributeMap = {\n",a.forEach(((e,t)=>{t>0&&(d+=",\n"),d+=` ${e.name}: {\n`,e.physical&&(d+=" physical: true,\n"),e.alias&&(d+=` alias: "${e.alias}",\n`),e.virtual&&(d+=" virtual: true,\n"),e.typeScriptStyle&&(d+=" typeScriptStyle: true,\n"),d+=` type: "${e.type}",\n`,d+=` attribute: "_${e.attribute}"\n`,d+=" }"})),d+="\n",d+=" };\n",d+="\n",d+=" static getClassName(): string {\n",d+=` return "${r}";\n`,d+=" }\n",d+="\n",d+=" static getTableName(): string {\n",d+=` return "${s}";\n`,d+=" }\n",d+="\n",d+=" static getPrimaryKey(): string {\n",d+=` return "${o}";\n`,d+=" }\n",d+="\n",d+=` static from(other: ${r} | ${r}Data): ${r} {\n`,d+=` let value: ${r} = null;\n`,d+=" if (other) {\n",d+=` value = new ${r}();\n`,d+=` if (other instanceof ${r}) {\n`,d+=" Object.assign(value, other);\n",d+=" } else {\n",d+=" value.assign(other);\n",d+=" }\n",d+=" }\n",d+=" return value;\n",d+=" }\n",d+="\n",d+=` constructor(data?: ${r} | ${r}Data) {\n`,d+=" super();\n",d+=" if (data) {\n",d+=" this.assign(data);\n",d+=" }\n",d+=" }\n",d+="\n",d+=` public clone(): ${r} {\n`,d+=` return ${r}.from(this);\n`,d+=" }\n",d+="\n",d+=" public getClassName(): string {\n",d+=` return "${r}";\n`,d+=" }\n",d+="\n",d+=" public getTableName(): string {\n",d+=` return "${s}";\n`,d+=" }\n",d+="\n",d+=" public getPrimaryKey(): string {\n",d+=` return "${o}";\n`,d+=" }\n",d+="\n",d+=" public getAttributeMap(): ModelAttributeMap {\n",d+=` return ${r}.attributeMap;\n`,d+=" }\n",a.forEach((e=>{let r;d+="\n",r=e.name.length<3||e.name.match(/_/)?"FunctionNamingConventionJS":"",""!==r&&(d+=` // noinspection ${r}\n`),d+=` get ${e.name}(): ${e.type} {\n`,d+=` return this._${e.attribute};\n`,d+=" }\n\n",""!==r&&(d+=` // noinspection ${r}\n`);let a=e.attribute;t.includes(a)&&(a="value"),d+=` set ${e.name}(${a}: ${e.type}) {\n`,d+=` this._${e.attribute} = ${a};\n`,d+=" }\n"})),"user"==s&&(d+="\n",d+=" get hash(): string {\n",d+=" return this._hash;\n",d+=" }\n\n",d+=" set hash(hash: string) {\n",d+=" this._hash = hash;\n",d+=" }\n",d+="\n",d+=" get privileges(): string[] {\n",d+=" return this._privileges;\n",d+=" }\n\n",d+=" set privileges(p: string[]) {\n",d+=" this._privileges = p;\n",d+=" }\n"),d+="}\n",e.separateApi?(m=c+"\n"+p+"\n"+m,fs.writeFileSync(`${e.modelDirectory}/${u+"-api.ts"}`,m),d=c+"\n"+b+"\n"+d):d=c+"\n"+b+"\n"+m+"\n"+d,fs.writeFileSync(`${e.modelDirectory}/${u+".ts"}`,d)}else console.log("error: table has no fields")})).catch((e=>{console.error(e),process.abort()}))}}let s=`import {AbstractModel} from "${e.abstractModelModule}";\n`;_.forEach(n,(e=>{s+=`import {${e.className}} from "./${e.fileName}";\n`})),s+="\n",s+="interface SmartDbDictionaryEntry {\n",s+=" cls: "+n.map((e=>"typeof "+e.className)).join(" |\n "),s+=";\n",s+="}\n\n",s+="export class SmartDbDictionary {\n",s+=" static models: { [relation: string]: SmartDbDictionaryEntry; } = {\n",_.forEach(n,(e=>{s+=` ${e.className}: {\n`,s+=` cls: ${e.className}\n`,s+=" },\n"})),s=s.substring(0,s.length-2)+"\n",s+=" };\n",s+="}\n",fs.writeFileSync(`${e.modelDirectory}/smart-db-dictionary.ts`,s)})).catch((e=>{console.error("extraction error",e)}))}(async()=>{let e=!1;const t=Array.from(process.argv);let r,a,n,s=!1;for(t.shift(),t.shift();t[0]&&"--"==t[0].substring(0,2);)"--separate-api"==t[0]?(e=!0,t.shift()):"--database"==t[0]?(r=t[1],t.shift(),t.shift()):"--username"==t[0]?(a=t[1],t.shift(),t.shift()):"--password"==t[0]?(n=t[1],t.shift(),t.shift()):"--create"==t[0]?(s=!0,t.shift()):(console.error(`unknown option '${t[0]}'`),process.exit(-1));if(r||(r=process.env.ORACLE_SID),fs.existsSync(r)||(a||(a=process.env.ORA_USER),n||(n=process.env.ORA_PASS)),r&&t.length<=1){let o;a&&n?o=new SmartDbOracle(r,{user:a,password:n,noDbLogging:!0}):s||fs.existsSync(r)?o=new SmartDbBetterSqlite3(r,{}):(console.error(`ERROR: missing sqlite3 database file ${r}`),process.exit(-1)),1==t.length?o.onReady().subscribe((async r=>{if(r){o.getLogger().setDbLogging(!1);const r={skipCoreTables:!0,modelDirectory:t[0],smartDbInterfaces:"@egi/smart-db",abstractModelModule:"@egi/smart-db",separateApi:e,db:o};await extractDbApi(r)}})):fs.existsSync("src/helpers/extract-db-api.ts")?o.onReady().subscribe((t=>{if(t){const t={justCoreTables:!0,modelDirectory:"src/models/generated",smartDbInterfaces:"../smart-db-interfaces",abstractModelModule:"./abstract-model",separateApi:e,db:o};t.db.initDb({module:"smart-db-core",sqlFilesDirectory:"assets/sqlite3"}).then((async()=>{await extractDbApi(t)}))}else console.error("unable to connect to database")})):console.log("command must be run at the root directory of the smart-db project")}else console.log("USAGE: extract-db-api --database {db-connector|path-to-db} [{options}] {target-models-directory}\n"),console.log("Options are: [--username {username}]"),console.log(" [--password {password}]"),console.log(" [--create"),console.log(" [--separate-api]")})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@egi/smart-db",
3
- "version": "2.6.2",
3
+ "version": "2.6.3",
4
4
  "description": "Unified Smart DB Access",
5
5
  "author": "Marcel Egloff",
6
6
  "type": "module",
package/smart-db.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { BehaviorSubject, Subject } from "rxjs";
1
+ import { BehaviorSubject, Observable } from "rxjs";
2
2
  import { AbstractModel } from "./models/abstract-model";
3
3
  import { SmartDbVersionViewModel } from "./models/smart-db-version-view-model";
4
4
  import { GenericModelData, IndexedGenericModelData, SmartDbConnector, SmartDbDatabase, SmartDbOptions, SmartDbRunResult, SmartDbSqlOptions, SmartDbTableInfo, SqlFieldDescriptor, SqlLimit, SqlOrderBy, SqlUpdateValues, SqlValueType, SqlWhere } from "./smart-db-interfaces";
@@ -49,7 +49,7 @@ export declare abstract class SmartDb {
49
49
  initDb(appOptions: SmartDbOptions): Promise<SmartDbVersionViewModel[]>;
50
50
  insert<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T): Promise<number>;
51
51
  insertSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T): number | false;
52
- onReady(): Subject<boolean>;
52
+ onReady(): Observable<boolean>;
53
53
  rollback(): Promise<void>;
54
54
  rollbackSync(): void;
55
55
  toDate(d: Date | number | string): Date | null;
package/smart-db.js CHANGED
@@ -1 +1 @@
1
- import fs from"fs";import _ from"lodash";import{BehaviorSubject}from"rxjs";import{AbstractModel}from"./models/abstract-model";import{SmartDbDictionary}from"./models/smart-db-dictionary";import{SmartDbLogModel}from"./models/smart-db-log-model";import{IN,smartDbToDate,toSmartDbDate,toSmartDbTimestamp}from"./smart-db-globals";import{FieldNamingStyle,SqlFieldOperationType,SqlOperationType}from"./smart-db-interfaces";import{SmartDbLog}from"./smart-db-log";import{SmartDbSqlBuildData}from"./smart-db-sql-build-data";import{SmartDbUpgradeManager}from"./smart-db-upgrade-manager";import{SmartError,SmartErrorLocation}from"./smart-error";export class SmartDb{constructor(t,e){this.dictionaries=[],this.dbConnector=t,this.smartDbLog=new SmartDbLog(e?null:this),this.dbLogging=!e,this.db=null,this._isReady=null,this._onReady=new BehaviorSubject(!1)}buildSelectStatement(t,e){e||(e={});const r=this.buildSelectSectionStatement(t,e);if(_.forEach(["union","minus","intersect"],(t=>{let s=_.get(e,t);s&&(_.isArray(s)||(s=[s]),_.forEach(s,(e=>{const s=this.buildSelectSectionStatement(e.model,e);r.sql+=" "+t.toUpperCase()+" ",r.append(s)})))})),e.orderBy){r.sql+=" ORDER BY ";const s=_.isString(e.orderBy)?e.orderBy.split(/ *, */):e.orderBy;r.sql+=s.map((e=>{let r="";const s=e.match(/^(\w*) (asc|desc)$/i);return s&&(e=s[1],r=s[2].toUpperCase()),e=this.translateFieldName(t,e),r&&(e+=" "+r),e})).join(", ")}return e.limit&&(e.limit.limit&&(r.sql+=" LIMIT "+e.limit.limit.toString()),e.limit.offset&&(r.sql+=" OFFSET "+e.limit.offset.toString())),this.lastBuildData=r,r}close(){return new Promise(((t,e)=>{try{t(this.closeSync())}catch(t){e(t)}}))}closeSync(){throw new Error("Method not implemented (close)")}commit(){return new Promise(((t,e)=>{try{this.commitSync(),t()}catch(t){e(t)}}))}commitSync(){throw new Error("Method not implemented (commit)")}delete(t,e){return new Promise(((r,s)=>{const a=this.buildDeleteStatement(t,e);this.statementRun(a).then((t=>{t?r(t.changes):s(this.getLastError())})).catch((t=>{this.lastError=t,s(t)}))}))}deleteSync(t,e){if(this.supportSyncCalls)return this.saveExecute((()=>{const r=this.buildDeleteStatement(t,e);return this.statementRunSync(r).changes}));throw"This database driver doesn't support sync calls (deleteSync)"}exec(t){return new Promise(((e,r)=>{try{this.execSync(t)?e():r(this.getLastError())}catch(t){r(t)}}))}execScript(t,e){return new Promise((async(r,s)=>{const a=this.scriptParser(t);let i=!1;for(const t of a)try{await this.exec(t)}catch(r){if(!e||"drop "!=t.trim().substring(0,5).toLowerCase()){i=!0,this.lastBuildData=new SmartDbSqlBuildData(t),this.lastError=r;break}}i?(await this.rollback(),s(this.lastError)):(await this.commit(),r())}))}execScriptSync(t){if(!this.supportSyncCalls)throw"This database driver doesn't support sync calls (execScriptSync)";{const e=this.scriptParser(t);for(const t of e)try{this.execSync(t)}catch(e){if("drop "!=t.substring(0,5).toLowerCase())throw this.lastBuildData=new SmartDbSqlBuildData(t),this.lastError=e,e}this.commitSync()}}execSync(t){throw new Error("Method not implemented (exec)")}exists(t,e,r){return new Promise(((s,a)=>{try{s(this.existsSync(t,e,r))}catch(t){a(t)}}))}existsSync(t,e,r){throw new Error("Method not implemented (exists)")}get(t,e){return new Promise(((r,s)=>{e||(e={});const a=this.buildSelectStatement(t,e);e.firstOnly||e.count?this.statementGet(a).then((s=>{r(this.prepareResultRow(t,s,e))})).catch((t=>{s(t)})):this.statementGetAll(a).then((s=>{r(this.prepareResultRows(t,s,e))})).catch((t=>{s(t)}))}))}getAll(t,e,r,s,a){return this.get(t,{where:e,fields:r,orderBy:s,limit:a})}getAllSync(t,e,r,s,a){return this.getSync(t,{where:e,fields:r,orderBy:s,limit:a})}getDb(){return this.db}getDbConnector(){return this.dbConnector}getDbQuote(){return'"'}getFirst(t,e,r,s){return this.get(t,{firstOnly:!0,where:e,fields:r,orderBy:s})}getFirstSync(t,e,r,s){return this.getSync(t,{firstOnly:!0,where:e,fields:r,orderBy:s})}getLastBuildData(){return this.lastBuildData}getLastError(){return this.lastError}getLogger(){return this.smartDbLog}getSync(t,e){if(this.supportSyncCalls)return this.saveExecute((()=>{e||(e={});const r=this.buildSelectStatement(t,e);let s;if(e.firstOnly||e.count){const a=this.statementGetSync(r);s=this.prepareResultRow(t,a,e)}else{const a=this.statementGetAllSync(r);s=this.prepareResultRows(t,a,e)}return s}));throw"This database driver doesn't support sync calls (getSync)"}hasConcurrentTransactions(){return!1}hasTransaction(){throw new Error("Method not implemented (hasTransaction)")}initDb(t){return new Promise(((e,r)=>{this.dictionaries.push(SmartDbDictionary);const s=new SmartDbUpgradeManager(this);let a;a=import.meta&&import.meta.url?import.meta.url.replace(/file:\/\//,"").replace(/\/[^/]*$/,""):__dirname;const i={module:"smart-db-core",sqlFilesDirectory:a+"/assets/"+this.getDatabaseType()};s.prepareDatabase(i).then((a=>{this.exists(SmartDbLogModel).then((i=>{this.smartDbLog.setDbLogging(this.dbLogging&&i),s.prepareDatabase(t).then((t=>{e([a,t])}),(t=>{r(t)}))}))})).catch((t=>{r(t)}))}))}insert(t,e){return new Promise(((r,s)=>{const a=this.buildInsertStatement(t,e);this.statementRun(a).then((t=>{t?r(t.lastId):s(this.getLastError())})).catch((t=>{s(t)}))}))}insertSync(t,e){if(this.supportSyncCalls)return this.saveExecute((()=>{const r=this.buildInsertStatement(t,e);return this.statementRunSync(r).lastId}));throw"This database driver doesn't support sync calls (insertSync)"}onReady(){return this._onReady}rollback(){return new Promise(((t,e)=>{try{this.rollbackSync(),t()}catch(t){e(t)}}))}rollbackSync(){throw new Error("Method not implemented (rollback)")}toDate(t){return smartDbToDate(t)}toDbDate(t){return toSmartDbDate(t)}toDbTimestamp(t){return toSmartDbTimestamp(t)}update(t,e,r){return new Promise(((s,a)=>{const i=this.buildUpdateStatement(t,e,r);this.statementRun(i).then((t=>{t?s(t.changes):a(this.getLastError())})).catch((t=>{a(t)}))}))}updateSync(t,e,r){if(this.supportSyncCalls)return this.saveExecute((()=>{const s=this.buildUpdateStatement(t,e,r);return this.statementRunSync(s).changes}));throw"This database driver doesn't support sync calls (updateSync)"}statementRun(t){return new Promise(((e,r)=>{try{e(this.statementRun(t))}catch(t){r(t)}}))}statementRunSync(t){throw new Error("Method not implemented (statementRun)")}statementGet(t){return new Promise(((e,r)=>{try{e(this.statementGetSync(t))}catch(t){r(t)}}))}statementGetSync(t){throw new Error("Method not implemented (statementGet)")}statementGetAll(t){return new Promise(((e,r)=>{try{e(this.statementGetAllSync(t))}catch(t){r(t)}}))}statementGetAllSync(t){throw new Error("Method not implemented (statementGetAll)")}buildWhere(t,e,r){const s=new SmartDbSqlBuildData;return e&&_.keys(e).length>0&&(r||(r="AND",s.sql+=" WHERE "),s.sql+=_.map(e,((e,a)=>{const i=a.toUpperCase();if("AND"==i||"OR"==i){let r="";return(_.isArray(e)?e:[e]).forEach(((e,a)=>{const n=this.buildWhere(t,e,i);a>0&&(r+=" "+i+" "),r+=n.sql,s.values=_.concat(s.values,n.values)})),r="("+r+")",r}if("EXPRESSION"==i){let a=[];return _.forEach(e,(e=>{const r=this.prepareField(t,e.compare,s.values),i=this.prepareField(t,e.with,s.values);let n;n=_.isString(e.operation)&&SqlOperationType[e.operation]?SqlOperationType[e.operation]:e.operation||SqlOperationType.EQ,a.push(`${r} ${n} ${i}`)})),a.join(" "+r+" ")}{let r,i,n=!0;if(_.isArray(e)&&(e=IN(e)),_.isObject(e)){const t=e;switch(_.isString(t.operation)&&SqlOperationType[t.operation]&&(t.operation=SqlOperationType[t.operation]),t.operation){case SqlOperationType.IN:case SqlOperationType.NOT_IN:const e=new Array(t.value.length);e.fill("?"),r=t.operation+" ("+e.join(", ")+")",s.values=_.concat(s.values,t.value);break;case SqlOperationType.IS_NULL:case SqlOperationType.IS_NOT_NULL:r=t.operation;break;case SqlOperationType.LITERAL:a=t.key;const i=t.literalOperation||SqlOperationType.EQ;if(i==SqlOperationType.IN||i==SqlOperationType.NOT_IN){const e=new Array(t.value.length);e.fill("?"),r=i+" ("+e.join(", ")+")",s.values=_.concat(s.values,t.value)}else _.isUndefined(t.value)?r=i:(r=i+" ?",s.values.push(this.makeDbValue(t.value)));n=!1;break;default:r=t.operation+" ?",s.values.push(this.makeDbValue(t.value))}}else null===e?r=SqlOperationType.IS_NULL:void 0===e?(a="1",r="= 1",n=!1):(r=_.isString(e)&&e.match(/[%_]/)?SqlOperationType.LIKE+" ?":SqlOperationType.EQ+" ?",s.values.push(this.makeDbValue(e)));return i=n?this.translateFieldName(t,a)+" "+r:a+" "+r,i}})).join(" "+r+" ")),s}buildDeleteStatement(t,e){const r=this.getTableName(t),s=new SmartDbSqlBuildData("DELETE FROM");return s.sql+=" "+r,e&&s.append(this.buildWhere(t,e)),this.lastBuildData=s,s}buildUpdateStatement(t,e,r){const s=this.getTableName(t),a=new SmartDbSqlBuildData("UPDATE");a.sql+=" "+s+" SET ";const i=[],n=e instanceof AbstractModel?e.getPlainObject(FieldNamingStyle.Database):e;return _.forOwn(n,((e,r)=>{i.push(this.translateFieldName(t,r)+" = ?"),a.values.push(this.makeDbValue(e))})),a.sql+=i.join(", "),r&&a.append(this.buildWhere(t,r)),this.lastBuildData=a,a}buildInsertStatement(t,e){const r=this.getTableName(t),s=new SmartDbSqlBuildData("INSERT");s.sql+=" INTO "+r;const a=[];e instanceof AbstractModel&&(e=e.getPlainObject(FieldNamingStyle.Database)),_.forOwn(e,((e,r)=>{r=this.translateFieldName(t,r),a.push(r),s.values.push(this.makeDbValue(e))}));const i=new Array(a.length);return i.fill("?"),s.sql+=" ("+a.join(", ")+") VALUES ("+i.join(", ")+")",this.lastBuildData=s,s}prepareFieldValue(t,e){let r="<undefined>";switch(e.operation){case SqlFieldOperationType.FIELD:r=this.translateFieldName(t,e.value);break;case SqlFieldOperationType.VALUE:null===e.value?r="NULL":e.literal?r=e.value:_.isString(e.value)?!isNaN(parseFloat(e.value))&&isFinite(e.value)||(r="'"+e.value+"'"):_.isNumber(e.value)?r=e.value.toString():_.isBoolean(e.value)?r=e.value?"1":"0":_.isDate(e.value)?r="'"+e.value.toISOString().substring(0,23).replace("T"," ")+"'":console.error("unhandled field data type",typeof e.value,e.value);break;case SqlFieldOperationType.COUNT:r=_.isArray(e.value)?"COUNT("+e.value.join(",")+")":"COUNT("+(e.value||"")+")";break;case SqlFieldOperationType.COALESCE:const s=_.isArray(e.value)?e.value:[e.value];r="COALESCE("+this.buildFieldList(t,s).join(",")+")"}if(e.alias){const t=this.getDbQuote();r+=` as ${t}${e.alias}${t}`}return r}prepareField(t,e,r){let s;if(null===e)s="NULL";else if(_.isString(e)){const a=e.match(/^'(.*)'$/);a?r?(s="?",r.push(a[1])):s=e:s=this.translateFieldName(t,e)}else e.operation?s=this.prepareFieldValue(t,e):r?(s="?",r.push(e)):s=this.makeArgumentDbValue(e).toString();return s}buildFieldList(t,e){const r=[];return _.forEach(e,(e=>{r.push(this.prepareField(t,e))})),r}buildSelectSectionStatement(t,e){const r=this.getTableName(t);let s,a;if(_.isArray(e.fields))s=e.fields;else if(_.isString(e.fields)){const t=e.fields.trim();s=""===t||"*"==t?[]:t.split(/,/)}else s=e.fields&&e.fields.operation?[e.fields]:[];if(s.length>0){a=this.buildFieldList(t,s).join(", ")}else a="*";e.distinct&&(a="DISTINCT "+a),e.count&&(a=`COUNT(${a})`);const i=new SmartDbSqlBuildData(`SELECT ${a} FROM ${r}`);if(e.where&&i.append(this.buildWhere(t,e.where)),e.groupBy){i.sql+=" GROUP BY ";const r=_.isArray(e.groupBy)?e.groupBy:[e.groupBy];i.sql+=r.map((e=>this.translateFieldName(t,e))).join(", ")}return i}translateFieldName(t,e){if(_.isString(t)){const e=t;let r=!1;_.forEach(this.dictionaries,(s=>(s.models&&s.models[e]&&(t=s.models[e].cls,r=!0),!r)))}if(!_.isString(t)){const r=t.attributeMap[e];if(r)r.alias&&(e=r.alias);else{const r=t.getTableName();this.lastError=new Error(`unknown field '${e}' in table '${r}'`),this.smartDbLog.logError(SmartErrorLocation.Database,"translateFieldName",this.lastError)}}return e}makeDbValue(t){return _.isBoolean(t)?t=t?1:0:_.isDate(t)&&(t=toSmartDbDate(t)),t}makeArgumentDbValue(t){return _.isBoolean(t)?t=t?1:0:_.isDate(t)?t=`'${toSmartDbDate(t)}'`:_.isString(t)&&(t=`'${t.replace(/'/,"''").replace(/\\/,"\\\\")}'`),t}saveExecute(t){let e;try{e=t()}catch(t){this.lastError=t instanceof Error?t:new Error(t||"Unknown error"),this.smartDbLog.logFatal(SmartErrorLocation.Database,"saveExecute-catch",this.lastError),e=!1}return e}scriptParser(t){const e=fs.readFileSync(t,"utf8"),r=[];let s=0,a=0,i=!1,n=0,l=!1,o="";for(;a<e.length;){if(l){if("\n"==e[a])for(l=!1,s=a+1;" "==e[s]||"\n"==e[s]||"\n"==e[s];)s+=1}else"'"==e[a]?i=!i:!i&&e.substring(a,a+6).match(/^begin(\s|\n)/)?(n+=1,a+=6):n>0&&!i&&e.substring(a,a+4).match(/^end;/)?(n-=1,a+=4):0!==n||i||"/"!=e[a]?i||"-"!=e[a]||"-"!=e[a+1]?0!==n||i||";"!=e[a]||(r.push((o+e.substring(s,a)).trim()),o="",s=a+2):(o+=e.substring(s,a),l=!0):(r.push((o+e.substring(s,a)).trim()),o="",s=a+2);a+=1}if(s<e.length){const t=e.substring(s,e.length).trim().replace(/;$/,"");console.log(t),""!==t&&r.push(t)}return r}prepareResultRow(t,e,r){let s;if(r.indexedBy&&this.smartDbLog.logWarning(SmartErrorLocation.Database,"AbstractModel.get","option 'indexedBy' not supported without 'all'"),e)if(r.count)s=parseInt(_.values(e)[0],10);else if(r.collapseRow)s=_.values(e).join(",");else{const a=t.from(e);s=r.style==FieldNamingStyle.TypeScript?a.getPlainObject():a}return s}prepareResultRows(t,e,r){let s;if(!e||!r.indexedBy&&!r.collapseRow&&_.isString(t))s=e;else{const a=t;s=r.indexedBy?{}:new Array(e.length),_.forEach(e,((t,e)=>{let i=a.from?a.from(t):null,n=null;if(r.indexedBy&&(n=i?i.getValue(r.indexedBy):t[r.indexedBy]),r.collapseRow){const r=_.values(t).join(",");n?s[n]=r:s[e]=r}else i&&r.style==FieldNamingStyle.TypeScript&&(i=i.getPlainObject()),n?s[n]=i||t:s[e]=i||t}))}return s}getTableName(t){let e;if(_.isString(t)){let r=t;_.forEach(this.dictionaries,(t=>(t.models&&t.models[r]&&(e=t.models[r].cls.getTableName()),!e))),e||(e=r)}else{if(!t||!t.getTableName)throw new Error(`unknown model: ${t}`);e=t.getTableName()}return e}get isReady(){return this._isReady}set isReady(t){this._isReady=t,this._onReady.next(t)}get lastError(){return this._lastError}set lastError(t){this._lastError=new SmartError(t),this._lastError.location=SmartErrorLocation.Database}get supportSyncCalls(){return!1}}
1
+ import fs from"fs";import _ from"lodash";import{BehaviorSubject,skip}from"rxjs";import{AbstractModel}from"./models/abstract-model";import{SmartDbDictionary}from"./models/smart-db-dictionary";import{SmartDbLogModel}from"./models/smart-db-log-model";import{IN,smartDbToDate,toSmartDbDate,toSmartDbTimestamp}from"./smart-db-globals";import{FieldNamingStyle,SqlFieldOperationType,SqlOperationType}from"./smart-db-interfaces";import{SmartDbLog}from"./smart-db-log";import{SmartDbSqlBuildData}from"./smart-db-sql-build-data";import{SmartDbUpgradeManager}from"./smart-db-upgrade-manager";import{SmartError,SmartErrorLocation}from"./smart-error";export class SmartDb{constructor(t,e){this.dictionaries=[],this.dbConnector=t,this.smartDbLog=new SmartDbLog(e?null:this),this.dbLogging=!e,this.db=null,this._isReady=null,this._onReady=new BehaviorSubject(!1)}buildSelectStatement(t,e){e||(e={});const r=this.buildSelectSectionStatement(t,e);if(_.forEach(["union","minus","intersect"],(t=>{let s=_.get(e,t);s&&(_.isArray(s)||(s=[s]),_.forEach(s,(e=>{const s=this.buildSelectSectionStatement(e.model,e);r.sql+=" "+t.toUpperCase()+" ",r.append(s)})))})),e.orderBy){r.sql+=" ORDER BY ";const s=_.isString(e.orderBy)?e.orderBy.split(/ *, */):e.orderBy;r.sql+=s.map((e=>{let r="";const s=e.match(/^(\w*) (asc|desc)$/i);return s&&(e=s[1],r=s[2].toUpperCase()),e=this.translateFieldName(t,e),r&&(e+=" "+r),e})).join(", ")}return e.limit&&(e.limit.limit&&(r.sql+=" LIMIT "+e.limit.limit.toString()),e.limit.offset&&(r.sql+=" OFFSET "+e.limit.offset.toString())),this.lastBuildData=r,r}close(){return new Promise(((t,e)=>{try{this.isReady=!1,t(this.closeSync())}catch(t){e(t)}}))}closeSync(){throw new Error("Method not implemented (close)")}commit(){return new Promise(((t,e)=>{try{this.commitSync(),t()}catch(t){e(t)}}))}commitSync(){throw new Error("Method not implemented (commit)")}delete(t,e){return new Promise(((r,s)=>{const a=this.buildDeleteStatement(t,e);this.statementRun(a).then((t=>{t?r(t.changes):s(this.getLastError())})).catch((t=>{this.lastError=t,s(t)}))}))}deleteSync(t,e){if(this.supportSyncCalls)return this.saveExecute((()=>{const r=this.buildDeleteStatement(t,e);return this.statementRunSync(r).changes}));throw"This database driver doesn't support sync calls (deleteSync)"}exec(t){return new Promise(((e,r)=>{try{this.execSync(t)?e():r(this.getLastError())}catch(t){r(t)}}))}execScript(t,e){return new Promise((async(r,s)=>{const a=this.scriptParser(t);let i=!1;for(const t of a)try{await this.exec(t)}catch(r){if(!e||"drop "!=t.trim().substring(0,5).toLowerCase()){i=!0,this.lastBuildData=new SmartDbSqlBuildData(t),this.lastError=r;break}}i?(await this.rollback(),s(this.lastError)):(await this.commit(),r())}))}execScriptSync(t){if(!this.supportSyncCalls)throw"This database driver doesn't support sync calls (execScriptSync)";{const e=this.scriptParser(t);for(const t of e)try{this.execSync(t)}catch(e){if("drop "!=t.substring(0,5).toLowerCase())throw this.lastBuildData=new SmartDbSqlBuildData(t),this.lastError=e,e}this.commitSync()}}execSync(t){throw new Error("Method not implemented (exec)")}exists(t,e,r){return new Promise(((s,a)=>{try{s(this.existsSync(t,e,r))}catch(t){a(t)}}))}existsSync(t,e,r){throw new Error("Method not implemented (exists)")}get(t,e){return new Promise(((r,s)=>{e||(e={});const a=this.buildSelectStatement(t,e);e.firstOnly||e.count?this.statementGet(a).then((s=>{r(this.prepareResultRow(t,s,e))})).catch((t=>{s(t)})):this.statementGetAll(a).then((s=>{r(this.prepareResultRows(t,s,e))})).catch((t=>{s(t)}))}))}getAll(t,e,r,s,a){return this.get(t,{where:e,fields:r,orderBy:s,limit:a})}getAllSync(t,e,r,s,a){return this.getSync(t,{where:e,fields:r,orderBy:s,limit:a})}getDb(){return this.db}getDbConnector(){return this.dbConnector}getDbQuote(){return'"'}getFirst(t,e,r,s){return this.get(t,{firstOnly:!0,where:e,fields:r,orderBy:s})}getFirstSync(t,e,r,s){return this.getSync(t,{firstOnly:!0,where:e,fields:r,orderBy:s})}getLastBuildData(){return this.lastBuildData}getLastError(){return this.lastError}getLogger(){return this.smartDbLog}getSync(t,e){if(this.supportSyncCalls)return this.saveExecute((()=>{e||(e={});const r=this.buildSelectStatement(t,e);let s;if(e.firstOnly||e.count){const a=this.statementGetSync(r);s=this.prepareResultRow(t,a,e)}else{const a=this.statementGetAllSync(r);s=this.prepareResultRows(t,a,e)}return s}));throw"This database driver doesn't support sync calls (getSync)"}hasConcurrentTransactions(){return!1}hasTransaction(){throw new Error("Method not implemented (hasTransaction)")}initDb(t){return new Promise(((e,r)=>{this.dictionaries.push(SmartDbDictionary);const s=new SmartDbUpgradeManager(this);let a;a=import.meta&&import.meta.url?import.meta.url.replace(/file:\/\//,"").replace(/\/[^/]*$/,""):__dirname;const i={module:"smart-db-core",sqlFilesDirectory:a+"/assets/"+this.getDatabaseType()};s.prepareDatabase(i).then((a=>{this.exists(SmartDbLogModel).then((i=>{this.smartDbLog.setDbLogging(this.dbLogging&&i),s.prepareDatabase(t).then((t=>{e([a,t])}),(t=>{r(t)}))}))})).catch((t=>{r(t)}))}))}insert(t,e){return new Promise(((r,s)=>{const a=this.buildInsertStatement(t,e);this.statementRun(a).then((t=>{t?r(t.lastId):s(this.getLastError())})).catch((t=>{s(t)}))}))}insertSync(t,e){if(this.supportSyncCalls)return this.saveExecute((()=>{const r=this.buildInsertStatement(t,e);return this.statementRunSync(r).lastId}));throw"This database driver doesn't support sync calls (insertSync)"}onReady(){return this._onReady.pipe(skip(1))}rollback(){return new Promise(((t,e)=>{try{this.rollbackSync(),t()}catch(t){e(t)}}))}rollbackSync(){throw new Error("Method not implemented (rollback)")}toDate(t){return smartDbToDate(t)}toDbDate(t){return toSmartDbDate(t)}toDbTimestamp(t){return toSmartDbTimestamp(t)}update(t,e,r){return new Promise(((s,a)=>{const i=this.buildUpdateStatement(t,e,r);this.statementRun(i).then((t=>{t?s(t.changes):a(this.getLastError())})).catch((t=>{a(t)}))}))}updateSync(t,e,r){if(this.supportSyncCalls)return this.saveExecute((()=>{const s=this.buildUpdateStatement(t,e,r);return this.statementRunSync(s).changes}));throw"This database driver doesn't support sync calls (updateSync)"}statementRun(t){return new Promise(((e,r)=>{try{e(this.statementRun(t))}catch(t){r(t)}}))}statementRunSync(t){throw new Error("Method not implemented (statementRun)")}statementGet(t){return new Promise(((e,r)=>{try{e(this.statementGetSync(t))}catch(t){r(t)}}))}statementGetSync(t){throw new Error("Method not implemented (statementGet)")}statementGetAll(t){return new Promise(((e,r)=>{try{e(this.statementGetAllSync(t))}catch(t){r(t)}}))}statementGetAllSync(t){throw new Error("Method not implemented (statementGetAll)")}buildWhere(t,e,r){const s=new SmartDbSqlBuildData;return e&&_.keys(e).length>0&&(r||(r="AND",s.sql+=" WHERE "),s.sql+=_.map(e,((e,a)=>{const i=a.toUpperCase();if("AND"==i||"OR"==i){let r="";return(_.isArray(e)?e:[e]).forEach(((e,a)=>{const n=this.buildWhere(t,e,i);a>0&&(r+=" "+i+" "),r+=n.sql,s.values=_.concat(s.values,n.values)})),r="("+r+")",r}if("EXPRESSION"==i){let a=[];return _.forEach(e,(e=>{const r=this.prepareField(t,e.compare,s.values),i=this.prepareField(t,e.with,s.values);let n;n=_.isString(e.operation)&&SqlOperationType[e.operation]?SqlOperationType[e.operation]:e.operation||SqlOperationType.EQ,a.push(`${r} ${n} ${i}`)})),a.join(" "+r+" ")}{let r,i,n=!0;if(_.isArray(e)&&(e=IN(e)),_.isObject(e)){const t=e;switch(_.isString(t.operation)&&SqlOperationType[t.operation]&&(t.operation=SqlOperationType[t.operation]),t.operation){case SqlOperationType.IN:case SqlOperationType.NOT_IN:const e=new Array(t.value.length);e.fill("?"),r=t.operation+" ("+e.join(", ")+")",s.values=_.concat(s.values,t.value);break;case SqlOperationType.IS_NULL:case SqlOperationType.IS_NOT_NULL:r=t.operation;break;case SqlOperationType.LITERAL:a=t.key;const i=t.literalOperation||SqlOperationType.EQ;if(i==SqlOperationType.IN||i==SqlOperationType.NOT_IN){const e=new Array(t.value.length);e.fill("?"),r=i+" ("+e.join(", ")+")",s.values=_.concat(s.values,t.value)}else _.isUndefined(t.value)?r=i:(r=i+" ?",s.values.push(this.makeDbValue(t.value)));n=!1;break;default:r=t.operation+" ?",s.values.push(this.makeDbValue(t.value))}}else null===e?r=SqlOperationType.IS_NULL:void 0===e?(a="1",r="= 1",n=!1):(r=_.isString(e)&&e.match(/[%_]/)?SqlOperationType.LIKE+" ?":SqlOperationType.EQ+" ?",s.values.push(this.makeDbValue(e)));return i=n?this.translateFieldName(t,a)+" "+r:a+" "+r,i}})).join(" "+r+" ")),s}buildDeleteStatement(t,e){const r=this.getTableName(t),s=new SmartDbSqlBuildData("DELETE FROM");return s.sql+=" "+r,e&&s.append(this.buildWhere(t,e)),this.lastBuildData=s,s}buildUpdateStatement(t,e,r){const s=this.getTableName(t),a=new SmartDbSqlBuildData("UPDATE");a.sql+=" "+s+" SET ";const i=[],n=e instanceof AbstractModel?e.getPlainObject(FieldNamingStyle.Database):e;return _.forOwn(n,((e,r)=>{i.push(this.translateFieldName(t,r)+" = ?"),a.values.push(this.makeDbValue(e))})),a.sql+=i.join(", "),r&&a.append(this.buildWhere(t,r)),this.lastBuildData=a,a}buildInsertStatement(t,e){const r=this.getTableName(t),s=new SmartDbSqlBuildData("INSERT");s.sql+=" INTO "+r;const a=[];e instanceof AbstractModel&&(e=e.getPlainObject(FieldNamingStyle.Database)),_.forOwn(e,((e,r)=>{r=this.translateFieldName(t,r),a.push(r),s.values.push(this.makeDbValue(e))}));const i=new Array(a.length);return i.fill("?"),s.sql+=" ("+a.join(", ")+") VALUES ("+i.join(", ")+")",this.lastBuildData=s,s}prepareFieldValue(t,e){let r="<undefined>";switch(e.operation){case SqlFieldOperationType.FIELD:r=this.translateFieldName(t,e.value);break;case SqlFieldOperationType.VALUE:null===e.value?r="NULL":e.literal?r=e.value:_.isString(e.value)?!isNaN(parseFloat(e.value))&&isFinite(e.value)||(r="'"+e.value+"'"):_.isNumber(e.value)?r=e.value.toString():_.isBoolean(e.value)?r=e.value?"1":"0":_.isDate(e.value)?r="'"+e.value.toISOString().substring(0,23).replace("T"," ")+"'":console.error("unhandled field data type",typeof e.value,e.value);break;case SqlFieldOperationType.COUNT:r=_.isArray(e.value)?"COUNT("+e.value.join(",")+")":"COUNT("+(e.value||"")+")";break;case SqlFieldOperationType.COALESCE:const s=_.isArray(e.value)?e.value:[e.value];r="COALESCE("+this.buildFieldList(t,s).join(",")+")"}if(e.alias){const t=this.getDbQuote();r+=` as ${t}${e.alias}${t}`}return r}prepareField(t,e,r){let s;if(null===e)s="NULL";else if(_.isString(e)){const a=e.match(/^'(.*)'$/);a?r?(s="?",r.push(a[1])):s=e:s=this.translateFieldName(t,e)}else e.operation?s=this.prepareFieldValue(t,e):r?(s="?",r.push(e)):s=this.makeArgumentDbValue(e).toString();return s}buildFieldList(t,e){const r=[];return _.forEach(e,(e=>{r.push(this.prepareField(t,e))})),r}buildSelectSectionStatement(t,e){const r=this.getTableName(t);let s,a;if(_.isArray(e.fields))s=e.fields;else if(_.isString(e.fields)){const t=e.fields.trim();s=""===t||"*"==t?[]:t.split(/,/)}else s=e.fields&&e.fields.operation?[e.fields]:[];if(s.length>0){a=this.buildFieldList(t,s).join(", ")}else a="*";e.distinct&&(a="DISTINCT "+a),e.count&&(a=`COUNT(${a})`);const i=new SmartDbSqlBuildData(`SELECT ${a} FROM ${r}`);if(e.where&&i.append(this.buildWhere(t,e.where)),e.groupBy){i.sql+=" GROUP BY ";const r=_.isArray(e.groupBy)?e.groupBy:[e.groupBy];i.sql+=r.map((e=>this.translateFieldName(t,e))).join(", ")}return i}translateFieldName(t,e){if(_.isString(t)){const e=t;let r=!1;_.forEach(this.dictionaries,(s=>(s.models&&s.models[e]&&(t=s.models[e].cls,r=!0),!r)))}if(!_.isString(t)){const r=t.attributeMap[e];if(r)r.alias&&(e=r.alias);else{const r=t.getTableName();this.lastError=new Error(`unknown field '${e}' in table '${r}'`),this.smartDbLog.logError(SmartErrorLocation.Database,"translateFieldName",this.lastError)}}return e}makeDbValue(t){return _.isBoolean(t)?t=t?1:0:_.isDate(t)&&(t=toSmartDbDate(t)),t}makeArgumentDbValue(t){return _.isBoolean(t)?t=t?1:0:_.isDate(t)?t=`'${toSmartDbDate(t)}'`:_.isString(t)&&(t=`'${t.replace(/'/,"''").replace(/\\/,"\\\\")}'`),t}saveExecute(t){let e;try{e=t()}catch(t){this.lastError=t instanceof Error?t:new Error(t||"Unknown error"),this.smartDbLog.logFatal(SmartErrorLocation.Database,"saveExecute-catch",this.lastError),e=!1}return e}scriptParser(t){const e=fs.readFileSync(t,"utf8"),r=[];let s=0,a=0,i=!1,n=0,l=!1,o="";for(;a<e.length;){if(l){if("\n"==e[a])for(l=!1,s=a+1;" "==e[s]||"\n"==e[s]||"\n"==e[s];)s+=1}else"'"==e[a]?i=!i:!i&&e.substring(a,a+6).match(/^begin(\s|\n)/)?(n+=1,a+=6):n>0&&!i&&e.substring(a,a+4).match(/^end;/)?(n-=1,a+=4):0!==n||i||"/"!=e[a]?i||"-"!=e[a]||"-"!=e[a+1]?0!==n||i||";"!=e[a]||(r.push((o+e.substring(s,a)).trim()),o="",s=a+2):(o+=e.substring(s,a),l=!0):(r.push((o+e.substring(s,a)).trim()),o="",s=a+2);a+=1}if(s<e.length){const t=e.substring(s,e.length).trim().replace(/;$/,"");console.log(t),""!==t&&r.push(t)}return r}prepareResultRow(t,e,r){let s;if(r.indexedBy&&this.smartDbLog.logWarning(SmartErrorLocation.Database,"AbstractModel.get","option 'indexedBy' not supported without 'all'"),e)if(r.count)s=parseInt(_.values(e)[0],10);else if(r.collapseRow)s=_.values(e).join(",");else{const a=t.from(e);s=r.style==FieldNamingStyle.TypeScript?a.getPlainObject():a}return s}prepareResultRows(t,e,r){let s;if(!e||!r.indexedBy&&!r.collapseRow&&_.isString(t))s=e;else{const a=t;s=r.indexedBy?{}:new Array(e.length),_.forEach(e,((t,e)=>{let i=a.from?a.from(t):null,n=null;if(r.indexedBy&&(n=i?i.getValue(r.indexedBy):t[r.indexedBy]),r.collapseRow){const r=_.values(t).join(",");n?s[n]=r:s[e]=r}else i&&r.style==FieldNamingStyle.TypeScript&&(i=i.getPlainObject()),n?s[n]=i||t:s[e]=i||t}))}return s}getTableName(t){let e;if(_.isString(t)){let r=t;_.forEach(this.dictionaries,(t=>(t.models&&t.models[r]&&(e=t.models[r].cls.getTableName()),!e))),e||(e=r)}else{if(!t||!t.getTableName)throw new Error(`unknown model: ${t}`);e=t.getTableName()}return e}get isReady(){return this._isReady}set isReady(t){this._isReady=t,this._onReady.next(t)}get lastError(){return this._lastError}set lastError(t){this._lastError=new SmartError(t),this._lastError.location=SmartErrorLocation.Database}get supportSyncCalls(){return!1}}