@egi/smart-db 2.6.5 → 3.0.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 (91) hide show
  1. package/README.md +355 -0
  2. package/assets/mysql/smart-db-core-update.001.sql +10 -0
  3. package/assets/oracle/smart-db-core-update.001.sql +13 -0
  4. package/assets/sqlite3/smart-db-core-update.001.sql +10 -0
  5. package/drivers/smart-db-better-sqlite3.d.ts +103 -16
  6. package/drivers/smart-db-better-sqlite3.js +1 -1
  7. package/drivers/smart-db-mysql.d.ts +53 -10
  8. package/drivers/smart-db-mysql.js +1 -1
  9. package/drivers/smart-db-oracle.d.ts +93 -20
  10. package/drivers/smart-db-oracle.js +1 -1
  11. package/helpers/extract-db-api.js +1 -1
  12. package/models/abstract-model.d.ts +39 -4
  13. package/models/abstract-model.js +1 -1
  14. package/models/mysql-tables-model.d.ts +109 -0
  15. package/models/mysql-tables-model.js +1 -0
  16. package/models/oracle-all-cons-columns-model.d.ts +55 -0
  17. package/models/oracle-all-cons-columns-model.js +1 -0
  18. package/models/oracle-all-constraints-model.d.ts +177 -0
  19. package/models/oracle-all-constraints-model.js +1 -0
  20. package/models/oracle-all-dependencies-model.d.ts +77 -0
  21. package/models/oracle-all-dependencies-model.js +1 -0
  22. package/models/oracle-all-objects-model.d.ts +201 -0
  23. package/models/oracle-all-objects-model.js +1 -0
  24. package/models/oracle-all-tab-columns-model.d.ts +305 -0
  25. package/models/oracle-all-tab-columns-model.js +1 -0
  26. package/models/oracle-all-triggers-model.d.ts +187 -0
  27. package/models/oracle-all-triggers-model.js +1 -0
  28. package/{models.generated/smart-db-user-tab-columns-view-model.d.ts → models/smart-db-all-tab-columns-view-model.d.ts} +14 -6
  29. package/models/smart-db-all-tab-columns-view-model.js +1 -0
  30. package/models/smart-db-core-table-model.d.ts +24 -22
  31. package/models/smart-db-core-table-model.js +1 -1
  32. package/models/smart-db-dictionary.d.ts +2 -10
  33. package/models/smart-db-dictionary.js +1 -1
  34. package/models/smart-db-log-model.d.ts +25 -8
  35. package/models/smart-db-log-model.js +1 -1
  36. package/models/smart-db-test-table-model.d.ts +79 -0
  37. package/models/smart-db-test-table-model.js +1 -0
  38. package/models/smart-db-user-tab-columns-view-model.d.ts +2 -0
  39. package/models/smart-db-user-tab-columns-view-model.js +1 -1
  40. package/models/smart-db-version-model.d.ts +25 -8
  41. package/models/smart-db-version-model.js +1 -1
  42. package/models/smart-db-version-view-model.d.ts +27 -8
  43. package/models/smart-db-version-view-model.js +1 -1
  44. package/models/sqlite-master-model.d.ts +14 -12
  45. package/models/sqlite-master-model.js +1 -1
  46. package/models/sqlite-sequence-model.d.ts +9 -7
  47. package/models/sqlite-sequence-model.js +1 -1
  48. package/package.json +40 -56
  49. package/smart-db-api.d.ts +2 -1
  50. package/smart-db-api.js +1 -1
  51. package/smart-db-browser.d.ts +5 -0
  52. package/smart-db-browser.js +1 -0
  53. package/smart-db-globals.d.ts +37 -5
  54. package/smart-db-globals.js +1 -1
  55. package/smart-db-interfaces.d.ts +330 -40
  56. package/smart-db-interfaces.js +1 -1
  57. package/smart-db-sql-build-data.d.ts +10 -1
  58. package/smart-db-sql-build-data.js +1 -1
  59. package/smart-db-upgrade-manager.d.ts +6 -4
  60. package/smart-db-upgrade-manager.js +1 -1
  61. package/smart-db.d.ts +451 -55
  62. package/smart-db.js +1 -1
  63. package/smart-error.d.ts +9 -28
  64. package/smart-error.js +1 -1
  65. package/smart-tools.d.ts +178 -0
  66. package/smart-tools.js +1 -0
  67. package/drivers/smart-db-mysql2.d.ts +0 -20
  68. package/drivers/smart-db-mysql2.js +0 -1
  69. package/drivers/smart-db-sqlite3.d.ts +0 -23
  70. package/drivers/smart-db-sqlite3.js +0 -1
  71. package/models/oracle-cat-model.d.ts +0 -23
  72. package/models/oracle-cat-model.js +0 -1
  73. package/models/oracle-user-tab-columns-model.d.ts +0 -39
  74. package/models/oracle-user-tab-columns-model.js +0 -1
  75. package/models/oracle-user-tab-columns-view-model.d.ts +0 -43
  76. package/models/oracle-user-tab-columns-view-model.js +0 -1
  77. package/models.generated/abstract-model.d.ts +0 -23
  78. package/models.generated/abstract-model.js +0 -1
  79. package/models.generated/smart-db-core-table-model.d.ts +0 -41
  80. package/models.generated/smart-db-core-table-model.js +0 -1
  81. package/models.generated/smart-db-dictionary.d.ts +0 -14
  82. package/models.generated/smart-db-dictionary.js +0 -1
  83. package/models.generated/smart-db-log-model.d.ts +0 -82
  84. package/models.generated/smart-db-log-model.js +0 -1
  85. package/models.generated/smart-db-user-tab-columns-view-model.js +0 -1
  86. package/models.generated/smart-db-version-model.d.ts +0 -82
  87. package/models.generated/smart-db-version-model.js +0 -1
  88. package/models.generated/smart-db-version-view-model.d.ts +0 -90
  89. package/models.generated/smart-db-version-view-model.js +0 -1
  90. package/smart-db-log.d.ts +0 -40
  91. package/smart-db-log.js +0 -1
