@egi/smart-db 2.3.2 → 2.3.4

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.
Files changed (74) hide show
  1. package/drivers/smart-db-better-sqlite3.d.ts +36 -0
  2. package/drivers/smart-db-better-sqlite3.js +1 -0
  3. package/drivers/smart-db-mysql.d.ts +26 -0
  4. package/drivers/smart-db-mysql.js +1 -0
  5. package/drivers/smart-db-mysql2.d.ts +26 -0
  6. package/drivers/smart-db-mysql2.js +1 -0
  7. package/drivers/smart-db-sqlite3.d.ts +30 -0
  8. package/drivers/smart-db-sqlite3.js +1 -0
  9. package/helpers/extract-db-api.d.ts +1 -0
  10. package/helpers/extract-db-api.js +1 -0
  11. package/models/abstract-model.d.ts +22 -0
  12. package/models/abstract-model.js +1 -0
  13. package/models/smart-db-core-table-model.d.ts +35 -0
  14. package/models/smart-db-core-table-model.js +1 -0
  15. package/models/smart-db-dictionary.d.ts +13 -0
  16. package/models/smart-db-dictionary.js +1 -0
  17. package/models/smart-db-log-model.d.ts +65 -0
  18. package/models/smart-db-log-model.js +1 -0
  19. package/models/smart-db-version-model.d.ts +65 -0
  20. package/models/smart-db-version-model.js +1 -0
  21. package/models/smart-db-version-view-model.d.ts +71 -0
  22. package/models/smart-db-version-view-model.js +1 -0
  23. package/models/sqlite-master-model.d.ts +36 -0
  24. package/models/sqlite-master-model.js +1 -0
  25. package/models/sqlite-sequence-model.d.ts +24 -0
  26. package/models/sqlite-sequence-model.js +1 -0
  27. package/package.json +1 -1
  28. package/{src/smart-db-api.ts → smart-db-api.d.ts} +0 -3
  29. package/smart-db-api.js +1 -0
  30. package/smart-db-globals.d.ts +22 -0
  31. package/smart-db-globals.js +1 -0
  32. package/{src/smart-db-interfaces.ts → smart-db-interfaces.d.ts} +34 -82
  33. package/smart-db-interfaces.js +1 -0
  34. package/smart-db-log.d.ts +58 -0
  35. package/smart-db-log.js +1 -0
  36. package/smart-db-sql-build-data.d.ts +9 -0
  37. package/smart-db-sql-build-data.js +1 -0
  38. package/smart-db-upgrade-manager.d.ts +13 -0
  39. package/smart-db-upgrade-manager.js +1 -0
  40. package/smart-db.d.ts +67 -0
  41. package/smart-db.js +1 -0
  42. package/.eslintrc.json +0 -212
  43. package/README.md +0 -2
  44. package/bin/copy-assets +0 -6
  45. package/src/drivers/smart-db-better-sqlite3.ts +0 -284
  46. package/src/drivers/smart-db-mysql.ts +0 -159
  47. package/src/drivers/smart-db-mysql2.ts +0 -159
  48. package/src/drivers/smart-db-sqlite3.ts +0 -198
  49. package/src/helpers/extract-db-api.ts +0 -465
  50. package/src/helpers/terser-tree.ts +0 -39
  51. package/src/models/abstract-model.ts +0 -209
  52. package/src/models/smart-db-core-table-model.ts +0 -161
  53. package/src/models/smart-db-dictionary.ts +0 -28
  54. package/src/models/smart-db-log-model.ts +0 -316
  55. package/src/models/smart-db-version-model.ts +0 -316
  56. package/src/models/smart-db-version-view-model.ts +0 -347
  57. package/src/models/sqlite-master-model.ts +0 -140
  58. package/src/models/sqlite-sequence-model.ts +0 -91
  59. package/src/smart-db-globals.ts +0 -136
  60. package/src/smart-db-log.ts +0 -262
  61. package/src/smart-db-sql-build-data.ts +0 -28
  62. package/src/smart-db-upgrade-manager.ts +0 -171
  63. package/src/smart-db.ts +0 -854
  64. package/test/data/sql-engine-tests.json +0 -232
  65. package/test/db/mysql/database-init.sql +0 -11
  66. package/test/db/sqlite3/database-init.sql +0 -11
  67. package/test/exer.js +0 -28
  68. package/test/model/smart-db-dictionary.ts +0 -19
  69. package/test/model/test-table-model.ts +0 -214
  70. package/test/test.js +0 -273
  71. package/test/test2.js +0 -252
  72. package/tsconfig.json +0 -32
  73. package/tsconfig.pro.json +0 -32
  74. package/tsconfig.test-model.json +0 -23
@@ -1,26 +1,22 @@
1
- import {AbstractModel} from "./models/abstract-model";
2
- import {SmartDbDictionary} from "./models/smart-db-dictionary";
3
- import {SmartDbVersionViewModel} from "./models/smart-db-version-view-model";
4
- import {SmartDbSqlBuildData} from "./smart-db-sql-build-data";
5
-
1
+ import { AbstractModel } from "./models/abstract-model";
2
+ import { SmartDbDictionary } from "./models/smart-db-dictionary";
3
+ import { SmartDbVersionViewModel } from "./models/smart-db-version-view-model";
4
+ import { SmartDbSqlBuildData } from "./smart-db-sql-build-data";
6
5
  export interface SmartDbOptions {
7
6
  module: string;
8
7
  sqlFilesDirectory: string;
9
8
  smartDbDictionary?: typeof SmartDbDictionary | any[];
10
9
  skipAutoUpgrade?: boolean;
11
10
  }
12
-
13
11
  export interface SmartDbRunResult {
14
12
  lastId: number;
15
13
  changes: number;
16
14
  affected: number;
17
15
  }
18
-
19
16
  export interface SmartDbTableInfo {
20
17
  name: string;
21
18
  fields: SmartDbFieldDescription[];
22
19
  }
23
-
24
20
  export interface SmartDbFieldDescription {
25
21
  cid?: string | number;
26
22
  name: string;
@@ -30,19 +26,18 @@ export interface SmartDbFieldDescription {
30
26
  defaultValue?: number | string | boolean;
31
27
  isPk?: boolean;
32
28
  }
33
-
34
29
  export interface SmartDbSqlComparison {
35
- compare: string | SqlFieldDescriptor,
30
+ compare: string | SqlFieldDescriptor;
36
31
  with: string | SqlFieldDescriptor;
37
32
  operation?: SqlOperationType;
38
33
  }
39
-
40
- export type SqlValueType = string | number | boolean | Date;
41
-
42
- export enum FieldNamingStyle { Database, TypeScript, All}
43
-
44
- export type GenericModelData = Record<string, SqlValueType>;
45
-
34
+ export declare type SqlValueType = string | number | boolean | Date;
35
+ export declare enum FieldNamingStyle {
36
+ Database = 0,
37
+ TypeScript = 1,
38
+ All = 2
39
+ }
40
+ export declare type GenericModelData = Record<string, SqlValueType>;
46
41
  export interface AttributeInfo {
47
42
  attribute: string;
48
43
  type: string;
@@ -52,42 +47,34 @@ export interface AttributeInfo {
52
47
  alternative?: boolean;
53
48
  typeScriptStyle?: boolean;
54
49
  }
55
-
56
50
  export interface ModelAttributeMap {
57
51
  [key: string]: AttributeInfo;
58
52
  }
59
-
60
53
  export interface AbstractModelGlobals<T extends AbstractModel<T, D>, D extends GenericModelData> {
61
54
  attributeMap: ModelAttributeMap;
62
55
  getTableName: () => string;
63
56
  from: (other: T | D) => T;
64
57
  }
65
-
66
58
  export interface SqlWhere {
67
59
  or?: SqlWhere | SqlWhere[];
68
60
  and?: SqlWhere | SqlWhere[];
69
61
  expression?: SmartDbSqlComparison[];
70
-
71
62
  [key: string]: SqlValueType | SqlValueType[] | SqlOperation | SqlWhere | SqlWhere[] | SmartDbSqlComparison[];
72
63
  }
73
-
74
- export type SqlUpdateValues = Record<string, SqlValueType>;
75
- export type SqlOrderBy = string | string[];
76
- type SqlGroupBy = string | string[];
77
-
64
+ export declare type SqlUpdateValues = Record<string, SqlValueType>;
65
+ export declare type SqlOrderBy = string | string[];
66
+ declare type SqlGroupBy = string | string[];
78
67
  export interface SqlLimit {
79
68
  offset?: number;
80
69
  limit?: number;
81
70
  }
82
-
83
71
  export interface SectionDescription<T extends AbstractModel<T, D>, D extends GenericModelData> {
84
- model: (new() => T) | string;
72
+ model: (new () => T) | string;
85
73
  where?: SqlWhere;
86
74
  fields?: string | SqlFieldDescriptor | (string | SqlFieldDescriptor)[] | null;
87
75
  groupBy?: SqlGroupBy;
88
76
  limit?: SqlLimit;
89
77
  }
90
-
91
78
  export interface SmartDbSqlOptions<T extends AbstractModel<T, D>, D extends GenericModelData> {
92
79
  firstOnly?: boolean;
93
80
  where?: SqlWhere;
@@ -103,116 +90,81 @@ export interface SmartDbSqlOptions<T extends AbstractModel<T, D>, D extends Gene
103
90
  minus?: SectionDescription<T, D> | SectionDescription<T, D>[];
104
91
  intersect?: SectionDescription<T, D> | SectionDescription<T, D>[];
105
92
  }
106
-
107
- export enum SqlOperationType {
108
- // noinspection JSUnusedGlobalSymbols,LocalVariableNamingConventionJS
109
- // eslint-disable-next-line no-shadow
110
- GT = ">", GE = ">=", LT = "<", LE = "<=", EQ = "=", NE = "!=",
111
- // eslint-disable-next-line no-shadow
112
- IN = "IN", LIKE = "LIKE", NOT_LIKE = "NOT LIKE",
113
- // eslint-disable-next-line no-shadow
114
- IS_NULL = "IS NULL", IS_NOT_NULL = "IS NOT NULL",
115
- // eslint-disable-next-line no-shadow
93
+ export declare enum SqlOperationType {
94
+ GT = ">",
95
+ GE = ">=",
96
+ LT = "<",
97
+ LE = "<=",
98
+ EQ = "=",
99
+ NE = "!=",
100
+ IN = "IN",
101
+ LIKE = "LIKE",
102
+ NOT_LIKE = "NOT LIKE",
103
+ IS_NULL = "IS NULL",
104
+ IS_NOT_NULL = "IS NOT NULL",
116
105
  LITERAL = "LITERAL",
117
106
  VALUE = "VALUE"
118
107
  }
119
-
120
- export enum SqlFieldOperationType {
108
+ export declare enum SqlFieldOperationType {
121
109
  VALUE = "VALUE",
122
110
  FIELD = "FIELD",
123
111
  COUNT = "COUNT",
124
112
  COALESCE = "COALESCE"
125
113
  }
126
-
127
114
  export interface SqlFieldDescriptor {
128
- operation: SqlFieldOperationType,
129
- value: SqlFieldDescriptor | SqlValueType | (SqlFieldDescriptor | SqlValueType)[],
130
- alias?: string,
115
+ operation: SqlFieldOperationType;
116
+ value: SqlFieldDescriptor | SqlValueType | (SqlFieldDescriptor | SqlValueType)[];
117
+ alias?: string;
131
118
  literal?: boolean;
132
119
  }
133
-
134
120
  export interface SqlOperation {
135
121
  operation: SqlOperationType;
136
122
  value: SqlValueType | SqlValueType[];
137
123
  key?: string;
138
124
  literalOperation?: SqlOperationType;
139
125
  }
140
-
141
126
  export interface KeyValueList {
142
127
  [key: string]: SqlValueType;
143
128
  }
144
-
145
129
  export interface IndexedGenericModelData<T extends AbstractModel<T, D>, D extends GenericModelData> {
146
130
  [key: string]: T | GenericModelData;
147
131
  }
148
-
149
132
  export interface SmartDbSqlBuildDataResults {
150
133
  sql: string;
151
134
  values: SqlValueType[];
152
135
  }
153
-
154
136
  export interface SmartDbApi {
155
137
  initDb(appOptions: SmartDbOptions): Promise<SmartDbVersionViewModel[]>;
156
-
157
138
  exists<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), type?: "view" | "table" | "index", indexTableName?: string): Promise<boolean>;
158
-
159
139
  existsSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), type?: "view" | "table" | "index", indexTableName?: string): boolean;
160
-
161
140
  get<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), options: SmartDbSqlOptions<T, D>): Promise<(T | D)[] | T | D | SqlValueType | IndexedGenericModelData<T, D> | string | string[]>;