@@ -1 +1 @@
1
- import _ from"lodash";import{SqlFieldOperationType,SqlOperationType}from"./smart-db-interfaces";export const OP=(e,t,o,p)=>o?{operation:e,value:t,key:o,literalOperation:p}:{operation:e,value:t};export const VALUE=(e,t,o)=>({operation:SqlFieldOperationType.VALUE,value:e,alias:t,literal:o});export const FIELD=(e,t)=>({operation:SqlFieldOperationType.FIELD,value:e,alias:t});export const COUNT=(e,t)=>({operation:SqlFieldOperationType.COUNT,value:e,alias:t});export const COALESCE=(e,t)=>({operation:SqlFieldOperationType.COALESCE,value:e,alias:t});export const NVL=(e,t)=>COALESCE(e,t);export const LITERAL=(e,t,o)=>OP(SqlOperationType.LITERAL,t,e,o||SqlOperationType.EQ);export const GT=e=>OP(SqlOperationType.GT,e);export const GE=e=>OP(SqlOperationType.GE,e);export const LT=e=>OP(SqlOperationType.LT,e);export const LE=e=>OP(SqlOperationType.LE,e);export const EQ=e=>OP(SqlOperationType.EQ,e);export const NE=e=>OP(SqlOperationType.NE,e);export const IN=e=>OP(SqlOperationType.IN,e);export const NOT_IN=e=>OP(SqlOperationType.NOT_IN,e);export const IS_NULL=()=>OP(SqlOperationType.IS_NULL);export const IS_NOT_NULL=()=>OP(SqlOperationType.IS_NOT_NULL);export const LIKE=e=>OP(SqlOperationType.LIKE,e);export const NOT_LIKE=e=>OP(SqlOperationType.NOT_LIKE,e);export const SmartDbDateRegexp=/^(\d{4}-[01]\d-[0-3]\d [0-2]\d:[0-5]\d:[0-5]\d)(Z| GMT| GMT[-+]\d{1,2})?$/;export const SmartDbTimestampRegexp=/^(\d{4}-[01]\d-[0-3]\d [0-2]\d:[0-5]\d:[0-5]\d\.\d{3})(Z| GMT| GMT[-+]\d{1,2})?$/;export function toSmartDbDate(e){let t;return e&&(_.isNumber(e)&&(e=new Date(e)),t=e.toISOString().substr(0,19).replace("T"," ")),t}export function toSmartDbTimestamp(e){let t;return e&&(_.isNumber(e)&&(e=new Date(e)),t=e.toISOString().substr(0,23).replace("T"," ")),t}export function smartDbToDate(e){let t=null;return _.isDate(e)?t=e:(_.isNumber(e)||_.isString(e)&&(e.match(SmartDbDateRegexp)||e.match(SmartDbTimestampRegexp)))&&(t=new Date(e)),t}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.validDateTimeFormats=exports.SmartDbTimestampRegexp=exports.SmartDbDateRegexp=exports.NOT_LIKE=exports.LIKE=exports.IS_NOT_NULL=exports.IS_NULL=exports.NOT_IN=exports.IN=exports.NE=exports.EQ=exports.LE=exports.LT=exports.GE=exports.BETWEEN=exports.GT=exports.LITERAL=exports.NVL=exports.COALESCE=exports.AVG=exports.SUM=exports.MIN=exports.MAX=exports.COUNT_FIELD=exports.COUNT=exports.FIELD=exports.VALUE=exports.OP=void 0,exports.toSmartDbDate=toSmartDbDate,exports.toSmartDbTimestamp=toSmartDbTimestamp,exports.toSmartZoneTimestamp=toSmartZoneTimestamp,exports.smartDbToDate=smartDbToDate,exports.smartDbToDateTime=smartDbToDateTime;var smart_db_interfaces_1=require("./smart-db-interfaces"),luxon_1=require("luxon"),OP=function(e,t,r){return r?{operation:e,value:t,literalOperation:r}:{operation:e,value:t}};exports.OP=OP;var VALUE=function(e,t,r){return{operation:smart_db_interfaces_1.SqlFieldOperationType.VALUE,value:e,alias:t,literal:r}};exports.VALUE=VALUE;var FIELD=function(e,t){return{operation:smart_db_interfaces_1.SqlFieldOperationType.FIELD,value:e,alias:t}};exports.FIELD=FIELD;var COUNT=function(e,t){return{operation:smart_db_interfaces_1.SqlFieldOperationType.COUNT,value:e,alias:t}};exports.COUNT=COUNT;var COUNT_FIELD=function(e,t){return{operation:smart_db_interfaces_1.SqlFieldOperationType.COUNT_FIELD,value:e,alias:t}};exports.COUNT_FIELD=COUNT_FIELD;var MAX=function(e,t){return{operation:smart_db_interfaces_1.SqlFieldOperationType.MAX,value:e,alias:t}};exports.MAX=MAX;var MIN=function(e,t){return{operation:smart_db_interfaces_1.SqlFieldOperationType.MIN,value:e,alias:t}};exports.MIN=MIN;var SUM=function(e,t){return{operation:smart_db_interfaces_1.SqlFieldOperationType.SUM,value:e,alias:t}};exports.SUM=SUM;var AVG=function(e,t){return{operation:smart_db_interfaces_1.SqlFieldOperationType.AVG,value:e,alias:t}};exports.AVG=AVG;var COALESCE=function(e,t){return{operation:smart_db_interfaces_1.SqlFieldOperationType.COALESCE,value:e,alias:t}};exports.COALESCE=COALESCE;var NVL=function(e,t){return(0,exports.COALESCE)(e,t)};exports.NVL=NVL;var LITERAL=function(e,t){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.LITERAL,e,t)};exports.LITERAL=LITERAL;var GT=function(e){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.GT,e)};exports.GT=GT;var BETWEEN=function(e,t){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.BETWEEN,[e,t])};exports.BETWEEN=BETWEEN;var GE=function(e){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.GE,e)};exports.GE=GE;var LT=function(e){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.LT,e)};exports.LT=LT;var LE=function(e){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.LE,e)};exports.LE=LE;var EQ=function(e){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.EQ,e)};exports.EQ=EQ;var NE=function(e){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.NE,e)};exports.NE=NE;var IN=function(e){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.IN,e)};exports.IN=IN;var NOT_IN=function(e){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.NOT_IN,e)};exports.NOT_IN=NOT_IN;var IS_NULL=function(){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.IS_NULL)};exports.IS_NULL=IS_NULL;var IS_NOT_NULL=function(){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.IS_NOT_NULL)};exports.IS_NOT_NULL=IS_NOT_NULL;var LIKE=function(e){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.LIKE,e)};exports.LIKE=LIKE;var NOT_LIKE=function(e){return(0,exports.OP)(smart_db_interfaces_1.SqlOperationType.NOT_LIKE,e)};function toSmartDbDate(e,t,r){if(!e)throw"no date given to toSmartDbDate()";var o=void 0;return o="number"==typeof e?luxon_1.DateTime.fromMillis(e,{zone:t}):e instanceof Date?luxon_1.DateTime.fromJSDate(e,{zone:t}):e,t&&r?"UTC"==t.toUpperCase()||"GMT"==t.toUpperCase()?o.toFormat("yyyy-MM-dd HH:mm:ss")+"Z":o.toFormat("yyyy-MM-dd HH:mm:ssZZ"):o.toFormat("yyyy-MM-dd HH:mm:ss")}function toSmartDbTimestamp(e,t){var r=smartDbToDateTime(null!=e?e:new Date);return t?r.setZone(t).toFormat("yyyy-MM-dd HH:mm:ss.uZZ").replace("+00:00","Z"):r.toFormat("yyyy-MM-dd HH:mm:ss.u")}function toSmartZoneTimestamp(e,t,r){var o=null;if(e){var a=void 0;a="number"==typeof e?luxon_1.DateTime.fromMillis(e,{zone:t}):e instanceof Date?luxon_1.DateTime.fromJSDate(e,{zone:t}):e.setZone(t),o=r?a.toFormat("yyyy-MM-dd HH:mm:ss.u"):a.toFormat("yyyy-MM-dd HH:mm:ss.uZZ").replace("+00:00","Z")}return o}function smartDbToDate(e,t){var r=smartDbToDateTime(e,t);return r&&r.isValid?r.toJSDate():null}function smartDbToDateTime(e,t){var r=null;if(e)if("number"==typeof e)r=luxon_1.DateTime.fromMillis(e,{zone:t});else if("string"==typeof e){var o=exports.validDateTimeFormats.find(function(t){return luxon_1.DateTime.fromFormat(e,t).isValid});o&&(r=luxon_1.DateTime.fromFormat(e,o,{zone:t}))}else r=e instanceof Date?luxon_1.DateTime.fromJSDate(e,{zone:t}):e.setZone(t);return r}exports.NOT_LIKE=NOT_LIKE,exports.SmartDbDateRegexp=/^(\d{4}-[01]\d-[0-3]\d [0-2]\d:[0-5]\d:[0-5]\d)(Z|[+-]\d\d:\d\d)?$/,exports.SmartDbTimestampRegexp=/^(\d{4}-[01]\d-[0-3]\d [0-2]\d:[0-5]\d:[0-5]\d\.\d{3})(Z|[+-]\d\d:\d\d)?$/,exports.validDateTimeFormats=["yyyy-MM-dd","yyyy-MM-ddZZ","yyyy-MM-dd HH:mm:ss","yyyy-MM-dd HH:mm:ssZZ","yyyy-MM-dd HH:mm:ss.u","yyyy-MM-dd HH:mm:ss.uZZ","yyyy-MM-dd'T'HH:mm:ss","yyyy-MM-dd'T'HH:mm:ssZZ","yyyy-MM-dd'T'HH:mm:ss.u","yyyy-MM-dd'T'HH:mm:ss.uZZ"];
@@ -1,35 +1,129 @@
1
+ import { Observable } from "rxjs";
1
2
  import { AbstractModel } from "./models/abstract-model";