162
-
163
141
  getSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), options: SmartDbSqlOptions<T, D>): (T | D)[] | T | D | IndexedGenericModelData<T, D> | SqlValueType | string[] | false;
164
-
165
142
  getFirst<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy): Promise<T>;
166
-
167
143
  getFirstSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy): T | false;
168
-
169
144
  getAll<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy, limit?: SqlLimit): Promise<T[]>;
170
-
171
145
  getAllSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy, limit?: SqlLimit): T[] | false;
172
-
173
146
  delete<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere): Promise<number>;
174
-
175
147
  deleteSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere): number | false;
176
-
177
148
  update<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T, where?: SqlWhere): Promise<number>;
178
-
179
149
  updateSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T, where?: SqlWhere): number | false;
180
-
181
150
  insert<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T): Promise<number>;
182
-
183
151
  insertSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T): number | false;
184
-
185
152
  exec(script: string): Promise<void>;
186
-
187
153
  execSync(script: string): SmartDbDatabase | false;
188
-
189
154
  getLastError(): any;
190
-
191
155
  getLastBuildData(): SmartDbSqlBuildData;
192
-
193
156
  getDbQuote(): string;
194
-
195
157
  getTableInfo(table: string): Promise<SmartDbTableInfo>;
196
-
197
158
  toDate(d: Date | number | string): Date | null;
198
-
199
159
  getDbConnector(): string | SmartDbConnector;
200
-
201
160
  toDbTimestamp(d: Date | number): string;
202
-
203
161
  toDbDate(d: Date | number): string;
204
-
205
162
  hasConcurrentTransactions(): boolean;
206
-
207
163
  closeSync(): boolean;
208
-
209
164
  close(): Promise<void>;
210
165
  }
211
-
212
166
  export interface SmartDbDatabase {
213
- // empty placeholder interface
214
167
  }