3
+ import { SmartDbVersionViewModel } from "./models/smart-db-version-view-model";
2
4
  import { SmartDbDictionary } from "./models/smart-db-dictionary";
3
- export interface SmartDbOptions {
4
- module: string;
5
- sqlFilesDirectory: string;
6
- smartDbDictionary?: typeof SmartDbDictionary | any[];
5
+ import { SmartDb } from "./smart-db";
6
+ import { SmartLog, SmartLogOptions } from "@egi/smart-log";
7
+ import { SmartDbSqlBuildData } from "./smart-db-sql-build-data";
8
+ import { SmartError } from "./smart-error";
9
+ import { SmartDbDateTimeMode, SmartToolOptions } from "./smart-tools";
10
+ /**
11
+ * Lifecycle states of a {@link SmartDb} database connection.
12
+ * - `INIT` — object created, connection not yet attempted.
13
+ * - `PREPARING` — driver is establishing the connection.
14
+ * - `CONNECTED` — connection established; schema upgrades may still be running.
15
+ * - `READY` — fully initialized and ready for queries.
16
+ * - `CLOSED` — connection has been closed.
17
+ * - `ERROR` — initialization or connection failed; check {@link SmartDb.lastError}.
18
+ */
19
+ export declare enum SmartDbReadyState {
20
+ INIT = 0,
21
+ PREPARING = 1,
22
+ CONNECTED = 2,
23
+ READY = 3,
24
+ CLOSED = 4,
25
+ ERROR = 5
26
+ }
27
+ export interface ModelClass<T> {
28
+ attributeMap: ModelAttributeMap;
29
+ new (): T;
30
+ getClassName(): string;
31
+ getTableName(): string;
32
+ getPkSequenceName(): string;
33
+ getPrimaryKey(): string;
34
+ from(other: any): any;
35
+ getPrimaryKeyName(): string;
36
+ }
37
+ export interface DbDictionaryEntry {
38
+ cls: ModelClass<any>;
39
+ }
40
+ /** Configuration options passed to the {@link SmartDb} constructor. */
41
+ export interface SmartDbOptions<T extends SmartDb<T>> extends SmartToolOptions {
42
+ /** When `true`, skip schema upgrades and only establish the connection (sets state to READY after CONNECTED). */
43
+ connectOnly?: boolean;
44
+ /** When `true`, do not call {@link SmartDb.initDb} from the constructor. Call it manually later. */
45
+ delayInit?: boolean;
46
+ /** When `true`, persists log entries to the `smart_db_log` database table once it exists. */
47
+ dbLogging?: boolean;
48
+ /** Logging configuration (log level, format, etc.). */
49
+ logOptions?: SmartLogOptions;
50
+ /**
51
+ * One or more module names to initialize via the upgrade manager.
52
+ * Each module must have a corresponding `${module}-init.sql` file in the SQL assets directory.
53
+ */
54
+ module?: string | string[];
55
+ /** When `true`, LIKE patterns with `%` or `_` emit an explicit `ESCAPE '\\'` clause (needed for Oracle). */
56
+ needsExplicitEscape?: boolean;
57
+ /**
58
+ * Callback invoked once the database reaches READY state (or ERROR).
59
+ * Receives the database instance and an error object if initialization failed.
60
+ */
61
+ onReady?: (db: T, error?: any) => void;
62
+ /** When `true`, suppress all log output (sets log level to Fatal). */
63
+ silent?: boolean;
64
+ /** When `true`, skip automatic schema upgrades during {@link SmartDb.initDb}. */
7
65
  skipAutoUpgrade?: boolean;
66
+ /** One or more dictionary classes providing default data for lookup tables. */
67
+ smartDbDictionary?: typeof SmartDbDictionary | (typeof SmartDbDictionary)[];
68
+ /** Directory path where SQL upgrade script files are located. Defaults to the built-in assets directory. */
69
+ sqlFilesDirectory?: string;
8
70
  }
71
+ /** Result returned by INSERT/UPDATE/DELETE statement execution. */
9
72
  export interface SmartDbRunResult {
10
- lastId: number;
11
- changes: number;
73
+ /** Number of rows affected by the statement (alias for `changes` on some drivers). */
12
74
  affected: number;
75
+ /** Number of rows changed by the statement. */
76
+ changes: number;
77
+ /** Auto-generated primary key of the last inserted row (0 for UPDATE/DELETE). */
78
+ lastId: number;
13
79
  }
80
+ /** Metadata about a database table returned by {@link SmartDb.getTableInfo}. */
14
81
  export interface SmartDbTableInfo {
15
- name: string;
82
+ /** Descriptions of each column in the table. */
16
83
  fields: SmartDbFieldDescription[];
84
+ /** The table name as it appears in the database. */
85
+ name: string;
86
+ /** For Oracle: the sequence name used to generate PK values, if any. */
87
+ pkSequenceName?: string;
17
88
  }
89
+ /** Metadata about a single column in a database table. */
18
90
  export interface SmartDbFieldDescription {
91
+ /** Column index (used by SQLite). */
19
92
  cid?: string | number;
20
- name: string;
21
- type: string;
22
- virtual?: boolean;
23
- notNull?: boolean;
93
+ /** Full database type string including precision/scale, e.g. `"VARCHAR2(100)"`. */
94
+ dbFullType: string;
95
+ /** Base database type, e.g. `"VARCHAR2"`, `"INTEGER"`, `"DATE"`. */
96
+ dbType: string;
97
+ /** Default value for the column, if any. */
24
98
  defaultValue?: number | string | boolean;
99
+ /** `true` if this column is (part of) the primary key. */
25
100
  isPk?: boolean;
101
+ /** Column name as it appears in the database. */
102
+ name: string;
103
+ /** `true` if the column has a NOT NULL constraint. */
104
+ notNull?: boolean;
105
+ /** `true` if this is a virtual/computed column. */
106
+ virtual?: boolean;
26
107
  }
108
+ /** Describes a field-to-field or field-to-value comparison used inside a {@link SqlWhere} `expression` clause. */
27
109
  export interface SmartDbSqlComparison {
110
+ /** The left-hand side of the comparison: a column name or a {@link SqlFieldDescriptor}. */
28
111
  compare: string | SqlFieldDescriptor;
29
- with: string | SqlFieldDescriptor;
112
+ /** The comparison operator. Defaults to `EQ` (`=`) when omitted. */
30
113
  operation?: SqlOperationType;
114
+ /** The right-hand side: a scalar value or a {@link SqlFieldDescriptor}. */
115
+ with: SqlValueType | SqlFieldDescriptor;
31
116
  }
32
- export declare type SqlValueType = string | number | boolean | Date;
117
+ /** Scalar value types accepted as SQL parameter values. */
118
+ export type SqlValueType = string | number | boolean | Date | null;
119
+ /** Names of value types accepted as SQL parameter values. */
120
+ export type SqlValueTypes = "string" | "number" | "boolean" | "Date" | "any" | "clob" | "SqlValueType";
121
+ /**
122
+ * Controls how column names are styled in query results.
123
+ * - `Database` — original column names as returned by the database (e.g. `CREATED_AT`).
124
+ * - `TypeScript` — camelCase aliases defined in the model's attribute map (e.g. `createdAt`).
125
+ * - `All` — both styles are included in the result objects.
126
+ */
33
127
  export declare enum FieldNamingStyle {
34
128
  Database = 0,
35
129
  TypeScript = 1,
@@ -39,58 +133,143 @@ export interface GenericModelData {
39
133
  [key: string]: any;
40
134
  }
41
135
  export interface AttributeInfo {
42
- attribute: string;
43
- type: string;
44
136
  alias?: string;
45
- physical?: boolean;
46
- virtual?: boolean;
47
137
  alternative?: boolean;
138
+ attribute: string;
139
+ dbFullType?: string;
140
+ dbType?: string;
141
+ physical?: boolean;
142
+ type: SqlValueTypes;
48
143
  typeScriptStyle?: boolean;
144
+ virtual?: boolean;
145
+ }
146
+ export interface ModelDbOptions {
147
+ dateTimeMode?: SmartDbDateTimeMode;
148
+ useNativeDate?: boolean;
149
+ }
150
+ export interface MakeDbValueOptions extends ModelDbOptions {
151
+ dbFullType?: string;
49
152
  }
50
153
  export interface ModelAttributeMap {
51
154
  [key: string]: AttributeInfo;
52
155
  }
53
156
  export interface AbstractModelGlobals<T extends AbstractModel<T, D>, D extends GenericModelData> {
54
157
  attributeMap: ModelAttributeMap;
55
- getTableName: () => string;
56
158
  from: (other: T | D) => T;
159
+ getTableName: () => string;
57
160
  }
161
+ /**
162
+ * Recursive WHERE clause builder.
163
+ *
164
+ * Each key in the object is interpreted as a column name whose value must match,
165
+ * unless it is one of the reserved keys below:
166
+ *
167
+ * - `and` — sub-clause(s) joined with `AND`.
168
+ * - `or` — sub-clause(s) joined with `OR`.
169
+ * - `expression` — array of {@link SmartDbSqlComparison} for field-to-field comparisons.
170
+ *
171
+ * Plain key/value pairs generate equality conditions (or `LIKE` when the value contains `%`/`_`).
172
+ * Pass a {@link SqlOperation} object as the value for other operators (GT, IN, IS NULL, etc.).
173
+ * Pass an array as the value to generate an `IN (...)` condition automatically.
174
+ * Pass `null` as the value to generate an `IS NULL` condition.
175
+ *
176
+ * @example
177
+ * ```ts
178
+ * // WHERE status = 'active' AND age >= 18
179
+ * const where: SqlWhere = {
180
+ * status: 'active',
181
+ * age: { operation: SqlOperationType.GE, value: 18 }
182
+ * };
183
+ * ```
184
+ */
58
185
  export interface SqlWhere {
59
- or?: SqlWhere | SqlWhere[];
60
186
  and?: SqlWhere | SqlWhere[];
61
187
  expression?: SmartDbSqlComparison[];
188
+ or?: SqlWhere | SqlWhere[];
62
189
  [key: string]: SqlValueType | SqlValueType[] | SqlOperation | SqlWhere | SqlWhere[] | SmartDbSqlComparison[];
63
190
  }
64
- export declare type SqlUpdateValues = GenericModelData;
65
- export declare type SqlOrderBy = string | string[];
66
- declare type SqlGroupBy = string | string[];
191
+ /** A plain object of `{columnName: value}` pairs used for INSERT and UPDATE values. */
192
+ export type SqlUpdateValues = GenericModelData;
193
+ /**
194
+ * ORDER BY specification. A single field name, optionally suffixed with `ASC` or `DESC`,
195
+ * or an array of such strings for multi-column ordering.
196
+ * @example `"name DESC"` or `["lastName ASC", "firstName ASC"]`
197
+ */
198
+ export type SqlOrderBy = string | string[];
199
+ type SqlGroupBy = string | string[];
200
+ /** LIMIT and OFFSET values for paginating query results. */
67
201
  export interface SqlLimit {
68
- offset?: number;
202
+ /** Maximum number of rows to return. */
69
203
  limit?: number;
204
+ /** Number of rows to skip before returning results. */
205
+ offset?: number;
70
206
  }
207
+ /**
208
+ * Describes one section of a UNION / INTERSECT / MINUS set operation.
209
+ * Used in the `union`, `intersect`, and `minus` arrays of {@link SmartDbSqlOptions}.
210
+ */
71
211
  export interface SectionDescription<T extends AbstractModel<T, D>, D extends GenericModelData> {
72
- model: (new () => T) | string;
73
- where?: SqlWhere;
212
+ /** Fields to SELECT in this section. */
74
213
  fields?: string | SqlFieldDescriptor | (string | SqlFieldDescriptor)[] | null;
214
+ /** GROUP BY clause for this section. */
75
215
  groupBy?: SqlGroupBy;
216
+ /** LIMIT/OFFSET for this section. */
76
217
  limit?: SqlLimit;
218
+ /** The model class or table name for this section. */
219
+ model: ModelClass<T> | string;
220
+ /** WHERE clause for this section. */
221
+ where?: SqlWhere;
77
222
  }
223
+ /**
224
+ * Full set of options for {@link SmartDb.get} and related query methods.
225
+ *
226
+ * @typeParam T - The model class (extends {@link AbstractModel}).
227
+ * @typeParam D - The plain data interface for the model.
228
+ */
78
229
  export interface SmartDbSqlOptions<T extends AbstractModel<T, D>, D extends GenericModelData> {
79
- firstOnly?: boolean;
80
- where?: SqlWhere;
81
- fields?: string | SqlFieldDescriptor | (string | SqlFieldDescriptor)[] | null;
82
- orderBy?: SqlOrderBy;
83
- groupBy?: SqlGroupBy;
84
- limit?: SqlLimit;
230
+ /**
231
+ * When `true`, a multi-column result row is collapsed into a single value
232
+ * (useful when SELECTing a single aggregate column).
233
+ */
234
+ collapseRow?: boolean;
235
+ /** When `true`, wraps the field list in `COUNT(...)` and returns a numeric count. */
85
236
  count?: boolean;
237
+ /** When `true`, adds `DISTINCT` to the SELECT clause. */
86
238
  distinct?: boolean;
87
- collapseRow?: boolean;
239
+ /**
240
+ * Fields to SELECT. Accepts a comma-separated string, a single field name,
241
+ * a {@link SqlFieldDescriptor}, or an array of field names/descriptors.
242
+ * Pass `null` or omit to select all columns (`*`).
243
+ */
244
+ fields?: string | SqlFieldDescriptor | (string | SqlFieldDescriptor)[] | null;
245
+ /** When `true`, returns only the first result row instead of an array. */
246
+ firstOnly?: boolean;
247
+ /** GROUP BY clause: a field name or array of field names. */
248
+ groupBy?: SqlGroupBy;
249
+ /** HAVING clause applied after GROUP BY. Uses the same {@link SqlWhere} syntax. */
250
+ having?: SqlWhere;
251
+ /** SQLite `INDEXED BY` hint to force use of a specific index. */
88
252
  indexedBy?: string;
89
- union?: SectionDescription<T, D> | SectionDescription<T, D>[];
90
- minus?: SectionDescription<T, D> | SectionDescription<T, D>[];
253
+ /** One or more INTERSECT sections to append to the query. */
91
254
  intersect?: SectionDescription<T, D> | SectionDescription<T, D>[];
255
+ /** LIMIT and OFFSET for pagination. */
256
+ limit?: SqlLimit;
257
+ /** One or more MINUS (EXCEPT) sections to append to the query. */
258
+ minus?: SectionDescription<T, D> | SectionDescription<T, D>[];
259
+ /** ORDER BY clause: a field name (optionally with `ASC`/`DESC`) or array of field names. */
260
+ orderBy?: SqlOrderBy;
261
+ /** Controls whether results use database column names or camelCase TypeScript aliases. */
92
262
  style?: FieldNamingStyle;
263
+ /** One or more UNION sections to append to the query. */
264
+ union?: SectionDescription<T, D> | SectionDescription<T, D>[];
265
+ /** WHERE clause to filter results. */
266
+ where?: SqlWhere;
93
267
  }
268
+ /**
269
+ * SQL comparison operators used in {@link SqlOperation} and {@link SmartDbSqlComparison}.
270
+ * Use the helper functions from `smart-db-globals` (e.g. `OP()`, `IN()`, `LITERAL()`)
271
+ * to construct {@link SqlOperation} objects rather than building them manually.
272
+ */
94
273
  export declare enum SqlOperationType {
95
274
  GT = ">",
96
275
  GE = ">=",
@@ -105,25 +284,58 @@ export declare enum SqlOperationType {
105
284
  IS_NULL = "IS NULL",
106
285
  IS_NOT_NULL = "IS NOT NULL",
107
286
  LITERAL = "LITERAL",
287
+ BETWEEN = "BETWEEN",
108
288
  VALUE = "VALUE"
109
289
  }
290
+ /**
291
+ * Aggregate/field operations used in {@link SqlFieldDescriptor} for SELECT field expressions.
292
+ * Use the helper functions `COUNT()`, `SUM()`, `AVG()`, `MIN()`, `MAX()`, `FIELD()`, `VALUE()`
293
+ * from `smart-db-globals` to create descriptors.
294
+ */
110
295
  export declare enum SqlFieldOperationType {
111
296
  VALUE = "VALUE",
112
297
  FIELD = "FIELD",
113
298
  COUNT = "COUNT",
299
+ MIN = "MIN",
300
+ MAX = "MAX",
301
+ AVG = "AVG",
302
+ SUM = "SUM",
303
+ COUNT_FIELD = "COUNT_FIELD",
114
304
  COALESCE = "COALESCE"
115
305
  }
306
+ /**
307
+ * Describes a SELECT field expression such as an aggregate function or aliased column.
308
+ * Construct instances using the helper functions exported from `smart-db-globals`:
309
+ * `COUNT()`, `SUM()`, `AVG()`, `MIN()`, `MAX()`, `FIELD()`, `VALUE()`.
310
+ */
116
311
  export interface SqlFieldDescriptor {
117
- operation: SqlFieldOperationType;
118
- value: SqlFieldDescriptor | SqlValueType | (SqlFieldDescriptor | SqlValueType)[];
312
+ /** Optional SQL alias (`AS alias`) for the expression. */
119
313
  alias?: string;
314
+ /** When `true`, the `value` is emitted verbatim into SQL without quoting or translation. */
120
315
  literal?: boolean;
316
+ /** The aggregate or field operation to apply. */
317
+ operation: SqlFieldOperationType;
318
+ /** The operand(s) for the operation: a field name, scalar value, or nested descriptor. */
319
+ value: SqlFieldDescriptor | SqlValueType | (SqlFieldDescriptor | SqlValueType)[];
121
320
  }
321
+ /**
322
+ * A WHERE condition with an explicit operator.
323
+ * Used as the value for a column key in a {@link SqlWhere} object.
324
+ * Prefer the helper functions `OP()`, `IN()`, `NE()`, `LITERAL()` from `smart-db-globals`.
325
+ *
326
+ * @example
327
+ * ```ts
328
+ * // WHERE age BETWEEN 18 AND 65
329
+ * const where: SqlWhere = { age: { operation: SqlOperationType.BETWEEN, value: [18, 65] } };
330
+ * ```
331
+ */
122
332
  export interface SqlOperation {
333
+ /** For LITERAL operations: the operator to use before the literal value. Defaults to `EQ`. */
334
+ literalOperation?: SqlOperationType;
335
+ /** The comparison operator. */
123
336
  operation: SqlOperationType;
337
+ /** The value(s) to compare against. Use an array for IN/NOT_IN and BETWEEN. */
124
338
  value: SqlValueType | SqlValueType[];
125
- key?: string;
126
- literalOperation?: SqlOperationType;
127
339
  }
128
340
  export interface KeyValueList {
129
341
  [key: string]: SqlValueType;
@@ -135,8 +347,86 @@ export interface SmartDbSqlBuildDataResults {
135
347
  sql: string;
136
348
  values: SqlValueType[];
137
349
  }
138
- export interface SmartDbDatabase {
139
- }
140
350
  export interface SmartDbConnector {
141
351
  }
352
+ /**
353
+ * Public interface of {@link SmartDb}.
354
+ * Describes all methods and properties available to consumers of any SmartDB driver.
355
+ */
356
+ export interface SmartDbInterface {
357
+ /** `true` when SQL statements are being written to the database log table. */
358
+ readonly dbLogging: boolean;
359
+ /** `true` when the database connection has been established (CONNECTED or later). */
360
+ readonly isConnected: boolean;
361
+ /** `true` when the database is fully initialized and ready for queries. */
362
+ readonly isReady: boolean;
363
+ /** The last error that occurred during initialization or query execution. */
364
+ lastError: SmartError;
365
+ /** Observable that emits every time the ready-state changes. */
366
+ readonly onReady: Observable<SmartDbReadyState>;
367
+ /** Current lifecycle state of the database connection. */
368
+ readonly readyState: SmartDbReadyState;
369
+ /** `true` when the driver supports synchronous calls (SQLite only). */
370
+ readonly supportSyncCalls: boolean;
371
+ /** Active date/time conversion mode for this connection. */
372
+ readonly dateTimeMode: SmartDbDateTimeMode;
373
+ /** Returns a string identifying the database type, e.g. `"sqlite"`, `"mysql"`, `"oracle"`. */
374
+ getDatabaseType(): string;
375
+ /** Returns metadata about the columns of a database table. */
376
+ getTableInfo(table: string): Promise<SmartDbTableInfo>;
377
+ /** Returns the raw underlying driver connection object. */
378
+ getDb(): any;
379
+ /** Returns the current SmartDb options. */
380
+ getOptions(): SmartDbOptions<any>;
381
+ /** Resolves when the database reaches `targetState` (defaults to READY). */
382
+ databaseReady(targetState?: SmartDbReadyState): Promise<SmartDbReadyState>;
383
+ /** Runs schema upgrade scripts and marks the database as READY. */
384
+ initDb(): Promise<SmartDbVersionViewModel[]>;
385
+ /** Closes the connection asynchronously. */
386
+ close(): Promise<boolean>;
387
+ /** Closes the connection synchronously. */
388
+ closeSync(): boolean;
389
+ commit(): Promise<void>;
390
+ commitSync(): void;
391
+ rollback(): Promise<void>;
392
+ rollbackSync(): void;
393
+ hasTransaction(): boolean;
394
+ hasConcurrentTransactions(): boolean;
395
+ get<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, options: SmartDbSqlOptions<T, D>): Promise<(T | D)[] | T | D | SqlValueType | IndexedGenericModelData<T, D> | string | string[] | false>;
396
+ /** Returns the first matching model instance. Alias for `get()` with `firstOnly: true`. */
397
+ async<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, options: SmartDbSqlOptions<T, D>): Promise<T>;
398
+ getFirst<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, where?: SqlWhere, fields?: SqlFieldDescriptor | string | (SqlFieldDescriptor | string)[] | null, orderBy?: SqlOrderBy): Promise<T>;
399
+ getAll<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy, limit?: SqlLimit): Promise<T[]>;
400
+ getAllWithOptions<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, options: SmartDbSqlOptions<T, D>): Promise<T[]>;
401
+ insert<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, values: SqlUpdateValues | T): Promise<number>;
402
+ update<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, values: SqlUpdateValues | T, where?: SqlWhere): Promise<number>;
403
+ delete<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, where?: SqlWhere): Promise<number>;
404
+ exists<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, type?: "view" | "table" | "index", indexTableName?: string): Promise<boolean>;
405
+ getSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, options: SmartDbSqlOptions<T, D>): (T | D)[] | T | D | SqlValueType | IndexedGenericModelData<T, D> | string | string[] | false;
406
+ getFirstSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, where?: SqlWhere, fields?: SqlFieldDescriptor | string | (SqlFieldDescriptor | string)[] | null, orderBy?: SqlOrderBy): T | false;
407
+ getFirstWithOptionsSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, options: SmartDbSqlOptions<T, D>): T | false;
408
+ getAllSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy, limit?: SqlLimit): T[] | false;
409
+ getAllWithOptionsSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, options: SmartDbSqlOptions<T, D>): T[] | false;
410
+ insertSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, values: SqlUpdateValues | T): number | false;
411
+ updateSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, values: SqlUpdateValues | T, where?: SqlWhere): number | false;
412
+ deleteSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, where?: SqlWhere): number | false;
413
+ existsSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, type?: "view" | "table" | "index", indexTableName?: string): boolean;
414
+ exec(script: string, params?: SqlValueType[]): Promise<void>;
415
+ execSync(script: string, params?: SqlValueType[]): boolean;
416
+ execScript(script: string, ignoreDropError?: boolean): Promise<void>;
417
+ execScriptSync(script: string): void;
418
+ query(script: string, params?: SqlValueType[]): Promise<GenericModelData[]>;
419
+ querySync(script: string, params?: SqlValueType[]): GenericModelData[];
420
+ buildSelectStatement<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, options: SmartDbSqlOptions<T, D>): SmartDbSqlBuildData;
421
+ getDbConnector(): string | SmartDbConnector;
422
+ getDbQuote(): string;
423
+ getLastBuildData<T extends AbstractModel<T, D>, D extends GenericModelData>(): SmartDbSqlBuildData;
424
+ getLastError(): SmartError;
425
+ getLogger(): SmartLog;
426
+ getModuleVersions(): SmartDbVersionViewModel[];
427
+ makeDbValue(value: SqlValueType, options?: MakeDbValueOptions): SqlValueType;
428
+ toDate(d: Date | number | string): Date | null;
429
+ toDbDate(d: Date | number): string;
430
+ toDbTimestamp(d: Date | number): string;
431
+ }
142
432
  export {};
@@ -1 +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.NOT_IN="NOT 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={}));
1
+ "use strict";var SmartDbReadyState,FieldNamingStyle,SqlOperationType,SqlFieldOperationType;Object.defineProperty(exports,"__esModule",{value:!0}),exports.SqlFieldOperationType=exports.SqlOperationType=exports.FieldNamingStyle=exports.SmartDbReadyState=void 0,function(e){e[e.INIT=0]="INIT",e[e.PREPARING=1]="PREPARING",e[e.CONNECTED=2]="CONNECTED",e[e.READY=3]="READY",e[e.CLOSED=4]="CLOSED",e[e.ERROR=5]="ERROR"}(SmartDbReadyState||(exports.SmartDbReadyState=SmartDbReadyState={})),function(e){e[e.Database=0]="Database",e[e.TypeScript=1]="TypeScript",e[e.All=2]="All"}(FieldNamingStyle||(exports.FieldNamingStyle=FieldNamingStyle={})),function(e){e.GT=">",e.GE=">=",e.LT="<",e.LE="<=",e.EQ="=",e.NE="!=",e.IN="IN",e.NOT_IN="NOT 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.BETWEEN="BETWEEN",e.VALUE="VALUE"}(SqlOperationType||(exports.SqlOperationType=SqlOperationType={})),function(e){e.VALUE="VALUE",e.FIELD="FIELD",e.COUNT="COUNT",e.MIN="MIN",e.MAX="MAX",e.AVG="AVG",e.SUM="SUM",e.COUNT_FIELD="COUNT_FIELD",e.COALESCE="COALESCE"}(SqlFieldOperationType||(exports.SqlFieldOperationType=SqlFieldOperationType={}));
@@ -1,8 +1,17 @@
1
1
  import { SmartDbSqlBuildDataResults, SqlValueType } from "./smart-db-interfaces";
2
+ export declare enum SmartDbSqlBuildDataType {
3
+ Select = 0,
4
+ Insert = 1,
5
+ Update = 2,
6
+ Delete = 3,
7
+ Other = 4
8
+ }
2
9
  export declare class SmartDbSqlBuildData {
10
+ modelName: string;
3
11
  sql: string;
12
+ type: SmartDbSqlBuildDataType;
4
13
  values: SqlValueType[];
5
- constructor(sql?: string, values?: SqlValueType[]);
14
+ constructor(sql?: string, modelName?: string, values?: SqlValueType[]);
6
15
  append(data: SmartDbSqlBuildData): void;
7
16
  toString(): string;
8
17
  results(): SmartDbSqlBuildDataResults;
@@ -1 +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}}}
1
+ "use strict";var SmartDbSqlBuildDataType,__read=this&&this.__read||function(t,e){var r="function"==typeof Symbol&&t[Symbol.iterator];if(!r)return t;var a,l,i=r.call(t),s=[];try{for(;(void 0===e||e-- >0)&&!(a=i.next()).done;)s.push(a.value)}catch(t){l={error:t}}finally{try{a&&!a.done&&(r=i.return)&&r.call(i)}finally{if(l)throw l.error}}return s},__spreadArray=this&&this.__spreadArray||function(t,e,r){if(r||2===arguments.length)for(var a,l=0,i=e.length;l<i;l++)!a&&l in e||(a||(a=Array.prototype.slice.call(e,0,l)),a[l]=e[l]);return t.concat(a||Array.prototype.slice.call(e))};Object.defineProperty(exports,"__esModule",{value:!0}),exports.SmartDbSqlBuildData=exports.SmartDbSqlBuildDataType=void 0,function(t){t[t.Select=0]="Select",t[t.Insert=1]="Insert",t[t.Update=2]="Update",t[t.Delete=3]="Delete",t[t.Other=4]="Other"}(SmartDbSqlBuildDataType||(exports.SmartDbSqlBuildDataType=SmartDbSqlBuildDataType={}));var SmartDbSqlBuildData=function(){function t(t,e,r){switch(this.sql=null!=t?t:"",this.sql.substring(0,6)){case"SELECT":this.type=SmartDbSqlBuildDataType.Select;break;case"INSERT":this.type=SmartDbSqlBuildDataType.Insert;break;case"UPDATE":this.type=SmartDbSqlBuildDataType.Update;break;case"DELETE":this.type=SmartDbSqlBuildDataType.Delete;break;default:this.type=SmartDbSqlBuildDataType.Other}this.values=r||[],this.modelName=e}return t.prototype.append=function(t){this.sql=this.sql.trim()+" "+t.sql.trim(),this.values=__spreadArray(__spreadArray([],__read(this.values),!1),__read(t.values),!1)},t.prototype.toString=function(){return this.sql+" <= ("+this.values.join(", ")+")"},t.prototype.results=function(){return{sql:this.sql,values:this.values}},t}();exports.SmartDbSqlBuildData=SmartDbSqlBuildData;
@@ -1,12 +1,14 @@
1
1
  import { SmartDbVersionViewModel } from "./models/smart-db-version-view-model";