215
-
216
168
  export interface SmartDbConnector {
217
- // empty placeholder interface
218
- }
169
+ }
170
+ export {};
@@ -0,0 +1 @@
1
+ export var FieldNamingStyle;!function(e){e[e.Database=0]="Database",e[e.TypeScript=1]="TypeScript",e[e.All=2]="All"}(FieldNamingStyle||(FieldNamingStyle={}));export var SqlOperationType;!function(e){e.GT=">",e.GE=">=",e.LT="<",e.LE="<=",e.EQ="=",e.NE="!=",e.IN="IN",e.LIKE="LIKE",e.NOT_LIKE="NOT LIKE",e.IS_NULL="IS NULL",e.IS_NOT_NULL="IS NOT NULL",e.LITERAL="LITERAL",e.VALUE="VALUE"}(SqlOperationType||(SqlOperationType={}));export var SqlFieldOperationType;!function(e){e.VALUE="VALUE",e.FIELD="FIELD",e.COUNT="COUNT",e.COALESCE="COALESCE"}(SqlFieldOperationType||(SqlFieldOperationType={}));
@@ -0,0 +1,58 @@
1
+ import { SmartDbApi } from "./smart-db-interfaces";
2
+ export declare const SmartDbLogLocation: {
3
+ Frontend: string;
4
+ Backend: string;
5
+ Database: string;
6
+ UpgradeManager: string;
7
+ Other: string;
8
+ };
9
+ export declare type SmartDbLogLocationType = typeof SmartDbLogLocation;
10
+ export declare type SmartDbLogLocationKey = keyof SmartDbLogLocationType;
11
+ export declare type SmartDbLogLocationValue = SmartDbLogLocationType[keyof SmartDbLogLocationType];
12
+ export declare const SeverityCode: {
13
+ readonly Fatal: "F";
14
+ readonly Error: "E";
15
+ readonly Warning: "W";
16
+ readonly Info: "I";
17
+ readonly Debug: "D";
18
+ readonly Local: "L";
19
+ };
20
+ export declare type SeverityCodeType = typeof SeverityCode;
21
+ export declare type SeverityCodeKey = keyof SeverityCodeType;
22
+ export declare type SeverityCodeValue = SeverityCodeType[keyof SeverityCodeType];
23
+ export declare const SeverityLevel: {
24
+ readonly None: 0;
25
+ readonly Fatal: 1;
26
+ readonly Error: 2;
27
+ readonly Warning: 3;
28
+ readonly Info: 4;
29
+ readonly Debug: 5;
30
+ readonly All: 9;
31
+ };
32
+ export declare type SeverityLevelType = typeof SeverityLevel;
33
+ export declare type SeverityLevelKey = keyof SeverityLevelType;
34
+ export declare type SeverityLevelValue = SeverityLevelType[keyof SeverityLevelType];
35
+ export declare class SmartDbLog {
36
+ private db;
37
+ private dbLogLevel;
38
+ private consoleLogLevel;
39
+ private userId;
40
+ private dbLogging;
41
+ private isLogging;
42
+ constructor(db?: SmartDbApi);
43
+ getConsoleLogLevel(): SeverityLevelValue;
44
+ setConsoleLogLevel(consoleLogLevel: SeverityLevelValue): void;
45
+ getDbLogLevel(): SeverityLevelValue;
46
+ setDbLogLevel(dbLogLevel: SeverityLevelValue): void;
47
+ setDb(db: SmartDbApi): void;
48
+ setUserId(userId: string | number): void;
49
+ setDbLogging(dbLogging: boolean): void;
50
+ getDbLogging(): boolean;
51
+ logFatal(type: SmartDbLogLocationValue, location: string, message: string | Error, data?: any): void;
52
+ logError(type: SmartDbLogLocationValue, location: string, message: string | Error, data?: any): void;
53
+ logWarning(type: SmartDbLogLocationValue, location: string, message: string | Error, data?: any): void;
54
+ logInfo(type: SmartDbLogLocationValue, location: string, message: string | Error, data?: any): void;
55
+ logDebug(type: SmartDbLogLocationValue, location: string, message: string | Error, data?: any): void;
56
+ writeLog(type: SmartDbLogLocationValue, location: string, severity: SeverityCodeValue, message: string | Error, data: unknown, timestamp?: Date | string | number): void;
57
+ }
58
+ export declare const smartDbLog: SmartDbLog;
@@ -0,0 +1 @@
1
+ import _ from"lodash";import{SmartDbLogModel}from"./models/smart-db-log-model";import{SmartDbDateRegexp,SmartDbTimestampRegexp,toSmartDbTimestamp}from"./smart-db-globals";export const SmartDbLogLocation={Frontend:"frontend",Backend:"backend",Database:"database",UpgradeManager:"upgrade-manager",Other:"other"};export const SeverityCode={Fatal:"F",Error:"E",Warning:"W",Info:"I",Debug:"D",Local:"L"};export const SeverityLevel={None:0,Fatal:1,Error:2,Warning:3,Info:4,Debug:5,All:9};export class SmartDbLog{constructor(e){this.userId=null,this.dbLogging=!0,this.isLogging=!1,this.db=e,this.dbLogLevel=SeverityLevel.Info,this.consoleLogLevel=SeverityLevel.Info}getConsoleLogLevel(){return this.consoleLogLevel}setConsoleLogLevel(e){this.consoleLogLevel=e}getDbLogLevel(){return this.dbLogLevel}setDbLogLevel(e){this.dbLogLevel=e}setDb(e){this.db=e,this.db?this.db.exists(SmartDbLogModel).then(e=>{this.dbLogging=e}).catch(e=>{throw e}):this.dbLogging=!1}setUserId(e){this.userId=e}setDbLogging(e){this.dbLogging=e}getDbLogging(){return this.dbLogging}logFatal(e,t,o,r){this.writeLog(e,t,SeverityCode.Fatal,o,r)}logError(e,t,o,r){this.writeLog(e,t,SeverityCode.Error,o,r)}logWarning(e,t,o,r){this.writeLog(e,t,SeverityCode.Warning,o,r)}logInfo(e,t,o,r){this.writeLog(e,t,SeverityCode.Info,o,r)}logDebug(e,t,o,r){this.writeLog(e,t,SeverityCode.Debug,o,r)}writeLog(e,t,o,r,i,s){try{if(this.isLogging)console.error("recursive logging error:",e,t,o,r,i);else{this.isLogging=!0;let a,g,n=SeverityLevel.None;switch(o){case SeverityCode.Fatal:a=console.error,n=SeverityLevel.Fatal;break;case SeverityCode.Error:a=console.error,n=SeverityLevel.Error;break;case SeverityCode.Warning:a=console.warn,n=SeverityLevel.Warning;break;case SeverityCode.Info:a=console.info,n=SeverityLevel.Info;break;case SeverityCode.Debug:a=console.debug,n=SeverityLevel.Debug}if(_.isString(s)){const e=s.match(SmartDbTimestampRegexp),t=e&&s.match(SmartDbDateRegexp);g=e?e[1]:t?t[1]+".000":toSmartDbTimestamp(new Date)}else g=_.isDate(s)?toSmartDbTimestamp(s):_.isNumber(s)?toSmartDbTimestamp(new Date(s)):toSmartDbTimestamp(new Date);if(_.isObjectLike(r))if(r instanceof Error)i||(i=r),r=r.message;else try{r=JSON.stringify(r)}catch(e){r=r.toString()}else"boolean"==typeof r&&(r=r?"<true>":"<false>");if(i){if(i instanceof Error)i=i.stack;else if(_.isObject(i))try{i=JSON.stringify(i)}catch(e){i=i.toString(),this.db&&this.dbLogLevel>=n&&console.error("unable to stringify log data",i)}else i.toString?i=i.toString():(i=null,this.db&&this.dbLogLevel>=n&&console.error("unable to store log data",i));i&&(r+=` (${i})`)}if(this.consoleLogLevel>=n){const s=e.substr(0,1).toUpperCase();if(e==SmartDbLogLocation.Database&&this.db&&a(`${o}-${s}-${g}: last statement:`,this.db.getLastBuildData()),a(`${o}-${s}-${g}: ${r}`),this.dbLogging)try{e==SmartDbLogLocation.Database&&(i||(i=JSON.stringify(this.db.getLastBuildData()))),this.db.insertSync(SmartDbLogModel,{severity:o,type:e,location:t,info:r||"<empty>",data:i,user:this.userId,timestamp:new Date(g)})}catch(e){console.error(`F-B-${g}: unable to write the log statement below to database`,e,e.code,e.name,e.message);try{a(`F-B-${g}: last statement:`,this.db.getLastBuildData())}catch{a(`F-B-${g}: last statement not available`)}}}}this.isLogging=!1}catch(e){this.isLogging=!1,console.error("fatal logging error",e)}}}export const smartDbLog=new SmartDbLog;
@@ -0,0 +1,9 @@
1
+ import { SmartDbSqlBuildDataResults, SqlValueType } from "./smart-db-interfaces";
2
+ export declare class SmartDbSqlBuildData {
3
+ sql: string;
4
+ values: SqlValueType[];
5
+ constructor(sql?: string, values?: SqlValueType[]);
6
+ append(data: SmartDbSqlBuildData): void;
7
+ toString(): string;
8
+ results(): SmartDbSqlBuildDataResults;
9
+ }
@@ -0,0 +1 @@
1
+ import _ from"lodash";export class SmartDbSqlBuildData{constructor(s,t){this.sql=s||"",this.values=t||[]}append(s){this.sql=this.sql.trim()+" "+s.sql.trim(),this.values=_.concat(this.values,s.values)}toString(){return this.sql+" <= ("+this.values.join(", ")+")"}results(){return{sql:this.sql,values:this.values}}}
@@ -0,0 +1,13 @@
1
+ import { SmartDbVersionViewModel } from "./models/smart-db-version-view-model";
2
+ import { SmartDb } from "./smart-db";
3
+ import { SmartDbOptions } from "./smart-db-interfaces";
4
+ export declare class SmartDbUpgradeManager {
5
+ private db;
6
+ private log;
7
+ constructor(db: SmartDb);
8
+ hasDatabaseModule(module: string): Promise<boolean>;
9
+ prepareDatabase(options: SmartDbOptions): Promise<SmartDbVersionViewModel>;
10
+ private executeSqlScript;
11
+ private upgradeDatabase;
12
+ private executeScriptSequentially;
13
+ }
@@ -0,0 +1 @@
1
+ import*as fs from"fs";import _ from"lodash";import{SmartDbVersionViewModel}from"./models/smart-db-version-view-model";import{SmartDbLogLocation}from"./smart-db-log";export class SmartDbUpgradeManager{constructor(e){this.db=e,this.log=e.getLogger()}hasDatabaseModule(e){return new Promise((t,a)=>{this.db.exists(SmartDbVersionViewModel).then(o=>{o?this.db.getFirst(SmartDbVersionViewModel,{module:e}).then(e=>{t(!!e)}).catch(e=>{a(e)}):t(!1)}).catch(e=>{a(e)})})}prepareDatabase(e){return new Promise((t,a)=>{try{const o=fs.existsSync(e.sqlFilesDirectory)&&fs.statSync(e.sqlFilesDirectory);if(o&&o.isDirectory()){const o=e.sqlFilesDirectory+`/${e.module}-init.sql`;fs.existsSync(o)?this.hasDatabaseModule(e.module).then(r=>{r?(this.log.logInfo(SmartDbLogLocation.UpgradeManager,"prepareDatabase",`database module '${e.module}' exists`),this.upgradeDatabase(e).then(a=>{this.log.logInfo(SmartDbLogLocation.UpgradeManager,"prepareDatabase",`connected to module '${e.module}' version ${a.versionString}`),t(a)}).catch(e=>{a(e)})):(this.log.setDbLogging(!1),this.log.logInfo(SmartDbLogLocation.UpgradeManager,"prepareDatabase",`database '${e.module}' doesn't exists - begin creation`),this.executeSqlScript(o).then(()=>{this.log.setDbLogging(!0),this.log.logInfo(SmartDbLogLocation.UpgradeManager,"prepareDatabase","database module creation complete"),this.hasDatabaseModule(e.module).then(o=>{o?(this.log.logInfo(SmartDbLogLocation.UpgradeManager,"prepareDatabase","successfully initialized database for new module "+e.module),this.upgradeDatabase(e).then(a=>{this.log.logInfo(SmartDbLogLocation.UpgradeManager,"prepareDatabase",`connected to module '${e.module}' version ${a.versionString}`),t(a)}).catch(e=>{a(e)})):a("error running database initialization script")}).catch(e=>{a(e)})}).catch(e=>{a(e)}))}).catch(e=>{a(e)}):a(`missing mandatory '${e.module}-init.sql' file in ${o}`)}else a(`option 'sqlFilesDirectory' (${e.sqlFilesDirectory}) must point to an existing directory (absolute or relative to ${fs.realpathSync(".")})`)}catch(e){a(e)}})}executeSqlScript(e){const t=fs.readFileSync(e,"utf8");return this.db.exec(t)}upgradeDatabase(e){return new Promise((t,a)=>{this.db.getFirst(SmartDbVersionViewModel,{module:e.module}).then(o=>{o?fs.readdir(e.sqlFilesDirectory,(r,s)=>{if(r)a("unable to read database files from "+e.sqlFilesDirectory);else{let r=[];s.forEach(t=>{const a=new RegExp(`^${e.module}-update.([0-9]{3})\\..*\\.sql$`),s=t.match(a);if(s){parseInt(s[1],10)>o.sequence&&r.push(t)}}),r=_.sortBy(r),this.executeScriptSequentially(r,e).then(()=>{this.db.getFirst(SmartDbVersionViewModel,{module:e.module},"*","sequence DESC").then(e=>{e?t(SmartDbVersionViewModel.from(e)):a("unable to determine final smart db version")}).catch(e=>{a(e)})}).catch(e=>{a(e)})}}):a(`missing version entry for module ${e.module} - add the mandatory insert into smart_db_version statement to your database creation script!`)}).catch(e=>{a(e)})})}executeScriptSequentially(e,t){return new Promise(async(a,o)=>{e&&e.length>0?(this.log.logInfo(SmartDbLogLocation.UpgradeManager,"upgradeDatabase",`execute update script '${e[0]}' for module ${t.module}`),await this.executeSqlScript(`${t.sqlFilesDirectory}/${e[0]}`).then(()=>{this.log.logInfo(SmartDbLogLocation.UpgradeManager,"upgradeDatabase",`successfully executed update script '${e[0]}' for module ${t.module}`),1==e.length&&a(!0)}).catch(e=>{o(e)}),e.length>1&&this.executeScriptSequentially(e.splice(1),t).then(e=>{a(e)}).catch(e=>{o(e)})):a(!0)})}}
package/smart-db.d.ts ADDED
@@ -0,0 +1,67 @@
1
+ import { AbstractModel } from "./models/abstract-model";
2
+ import { SmartDbVersionViewModel } from "./models/smart-db-version-view-model";
3
+ import { GenericModelData, IndexedGenericModelData, SmartDbApi, SmartDbConnector, SmartDbDatabase, SmartDbOptions, SmartDbRunResult, SmartDbSqlOptions, SmartDbTableInfo, SqlFieldDescriptor, SqlLimit, SqlOrderBy, SqlUpdateValues, SqlValueType, SqlWhere } from "./smart-db-interfaces";
4
+ import { SmartDbLog } from "./smart-db-log";
5
+ import { SmartDbSqlBuildData } from "./smart-db-sql-build-data";
6
+ export declare abstract class SmartDb implements SmartDbApi {
7
+ abstract getDatabaseType(): string;
8
+ abstract hasConcurrentTransactions(): boolean;
9
+ abstract exists<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), type?: "view" | "table" | "index", indexTableName?: string): Promise<boolean>;
10
+ abstract existsSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), type?: "view" | "table" | "index", indexTableName?: string): boolean;
11
+ abstract exec(script: string): Promise<void>;
12
+ abstract execSync(script: string): SmartDbDatabase | false;
13
+ abstract close(): Promise<void>;
14
+ abstract closeSync(): boolean;
15
+ abstract getDbQuote(): string;
16
+ abstract getTableInfo(table: string): Promise<SmartDbTableInfo>;
17
+ abstract getDbConnector(): string | SmartDbConnector;
18
+ protected abstract statementRun(buildData: SmartDbSqlBuildData): Promise<SmartDbRunResult>;
19
+ protected abstract statementRunSync(buildData: SmartDbSqlBuildData): SmartDbRunResult;
20
+ protected abstract statementGet(buildData: SmartDbSqlBuildData): Promise<any>;
21
+ protected abstract statementGetSync(buildData: SmartDbSqlBuildData): any;
22
+ protected abstract statementGetAll(buildData: SmartDbSqlBuildData): Promise<any[]>;
23
+ protected abstract statementGetAllSync(buildData: SmartDbSqlBuildData): any[];
24
+ protected db: SmartDbDatabase;
25
+ protected dbConnector: SmartDbConnector;
26
+ protected lastError: Error;
27
+ protected lastBuildData: SmartDbSqlBuildData;
28
+ protected smartDbLog: SmartDbLog;
29
+ private dictionaries;
30
+ protected constructor(dbConnector: SmartDbConnector);
31
+ initDb(appOptions: SmartDbOptions): Promise<SmartDbVersionViewModel[]>;
32
+ getLogger(): SmartDbLog;
33
+ getDb(): SmartDbDatabase;
34
+ getLastBuildData(): SmartDbSqlBuildData;
35
+ get<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), options: SmartDbSqlOptions<T, D>): Promise<(T | D)[] | T | D | SqlValueType | IndexedGenericModelData<T, D> | string | string[]>;
36
+ getSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), options: SmartDbSqlOptions<T, D>): (T | D)[] | T | D | SqlValueType | IndexedGenericModelData<T, D> | string | string[] | false;
37
+ getFirst<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy): Promise<T>;
38
+ getFirstSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy): T | false;
39
+ getAll<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy, limit?: SqlLimit): Promise<T[]>;
40
+ getAllSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy, limit?: SqlLimit): T[] | false;
41
+ delete<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere): Promise<number>;
42
+ deleteSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere): number | false;
43
+ update<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T, where?: SqlWhere): Promise<number>;
44
+ updateSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T, where?: SqlWhere): number | false;
45
+ insert<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T): Promise<number>;
46
+ insertSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T): number | false;
47
+ getLastError(): Error;
48
+ buildSelectStatement<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), options: SmartDbSqlOptions<T, D>): SmartDbSqlBuildData;
49
+ toDate(d: Date | number | string): Date | null;
50
+ toDbTimestamp(d: Date | number): string;
51
+ toDbDate(d: Date | number): string;
52
+ protected buildWhere<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where: SqlWhere, op?: string): SmartDbSqlBuildData;
53
+ protected buildDeleteStatement<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere): SmartDbSqlBuildData;
54
+ protected buildUpdateStatement<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T, where?: SqlWhere): SmartDbSqlBuildData;
55
+ protected buildInsertStatement<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T): SmartDbSqlBuildData;
56
+ protected prepareFieldValue<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), fieldOperation: SqlFieldDescriptor): string;
57
+ protected prepareField<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), field: SqlValueType | SqlFieldDescriptor, values?: SqlValueType[]): string;
58
+ protected buildFieldList<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), fields: (SqlValueType | SqlFieldDescriptor)[]): string[];
59
+ protected buildSelectSectionStatement<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), options: SmartDbSqlOptions<T, D>): SmartDbSqlBuildData;
60
+ protected translateFieldName<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), field: string): string;
61
+ protected makeDbValue(value: SqlValueType): SqlValueType;
62
+ protected makeArgumentDbValue(value: SqlValueType): SqlValueType;
63
+ protected saveExecute<T>(fn: () => T): T | false;
64
+ private prepareResultRow;
65
+ private prepareResultRows;
66
+ private getTableName;
67
+ }
package/smart-db.js ADDED
@@ -0,0 +1 @@
1
+ import _ from"lodash";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,SmartDbLogLocation}from"./smart-db-log";import{SmartDbSqlBuildData}from"./smart-db-sql-build-data";import{SmartDbUpgradeManager}from"./smart-db-upgrade-manager";export class SmartDb{constructor(e){this.dictionaries=[],this.dbConnector=e,this.smartDbLog=new SmartDbLog(this)}initDb(e){return new Promise((t,a)=>{this.dictionaries.push(SmartDbDictionary);const r=new SmartDbUpgradeManager(this);let i;i=import.meta&&import.meta.url?import.meta.url.replace(/file:\/\//,"").replace(/\/[^/]*$/,""):__dirname;const s={module:"smart-db-core",sqlFilesDirectory:i+"/assets/"+this.getDatabaseType()};r.prepareDatabase(s).then(i=>{this.exists(SmartDbLogModel).then(s=>{this.smartDbLog.setDbLogging(s),r.prepareDatabase(e).then(e=>{t([i,e])},e=>{a(e)})})}).catch(e=>{a(e)})})}getLogger(){return this.smartDbLog}getDb(){return this.db}getLastBuildData(){return this.lastBuildData}get(e,t){return new Promise((a,r)=>{t||(t={});const i=this.buildSelectStatement(e,t);t.firstOnly||t.count?this.statementGet(i).then(r=>{a(this.prepareResultRow(e,r,t))}).catch(e=>{r(e)}):this.statementGetAll(i).then(r=>{a(this.prepareResultRows(e,r,t))}).catch(e=>{r(e)})})}getSync(e,t){return this.saveExecute(()=>{t||(t={});const a=this.buildSelectStatement(e,t);let r;if(t.firstOnly||t.count){const i=this.statementGetSync(a);r=this.prepareResultRow(e,i,t)}else{const i=this.statementGetAllSync(a);r=this.prepareResultRows(e,i,t)}return r})}getFirst(e,t,a,r){return this.get(e,{firstOnly:!0,where:t,fields:a,orderBy:r})}getFirstSync(e,t,a,r){return this.getSync(e,{firstOnly:!0,where:t,fields:a,orderBy:r})}getAll(e,t,a,r,i){return this.get(e,{where:t,fields:a,orderBy:r,limit:i})}getAllSync(e,t,a,r,i){return this.getSync(e,{where:t,fields:a,orderBy:r,limit:i})}delete(e,t){return new Promise((a,r)=>{const i=this.buildDeleteStatement(e,t);this.statementRun(i).then(e=>{e?a(e.changes):r(this.getLastError())}).catch(e=>{r(e)})})}deleteSync(e,t){return this.saveExecute(()=>{const a=this.buildDeleteStatement(e,t);return this.statementRunSync(a).changes})}update(e,t,a){return new Promise((r,i)=>{const s=this.buildUpdateStatement(e,t,a);this.statementRun(s).then(e=>{e?r(e.changes):i(this.getLastError())}).catch(e=>{i(e)})})}updateSync(e,t,a){return this.saveExecute(()=>{const r=this.buildUpdateStatement(e,t,a);return this.statementRunSync(r).changes})}insert(e,t){return new Promise((a,r)=>{const i=this.buildInsertStatement(e,t);this.statementRun(i).then(e=>{e?a(e.lastId):r(this.getLastError())}).catch(e=>{r(e)})})}insertSync(e,t){return this.saveExecute(()=>{const a=this.buildInsertStatement(e,t);return this.statementRunSync(a).lastId})}getLastError(){return this.lastError}buildSelectStatement(e,t){t||(t={});const a=this.buildSelectSectionStatement(e,t);if(_.forEach(["union","minus","intersect"],e=>{let r=_.get(t,e);r&&(_.isArray(r)||(r=[r]),_.forEach(r,t=>{const r=this.buildSelectSectionStatement(t.model,t);a.sql+=" "+e.toUpperCase()+" ",a.append(r)}))}),t.orderBy){a.sql+=" ORDER BY ";const r=_.isString(t.orderBy)?t.orderBy.split(/ *, */):t.orderBy;a.sql+=r.map(t=>{let a="";const r=t.match(/^(\w*) (asc|desc)$/i);return r&&(t=r[1],a=r[2].toUpperCase()),t=this.translateFieldName(e,t),a&&(t+=" "+a),t}).join(", ")}return t.limit&&(t.limit.limit&&(a.sql+=" LIMIT "+t.limit.limit.toString()),t.limit.offset&&(a.sql+=" OFFSET "+t.limit.offset.toString())),this.lastBuildData=a,a}toDate(e){return smartDbToDate(e)}toDbTimestamp(e){return toSmartDbTimestamp(e)}toDbDate(e){return toSmartDbDate(e)}buildWhere(e,t,a){const r=new SmartDbSqlBuildData;return t&&_.keys(t).length>0&&(a||(a="AND",r.sql+=" WHERE "),r.sql+=_.map(t,(t,i)=>{const s=i.toUpperCase();if("AND"==s||"OR"==s){let a="";return(_.isArray(t)?t:[t]).forEach((t,i)=>{const l=this.buildWhere(e,t,s);i>0&&(a+=" "+s+" "),a+=l.sql,r.values=_.concat(r.values,l.values)}),a="("+a+")",a}if("EXPRESSION"==s){let i=[];return _.forEach(t,t=>{const a=this.prepareField(e,t.compare,r.values),s=this.prepareField(e,t.with,r.values);let l;l=_.isString(t.operation)&&SqlOperationType[t.operation]?SqlOperationType[t.operation]:t.operation||SqlOperationType.EQ,i.push(`${a} ${l} ${s}`)}),i.join(" "+a+" ")}{let a,s,l=!0;if(_.isArray(t)&&(t=IN(t)),_.isObject(t)){const e=t;switch(_.isString(e.operation)&&SqlOperationType[e.operation]&&(e.operation=SqlOperationType[e.operation]),e.operation){case SqlOperationType.IN:const t=new Array(e.value.length);t.fill("?"),a=SqlOperationType.IN+" ("+t.join(", ")+")",r.values=_.concat(r.values,e.value);break;case SqlOperationType.IS_NULL:case SqlOperationType.IS_NOT_NULL:a=e.operation;break;case SqlOperationType.LITERAL:i=e.key;const s=e.literalOperation||SqlOperationType.EQ;if(s==SqlOperationType.IN){const t=new Array(e.value.length);t.fill("?"),a=SqlOperationType.IN+" ("+t.join(", ")+")",r.values=_.concat(r.values,e.value)}else _.isUndefined(e.value)?a=s:(a=s+" ?",r.values.push(this.makeDbValue(e.value)));l=!1;break;default:a=e.operation+" ?",r.values.push(this.makeDbValue(e.value))}}else null===t?a=SqlOperationType.IS_NULL:void 0===t?(i="1",a="= 1",l=!1):(a=_.isString(t)&&t.match(/[%_]/)?SqlOperationType.LIKE+" ?":SqlOperationType.EQ+" ?",r.values.push(this.makeDbValue(t)));return s=l?this.translateFieldName(e,i)+" "+a:i+" "+a,s}}).join(" "+a+" ")),r}buildDeleteStatement(e,t){const a=this.getTableName(e),r=new SmartDbSqlBuildData("DELETE FROM");return r.sql+=" "+a,t&&r.append(this.buildWhere(e,t)),this.lastBuildData=r,r}buildUpdateStatement(e,t,a){const r=this.getTableName(e),i=new SmartDbSqlBuildData("UPDATE");i.sql+=" "+r+" SET ";const s=[];return t instanceof AbstractModel&&(t=t.getPlainObject(FieldNamingStyle.Database)),_.forOwn(t,(t,a)=>{s.push(this.translateFieldName(e,a)+" = ?"),i.values.push(this.makeDbValue(t))}),i.sql+=s.join(", "),a&&i.append(this.buildWhere(e,a)),this.lastBuildData=i,i}buildInsertStatement(e,t){const a=this.getTableName(e),r=new SmartDbSqlBuildData("INSERT");r.sql+=" INTO "+a;const i=[];t instanceof AbstractModel&&(t=t.getPlainObject(FieldNamingStyle.Database)),_.forOwn(t,(t,a)=>{a=this.translateFieldName(e,a),i.push(a),r.values.push(this.makeDbValue(t))});const s=new Array(i.length);return s.fill("?"),r.sql+=" ("+i.join(", ")+") VALUES ("+s.join(", ")+")",this.lastBuildData=r,r}prepareFieldValue(e,t){let a="<undefined>";switch(t.operation){case SqlFieldOperationType.FIELD:a=this.translateFieldName(e,t.value);break;case SqlFieldOperationType.VALUE:null===t.value?a="NULL":t.literal?a=t.value:_.isString(t.value)?!isNaN(parseFloat(t.value))&&isFinite(t.value)||(a="'"+t.value+"'"):_.isNumber(t.value)?a=t.value.toString():_.isBoolean(t.value)?a=t.value?"1":"0":_.isDate(t.value)?a="'"+t.value.toISOString().substr(0,23).replace("T"," ")+"'":console.error("unhandled field data type",typeof t.value,t.value);break;case SqlFieldOperationType.COUNT:a=_.isArray(t.value)?"COUNT("+t.value.join(",")+")":"COUNT("+(t.value||"")+")";break;case SqlFieldOperationType.COALESCE:const r=_.isArray(t.value)?t.value:[t.value];a="COALESCE("+this.buildFieldList(e,r).join(",")+")"}if(t.alias){const e=this.getDbQuote();a+=` as ${e}${t.alias}${e}`}return a}prepareField(e,t,a){let r;if(null===t)r="NULL";else if(_.isString(t)){const i=t.match(/^'(.*)'$/);i?a?(r="?",a.push(i[1])):r=t:r=this.translateFieldName(e,t)}else t.operation?r=this.prepareFieldValue(e,t):a?(r="?",a.push(t)):r=this.makeArgumentDbValue(t).toString();return r}buildFieldList(e,t){const a=[];return _.forEach(t,t=>{a.push(this.prepareField(e,t))}),a}buildSelectSectionStatement(e,t){const a=this.getTableName(e);let r,i;if(_.isArray(t.fields))r=t.fields;else if(_.isString(t.fields)){const e=t.fields.trim();r=""===e||"*"==e?[]:e.split(/,/)}else r=t.fields&&t.fields.operation?[t.fields]:[];if(r.length>0){i=this.buildFieldList(e,r).join(", ")}else i="*";t.distinct&&(i="DISTINCT "+i),t.count&&(i=`COUNT(${i})`);const s=new SmartDbSqlBuildData(`SELECT ${i} FROM ${a}`);if(t.where&&s.append(this.buildWhere(e,t.where)),t.groupBy){s.sql+=" GROUP BY ";const a=_.isArray(t.groupBy)?t.groupBy:[t.groupBy];s.sql+=a.map(t=>this.translateFieldName(e,t)).join(", ")}return s}translateFieldName(e,t){if(_.isString(e)){const t=e;let a=!1;_.forEach(this.dictionaries,r=>(r.models&&r.models[t]&&(e=r.models[t].cls,a=!0),!a))}if(!_.isString(e)){const a=e.attributeMap[t];if(a)a.alias&&(t=a.alias);else{const a=e.getTableName();this.lastError=new Error(`unknown field '${t}' in table '${a}'`),this.smartDbLog.logError(SmartDbLogLocation.Database,"translateFieldName",this.lastError)}}return t}makeDbValue(e){return _.isBoolean(e)?e=e?1:0:_.isDate(e)&&(e=toSmartDbDate(e)),e}makeArgumentDbValue(e){return _.isBoolean(e)?e=e?1:0:_.isDate(e)?e=`'${toSmartDbDate(e)}'`:_.isString(e)&&(e=`'${e}'`),e}saveExecute(e){let t;try{t=e()}catch(e){this.lastError=e instanceof Error?e:new Error(e||"Unknown error"),this.smartDbLog.logFatal(SmartDbLogLocation.Database,"saveExecute-catch",this.lastError),t=!1}return t}prepareResultRow(e,t,a){let r;if(a.indexedBy&&this.smartDbLog.logWarning(SmartDbLogLocation.Database,"AbstractModel.get","option 'indexedBy' not supported without 'all'"),t)if(a.count)r=parseInt(_.values(t)[0],10);else if(a.collapseRow)r=_.values(t).join(",");else{r=e.from(t)}return r}prepareResultRows(e,t,a){let r;if(a.indexedBy||a.collapseRow||!_.isString(e)){const i=e;r=a.indexedBy?{}:new Array(t.length),_.forEach(t,(e,t)=>{const s=i.from?i.from(e):null;let l=null;if(a.indexedBy&&(l=s?s.getValue(a.indexedBy):e[a.indexedBy]),a.collapseRow){const a=_.values(e).join(",");l?r[l]=a:r[t]=a}else l?r[l]=s||e:r[t]=s||e})}else r=t;return r}getTableName(e){let t;if(_.isString(e)){let a=e;_.forEach(this.dictionaries,e=>(e.models&&e.models[a]&&(t=e.models[a].cls.getTableName()),!t)),t||(t=a)}else{if(!e||!e.getTableName)throw new Error("unknown model: "+e);t=e.getTableName()}return t}}