2
2
  import { SmartDb } from "./smart-db";
3
- import { SmartDbOptions } from "./smart-db-interfaces";
3
+ import { SmartLog } from "@egi/smart-log";
4
4
  export declare class SmartDbUpgradeManager {
5
5
  private db;
6
- private log;
7
- constructor(db: SmartDb);
6
+ private sqlScriptDirectory;
7
+ constructor(db: SmartDb<any>, sqlScriptDirectory: string);
8
+ get log(): SmartLog;
9
+ setSqlScriptDirectory(dir: string): void;
8
10
  hasDatabaseModule(module: string): Promise<boolean>;
9
- prepareDatabase(options: SmartDbOptions): Promise<SmartDbVersionViewModel>;
11
+ prepareDatabaseModule(module: string): Promise<SmartDbVersionViewModel>;
10
12
  private upgradeDatabase;
11
13
  private executeScriptsSequentially;
12
14
  }
@@ -1 +1 @@
1
- import*as fs from"fs";import _ from"lodash";import{SmartDbVersionModel}from"./models/smart-db-version-model";import{SmartDbVersionViewModel}from"./models/smart-db-version-view-model";import{SmartErrorLocation}from"./smart-error";export class SmartDbUpgradeManager{constructor(e){this.db=e,this.log=e.getLogger()}hasDatabaseModule(e){return new Promise(((t,r)=>{this.db.exists(SmartDbVersionModel).then((a=>{a?this.db.getFirst(SmartDbVersionModel,{module:e}).then((e=>{t(!!e)})).catch((e=>{r(e)})):t(!1)})).catch((e=>{r(e)}))}))}prepareDatabase(e){return new Promise(((t,r)=>{try{const a=fs.existsSync(e.sqlFilesDirectory)&&fs.statSync(e.sqlFilesDirectory);if(a&&a.isDirectory()){const a=e.sqlFilesDirectory+`/${e.module}-init.sql`;fs.existsSync(a)?this.hasDatabaseModule(e.module).then((o=>{o?(this.log.logInfo(SmartErrorLocation.UpgradeManager,"prepareDatabase",`database module '${e.module}' exists`),this.upgradeDatabase(e).then((r=>{this.log.logInfo(SmartErrorLocation.UpgradeManager,"prepareDatabase",`connected to module '${e.module}' version ${r.versionString}`),t(r)})).catch((e=>{r(e)}))):(this.log.setDbLogging(!1),this.log.logInfo(SmartErrorLocation.UpgradeManager,"prepareDatabase",`database module '${e.module}' doesn't exists - begin creation`),this.db.execScript(a,!0).then((()=>{this.log.setDbLogging(this.db.dbLogging),this.log.logInfo(SmartErrorLocation.UpgradeManager,"prepareDatabase","database module creation complete"),this.hasDatabaseModule(e.module).then((a=>{a?(this.log.logInfo(SmartErrorLocation.UpgradeManager,"prepareDatabase",`successfully initialized database for new module ${e.module}`),this.upgradeDatabase(e).then((r=>{this.log.logInfo(SmartErrorLocation.UpgradeManager,"prepareDatabase",`connected to module '${e.module}' version ${r.versionString}`),t(r)})).catch((e=>{r(e)}))):r("error running database initialization script")})).catch((e=>{r(e)}))})).catch((e=>{r(e)})))})).catch((e=>{r(e)})):r(`missing mandatory '${e.module}-init.sql' file in ${a}`)}else r(`option 'sqlFilesDirectory' (${e.sqlFilesDirectory}) must point to an existing directory (absolute or relative to ${fs.realpathSync(".")})`)}catch(e){r(e)}}))}upgradeDatabase(e){return new Promise(((t,r)=>{this.db.getFirst(SmartDbVersionViewModel,{module:e.module}).then((a=>{a?fs.readdir(e.sqlFilesDirectory,((o,s)=>{if(o)r(`unable to read database files from ${e.sqlFilesDirectory}`);else{let o=[];s.forEach((t=>{const r=new RegExp(`^${e.module}-update.([0-9]{3})\\..*\\.sql$`),s=t.match(r);if(s){parseInt(s[1],10)>a.sequence&&o.push(t)}})),o=_.sortBy(o),this.executeScriptsSequentially(o,e).then((()=>{this.db.getFirst(SmartDbVersionViewModel,{module:e.module},"*","sequence DESC").then((e=>{e?t(SmartDbVersionViewModel.from(e)):r("unable to determine final smart db version")})).catch((e=>{r(e)}))})).catch((e=>{r(e)}))}})):r(`missing version entry for module ${e.module} - add the mandatory insert into smart_db_version statement to your database creation script!`)})).catch((e=>{r(e)}))}))}executeScriptsSequentially(e,t){return new Promise((async(r,a)=>{e&&e.length>0?(this.log.logInfo(SmartErrorLocation.UpgradeManager,"upgradeDatabase",`execute update script '${e[0]}' for module ${t.module}`),await this.db.execScript(`${t.sqlFilesDirectory}/${e[0]}`).then((()=>{this.log.logInfo(SmartErrorLocation.UpgradeManager,"upgradeDatabase",`successfully executed update script '${e[0]}' for module ${t.module}`),1==e.length&&r(!0)})).catch((e=>{a(e)})),e.length>1&&this.executeScriptsSequentially(e.splice(1),t).then((e=>{r(e)})).catch((e=>{a(e)}))):r(!0)}))}}
1
+ "use strict";var __awaiter=this&&this.__awaiter||function(e,t,r,a){return new(r||(r=Promise))(function(n,o){function i(e){try{c(a.next(e))}catch(e){o(e)}}function s(e){try{c(a.throw(e))}catch(e){o(e)}}function c(e){var t;e.done?n(e.value):(t=e.value,t instanceof r?t:new r(function(e){e(t)})).then(i,s)}c((a=a.apply(e,t||[])).next())})},__generator=this&&this.__generator||function(e,t){var r,a,n,o={label:0,sent:function(){if(1&n[0])throw n[1];return n[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return i.next=s(0),i.throw=s(1),i.return=s(2),"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(s){return function(c){return function(s){if(r)throw new TypeError("Generator is already executing.");for(;i&&(i=0,s[0]&&(o=0)),o;)try{if(r=1,a&&(n=2&s[0]?a.return:s[0]?a.throw||((n=a.return)&&n.call(a),0):a.next)&&!(n=n.call(a,s[1])).done)return n;switch(a=0,n&&(s=[2&s[0],n.value]),s[0]){case 0:case 1:n=s;break;case 4:return o.label++,{value:s[1],done:!1};case 5:o.label++,a=s[1],s=[0];continue;case 7:s=o.ops.pop(),o.trys.pop();continue;default:if(!(n=o.trys,(n=n.length>0&&n[n.length-1])||6!==s[0]&&2!==s[0])){o=0;continue}if(3===s[0]&&(!n||s[1]>n[0]&&s[1]<n[3])){o.label=s[1];break}if(6===s[0]&&o.label<n[1]){o.label=n[1],n=s;break}if(n&&o.label<n[2]){o.label=n[2],o.ops.push(s);break}n[2]&&o.ops.pop(),o.trys.pop();continue}s=t.call(e,o)}catch(e){s=[6,e],a=0}finally{r=n=0}if(5&s[0])throw s[1];return{value:s[0]?s[1]:void 0,done:!0}}([s,c])}}},__values=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],a=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&a>=e.length&&(e=void 0),{value:e&&e[a++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(exports,"__esModule",{value:!0}),exports.SmartDbUpgradeManager=void 0;var fs=require("fs"),smart_db_version_model_1=require("./models/smart-db-version-model"),smart_db_version_view_model_1=require("./models/smart-db-version-view-model"),path=require("node:path"),smart_log_1=require("@egi/smart-log"),SmartDbUpgradeManager=function(){function e(e,t){this.db=e,this.sqlScriptDirectory=t}return Object.defineProperty(e.prototype,"log",{get:function(){return this.db.getLogger()},enumerable:!1,configurable:!0}),e.prototype.setSqlScriptDirectory=function(e){this.sqlScriptDirectory=e},e.prototype.hasDatabaseModule=function(e){return __awaiter(this,void 0,void 0,function(){var t,r;return __generator(this,function(a){switch(a.label){case 0:return[4,this.db.exists(smart_db_version_model_1.SmartDbVersionModel)];case 1:return t=a.sent(),(r=t)?[4,this.db.getFirst(smart_db_version_model_1.SmartDbVersionModel,{module:e})]:[3,3];case 2:r=!!a.sent(),a.label=3;case 3:return[2,r]}})})},e.prototype.prepareDatabaseModule=function(e){return __awaiter(this,void 0,void 0,function(){var t,r,a;return __generator(this,function(n){switch(n.label){case 0:return(r=fs.existsSync(this.sqlScriptDirectory)&&fs.statSync(this.sqlScriptDirectory))&&r.isDirectory()?(a=this.sqlScriptDirectory+"/".concat(e,"-init.sql"),fs.existsSync(a)?(this.log.debug("check module ".concat(e),{type:smart_log_1.SmartLocation.UpgradeManager}),[4,this.hasDatabaseModule(e)]):[3,10]):[3,12];case 1:return n.sent()?(this.log.info("database module '".concat(e,"' exists"),{type:smart_log_1.SmartLocation.UpgradeManager}),[4,this.upgradeDatabase(e)]):[3,3];case 2:case 7:return t=n.sent(),this.log.info("connected to module '".concat(e,"' version ").concat(t.versionString),{type:smart_log_1.SmartLocation.UpgradeManager}),[3,9];case 3:return this.log.setDbWriter(null),this.log.info("database module '".concat(e,"' doesn't exists - begin creation"),{type:smart_log_1.SmartLocation.UpgradeManager}),[4,this.db.execScript(a,!0)];case 4:return n.sent(),this.log.debug("script executed successfully",{type:smart_log_1.SmartLocation.UpgradeManager}),[4,this.db.enableDbLogging()];case 5:return n.sent(),this.log.info("database module creation complete",{type:smart_log_1.SmartLocation.UpgradeManager}),[4,this.hasDatabaseModule(e)];case 6:return n.sent()?(this.log.info("successfully initialized database for new module ".concat(e),{type:smart_log_1.SmartLocation.UpgradeManager}),[4,this.upgradeDatabase(e)]):[3,8];case 8:throw"error running database initialization script - does the initialization script insert version record into table 'smart_db_version'? ";case 9:return[3,11];case 10:throw"missing mandatory '".concat(e,"-init.sql' file in ").concat(a);case 11:return[3,13];case 12:throw"option 'sqlFilesDirectory' (".concat(this.sqlScriptDirectory,") must point to an existing directory for module(s) '").concat(e,"' (absolute or relative to ").concat(fs.realpathSync("."),")");case 13:return[2,t]}})})},e.prototype.upgradeDatabase=function(e){return __awaiter(this,void 0,void 0,function(){var t,r,a,n,o,i=this;return __generator(this,function(s){switch(s.label){case 0:return[4,this.db.getFirst(smart_db_version_view_model_1.SmartDbVersionViewModel,{module:e})];case 1:return(r=s.sent())?(a=fs.readdirSync(this.sqlScriptDirectory),n=[],a.forEach(function(t){var a=new RegExp("^".concat(e,"-update\\.([0-9]{3})(\\..*)?\\.sql$")),o=t.match(a);o&&(parseInt(o[1],10)>r.sequence&&n.push(t))}),n=n.sort().map(function(e){return i.sqlScriptDirectory+"/"+e}),o=!0,n.length>0?(this.log.info("using script directory script '".concat(this.sqlScriptDirectory,"' for module ").concat(e),{type:smart_log_1.SmartLocation.UpgradeManager}),[4,this.executeScriptsSequentially(n,e)]):[3,3]):[3,7];case 2:o=s.sent(),s.label=3;case 3:return o?[4,this.db.getFirst(smart_db_version_view_model_1.SmartDbVersionViewModel,{module:e},"*","sequence DESC")]:[3,5];case 4:if(!(t=s.sent()))throw"unable to determine final smart db version";return[3,6];case 5:throw"upgrade error";case 6:return[3,8];case 7:throw"missing version entry for module ".concat(e," - add the mandatory insert into smart_db_version statement to your database creation script!");case 8:return[2,t]}})})},e.prototype.executeScriptsSequentially=function(e,t){return __awaiter(this,void 0,void 0,function(){var r,a,n,o,i,s,c,l,u;return __generator(this,function(d){switch(d.label){case 0:r=!0,d.label=1;case 1:d.trys.push([1,8,9,10]),a=__values(e),n=a.next(),d.label=2;case 2:if(n.done)return[3,7];o=n.value,i=path.basename(o),d.label=3;case 3:return d.trys.push([3,5,,6]),this.log.info("execute update script '".concat(i,"' for module ").concat(t),{type:smart_log_1.SmartLocation.UpgradeManager}),[4,this.db.execScript(o)];case 4:return d.sent(),this.log.info("successfully executed update script '".concat(i,"' for module ").concat(t),{type:smart_log_1.SmartLocation.UpgradeManager}),[3,6];case 5:return s=d.sent(),this.log.fatal("unable to execute update script '".concat(i,"' for module ").concat(t),{type:smart_log_1.SmartLocation.UpgradeManager,data:s}),r=!1,[3,7];case 6:return n=a.next(),[3,2];case 7:return[3,10];case 8:return c=d.sent(),l={error:c},[3,10];case 9:try{n&&!n.done&&(u=a.return)&&u.call(a)}finally{if(l)throw l.error}return[7];case 10:return[2,r]}})})},e}();exports.SmartDbUpgradeManager=SmartDbUpgradeManager;