bigal 12.1.5 → 13.0.0-beta2

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 (213) hide show
  1. package/.devcontainer/devcontainer.json +16 -0
  2. package/.husky/pre-commit +4 -0
  3. package/.prettierrc.cjs +34 -0
  4. package/CHANGELOG.md +5 -0
  5. package/dist/index.cjs +2626 -0
  6. package/dist/index.d.cts +892 -0
  7. package/dist/index.d.mts +892 -0
  8. package/dist/index.d.ts +892 -0
  9. package/dist/index.mjs +2605 -0
  10. package/eslint.config.mjs +25 -0
  11. package/package.json +44 -35
  12. package/tsconfig.build.json +7 -0
  13. package/Entity.d.ts +0 -16
  14. package/Entity.js +0 -13
  15. package/Entity.js.map +0 -1
  16. package/IReadonlyRepository.d.ts +0 -36
  17. package/IReadonlyRepository.js +0 -3
  18. package/IReadonlyRepository.js.map +0 -1
  19. package/IRepository.d.ts +0 -99
  20. package/IRepository.js +0 -3
  21. package/IRepository.js.map +0 -1
  22. package/ReadonlyRepository.d.ts +0 -69
  23. package/ReadonlyRepository.js +0 -687
  24. package/ReadonlyRepository.js.map +0 -1
  25. package/Repository.d.ts +0 -69
  26. package/Repository.js +0 -171
  27. package/Repository.js.map +0 -1
  28. package/SqlHelper.d.ts +0 -144
  29. package/SqlHelper.js +0 -1081
  30. package/SqlHelper.js.map +0 -1
  31. package/decorators/ColumnBaseOptions.d.ts +0 -10
  32. package/decorators/ColumnBaseOptions.js +0 -3
  33. package/decorators/ColumnBaseOptions.js.map +0 -1
  34. package/decorators/ColumnCollectionOptions.d.ts +0 -15
  35. package/decorators/ColumnCollectionOptions.js +0 -3
  36. package/decorators/ColumnCollectionOptions.js.map +0 -1
  37. package/decorators/ColumnModelOptions.d.ts +0 -7
  38. package/decorators/ColumnModelOptions.js +0 -3
  39. package/decorators/ColumnModelOptions.js.map +0 -1
  40. package/decorators/ColumnTypeOptions.d.ts +0 -21
  41. package/decorators/ColumnTypeOptions.js +0 -3
  42. package/decorators/ColumnTypeOptions.js.map +0 -1
  43. package/decorators/TableOptions.d.ts +0 -14
  44. package/decorators/TableOptions.js +0 -3
  45. package/decorators/TableOptions.js.map +0 -1
  46. package/decorators/column.d.ts +0 -9
  47. package/decorators/column.js +0 -93
  48. package/decorators/column.js.map +0 -1
  49. package/decorators/createDateColumn.d.ts +0 -6
  50. package/decorators/createDateColumn.js +0 -50
  51. package/decorators/createDateColumn.js.map +0 -1
  52. package/decorators/index.d.ts +0 -6
  53. package/decorators/index.js +0 -23
  54. package/decorators/index.js.map +0 -1
  55. package/decorators/primaryColumn.d.ts +0 -8
  56. package/decorators/primaryColumn.js +0 -66
  57. package/decorators/primaryColumn.js.map +0 -1
  58. package/decorators/table.d.ts +0 -5
  59. package/decorators/table.js +0 -40
  60. package/decorators/table.js.map +0 -1
  61. package/decorators/updateDateColumn.d.ts +0 -6
  62. package/decorators/updateDateColumn.js +0 -51
  63. package/decorators/updateDateColumn.js.map +0 -1
  64. package/decorators/versionColumn.d.ts +0 -6
  65. package/decorators/versionColumn.js +0 -51
  66. package/decorators/versionColumn.js.map +0 -1
  67. package/errors/QueryError.d.ts +0 -8
  68. package/errors/QueryError.js +0 -13
  69. package/errors/QueryError.js.map +0 -1
  70. package/errors/index.d.ts +0 -1
  71. package/errors/index.js +0 -18
  72. package/errors/index.js.map +0 -1
  73. package/index.d.ts +0 -35
  74. package/index.js +0 -220
  75. package/index.js.map +0 -1
  76. package/metadata/ColumnBaseMetadata.d.ts +0 -93
  77. package/metadata/ColumnBaseMetadata.js +0 -19
  78. package/metadata/ColumnBaseMetadata.js.map +0 -1
  79. package/metadata/ColumnCollectionMetadata.d.ts +0 -36
  80. package/metadata/ColumnCollectionMetadata.js +0 -63
  81. package/metadata/ColumnCollectionMetadata.js.map +0 -1
  82. package/metadata/ColumnMetadata.d.ts +0 -4
  83. package/metadata/ColumnMetadata.js +0 -3
  84. package/metadata/ColumnMetadata.js.map +0 -1
  85. package/metadata/ColumnModelMetadata.d.ts +0 -18
  86. package/metadata/ColumnModelMetadata.js +0 -43
  87. package/metadata/ColumnModelMetadata.js.map +0 -1
  88. package/metadata/ColumnModifierMetadata.d.ts +0 -46
  89. package/metadata/ColumnModifierMetadata.js +0 -3
  90. package/metadata/ColumnModifierMetadata.js.map +0 -1
  91. package/metadata/ColumnTypeMetadata.d.ts +0 -43
  92. package/metadata/ColumnTypeMetadata.js +0 -26
  93. package/metadata/ColumnTypeMetadata.js.map +0 -1
  94. package/metadata/MetadataStorage.d.ts +0 -13
  95. package/metadata/MetadataStorage.js +0 -19
  96. package/metadata/MetadataStorage.js.map +0 -1
  97. package/metadata/ModelMetadata.d.ts +0 -36
  98. package/metadata/ModelMetadata.js +0 -81
  99. package/metadata/ModelMetadata.js.map +0 -1
  100. package/metadata/index.d.ts +0 -10
  101. package/metadata/index.js +0 -33
  102. package/metadata/index.js.map +0 -1
  103. package/query/Comparer.d.ts +0 -1
  104. package/query/Comparer.js +0 -3
  105. package/query/Comparer.js.map +0 -1
  106. package/query/CountArgs.d.ts +0 -7
  107. package/query/CountArgs.js +0 -3
  108. package/query/CountArgs.js.map +0 -1
  109. package/query/CountResult.d.ts +0 -5
  110. package/query/CountResult.js +0 -3
  111. package/query/CountResult.js.map +0 -1
  112. package/query/CreateOptions.d.ts +0 -9
  113. package/query/CreateOptions.js +0 -3
  114. package/query/CreateOptions.js.map +0 -1
  115. package/query/CreateUpdateOptions.d.ts +0 -4
  116. package/query/CreateUpdateOptions.js +0 -3
  117. package/query/CreateUpdateOptions.js.map +0 -1
  118. package/query/DeleteOptions.d.ts +0 -12
  119. package/query/DeleteOptions.js +0 -3
  120. package/query/DeleteOptions.js.map +0 -1
  121. package/query/DestroyResult.d.ts +0 -5
  122. package/query/DestroyResult.js +0 -3
  123. package/query/DestroyResult.js.map +0 -1
  124. package/query/DoNotReturnRecords.d.ts +0 -3
  125. package/query/DoNotReturnRecords.js +0 -3
  126. package/query/DoNotReturnRecords.js.map +0 -1
  127. package/query/FindArgs.d.ts +0 -6
  128. package/query/FindArgs.js +0 -3
  129. package/query/FindArgs.js.map +0 -1
  130. package/query/FindOneArgs.d.ts +0 -11
  131. package/query/FindOneArgs.js +0 -3
  132. package/query/FindOneArgs.js.map +0 -1
  133. package/query/FindOneResult.d.ts +0 -12
  134. package/query/FindOneResult.js +0 -3
  135. package/query/FindOneResult.js.map +0 -1
  136. package/query/FindResult.d.ts +0 -15
  137. package/query/FindResult.js +0 -3
  138. package/query/FindResult.js.map +0 -1
  139. package/query/OnConflictOptions.d.ts +0 -25
  140. package/query/OnConflictOptions.js +0 -3
  141. package/query/OnConflictOptions.js.map +0 -1
  142. package/query/PaginateOptions.d.ts +0 -4
  143. package/query/PaginateOptions.js +0 -3
  144. package/query/PaginateOptions.js.map +0 -1
  145. package/query/PopulateArgs.d.ts +0 -13
  146. package/query/PopulateArgs.js +0 -3
  147. package/query/PopulateArgs.js.map +0 -1
  148. package/query/ReturnSelect.d.ts +0 -5
  149. package/query/ReturnSelect.js +0 -3
  150. package/query/ReturnSelect.js.map +0 -1
  151. package/query/Sort.d.ts +0 -15
  152. package/query/Sort.js +0 -3
  153. package/query/Sort.js.map +0 -1
  154. package/query/WhereQuery.d.ts +0 -21
  155. package/query/WhereQuery.js +0 -3
  156. package/query/WhereQuery.js.map +0 -1
  157. package/query/index.d.ts +0 -15
  158. package/query/index.js +0 -32
  159. package/query/index.js.map +0 -1
  160. package/types/ClassLike.d.ts +0 -8
  161. package/types/ClassLike.js +0 -3
  162. package/types/ClassLike.js.map +0 -1
  163. package/types/CreateUpdateParams.d.ts +0 -9
  164. package/types/CreateUpdateParams.js +0 -3
  165. package/types/CreateUpdateParams.js.map +0 -1
  166. package/types/EntityPrimitiveOrId.d.ts +0 -2
  167. package/types/EntityPrimitiveOrId.js +0 -3
  168. package/types/EntityPrimitiveOrId.js.map +0 -1
  169. package/types/ExcludeEntityCollections.d.ts +0 -5
  170. package/types/ExcludeEntityCollections.js +0 -3
  171. package/types/ExcludeEntityCollections.js.map +0 -1
  172. package/types/ExcludeFunctions.d.ts +0 -4
  173. package/types/ExcludeFunctions.js +0 -3
  174. package/types/ExcludeFunctions.js.map +0 -1
  175. package/types/GetValueType.d.ts +0 -1
  176. package/types/GetValueType.js +0 -3
  177. package/types/GetValueType.js.map +0 -1
  178. package/types/IncludeFunctions.d.ts +0 -4
  179. package/types/IncludeFunctions.js +0 -3
  180. package/types/IncludeFunctions.js.map +0 -1
  181. package/types/IsValueOfType.d.ts +0 -1
  182. package/types/IsValueOfType.js +0 -3
  183. package/types/IsValueOfType.js.map +0 -1
  184. package/types/OmitEntityCollections.d.ts +0 -7
  185. package/types/OmitEntityCollections.js +0 -3
  186. package/types/OmitEntityCollections.js.map +0 -1
  187. package/types/OmitFunctions.d.ts +0 -7
  188. package/types/OmitFunctions.js +0 -3
  189. package/types/OmitFunctions.js.map +0 -1
  190. package/types/PickAsType.d.ts +0 -3
  191. package/types/PickAsType.js +0 -3
  192. package/types/PickAsType.js.map +0 -1
  193. package/types/PickByValueType.d.ts +0 -5
  194. package/types/PickByValueType.js +0 -3
  195. package/types/PickByValueType.js.map +0 -1
  196. package/types/PickFunctions.d.ts +0 -4
  197. package/types/PickFunctions.js +0 -3
  198. package/types/PickFunctions.js.map +0 -1
  199. package/types/Populated.d.ts +0 -9
  200. package/types/Populated.js +0 -3
  201. package/types/Populated.js.map +0 -1
  202. package/types/QueryResult.d.ts +0 -9
  203. package/types/QueryResult.js +0 -3
  204. package/types/QueryResult.js.map +0 -1
  205. package/types/QueryResultOptionalPopulated.d.ts +0 -9
  206. package/types/QueryResultOptionalPopulated.js +0 -3
  207. package/types/QueryResultOptionalPopulated.js.map +0 -1
  208. package/types/QueryResultPopulated.d.ts +0 -9
  209. package/types/QueryResultPopulated.js +0 -3
  210. package/types/QueryResultPopulated.js.map +0 -1
  211. package/types/index.d.ts +0 -17
  212. package/types/index.js +0 -34
  213. package/types/index.js.map +0 -1
package/dist/index.mjs ADDED
@@ -0,0 +1,2605 @@
1
+ import _ from 'lodash';
2
+
3
+ var __defProp$7 = Object.defineProperty;
4
+ var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5
+ var __publicField$7 = (obj, key, value) => {
6
+ __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
7
+ return value;
8
+ };
9
+ class MetadataStorage {
10
+ constructor() {
11
+ __publicField$7(this, "models", []);
12
+ // All columns for all models. This data only represents @column specifics, not additional column modifiers
13
+ __publicField$7(this, "columns", []);
14
+ // This represents additional column behavior separate from the main @column decorator. For example, @primaryColumn, @versionColumn, etc
15
+ // This behavior will be merged over defaults from @column()
16
+ __publicField$7(this, "columnModifiers", []);
17
+ }
18
+ }
19
+
20
+ var __defProp$6 = Object.defineProperty;
21
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
22
+ var __publicField$6 = (obj, key, value) => {
23
+ __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
24
+ return value;
25
+ };
26
+ class ColumnBaseMetadata {
27
+ constructor({
28
+ target,
29
+ name,
30
+ propertyName,
31
+ required = false,
32
+ insert = true,
33
+ update = true,
34
+ primary = false,
35
+ createDate = false,
36
+ updateDate = false,
37
+ version = false
38
+ }) {
39
+ /**
40
+ * Name of class with @table decorator
41
+ */
42
+ __publicField$6(this, "target");
43
+ /**
44
+ * Column name in the database
45
+ */
46
+ __publicField$6(this, "name");
47
+ /**
48
+ * Class property to which the column is applied
49
+ */
50
+ __publicField$6(this, "propertyName");
51
+ /**
52
+ * Indicates if a value is required for creates.
53
+ */
54
+ __publicField$6(this, "required");
55
+ /**
56
+ * Indicates if column is inserted by default. Default is true
57
+ */
58
+ __publicField$6(this, "insert");
59
+ /**
60
+ * Indicates if column value is updated by "save" operation. Default is true
61
+ */
62
+ __publicField$6(this, "update");
63
+ /**
64
+ * Indicates if this column is a primary key.
65
+ * Same can be achieved when @primaryColumn decorator is used
66
+ */
67
+ __publicField$6(this, "primary");
68
+ /**
69
+ * Value will be equal to `new Date()` when the row is inserted into the table
70
+ * Same can be achieved when @createDateColumn decorator is used
71
+ */
72
+ __publicField$6(this, "createDate");
73
+ /**
74
+ * Value will be equal to `new Date()` when the row is updated
75
+ * Same can be achieved when @updateDateColumn decorator is used
76
+ */
77
+ __publicField$6(this, "updateDate");
78
+ /**
79
+ * Value will be set to 1 when the row is inserted. Value will be incremented by one when the row is updated
80
+ * Same can be achieved when @versionColumn decorator is used
81
+ */
82
+ __publicField$6(this, "version");
83
+ this.target = target;
84
+ this.name = name;
85
+ this.propertyName = propertyName;
86
+ this.required = required;
87
+ this.insert = insert;
88
+ this.update = update;
89
+ this.primary = primary;
90
+ this.createDate = createDate;
91
+ this.updateDate = updateDate;
92
+ this.version = version;
93
+ }
94
+ }
95
+
96
+ var __defProp$5 = Object.defineProperty;
97
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
98
+ var __publicField$5 = (obj, key, value) => {
99
+ __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
100
+ return value;
101
+ };
102
+ class ColumnCollectionMetadata extends ColumnBaseMetadata {
103
+ constructor({
104
+ target,
105
+ //
106
+ name,
107
+ propertyName,
108
+ required,
109
+ insert,
110
+ update,
111
+ primary,
112
+ createDate,
113
+ updateDate,
114
+ version,
115
+ collection,
116
+ via,
117
+ through
118
+ }) {
119
+ super({
120
+ target,
121
+ name,
122
+ propertyName,
123
+ required,
124
+ insert,
125
+ update,
126
+ primary,
127
+ createDate,
128
+ updateDate,
129
+ version
130
+ });
131
+ __publicField$5(this, "_collectionString");
132
+ __publicField$5(this, "_collectionFn");
133
+ __publicField$5(this, "_throughString");
134
+ __publicField$5(this, "_throughFn");
135
+ /**
136
+ * Property name of the on the collection item type
137
+ */
138
+ __publicField$5(this, "via");
139
+ this.via = via;
140
+ if (typeof collection === "string") {
141
+ this._collectionString = collection;
142
+ } else {
143
+ this._collectionFn = collection;
144
+ }
145
+ if (typeof through === "string") {
146
+ this._throughString = through;
147
+ } else if (through) {
148
+ this._throughFn = through;
149
+ }
150
+ }
151
+ /**
152
+ * Type of the items in the collection
153
+ */
154
+ get collection() {
155
+ if (this._collectionString) {
156
+ return this._collectionString;
157
+ }
158
+ if (!this._collectionFn) {
159
+ throw new Error(`Unable to determine collection type for ${this.target}#${this.propertyName}`);
160
+ }
161
+ this._collectionString = this._collectionFn();
162
+ return this._collectionString;
163
+ }
164
+ /**
165
+ * Name of the junction table for multi-multi associations
166
+ */
167
+ get through() {
168
+ if (this._throughString) {
169
+ return this._throughString;
170
+ }
171
+ if (this._throughFn) {
172
+ this._throughString = this._throughFn();
173
+ return this._throughString;
174
+ }
175
+ return void 0;
176
+ }
177
+ }
178
+
179
+ var __defProp$4 = Object.defineProperty;
180
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
181
+ var __publicField$4 = (obj, key, value) => {
182
+ __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
183
+ return value;
184
+ };
185
+ class ColumnModelMetadata extends ColumnBaseMetadata {
186
+ constructor({
187
+ target,
188
+ //
189
+ name,
190
+ propertyName,
191
+ required,
192
+ insert,
193
+ update,
194
+ primary,
195
+ createDate,
196
+ updateDate,
197
+ version,
198
+ model
199
+ }) {
200
+ super({
201
+ target,
202
+ name,
203
+ propertyName,
204
+ required,
205
+ insert,
206
+ update,
207
+ primary,
208
+ createDate,
209
+ updateDate,
210
+ version
211
+ });
212
+ __publicField$4(this, "_modelString");
213
+ __publicField$4(this, "_modelFn");
214
+ if (typeof model === "string") {
215
+ this._modelString = model;
216
+ } else {
217
+ this._modelFn = model;
218
+ }
219
+ }
220
+ /**
221
+ * Name of the model represented by this column id
222
+ */
223
+ get model() {
224
+ if (this._modelString) {
225
+ return this._modelString;
226
+ }
227
+ if (!this._modelFn) {
228
+ throw new Error(`Unable to determine model type for ${this.target}#${this.propertyName}`);
229
+ }
230
+ this._modelString = this._modelFn();
231
+ return this._modelString;
232
+ }
233
+ }
234
+
235
+ var __defProp$3 = Object.defineProperty;
236
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
237
+ var __publicField$3 = (obj, key, value) => {
238
+ __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
239
+ return value;
240
+ };
241
+ class ColumnTypeMetadata extends ColumnBaseMetadata {
242
+ constructor(options) {
243
+ super({
244
+ target: options.target,
245
+ name: options.name,
246
+ propertyName: options.propertyName,
247
+ required: options.required,
248
+ insert: options.insert,
249
+ update: options.update,
250
+ primary: options.primary,
251
+ createDate: options.createDate,
252
+ updateDate: options.updateDate,
253
+ version: options.version
254
+ });
255
+ /**
256
+ * Type of the column
257
+ */
258
+ __publicField$3(this, "type");
259
+ /**
260
+ * Default database value
261
+ */
262
+ __publicField$3(this, "defaultsTo");
263
+ /**
264
+ * Array of possible enumerated values
265
+ */
266
+ __publicField$3(this, "enum");
267
+ /**
268
+ * If set, enforces a maximum length check on the column
269
+ *
270
+ * Applies to types: string | string[]
271
+ */
272
+ __publicField$3(this, "maxLength");
273
+ this.type = options.type;
274
+ this.defaultsTo = options.defaultsTo;
275
+ this.enum = options.enum;
276
+ this.maxLength = options.maxLength;
277
+ }
278
+ }
279
+
280
+ var __defProp$2 = Object.defineProperty;
281
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
282
+ var __publicField$2 = (obj, key, value) => {
283
+ __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
284
+ return value;
285
+ };
286
+ class ModelMetadata {
287
+ constructor({
288
+ name,
289
+ //
290
+ type,
291
+ connection,
292
+ tableName,
293
+ readonly = false
294
+ }) {
295
+ __publicField$2(this, "_columns", []);
296
+ __publicField$2(this, "_primaryKeyColumn");
297
+ __publicField$2(this, "_createDateColumns", []);
298
+ __publicField$2(this, "_updateDateColumns", []);
299
+ __publicField$2(this, "_versionDateColumns", []);
300
+ __publicField$2(this, "name");
301
+ __publicField$2(this, "type");
302
+ __publicField$2(this, "connection");
303
+ __publicField$2(this, "tableName");
304
+ __publicField$2(this, "readonly");
305
+ __publicField$2(this, "columnsByColumnName", {});
306
+ __publicField$2(this, "columnsByPropertyName", {});
307
+ this.name = name;
308
+ this.type = type;
309
+ this.connection = connection;
310
+ this.tableName = tableName ?? _.snakeCase(name);
311
+ this.readonly = readonly;
312
+ }
313
+ set columns(columns) {
314
+ this._columns = columns;
315
+ this.columnsByColumnName = {};
316
+ this.columnsByPropertyName = {};
317
+ for (const column of columns) {
318
+ this.columnsByColumnName[column.name] = column;
319
+ this.columnsByPropertyName[column.propertyName] = column;
320
+ if (column.primary) {
321
+ this._primaryKeyColumn = column;
322
+ }
323
+ if (column.createDate) {
324
+ this._createDateColumns.push(column);
325
+ }
326
+ if (column.updateDate) {
327
+ this._updateDateColumns.push(column);
328
+ }
329
+ if (column.version) {
330
+ this._versionDateColumns.push(column);
331
+ }
332
+ }
333
+ }
334
+ get columns() {
335
+ return this._columns;
336
+ }
337
+ get primaryKeyColumn() {
338
+ return this._primaryKeyColumn;
339
+ }
340
+ get createDateColumns() {
341
+ return this._createDateColumns;
342
+ }
343
+ get updateDateColumns() {
344
+ return this._updateDateColumns;
345
+ }
346
+ get versionColumns() {
347
+ return this._versionDateColumns;
348
+ }
349
+ }
350
+
351
+ function getMetadataStorage() {
352
+ if (!global.bigAlMetadataArgsStorage) {
353
+ global.bigAlMetadataArgsStorage = new MetadataStorage();
354
+ }
355
+ return global.bigAlMetadataArgsStorage;
356
+ }
357
+
358
+ var __defProp$1 = Object.defineProperty;
359
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
360
+ var __publicField$1 = (obj, key, value) => {
361
+ __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
362
+ return value;
363
+ };
364
+ class QueryError extends Error {
365
+ constructor(message, model, where) {
366
+ super(message);
367
+ __publicField$1(this, "model");
368
+ __publicField$1(this, "where");
369
+ this.name = "QueryError";
370
+ this.model = model;
371
+ this.where = where;
372
+ Object.setPrototypeOf(this, QueryError.prototype);
373
+ }
374
+ }
375
+
376
+ function getSelectQueryAndParams({
377
+ repositoriesByModelNameLowered,
378
+ model,
379
+ select,
380
+ where,
381
+ sorts,
382
+ skip,
383
+ limit
384
+ }) {
385
+ let query = "SELECT ";
386
+ query += getColumnsToSelect({
387
+ model,
388
+ select
389
+ });
390
+ query += ` FROM "${model.tableName}"`;
391
+ const { whereStatement, params } = buildWhereStatement({
392
+ repositoriesByModelNameLowered,
393
+ model,
394
+ where
395
+ });
396
+ if (whereStatement) {
397
+ query += ` ${whereStatement}`;
398
+ }
399
+ const orderStatement = buildOrderStatement({
400
+ model,
401
+ sorts
402
+ });
403
+ if (orderStatement) {
404
+ query += ` ${orderStatement}`;
405
+ }
406
+ if (limit) {
407
+ if (_.isString(limit)) {
408
+ limit = Number(limit);
409
+ }
410
+ if (!_.isFinite(limit)) {
411
+ throw new QueryError("Limit should be a number", model, where);
412
+ }
413
+ query += ` LIMIT ${limit}`;
414
+ }
415
+ if (skip) {
416
+ if (_.isString(skip)) {
417
+ skip = Number(skip);
418
+ }
419
+ if (!_.isFinite(skip)) {
420
+ throw new QueryError("Skip should be a number", model, where);
421
+ }
422
+ query += ` OFFSET ${skip}`;
423
+ }
424
+ if (process.env.DEBUG_BIGAL?.toLowerCase() === "true") {
425
+ console.log(`BigAl: ${query}`);
426
+ }
427
+ return {
428
+ query,
429
+ params
430
+ };
431
+ }
432
+ function getCountQueryAndParams({
433
+ repositoriesByModelNameLowered,
434
+ model,
435
+ where
436
+ }) {
437
+ let query = `SELECT count(*) AS "count" FROM "${model.tableName}"`;
438
+ const { whereStatement, params } = buildWhereStatement({
439
+ repositoriesByModelNameLowered,
440
+ model,
441
+ where
442
+ });
443
+ if (whereStatement) {
444
+ query += ` ${whereStatement}`;
445
+ }
446
+ return {
447
+ query,
448
+ params
449
+ };
450
+ }
451
+ function getInsertQueryAndParams({
452
+ repositoriesByModelNameLowered,
453
+ model,
454
+ values,
455
+ returnRecords = true,
456
+ returnSelect,
457
+ onConflict
458
+ }) {
459
+ const entitiesToInsert = _.isArray(values) ? values : [values];
460
+ const conflictTargetColumns = [];
461
+ const columnsToInsert = [];
462
+ const columnsToMerge = [];
463
+ let hasEmptyMergeColumns = false;
464
+ for (const column of model.columns) {
465
+ const collectionColumn = column;
466
+ if (!collectionColumn.collection) {
467
+ const { defaultsTo } = column;
468
+ let defaultValue;
469
+ if (_.isFunction(defaultsTo)) {
470
+ defaultValue = defaultsTo();
471
+ } else if (!_.isUndefined(defaultsTo)) {
472
+ defaultValue = defaultsTo;
473
+ } else if (column.createDate) {
474
+ defaultValue = /* @__PURE__ */ new Date();
475
+ } else if (column.updateDate) {
476
+ defaultValue = /* @__PURE__ */ new Date();
477
+ } else if (column.version) {
478
+ defaultValue = 1;
479
+ }
480
+ const hasDefaultValue = !_.isUndefined(defaultValue);
481
+ let includePropertyName = false;
482
+ for (const entity of entitiesToInsert) {
483
+ if (hasDefaultValue && _.isUndefined(entity[column.propertyName])) {
484
+ entity[column.propertyName] = defaultValue;
485
+ }
486
+ if (_.isUndefined(entity[column.propertyName])) {
487
+ if (column.required) {
488
+ throw new QueryError(`Create statement for "${model.name}" is missing value for required field: ${column.propertyName}`, model);
489
+ }
490
+ } else {
491
+ includePropertyName = true;
492
+ const { maxLength, type } = column;
493
+ if (maxLength && ["string", "string[]"].includes(type)) {
494
+ const entityValues = entity[column.propertyName] ?? "";
495
+ const normalizedValues = Array.isArray(entityValues) ? entityValues : [entityValues];
496
+ for (const normalizedValue of normalizedValues) {
497
+ if (normalizedValue.length > maxLength) {
498
+ throw new QueryError(`Create statement for "${model.name}" contains a value that exceeds maxLength on field: ${column.propertyName}`, model);
499
+ }
500
+ }
501
+ }
502
+ }
503
+ }
504
+ if (includePropertyName) {
505
+ columnsToInsert.push(column);
506
+ }
507
+ if (onConflict) {
508
+ if (Array.isArray(onConflict.targets) && onConflict.targets.includes(column.propertyName) || !Array.isArray(onConflict.targets) && onConflict.targets.columns.includes(column.propertyName)) {
509
+ conflictTargetColumns.push(column);
510
+ }
511
+ if (onConflict.action === "merge") {
512
+ const mergeColumns = Array.isArray(onConflict.merge) ? onConflict.merge : onConflict.merge?.columns;
513
+ if (mergeColumns) {
514
+ hasEmptyMergeColumns = !mergeColumns.length;
515
+ if (mergeColumns.includes(column.propertyName)) {
516
+ columnsToMerge.push(column);
517
+ }
518
+ } else if (!column.createDate && !column.primary) {
519
+ columnsToMerge.push(column);
520
+ }
521
+ }
522
+ }
523
+ }
524
+ }
525
+ const valueCollections = entitiesToInsert.map(() => []);
526
+ const params = [];
527
+ let query = `INSERT INTO "${model.tableName}" (`;
528
+ for (const [columnIndex, column] of columnsToInsert.entries()) {
529
+ if (columnIndex > 0) {
530
+ query += ",";
531
+ }
532
+ query += `"${column.name}"`;
533
+ for (const [entityIndex, entity] of entitiesToInsert.entries()) {
534
+ let value;
535
+ const entityValue = entity[column.propertyName];
536
+ if (_.isNil(entityValue)) {
537
+ value = "NULL";
538
+ } else {
539
+ const isJsonArray = column.type === "json" && _.isArray(entityValue);
540
+ const relatedModelName = column.model;
541
+ if (relatedModelName && _.isObject(entityValue)) {
542
+ const relatedModelRepository = repositoriesByModelNameLowered[relatedModelName.toLowerCase()];
543
+ if (!relatedModelRepository) {
544
+ throw new QueryError(`Unable to find model schema (${relatedModelName}) specified as model type for "${column.propertyName}" on "${model.name}"`, model);
545
+ }
546
+ const relatedModelPrimaryKey = relatedModelRepository.model.primaryKeyColumn;
547
+ if (!relatedModelPrimaryKey) {
548
+ throw new QueryError(`Unable to find primary key column for ${relatedModelName} when inserting ${model.name}.${column.propertyName} value.`, model);
549
+ }
550
+ const primaryKeyValue = entityValue[relatedModelPrimaryKey.propertyName];
551
+ if (_.isNil(primaryKeyValue)) {
552
+ throw new QueryError(`Undefined primary key value for hydrated object value for "${column.propertyName}" on "${model.name}"`, model);
553
+ }
554
+ params.push(primaryKeyValue);
555
+ } else if (isJsonArray) {
556
+ params.push(JSON.stringify(entityValue));
557
+ } else {
558
+ params.push(entityValue);
559
+ }
560
+ value = `$${params.length}`;
561
+ if (isJsonArray) {
562
+ value += "::jsonb";
563
+ }
564
+ }
565
+ const valuesForEntityIndex = valueCollections[entityIndex];
566
+ if (!valuesForEntityIndex) {
567
+ throw new QueryError("Error trying to get insert values for entity index", model);
568
+ }
569
+ valuesForEntityIndex.push(value);
570
+ }
571
+ }
572
+ query += ") VALUES ";
573
+ for (const [index, valueCollection] of valueCollections.entries()) {
574
+ if (index > 0) {
575
+ query += ",";
576
+ }
577
+ query += `(${valueCollection.join(",")})`;
578
+ }
579
+ if (onConflict) {
580
+ query += " ON CONFLICT (";
581
+ for (const [index, targetColumn] of conflictTargetColumns.entries()) {
582
+ if (index > 0) {
583
+ query += ",";
584
+ }
585
+ query += `"${targetColumn.name}"`;
586
+ }
587
+ query += ") ";
588
+ if (!Array.isArray(onConflict.targets)) {
589
+ const { whereStatement } = buildWhereStatement({
590
+ repositoriesByModelNameLowered,
591
+ model,
592
+ where: onConflict.targets.where,
593
+ params
594
+ });
595
+ if (whereStatement) {
596
+ query += `${whereStatement} `;
597
+ }
598
+ }
599
+ if (onConflict.action === "ignore" || hasEmptyMergeColumns) {
600
+ query += "DO NOTHING";
601
+ } else {
602
+ query += "DO UPDATE SET ";
603
+ for (const [index, column] of columnsToMerge.entries()) {
604
+ if (index > 0) {
605
+ query += ",";
606
+ }
607
+ if (column.version) {
608
+ query += `"${column.name}"="${column.name}"+1`;
609
+ } else {
610
+ query += `"${column.name}"=EXCLUDED."${column.name}"`;
611
+ }
612
+ }
613
+ if (!Array.isArray(onConflict.merge) && onConflict.merge?.where) {
614
+ const { whereStatement } = buildWhereStatement({
615
+ repositoriesByModelNameLowered,
616
+ model,
617
+ where: onConflict.merge.where,
618
+ params
619
+ });
620
+ if (whereStatement) {
621
+ query += ` ${whereStatement}`;
622
+ }
623
+ }
624
+ }
625
+ }
626
+ if (returnRecords) {
627
+ query += " RETURNING ";
628
+ query += getColumnsToSelect({
629
+ model,
630
+ select: returnSelect
631
+ });
632
+ }
633
+ return {
634
+ query,
635
+ params
636
+ };
637
+ }
638
+ function getUpdateQueryAndParams({
639
+ repositoriesByModelNameLowered,
640
+ model,
641
+ where,
642
+ values = {},
643
+ returnRecords = true,
644
+ returnSelect
645
+ }) {
646
+ for (const column of model.updateDateColumns) {
647
+ if (_.isUndefined(values[column.propertyName])) {
648
+ values[column.propertyName] = /* @__PURE__ */ new Date();
649
+ }
650
+ }
651
+ const params = [];
652
+ let query = `UPDATE "${model.tableName}" SET `;
653
+ let isFirstProperty = true;
654
+ for (const [propertyName, value] of Object.entries(values)) {
655
+ const column = model.columnsByPropertyName[propertyName];
656
+ if (column && !column.collection) {
657
+ if (!isFirstProperty) {
658
+ query += ",";
659
+ }
660
+ query += `"${column.name}"=`;
661
+ if (_.isNil(value)) {
662
+ query += "NULL";
663
+ } else {
664
+ const isJsonArray = column.type === "json" && _.isArray(value);
665
+ const relatedModelName = column.model;
666
+ const { maxLength, type } = column;
667
+ if (maxLength && ["string", "string[]"].includes(type)) {
668
+ const normalizedValues = Array.isArray(value) ? value : [value];
669
+ for (const normalizedValue of normalizedValues) {
670
+ if (normalizedValue?.length > maxLength) {
671
+ throw new QueryError(`Update statement for "${model.name}" contains a value that exceeds maxLength on field: ${column.propertyName}`, model);
672
+ }
673
+ }
674
+ }
675
+ if (relatedModelName && _.isObject(value)) {
676
+ const relatedModelRepository = repositoriesByModelNameLowered[relatedModelName.toLowerCase()];
677
+ if (!relatedModelRepository) {
678
+ throw new QueryError(`Unable to find model schema (${relatedModelName}) specified as model type for "${propertyName}" on "${model.name}"`, model);
679
+ }
680
+ const relatedModelPrimaryKey = relatedModelRepository.model.primaryKeyColumn;
681
+ if (!relatedModelPrimaryKey) {
682
+ throw new QueryError(`Unable to find primary key column for ${relatedModelName} when inserting ${model.name}.${column.propertyName} value.`, model);
683
+ }
684
+ const primaryKeyValue = value[relatedModelPrimaryKey.propertyName];
685
+ if (_.isNil(primaryKeyValue)) {
686
+ throw new QueryError(`Undefined primary key value for hydrated object value for "${column.propertyName}" on "${model.name}"`, model);
687
+ }
688
+ params.push(primaryKeyValue);
689
+ } else if (isJsonArray) {
690
+ params.push(JSON.stringify(value));
691
+ } else {
692
+ params.push(value);
693
+ }
694
+ query += `$${params.length}`;
695
+ if (isJsonArray) {
696
+ query += "::jsonb";
697
+ }
698
+ }
699
+ isFirstProperty = false;
700
+ }
701
+ }
702
+ for (const column of model.versionColumns) {
703
+ if (!_.isUndefined(values[column.propertyName])) {
704
+ if (!isFirstProperty) {
705
+ query += ",";
706
+ }
707
+ query += `"${column.name}"="${column.name}"+1`;
708
+ isFirstProperty = false;
709
+ }
710
+ }
711
+ const { whereStatement } = buildWhereStatement({
712
+ repositoriesByModelNameLowered,
713
+ model,
714
+ where,
715
+ params
716
+ });
717
+ if (whereStatement) {
718
+ query += ` ${whereStatement}`;
719
+ }
720
+ if (returnRecords) {
721
+ query += " RETURNING ";
722
+ query += getColumnsToSelect({
723
+ model,
724
+ select: returnSelect
725
+ });
726
+ }
727
+ return {
728
+ query,
729
+ params
730
+ };
731
+ }
732
+ function getDeleteQueryAndParams({
733
+ repositoriesByModelNameLowered,
734
+ model,
735
+ where,
736
+ returnRecords = true,
737
+ returnSelect
738
+ }) {
739
+ let query = `DELETE FROM "${model.tableName}"`;
740
+ const { whereStatement, params } = buildWhereStatement({
741
+ repositoriesByModelNameLowered,
742
+ model,
743
+ where
744
+ });
745
+ if (whereStatement) {
746
+ query += ` ${whereStatement}`;
747
+ }
748
+ if (returnRecords) {
749
+ query += " RETURNING ";
750
+ query += getColumnsToSelect({
751
+ model,
752
+ select: returnSelect
753
+ });
754
+ }
755
+ return {
756
+ query,
757
+ params
758
+ };
759
+ }
760
+ function getColumnsToSelect({
761
+ model,
762
+ select
763
+ }) {
764
+ let selectColumns;
765
+ if (select) {
766
+ const { primaryKeyColumn } = model;
767
+ selectColumns = new Set(select);
768
+ if (primaryKeyColumn) {
769
+ selectColumns.add(primaryKeyColumn.propertyName);
770
+ }
771
+ } else {
772
+ selectColumns = /* @__PURE__ */ new Set();
773
+ for (const column of model.columns) {
774
+ if (!column.collection) {
775
+ selectColumns.add(column.propertyName);
776
+ }
777
+ }
778
+ }
779
+ let query = "";
780
+ for (const [index, propertyName] of Array.from(selectColumns).entries()) {
781
+ const column = model.columnsByPropertyName[propertyName];
782
+ if (!column) {
783
+ throw new QueryError(`Unable to find column for property: ${propertyName} on ${model.tableName}`, model);
784
+ }
785
+ if (index > 0) {
786
+ query += ",";
787
+ }
788
+ if (column.name === propertyName) {
789
+ query += `"${propertyName}"`;
790
+ } else {
791
+ query += `"${column.name}" AS "${propertyName}"`;
792
+ }
793
+ }
794
+ return query;
795
+ }
796
+ function buildWhereStatement({
797
+ repositoriesByModelNameLowered,
798
+ model,
799
+ where,
800
+ params = []
801
+ }) {
802
+ let whereStatement;
803
+ if (_.isObject(where) && Object.keys(where).length) {
804
+ whereStatement = buildWhere({
805
+ repositoriesByModelNameLowered,
806
+ model,
807
+ comparer: "and",
808
+ value: where,
809
+ params
810
+ });
811
+ if (!whereStatement) {
812
+ throw new QueryError(`WHERE statement is unexpectedly empty.`, model, where);
813
+ }
814
+ }
815
+ if (whereStatement) {
816
+ whereStatement = `WHERE ${whereStatement}`;
817
+ }
818
+ return {
819
+ whereStatement,
820
+ params
821
+ };
822
+ }
823
+ function buildOrderStatement({ model, sorts }) {
824
+ if (_.isNil(sorts) || !_.some(sorts)) {
825
+ return "";
826
+ }
827
+ let orderStatement = "ORDER BY ";
828
+ for (const [index, orderProperty] of sorts.entries()) {
829
+ if (index > 0) {
830
+ orderStatement += ",";
831
+ }
832
+ const { propertyName, descending } = orderProperty;
833
+ const column = model.columnsByPropertyName[propertyName];
834
+ if (!column) {
835
+ throw new QueryError(`Property (${propertyName}) not found in model (${model.name}).`, model);
836
+ }
837
+ orderStatement += `"${column.name}"`;
838
+ if (descending) {
839
+ orderStatement += " DESC";
840
+ }
841
+ }
842
+ return orderStatement;
843
+ }
844
+ function buildWhere({
845
+ repositoriesByModelNameLowered,
846
+ model,
847
+ propertyName,
848
+ comparer,
849
+ isNegated = false,
850
+ value,
851
+ params = []
852
+ }) {
853
+ switch (comparer ?? propertyName) {
854
+ case "!":
855
+ case "not":
856
+ return buildWhere({
857
+ repositoriesByModelNameLowered,
858
+ model,
859
+ propertyName,
860
+ isNegated: true,
861
+ value,
862
+ params
863
+ });
864
+ case "or":
865
+ return buildOrOperatorStatement({
866
+ repositoriesByModelNameLowered,
867
+ model,
868
+ isNegated,
869
+ value,
870
+ params
871
+ });
872
+ case "contains":
873
+ if (_.isArray(value)) {
874
+ const values = value.map((val) => {
875
+ if (!_.isString(val)) {
876
+ throw new QueryError(`Expected all array values to be strings for "contains" constraint. Property (${propertyName ?? ""}) in model (${model.name}).`, model);
877
+ }
878
+ return `%${val}%`;
879
+ });
880
+ return buildWhere({
881
+ repositoriesByModelNameLowered,
882
+ model,
883
+ propertyName,
884
+ comparer: "like",
885
+ isNegated,
886
+ value: values,
887
+ params
888
+ });
889
+ }
890
+ if (_.isString(value)) {
891
+ return buildWhere({
892
+ repositoriesByModelNameLowered,
893
+ model,
894
+ propertyName,
895
+ comparer: "like",
896
+ isNegated,
897
+ value: `%${value}%`,
898
+ params
899
+ });
900
+ }
901
+ throw new QueryError(`Expected value to be a string for "contains" constraint. Property (${propertyName ?? ""}) in model (${model.name}).`, model);
902
+ case "startsWith":
903
+ if (_.isArray(value)) {
904
+ const values = value.map((val) => {
905
+ if (!_.isString(val)) {
906
+ throw new QueryError(`Expected all array values to be strings for "startsWith" constraint. Property (${propertyName ?? ""}) in model (${model.name}).`, model);
907
+ }
908
+ return `${val}%`;
909
+ });
910
+ return buildWhere({
911
+ repositoriesByModelNameLowered,
912
+ model,
913
+ propertyName,
914
+ comparer: "like",
915
+ isNegated,
916
+ value: values,
917
+ params
918
+ });
919
+ }
920
+ if (_.isString(value)) {
921
+ return buildWhere({
922
+ repositoriesByModelNameLowered,
923
+ model,
924
+ propertyName,
925
+ comparer: "like",
926
+ isNegated,
927
+ value: `${value}%`,
928
+ params
929
+ });
930
+ }
931
+ throw new QueryError(`Expected value to be a string for "startsWith" constraint. Property (${propertyName ?? ""}) in model (${model.name}).`, model);
932
+ case "endsWith":
933
+ if (_.isArray(value)) {
934
+ const values = value.map((val) => {
935
+ if (!_.isString(val)) {
936
+ throw new QueryError(`Expected all array values to be strings for "endsWith" constraint. Property (${propertyName ?? ""}) in model (${model.name}).`, model);
937
+ }
938
+ return `%${val}`;
939
+ });
940
+ return buildWhere({
941
+ repositoriesByModelNameLowered,
942
+ model,
943
+ propertyName,
944
+ comparer: "like",
945
+ isNegated,
946
+ value: values,
947
+ params
948
+ });
949
+ }
950
+ if (_.isString(value)) {
951
+ return buildWhere({
952
+ repositoriesByModelNameLowered,
953
+ model,
954
+ propertyName,
955
+ comparer: "like",
956
+ isNegated,
957
+ value: `%${value}`,
958
+ params
959
+ });
960
+ }
961
+ throw new QueryError(`Expected value to be a string for "endsWith" constraint. Property (${propertyName ?? ""}) in model (${model.name}).`, model);
962
+ case "like":
963
+ return buildLikeOperatorStatement({
964
+ model,
965
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
966
+ propertyName,
967
+ isNegated,
968
+ value,
969
+ params
970
+ });
971
+ default: {
972
+ if (_.isUndefined(value)) {
973
+ throw new QueryError(`Attempting to query with an undefined value. ${propertyName ?? ""} on ${model.name}`, model);
974
+ }
975
+ if (propertyName) {
976
+ const column = model.columnsByPropertyName[propertyName];
977
+ if (column && _.isObject(value)) {
978
+ if (column.primary) {
979
+ const primaryKeyValue = value[column.propertyName];
980
+ if (!_.isNil(primaryKeyValue)) {
981
+ return buildWhere({
982
+ repositoriesByModelNameLowered,
983
+ model,
984
+ propertyName,
985
+ comparer,
986
+ isNegated,
987
+ value: primaryKeyValue,
988
+ params
989
+ });
990
+ }
991
+ } else if (column.model) {
992
+ const relatedModelRepository = repositoriesByModelNameLowered[column.model.toLowerCase()];
993
+ if (!relatedModelRepository) {
994
+ throw new QueryError(`Unable to find model schema (${column.model}) specified in where clause for "${column.propertyName}"`, model);
995
+ }
996
+ const relatedModelPrimaryKey = relatedModelRepository.model.primaryKeyColumn;
997
+ if (!relatedModelPrimaryKey) {
998
+ throw new QueryError(`Unable to find primary key column for ${column.model} specified in where clause for ${model.name}.${column.propertyName}`, model);
999
+ }
1000
+ const primaryKeyValue = value[relatedModelPrimaryKey.propertyName];
1001
+ if (!_.isNil(primaryKeyValue)) {
1002
+ return buildWhere({
1003
+ repositoriesByModelNameLowered,
1004
+ model,
1005
+ propertyName,
1006
+ comparer,
1007
+ isNegated,
1008
+ value: primaryKeyValue,
1009
+ params
1010
+ });
1011
+ }
1012
+ }
1013
+ }
1014
+ }
1015
+ if (_.isArray(value)) {
1016
+ if (!value.length) {
1017
+ const columnTypeFromPropertyName = propertyName ? model.columnsByPropertyName[propertyName] : null;
1018
+ const columnTypeFromComparer = comparer ? model.columnsByPropertyName[comparer] : null;
1019
+ const arrayColumn = columnTypeFromPropertyName ?? columnTypeFromComparer;
1020
+ if (arrayColumn) {
1021
+ const arrayColumnType = arrayColumn.type ? arrayColumn.type.toLowerCase() : "";
1022
+ if (arrayColumnType === "array" || arrayColumnType === "string[]" || arrayColumnType === "integer[]" || arrayColumnType === "float[]" || arrayColumnType === "boolean[]") {
1023
+ return `"${arrayColumn.name}"${isNegated ? "<>" : "="}'{}'`;
1024
+ }
1025
+ }
1026
+ if (isNegated) {
1027
+ return "1=1";
1028
+ }
1029
+ return "1<>1";
1030
+ }
1031
+ const orConstraints = [];
1032
+ const valueWithoutNull = [];
1033
+ for (const item of value) {
1034
+ if (_.isNull(item)) {
1035
+ orConstraints.push(
1036
+ buildWhere({
1037
+ repositoriesByModelNameLowered,
1038
+ model,
1039
+ propertyName,
1040
+ isNegated,
1041
+ value: null,
1042
+ params
1043
+ })
1044
+ );
1045
+ } else if (item === "") {
1046
+ orConstraints.push(
1047
+ buildWhere({
1048
+ repositoriesByModelNameLowered,
1049
+ model,
1050
+ propertyName,
1051
+ isNegated,
1052
+ value: "",
1053
+ params
1054
+ })
1055
+ );
1056
+ } else {
1057
+ valueWithoutNull.push(item);
1058
+ }
1059
+ }
1060
+ if (valueWithoutNull.length === 1) {
1061
+ orConstraints.push(
1062
+ buildWhere({
1063
+ repositoriesByModelNameLowered,
1064
+ model,
1065
+ propertyName,
1066
+ isNegated,
1067
+ value: valueWithoutNull[0],
1068
+ params
1069
+ })
1070
+ );
1071
+ } else if (valueWithoutNull.length) {
1072
+ const columnTypeFromPropertyName = propertyName ? model.columnsByPropertyName[propertyName] : null;
1073
+ const columnTypeFromComparer = comparer ? model.columnsByPropertyName[comparer] : null;
1074
+ const columnType = columnTypeFromPropertyName ?? columnTypeFromComparer;
1075
+ if (columnType) {
1076
+ let columnTypeLowered = columnType.type ? columnType.type.toLowerCase() : "";
1077
+ if (columnTypeLowered === "array" || columnTypeLowered === "string[]" || columnTypeLowered === "integer[]" || columnTypeLowered === "float[]" || columnTypeLowered === "boolean[]") {
1078
+ for (const val of valueWithoutNull) {
1079
+ orConstraints.push(
1080
+ buildWhere({
1081
+ repositoriesByModelNameLowered,
1082
+ model,
1083
+ propertyName,
1084
+ isNegated,
1085
+ value: val,
1086
+ params
1087
+ })
1088
+ );
1089
+ }
1090
+ } else {
1091
+ if (!columnTypeLowered) {
1092
+ const columnAsModelType = columnType;
1093
+ if (columnAsModelType.model) {
1094
+ const relatedModelRepository = repositoriesByModelNameLowered[columnAsModelType.model.toLowerCase()];
1095
+ if (!relatedModelRepository) {
1096
+ throw new QueryError(`Unable to find model schema (${columnAsModelType.model}) specified in where clause for "${columnAsModelType.propertyName}"`, model);
1097
+ }
1098
+ const relatedModelPrimaryKey = relatedModelRepository.model.primaryKeyColumn;
1099
+ if (!relatedModelPrimaryKey) {
1100
+ throw new QueryError(`Unable to find primary key column for ${columnAsModelType.model} specified in where clause for ${model.name}.${columnAsModelType.propertyName}`, model);
1101
+ }
1102
+ columnTypeLowered = relatedModelPrimaryKey.type ? relatedModelPrimaryKey.type.toLowerCase() : "";
1103
+ }
1104
+ }
1105
+ let castType;
1106
+ switch (columnTypeLowered) {
1107
+ case "int":
1108
+ case "integer":
1109
+ case "integer[]":
1110
+ castType = "::INTEGER[]";
1111
+ break;
1112
+ case "float":
1113
+ case "float[]":
1114
+ castType = "::NUMERIC[]";
1115
+ break;
1116
+ case "boolean":
1117
+ case "boolean[]":
1118
+ castType = "::BOOLEAN[]";
1119
+ break;
1120
+ default:
1121
+ castType = "::TEXT[]";
1122
+ break;
1123
+ }
1124
+ params.push(valueWithoutNull);
1125
+ orConstraints.push(`"${columnType.name}"${isNegated ? "<>ALL" : "=ANY"}($${params.length}${castType})`);
1126
+ }
1127
+ }
1128
+ }
1129
+ if (orConstraints.length === 1) {
1130
+ return orConstraints[0] ?? "";
1131
+ }
1132
+ if (isNegated) {
1133
+ return orConstraints.join(" AND ");
1134
+ }
1135
+ if (orConstraints.length) {
1136
+ return `(${orConstraints.join(" OR ")})`;
1137
+ }
1138
+ return "";
1139
+ }
1140
+ if (_.isObject(value) && !_.isDate(value)) {
1141
+ const andValues = [];
1142
+ for (const [key, where] of Object.entries(value)) {
1143
+ let subQueryComparer;
1144
+ if (isComparer(key)) {
1145
+ subQueryComparer = key;
1146
+ } else {
1147
+ propertyName = key;
1148
+ }
1149
+ andValues.push(
1150
+ buildWhere({
1151
+ repositoriesByModelNameLowered,
1152
+ model,
1153
+ propertyName,
1154
+ comparer: subQueryComparer,
1155
+ isNegated,
1156
+ value: where,
1157
+ params
1158
+ })
1159
+ );
1160
+ }
1161
+ return andValues.join(" AND ");
1162
+ }
1163
+ return buildComparisonOperatorStatement({
1164
+ model,
1165
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1166
+ propertyName,
1167
+ comparer,
1168
+ isNegated,
1169
+ value,
1170
+ params
1171
+ });
1172
+ }
1173
+ }
1174
+ }
1175
+ function buildOrOperatorStatement({
1176
+ repositoriesByModelNameLowered,
1177
+ model,
1178
+ isNegated,
1179
+ value,
1180
+ params = []
1181
+ }) {
1182
+ const orClauses = [];
1183
+ for (const constraint of value) {
1184
+ const orClause = buildWhere({
1185
+ repositoriesByModelNameLowered,
1186
+ model,
1187
+ isNegated,
1188
+ value: constraint,
1189
+ params
1190
+ });
1191
+ if (orClause) {
1192
+ orClauses.push(`(${orClause})`);
1193
+ }
1194
+ }
1195
+ if (orClauses.length === 1) {
1196
+ return orClauses[0] ?? "";
1197
+ }
1198
+ if (isNegated) {
1199
+ return orClauses.join(" AND ");
1200
+ }
1201
+ if (orClauses.length) {
1202
+ return `(${orClauses.join(" OR ")})`;
1203
+ }
1204
+ return "";
1205
+ }
1206
+ function buildLikeOperatorStatement({ model, propertyName, isNegated, value, params }) {
1207
+ if (_.isArray(value)) {
1208
+ if (!value.length) {
1209
+ if (isNegated) {
1210
+ return "1=1";
1211
+ }
1212
+ return "1<>1";
1213
+ }
1214
+ if (value.length > 1) {
1215
+ const orConstraints = [];
1216
+ for (const item of value) {
1217
+ if (_.isNull(item)) {
1218
+ orConstraints.push(
1219
+ buildLikeOperatorStatement({
1220
+ model,
1221
+ propertyName,
1222
+ isNegated,
1223
+ value: null,
1224
+ params
1225
+ })
1226
+ );
1227
+ } else if (item === "") {
1228
+ orConstraints.push(
1229
+ buildLikeOperatorStatement({
1230
+ model,
1231
+ propertyName,
1232
+ isNegated,
1233
+ value: "",
1234
+ params
1235
+ })
1236
+ );
1237
+ } else {
1238
+ orConstraints.push(
1239
+ buildLikeOperatorStatement({
1240
+ model,
1241
+ propertyName,
1242
+ isNegated,
1243
+ value: item,
1244
+ params
1245
+ })
1246
+ );
1247
+ }
1248
+ }
1249
+ if (orConstraints.length === 1) {
1250
+ return orConstraints[0] ?? "";
1251
+ }
1252
+ if (isNegated) {
1253
+ return orConstraints.join(" AND ");
1254
+ }
1255
+ if (orConstraints.length) {
1256
+ return `(${orConstraints.join(" OR ")})`;
1257
+ }
1258
+ return "";
1259
+ }
1260
+ value = value[0];
1261
+ }
1262
+ const column = model.columnsByPropertyName[propertyName];
1263
+ if (!column) {
1264
+ throw new QueryError(`Unable to find property ${propertyName} on model ${model.name}`, model);
1265
+ }
1266
+ if (_.isNull(value)) {
1267
+ return `"${column.name}" ${isNegated ? "IS NOT" : "IS"} NULL`;
1268
+ }
1269
+ if (_.isString(value)) {
1270
+ if (value) {
1271
+ params.push(value);
1272
+ const columnType = column.type?.toLowerCase();
1273
+ if (columnType === "array" || columnType === "string[]") {
1274
+ return `${isNegated ? "NOT " : ""}EXISTS(SELECT 1 FROM (SELECT unnest("${column.name}") AS "unnested_${column.name}") __unnested WHERE "unnested_${column.name}" ILIKE $${params.length})`;
1275
+ }
1276
+ return `"${column.name}"${isNegated ? " NOT" : ""} ILIKE $${params.length}`;
1277
+ }
1278
+ return `"${column.name}" ${isNegated ? "!=" : "="} ''`;
1279
+ }
1280
+ throw new QueryError(`Expected value to be a string for "like" constraint. Property (${propertyName}) in model (${model.name}).`, model);
1281
+ }
1282
+ function buildComparisonOperatorStatement({ model, propertyName, comparer, isNegated, value, params = [] }) {
1283
+ const column = model.columnsByPropertyName[propertyName];
1284
+ if (!column) {
1285
+ throw new QueryError(`Unable to find property ${propertyName} on model ${model.name}`, model);
1286
+ }
1287
+ if (_.isNull(value)) {
1288
+ return `"${column.name}" ${isNegated ? "IS NOT" : "IS"} NULL`;
1289
+ }
1290
+ params.push(value);
1291
+ const columnType = column.type ?? "unknown";
1292
+ const supportsLessThanGreaterThan = columnType !== "array" && columnType !== "json";
1293
+ switch (comparer) {
1294
+ case "<":
1295
+ if (!supportsLessThanGreaterThan) {
1296
+ throw new QueryError(`< operator is not supported for ${columnType} type. ${propertyName || ""} on ${model.name}`, model);
1297
+ }
1298
+ return `"${column.name}"${isNegated ? ">=" : "<"}$${params.length}`;
1299
+ case "<=":
1300
+ if (!supportsLessThanGreaterThan) {
1301
+ throw new QueryError(`<= operator is not supported for ${columnType} type. ${propertyName || ""} on ${model.name}`, model);
1302
+ }
1303
+ return `"${column.name}"${isNegated ? ">" : "<="}$${params.length}`;
1304
+ case ">":
1305
+ if (!supportsLessThanGreaterThan) {
1306
+ throw new QueryError(`> operator is not supported for ${columnType} type. ${propertyName || ""} on ${model.name}`, model);
1307
+ }
1308
+ return `"${column.name}"${isNegated ? "<=" : ">"}$${params.length}`;
1309
+ case ">=":
1310
+ if (!supportsLessThanGreaterThan) {
1311
+ throw new QueryError(`>= operator is not supported for ${columnType} type. ${propertyName || ""} on ${model.name}`, model);
1312
+ }
1313
+ return `"${column.name}"${isNegated ? "<" : ">="}$${params.length}`;
1314
+ default:
1315
+ if (columnType === "array" || columnType.endsWith("[]")) {
1316
+ return `$${params.length}${isNegated ? "<>ALL(" : "=ANY("}"${column.name}")`;
1317
+ }
1318
+ return `"${column.name}"${isNegated ? "<>" : "="}$${params.length}`;
1319
+ }
1320
+ }
1321
+ function isComparer(value) {
1322
+ switch (value) {
1323
+ case "!":
1324
+ case "not":
1325
+ case "or":
1326
+ case "and":
1327
+ case "contains":
1328
+ case "startsWith":
1329
+ case "endsWith":
1330
+ case "like":
1331
+ case "<":
1332
+ case "<=":
1333
+ case ">":
1334
+ case ">=":
1335
+ return true;
1336
+ default:
1337
+ return false;
1338
+ }
1339
+ }
1340
+
1341
+ var __defProp = Object.defineProperty;
1342
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1343
+ var __publicField = (obj, key, value) => {
1344
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1345
+ return value;
1346
+ };
1347
+ class ReadonlyRepository {
1348
+ constructor({ modelMetadata, type, pool, readonlyPool, repositoriesByModelNameLowered }) {
1349
+ __publicField(this, "_modelMetadata");
1350
+ __publicField(this, "_type");
1351
+ __publicField(this, "_pool");
1352
+ __publicField(this, "_readonlyPool");
1353
+ __publicField(this, "_repositoriesByModelNameLowered");
1354
+ __publicField(this, "_floatProperties", []);
1355
+ __publicField(this, "_intProperties", []);
1356
+ this._modelMetadata = modelMetadata;
1357
+ this._type = type;
1358
+ this._pool = pool;
1359
+ this._readonlyPool = readonlyPool ?? pool;
1360
+ this._repositoriesByModelNameLowered = repositoriesByModelNameLowered;
1361
+ for (const column of modelMetadata.columns) {
1362
+ if (column.type === "float") {
1363
+ this._floatProperties.push(column.propertyName);
1364
+ } else if (column.type === "integer") {
1365
+ this._intProperties.push(column.propertyName);
1366
+ }
1367
+ }
1368
+ }
1369
+ get model() {
1370
+ return this._modelMetadata;
1371
+ }
1372
+ /**
1373
+ * Gets a single object
1374
+ * @param {object} [args] - Arguments
1375
+ * @param {string[]} [args.select] - Array of model property names to return from the query.
1376
+ * @param {object} [args.where] - Object representing the where query
1377
+ * @param {string|object} [args.sort] - Property name(s) to sort by
1378
+ */
1379
+ findOne(args = {}) {
1380
+ const { stack } = new Error(`${this.model.name}.findOne()`);
1381
+ let select;
1382
+ let where = {};
1383
+ let sort = null;
1384
+ let poolOverride;
1385
+ for (const [name, value] of Object.entries(args)) {
1386
+ let isWhereCriteria = false;
1387
+ switch (name) {
1388
+ case "select":
1389
+ if (value) {
1390
+ select = new Set(value);
1391
+ }
1392
+ break;
1393
+ case "where":
1394
+ where = value;
1395
+ break;
1396
+ case "sort":
1397
+ sort = value;
1398
+ break;
1399
+ case "pool":
1400
+ poolOverride = value;
1401
+ break;
1402
+ default:
1403
+ select = void 0;
1404
+ where = args;
1405
+ sort = null;
1406
+ isWhereCriteria = true;
1407
+ break;
1408
+ }
1409
+ if (isWhereCriteria) {
1410
+ break;
1411
+ }
1412
+ }
1413
+ const populates = [];
1414
+ const manuallySetFields = [];
1415
+ const sorts = sort ? this._convertSortsToOrderBy(sort) : [];
1416
+ const modelInstance = this;
1417
+ return {
1418
+ /**
1419
+ * Filters the query
1420
+ * @param {object} value - Object representing the where query
1421
+ */
1422
+ where(value) {
1423
+ where = value;
1424
+ return this;
1425
+ },
1426
+ /**
1427
+ * Populates/hydrates relations
1428
+ * @param {string} propertyName - Name of property to join
1429
+ * @param {object} [options] - Populate options
1430
+ * @param {object} [options.where] - Object representing the where query
1431
+ * @param {string[]} [options.select] - Array of model property names to return from the query.
1432
+ * @param {string|object} [options.sort] - Property name(s) to sort by
1433
+ * @param {string|number} [options.skip] - Number of records to skip
1434
+ * @param {string|number} [options.limit] - Number of results to return
1435
+ */
1436
+ populate(propertyName, options) {
1437
+ if (select && !select.has(propertyName)) {
1438
+ for (const column of modelInstance.model.columns) {
1439
+ if (column.model && column.propertyName === propertyName) {
1440
+ select.add(column.propertyName);
1441
+ }
1442
+ }
1443
+ }
1444
+ populates.push({
1445
+ propertyName,
1446
+ where: options?.where,
1447
+ select: options?.select,
1448
+ sort: options?.sort,
1449
+ skip: options?.skip,
1450
+ limit: options?.limit,
1451
+ pool: options?.pool ?? poolOverride
1452
+ });
1453
+ return this;
1454
+ },
1455
+ /**
1456
+ * Sorts the query
1457
+ * @param {string|object} [value]
1458
+ */
1459
+ sort(value) {
1460
+ if (value) {
1461
+ sorts.push(...modelInstance._convertSortsToOrderBy(value));
1462
+ }
1463
+ return this;
1464
+ },
1465
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1466
+ UNSAFE_withOriginalFieldType(_propertyName) {
1467
+ return this;
1468
+ },
1469
+ UNSAFE_withFieldValue(propertyName, value) {
1470
+ manuallySetFields.push({
1471
+ propertyName,
1472
+ value
1473
+ });
1474
+ return this;
1475
+ },
1476
+ async then(resolve, reject) {
1477
+ try {
1478
+ if (_.isString(where)) {
1479
+ return await reject(new Error("The query cannot be a string, it must be an object"));
1480
+ }
1481
+ const { query, params } = getSelectQueryAndParams({
1482
+ repositoriesByModelNameLowered: modelInstance._repositoriesByModelNameLowered,
1483
+ model: modelInstance.model,
1484
+ select: select ? Array.from(select) : void 0,
1485
+ where,
1486
+ sorts,
1487
+ limit: 1,
1488
+ skip: 0
1489
+ });
1490
+ const pool = poolOverride ?? modelInstance._readonlyPool;
1491
+ const results = await pool.query(query, params);
1492
+ const firstResult = _.first(results.rows);
1493
+ if (firstResult) {
1494
+ const result = modelInstance._buildInstance(firstResult);
1495
+ if (populates.length) {
1496
+ await modelInstance.populateFields([result], populates);
1497
+ }
1498
+ for (const manuallySetField of manuallySetFields) {
1499
+ result[manuallySetField.propertyName] = manuallySetField.value;
1500
+ }
1501
+ return await resolve(result);
1502
+ }
1503
+ return await resolve(null);
1504
+ } catch (ex) {
1505
+ const typedException = ex;
1506
+ if (typedException.stack) {
1507
+ typedException.stack += `
1508
+ ${stack ?? ""}`;
1509
+ } else {
1510
+ typedException.stack = stack;
1511
+ }
1512
+ return reject(typedException);
1513
+ }
1514
+ }
1515
+ };
1516
+ }
1517
+ /**
1518
+ * Gets a collection of objects
1519
+ * @param {object} [args] - Arguments
1520
+ * @param {string[]} [args.select] - Array of model property names to return from the query.
1521
+ * @param {object} [args.where] - Object representing the where query
1522
+ * @param {string|object} [args.sort] - Property name(s) to sort by
1523
+ * @param {string|number} [args.skip] - Number of records to skip
1524
+ * @param {string|number} [args.limit] - Number of results to return
1525
+ */
1526
+ find(args = {}) {
1527
+ const { stack } = new Error(`${this.model.name}.find()`);
1528
+ let select;
1529
+ let where = {};
1530
+ let sort = null;
1531
+ let skip = null;
1532
+ let limit = null;
1533
+ let poolOverride;
1534
+ for (const [name, value] of Object.entries(args)) {
1535
+ let isWhereCriteria = false;
1536
+ switch (name) {
1537
+ case "select":
1538
+ if (value) {
1539
+ select = new Set(value);
1540
+ }
1541
+ break;
1542
+ case "where":
1543
+ where = value;
1544
+ break;
1545
+ case "sort":
1546
+ sort = value;
1547
+ break;
1548
+ case "skip":
1549
+ skip = value;
1550
+ break;
1551
+ case "limit":
1552
+ limit = value;
1553
+ break;
1554
+ case "pool":
1555
+ poolOverride = value;
1556
+ break;
1557
+ default:
1558
+ select = void 0;
1559
+ where = args;
1560
+ sort = null;
1561
+ skip = null;
1562
+ limit = null;
1563
+ isWhereCriteria = true;
1564
+ break;
1565
+ }
1566
+ if (isWhereCriteria) {
1567
+ break;
1568
+ }
1569
+ }
1570
+ const populates = [];
1571
+ const sorts = sort ? this._convertSortsToOrderBy(sort) : [];
1572
+ const modelInstance = this;
1573
+ return {
1574
+ /**
1575
+ * Filters the query
1576
+ * @param {object} value - Object representing the where query
1577
+ */
1578
+ where(value) {
1579
+ where = value;
1580
+ return this;
1581
+ },
1582
+ /**
1583
+ * Populates/hydrates relations
1584
+ * @param {string} propertyName - Name of property to join
1585
+ * @param {object} [options] - Populate options
1586
+ * @param {object} [options.where] - Object representing the where query
1587
+ * @param {string[]} [options.select] - Array of model property names to return from the query.
1588
+ * @param {string|object} [options.sort] - Property name(s) to sort by
1589
+ * @param {string|number} [options.skip] - Number of records to skip
1590
+ * @param {string|number} [options.limit] - Number of results to return
1591
+ */
1592
+ populate(propertyName, options) {
1593
+ if (select && !select.has(propertyName)) {
1594
+ for (const column of modelInstance.model.columns) {
1595
+ if (column.model && column.propertyName === propertyName) {
1596
+ select.add(column.propertyName);
1597
+ }
1598
+ }
1599
+ }
1600
+ populates.push({
1601
+ propertyName,
1602
+ where: options?.where,
1603
+ select: options?.select,
1604
+ sort: options?.sort,
1605
+ skip: options?.skip,
1606
+ limit: options?.limit,
1607
+ pool: options?.pool ?? poolOverride
1608
+ });
1609
+ return this;
1610
+ },
1611
+ /**
1612
+ * Sorts the query
1613
+ * @param {string|string[]|object} [value]
1614
+ */
1615
+ sort(value) {
1616
+ if (value) {
1617
+ sorts.push(...modelInstance._convertSortsToOrderBy(value));
1618
+ }
1619
+ return this;
1620
+ },
1621
+ /**
1622
+ * Limits results returned by the query
1623
+ * @param {number} value
1624
+ */
1625
+ limit(value) {
1626
+ limit = value;
1627
+ return this;
1628
+ },
1629
+ /**
1630
+ * Skips records returned by the query
1631
+ * @param {number} value
1632
+ */
1633
+ skip(value) {
1634
+ skip = value;
1635
+ return this;
1636
+ },
1637
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1638
+ UNSAFE_withOriginalFieldType(_propertyName) {
1639
+ return this;
1640
+ },
1641
+ /**
1642
+ * Pages records returned by the query
1643
+ * @param {number} [page=1] - Page to return - Starts at 1
1644
+ * @param {number} [limit=10] - Number of records to return
1645
+ */
1646
+ paginate({ page = 1, limit: paginateLimit = 10 }) {
1647
+ const safePage = Math.max(page, 1);
1648
+ return this.skip(safePage * paginateLimit - paginateLimit).limit(paginateLimit);
1649
+ },
1650
+ async then(resolve, reject) {
1651
+ try {
1652
+ if (_.isString(where)) {
1653
+ return await reject(new Error("The query cannot be a string, it must be an object"));
1654
+ }
1655
+ const { query, params } = getSelectQueryAndParams({
1656
+ repositoriesByModelNameLowered: modelInstance._repositoriesByModelNameLowered,
1657
+ model: modelInstance.model,
1658
+ select: select ? Array.from(select) : void 0,
1659
+ where,
1660
+ sorts,
1661
+ skip: skip ?? 0,
1662
+ limit: limit ?? 0
1663
+ });
1664
+ const pool = poolOverride ?? modelInstance._readonlyPool;
1665
+ const results = await pool.query(query, params);
1666
+ const entities = modelInstance._buildInstances(results.rows);
1667
+ if (populates.length) {
1668
+ await modelInstance.populateFields(entities, populates);
1669
+ }
1670
+ return await resolve(entities);
1671
+ } catch (ex) {
1672
+ const typedException = ex;
1673
+ if (typedException.stack) {
1674
+ typedException.stack += `
1675
+ ${stack ?? ""}`;
1676
+ } else {
1677
+ typedException.stack = stack;
1678
+ }
1679
+ return reject(typedException);
1680
+ }
1681
+ }
1682
+ };
1683
+ }
1684
+ /**
1685
+ * Gets a count of rows matching the where query
1686
+ * @param {object} [args] - Arguments
1687
+ * @param {object} [args.where] - Object representing the where query
1688
+ * @param {object} [args.pool] - Override the db pool to use for the query
1689
+ * @returns {number} Number of records matching the where criteria
1690
+ */
1691
+ count(args = {}) {
1692
+ const { stack } = new Error(`${this.model.name}.count()`);
1693
+ let where = {};
1694
+ let poolOverride;
1695
+ for (const [name, value] of Object.entries(args)) {
1696
+ let isWhereCriteria = false;
1697
+ switch (name) {
1698
+ case "where":
1699
+ where = value;
1700
+ break;
1701
+ case "pool":
1702
+ poolOverride = value;
1703
+ break;
1704
+ default:
1705
+ where = args;
1706
+ isWhereCriteria = true;
1707
+ break;
1708
+ }
1709
+ if (isWhereCriteria) {
1710
+ break;
1711
+ }
1712
+ }
1713
+ const modelInstance = this;
1714
+ return {
1715
+ /**
1716
+ * Filters the query
1717
+ * @param {object} value - Object representing the where query
1718
+ */
1719
+ where(value) {
1720
+ where = value;
1721
+ return this;
1722
+ },
1723
+ async then(resolve, reject) {
1724
+ try {
1725
+ const { query, params } = getCountQueryAndParams({
1726
+ repositoriesByModelNameLowered: modelInstance._repositoriesByModelNameLowered,
1727
+ model: modelInstance.model,
1728
+ where
1729
+ });
1730
+ const pool = poolOverride ?? modelInstance._readonlyPool;
1731
+ const result = await pool.query(query, params);
1732
+ const firstResult = _.first(result.rows);
1733
+ const originalValue = firstResult ? firstResult.count : 0;
1734
+ return await resolve(Number(originalValue));
1735
+ } catch (ex) {
1736
+ const typedException = ex;
1737
+ if (typedException.stack) {
1738
+ typedException.stack += `
1739
+ ${stack ?? ""}`;
1740
+ } else {
1741
+ typedException.stack = stack;
1742
+ }
1743
+ return reject(typedException);
1744
+ }
1745
+ }
1746
+ };
1747
+ }
1748
+ _buildInstance(row) {
1749
+ if (_.isNil(row)) {
1750
+ return row;
1751
+ }
1752
+ const instance = new this._type();
1753
+ Object.assign(instance, row);
1754
+ for (const name of this._floatProperties) {
1755
+ const originalValue = row[name];
1756
+ if (!_.isNil(originalValue) && typeof originalValue === "string") {
1757
+ try {
1758
+ const value = Number(originalValue);
1759
+ if (_.isFinite(value) && value.toString() === originalValue) {
1760
+ instance[name] = value;
1761
+ }
1762
+ } catch {
1763
+ }
1764
+ }
1765
+ }
1766
+ for (const name of this._intProperties) {
1767
+ const originalValue = row[name];
1768
+ if (!_.isNil(originalValue) && typeof originalValue === "string") {
1769
+ try {
1770
+ const value = Number(originalValue);
1771
+ if (_.isFinite(value) && value.toString() === originalValue) {
1772
+ const valueAsInt = _.toInteger(value);
1773
+ if (Number.isSafeInteger(valueAsInt)) {
1774
+ instance[name] = valueAsInt;
1775
+ }
1776
+ }
1777
+ } catch {
1778
+ }
1779
+ }
1780
+ }
1781
+ return instance;
1782
+ }
1783
+ _buildInstances(rows) {
1784
+ if (_.isNil(rows)) {
1785
+ return [];
1786
+ }
1787
+ return rows.map((row) => this._buildInstance(row));
1788
+ }
1789
+ // eslint-disable-next-line class-methods-use-this
1790
+ _convertSortsToOrderBy(sorts) {
1791
+ const result = [];
1792
+ if (sorts) {
1793
+ if (Array.isArray(sorts)) {
1794
+ for (const sort of sorts) {
1795
+ const parts = sort.trim().split(" ");
1796
+ const propertyName = parts.shift();
1797
+ result.push({
1798
+ propertyName,
1799
+ descending: /desc/i.test(parts.join(""))
1800
+ });
1801
+ }
1802
+ } else if (_.isString(sorts)) {
1803
+ for (const sort of sorts.split(",")) {
1804
+ const parts = sort.trim().split(" ");
1805
+ const propertyName = parts.shift();
1806
+ result.push({
1807
+ propertyName,
1808
+ descending: /desc/i.test(parts.join(""))
1809
+ });
1810
+ }
1811
+ } else if (_.isObject(sorts)) {
1812
+ for (const [propertyName, orderValue] of Object.entries(sorts)) {
1813
+ let descending = false;
1814
+ const order = orderValue;
1815
+ if (order && (order === -1 || /desc/i.test(`${order}`))) {
1816
+ descending = true;
1817
+ }
1818
+ result.push({
1819
+ propertyName,
1820
+ descending
1821
+ });
1822
+ }
1823
+ }
1824
+ }
1825
+ return result;
1826
+ }
1827
+ // NOTE: This will mutate `entities`
1828
+ async populateFields(entities, populates) {
1829
+ if (!entities.length) {
1830
+ return;
1831
+ }
1832
+ const populateQueries = [];
1833
+ for (const populate of populates) {
1834
+ const column = this.model.columnsByPropertyName[populate.propertyName];
1835
+ if (!column) {
1836
+ throw new Error(`Unable to find ${populate.propertyName} on ${this.model.name} model for populating.`);
1837
+ }
1838
+ const modelColumn = column;
1839
+ const collectionColumn = column;
1840
+ if (modelColumn.model) {
1841
+ populateQueries.push(this.populateSingleAssociation(entities, populate, modelColumn));
1842
+ } else if (collectionColumn.collection) {
1843
+ const populateRepository = this._repositoriesByModelNameLowered[collectionColumn.collection.toLowerCase()];
1844
+ if (!populateRepository) {
1845
+ throw new Error(`Unable to find populate repository for collection by name ${collectionColumn.collection}. From ${column.target}#${populate.propertyName}`);
1846
+ }
1847
+ const { primaryKeyColumn } = this.model;
1848
+ if (!primaryKeyColumn) {
1849
+ throw new Error(`Unable to populate ${column.target}#${column.propertyName}. There is no primary key defined in ${this.model.name}`);
1850
+ }
1851
+ const entityIds = /* @__PURE__ */ new Set();
1852
+ for (const entity of entities) {
1853
+ const id = entity[primaryKeyColumn.propertyName];
1854
+ if (_.isNil(id)) {
1855
+ throw new Error(`Primary key (${primaryKeyColumn.propertyName}) has no value for entity ${column.target}.`);
1856
+ }
1857
+ entityIds.add(id);
1858
+ }
1859
+ if (collectionColumn.through) {
1860
+ const populateModelPrimaryKeyColumn = populateRepository.model.primaryKeyColumn;
1861
+ if (!populateModelPrimaryKeyColumn) {
1862
+ throw new Error(
1863
+ `Unable to populate ${collectionColumn.collection} objects from ${column.target}#${column.propertyName}. There is no primary key defined in ${collectionColumn.collection}`
1864
+ );
1865
+ }
1866
+ populateQueries.push(
1867
+ this.populateManyManyCollection(
1868
+ entities,
1869
+ primaryKeyColumn.propertyName,
1870
+ Array.from(entityIds),
1871
+ populateModelPrimaryKeyColumn.propertyName,
1872
+ populate,
1873
+ collectionColumn,
1874
+ populateRepository
1875
+ )
1876
+ );
1877
+ } else {
1878
+ populateQueries.push(this.populateOneManyCollection(entities, primaryKeyColumn.propertyName, Array.from(entityIds), populate, collectionColumn, populateRepository));
1879
+ }
1880
+ }
1881
+ }
1882
+ if (populateQueries.length) {
1883
+ await Promise.all(populateQueries);
1884
+ }
1885
+ }
1886
+ async populateSingleAssociation(entities, populate, column) {
1887
+ const populateRepository = this._repositoriesByModelNameLowered[column.model.toLowerCase()];
1888
+ if (!populateRepository) {
1889
+ throw new Error(`Unable to find populate repository by entity name: ${column.model}. From ${column.target}#${column.propertyName}`);
1890
+ }
1891
+ if (!populateRepository.model.primaryKeyColumn) {
1892
+ throw new Error(`Unable to populate ${column.model} from ${column.target}#${column.propertyName}. There is no primary key defined in ${column.model}`);
1893
+ }
1894
+ const propertyName = populate.propertyName;
1895
+ const populateIds = /* @__PURE__ */ new Set();
1896
+ for (const entity of entities) {
1897
+ const populateId = entity[propertyName];
1898
+ if (populateId) {
1899
+ populateIds.add(populateId);
1900
+ }
1901
+ }
1902
+ const populateWhere = {
1903
+ [populateRepository.model.primaryKeyColumn.propertyName]: Array.from(populateIds),
1904
+ ...populate.where
1905
+ };
1906
+ const populateResults = await populateRepository.find({
1907
+ select: populate.select,
1908
+ where: populateWhere,
1909
+ sort: populate.sort,
1910
+ pool: populate.pool
1911
+ });
1912
+ const populateResultsById = _.keyBy(populateResults, populateRepository.model.primaryKeyColumn.propertyName);
1913
+ for (const entity of entities) {
1914
+ entity[propertyName] = populateResultsById[entity[propertyName]];
1915
+ }
1916
+ }
1917
+ async populateOneManyCollection(entities, primaryKeyPropertyName, entityIds, populate, column, populateRepository) {
1918
+ if (entities.length > 1 && populate.select && !populate.select.includes(column.via)) {
1919
+ throw new Error(`Unable to populate "${populate.propertyName}" on ${this.model.name}. "${column.via}" is not included in select array.`);
1920
+ }
1921
+ const populateWhere = {
1922
+ [column.via]: entityIds,
1923
+ ...populate.where
1924
+ };
1925
+ const populateResults = await populateRepository.find({
1926
+ select: populate.select,
1927
+ where: populateWhere,
1928
+ sort: populate.sort,
1929
+ skip: populate.skip,
1930
+ limit: populate.limit,
1931
+ pool: populate.pool
1932
+ });
1933
+ if (entities.length === 1) {
1934
+ for (const entity of entities) {
1935
+ entity[populate.propertyName] = populateResults;
1936
+ }
1937
+ } else {
1938
+ const populateResultsByEntityId = _.groupBy(populateResults, column.via);
1939
+ for (const entity of entities) {
1940
+ const id = entity[primaryKeyPropertyName];
1941
+ entity[populate.propertyName] = populateResultsByEntityId[id] || [];
1942
+ }
1943
+ }
1944
+ }
1945
+ async populateManyManyCollection(entities, primaryKeyPropertyName, entityIds, populateModelPrimaryKeyPropertyName, populate, column, populateRepository) {
1946
+ if (!column.through) {
1947
+ throw new Error(`Unable to populate multi-map collection: Missing "through" value. From ${column.target}#${populate.propertyName}`);
1948
+ }
1949
+ const throughRepository = this._repositoriesByModelNameLowered[column.through.toLowerCase()];
1950
+ if (!throughRepository) {
1951
+ throw new Error(`Unable to find repository for multi-map collection: ${column.through}. From ${column.target}#${populate.propertyName}`);
1952
+ }
1953
+ let relatedModelColumn;
1954
+ for (const populateModelColumn of populateRepository.model.columns) {
1955
+ const { through } = populateModelColumn;
1956
+ if (through && through.toLowerCase() === column.through.toLowerCase()) {
1957
+ relatedModelColumn = populateModelColumn;
1958
+ break;
1959
+ }
1960
+ }
1961
+ if (!relatedModelColumn) {
1962
+ throw new Error(`Unable to find property on related model for multi-map collection: ${column.through}. From ${column.target}#${populate.propertyName}`);
1963
+ }
1964
+ const mapRecords = await throughRepository.find({
1965
+ select: [column.via, relatedModelColumn.via],
1966
+ where: {
1967
+ [column.via]: entityIds
1968
+ },
1969
+ pool: populate.pool
1970
+ });
1971
+ const populateIds = /* @__PURE__ */ new Set();
1972
+ const populateIdsByEntityId = {};
1973
+ for (const mapRecord of mapRecords) {
1974
+ const entityId = mapRecord[column.via];
1975
+ const populatedId = mapRecord[relatedModelColumn.via];
1976
+ populateIds.add(populatedId);
1977
+ const entityPopulateIds = populateIdsByEntityId[entityId] ?? [];
1978
+ entityPopulateIds.push(populatedId);
1979
+ populateIdsByEntityId[entityId] = entityPopulateIds;
1980
+ }
1981
+ const populateWhere = _.merge(
1982
+ {
1983
+ [populateModelPrimaryKeyPropertyName]: Array.from(populateIds)
1984
+ },
1985
+ populate.where
1986
+ );
1987
+ const populateResults = await populateRepository.find({
1988
+ select: populate.select,
1989
+ where: populateWhere,
1990
+ sort: populate.sort,
1991
+ skip: populate.skip,
1992
+ limit: populate.limit,
1993
+ pool: populate.pool
1994
+ });
1995
+ const populateResultsById = _.keyBy(populateResults, populateModelPrimaryKeyPropertyName);
1996
+ for (const entity of entities) {
1997
+ const populatedItems = [];
1998
+ const entityId = entity[primaryKeyPropertyName];
1999
+ const populateIdsForEntity = populateIdsByEntityId[entityId] ?? [];
2000
+ for (const id of populateIdsForEntity) {
2001
+ const populatedItem = populateResultsById[id];
2002
+ if (populatedItem) {
2003
+ populatedItems.push(populatedItem);
2004
+ }
2005
+ }
2006
+ entity[populate.propertyName] = populatedItems;
2007
+ }
2008
+ }
2009
+ }
2010
+
2011
+ class Repository extends ReadonlyRepository {
2012
+ /**
2013
+ * Creates an object using the specified values
2014
+ * @param {object|object[]} values - Values to insert as a new object. If an array is specified, multiple rows will be inserted
2015
+ * @param {object} [options]
2016
+ * @param {boolean} [options.returnRecords=true] - Determines if inserted records should be returned
2017
+ * @param {string[]} [options.returnSelect] - Array of model property names to return from the query.
2018
+ * @param {object} [options.onConflict] - Options to handle conflicts due to a unique constraint or exclusion constraint error during insert
2019
+ * @returns {object|object[]|void} Return value from the db
2020
+ */
2021
+ async create(values, options) {
2022
+ if (this.model.readonly) {
2023
+ throw new Error(`${this.model.name} is readonly.`);
2024
+ }
2025
+ if (_.isArray(values) && !values.length) {
2026
+ return [];
2027
+ }
2028
+ if (this._type.beforeCreate) {
2029
+ if (Array.isArray(values)) {
2030
+ values = await Promise.all(values.map((value) => this._type.beforeCreate ? this._type.beforeCreate(value) : Promise.resolve()));
2031
+ } else {
2032
+ values = await this._type.beforeCreate(values);
2033
+ }
2034
+ }
2035
+ let returnRecords = true;
2036
+ let returnSelect;
2037
+ if (options) {
2038
+ if (options.returnRecords === false) {
2039
+ returnRecords = false;
2040
+ } else if (options.returnSelect) {
2041
+ returnSelect = options.returnSelect;
2042
+ }
2043
+ }
2044
+ const { query, params } = getInsertQueryAndParams({
2045
+ repositoriesByModelNameLowered: this._repositoriesByModelNameLowered,
2046
+ model: this.model,
2047
+ values,
2048
+ returnRecords,
2049
+ returnSelect,
2050
+ onConflict: options?.onConflict
2051
+ });
2052
+ const results = await this._pool.query(query, params);
2053
+ if (returnRecords) {
2054
+ if (_.isArray(values)) {
2055
+ return this._buildInstances(results.rows);
2056
+ }
2057
+ const firstResult = _.first(results.rows);
2058
+ if (firstResult) {
2059
+ return this._buildInstance(firstResult);
2060
+ }
2061
+ throw new Error("Unknown error getting created rows back from the database");
2062
+ }
2063
+ return void 0;
2064
+ }
2065
+ /**
2066
+ * Updates object(s) matching the where query, with the specified values
2067
+ * @param {object} where - Object representing the where query
2068
+ * @param {object} values - Values to update
2069
+ * @param {object} [options]
2070
+ * @param {boolean} [options.returnRecords=true] - Determines if inserted records should be returned
2071
+ * @param {string[]} [options.returnSelect] - Array of model property names to return from the query.
2072
+ * @returns {object[]|void} Return values from the db or `true` if returnRecords=false
2073
+ */
2074
+ async update(where, values, options) {
2075
+ if (this.model.readonly) {
2076
+ throw new Error(`${this.model.name} is readonly.`);
2077
+ }
2078
+ if (_.isString(where)) {
2079
+ throw new Error("The query cannot be a string, it must be an object");
2080
+ }
2081
+ if (this._type.beforeUpdate) {
2082
+ values = await this._type.beforeUpdate(values);
2083
+ }
2084
+ let returnRecords = true;
2085
+ let returnSelect;
2086
+ if (options) {
2087
+ if (options.returnRecords === false) {
2088
+ returnRecords = false;
2089
+ } else if (options.returnSelect) {
2090
+ returnSelect = options.returnSelect;
2091
+ }
2092
+ }
2093
+ const { query, params } = getUpdateQueryAndParams({
2094
+ repositoriesByModelNameLowered: this._repositoriesByModelNameLowered,
2095
+ model: this.model,
2096
+ where,
2097
+ values,
2098
+ returnRecords,
2099
+ returnSelect
2100
+ });
2101
+ const results = await this._pool.query(query, params);
2102
+ if (returnRecords) {
2103
+ return this._buildInstances(results.rows);
2104
+ }
2105
+ return void 0;
2106
+ }
2107
+ /**
2108
+ * Destroys object(s) matching the where query
2109
+ * @param {object} where - Object representing the where query
2110
+ * @param {object} [options]
2111
+ * @param {boolean} [options.returnRecords=false] - Determines if inserted records should be returned
2112
+ * @param {string[]} [options.returnSelect] - Array of model property names to return from the query.
2113
+ * @returns {object[]|void} `void` or records affected if returnRecords=true
2114
+ */
2115
+ destroy(where = {}, options) {
2116
+ if (this.model.readonly) {
2117
+ throw new Error(`${this.model.name} is readonly.`);
2118
+ }
2119
+ const { stack } = new Error(`${this.model.name}.destroy()`);
2120
+ const modelInstance = this;
2121
+ const returnSelect = options?.returnSelect;
2122
+ const returnRecords = options?.returnRecords ?? !!returnSelect;
2123
+ return {
2124
+ /**
2125
+ * Filters the query
2126
+ * @param {object} value - Object representing the where query
2127
+ */
2128
+ where(value) {
2129
+ where = value;
2130
+ return this;
2131
+ },
2132
+ async then(resolve, reject) {
2133
+ if (_.isString(where)) {
2134
+ return reject(new Error("The query cannot be a string, it must be an object"));
2135
+ }
2136
+ try {
2137
+ const { query, params } = getDeleteQueryAndParams({
2138
+ repositoriesByModelNameLowered: modelInstance._repositoriesByModelNameLowered,
2139
+ model: modelInstance.model,
2140
+ where,
2141
+ returnRecords,
2142
+ returnSelect
2143
+ });
2144
+ const result = await modelInstance._pool.query(query, params);
2145
+ if (returnRecords) {
2146
+ return await resolve(modelInstance._buildInstances(result.rows));
2147
+ }
2148
+ return await resolve();
2149
+ } catch (ex) {
2150
+ const typedException = ex;
2151
+ if (typedException.stack) {
2152
+ typedException.stack = `${typedException.stack}
2153
+
2154
+ ${stack}`;
2155
+ } else {
2156
+ typedException.stack = stack;
2157
+ }
2158
+ return reject(typedException);
2159
+ }
2160
+ }
2161
+ };
2162
+ }
2163
+ }
2164
+
2165
+ function column(dbColumnNameOrOptions, options) {
2166
+ return function columnDecorator(object, propertyName) {
2167
+ if (!dbColumnNameOrOptions) {
2168
+ dbColumnNameOrOptions = _.snakeCase(propertyName);
2169
+ }
2170
+ let dbColumnName;
2171
+ if (typeof dbColumnNameOrOptions === "string") {
2172
+ dbColumnName = dbColumnNameOrOptions;
2173
+ } else {
2174
+ options = dbColumnNameOrOptions;
2175
+ }
2176
+ if (!options) {
2177
+ options = {};
2178
+ }
2179
+ if (!dbColumnName) {
2180
+ dbColumnName = options.name ?? _.snakeCase(propertyName);
2181
+ }
2182
+ const metadataStorage = getMetadataStorage();
2183
+ const columnCollectionOptions = options;
2184
+ if (columnCollectionOptions.collection || columnCollectionOptions.via) {
2185
+ if (!columnCollectionOptions.collection) {
2186
+ throw new Error("Unable to determine collection value. Please try specifying values as a strings to avoid circular dependency issues.");
2187
+ }
2188
+ metadataStorage.columns.push(
2189
+ new ColumnCollectionMetadata({
2190
+ target: object.constructor.name,
2191
+ name: dbColumnName,
2192
+ propertyName,
2193
+ required: columnCollectionOptions.required,
2194
+ collection: columnCollectionOptions.collection,
2195
+ through: columnCollectionOptions.through,
2196
+ via: columnCollectionOptions.via
2197
+ })
2198
+ );
2199
+ return;
2200
+ }
2201
+ const columnModelOptions = options;
2202
+ if (columnModelOptions.model) {
2203
+ metadataStorage.columns.push(
2204
+ new ColumnModelMetadata({
2205
+ target: object.constructor.name,
2206
+ name: dbColumnName,
2207
+ propertyName,
2208
+ required: columnModelOptions.required,
2209
+ model: columnModelOptions.model
2210
+ })
2211
+ );
2212
+ return;
2213
+ }
2214
+ const columnTypeOptions = options;
2215
+ metadataStorage.columns.push(
2216
+ new ColumnTypeMetadata({
2217
+ target: object.constructor.name,
2218
+ name: dbColumnName,
2219
+ propertyName,
2220
+ required: columnTypeOptions.required,
2221
+ type: columnTypeOptions.type,
2222
+ defaultsTo: columnTypeOptions.defaultsTo,
2223
+ enum: columnTypeOptions.enum,
2224
+ maxLength: columnTypeOptions.maxLength
2225
+ })
2226
+ );
2227
+ };
2228
+ }
2229
+
2230
+ function createDateColumn(dbColumnNameOrOptions, options) {
2231
+ return function createDateColumnDecorator(object, propertyName) {
2232
+ const metadataStorage = getMetadataStorage();
2233
+ let dbColumnName;
2234
+ if (typeof dbColumnNameOrOptions === "string") {
2235
+ dbColumnName = dbColumnNameOrOptions;
2236
+ } else {
2237
+ options = dbColumnNameOrOptions;
2238
+ }
2239
+ if (dbColumnNameOrOptions) {
2240
+ if (!options) {
2241
+ options = {};
2242
+ }
2243
+ if (!dbColumnName) {
2244
+ dbColumnName = options.name ?? _.snakeCase(propertyName);
2245
+ }
2246
+ metadataStorage.columns.push(
2247
+ new ColumnTypeMetadata({
2248
+ target: object.constructor.name,
2249
+ name: dbColumnName,
2250
+ propertyName,
2251
+ createDate: true,
2252
+ required: options.required,
2253
+ type: options.type
2254
+ })
2255
+ );
2256
+ } else {
2257
+ metadataStorage.columnModifiers.push({
2258
+ target: object.constructor.name,
2259
+ name: dbColumnName ?? _.snakeCase(propertyName),
2260
+ propertyName,
2261
+ createDate: true,
2262
+ required: options ? options.required : void 0,
2263
+ type: options ? options.type : "datetime"
2264
+ });
2265
+ }
2266
+ };
2267
+ }
2268
+
2269
+ function primaryColumn(dbColumnNameOrOptions, options) {
2270
+ return function primaryColumnDecorator(object, propertyName) {
2271
+ let dbColumnName;
2272
+ if (typeof dbColumnNameOrOptions === "string") {
2273
+ dbColumnName = dbColumnNameOrOptions;
2274
+ } else {
2275
+ options = dbColumnNameOrOptions;
2276
+ }
2277
+ if (dbColumnNameOrOptions) {
2278
+ if (!options) {
2279
+ options = {};
2280
+ }
2281
+ if (!dbColumnName) {
2282
+ dbColumnName = options.name ?? _.snakeCase(propertyName);
2283
+ }
2284
+ const { type } = options;
2285
+ const { model } = options;
2286
+ const metadataStorage = getMetadataStorage();
2287
+ if (model) {
2288
+ metadataStorage.columns.push(
2289
+ new ColumnModelMetadata({
2290
+ target: object.constructor.name,
2291
+ name: dbColumnName,
2292
+ propertyName,
2293
+ primary: true,
2294
+ required: options.required,
2295
+ model
2296
+ })
2297
+ );
2298
+ } else {
2299
+ metadataStorage.columns.push(
2300
+ new ColumnTypeMetadata({
2301
+ target: object.constructor.name,
2302
+ name: dbColumnName,
2303
+ propertyName,
2304
+ primary: true,
2305
+ required: options.required,
2306
+ type
2307
+ })
2308
+ );
2309
+ }
2310
+ } else {
2311
+ const metadataStorage = getMetadataStorage();
2312
+ metadataStorage.columnModifiers.push({
2313
+ target: object.constructor.name,
2314
+ name: dbColumnName ?? _.snakeCase(propertyName),
2315
+ propertyName,
2316
+ primary: true,
2317
+ required: options ? options.required : void 0,
2318
+ type: options ? options.type : void 0,
2319
+ model: options ? options.model : void 0
2320
+ });
2321
+ }
2322
+ };
2323
+ }
2324
+
2325
+ function table(dbNameOrTableOptions, options) {
2326
+ return function tableDecorator(classObject) {
2327
+ const className = classObject.name;
2328
+ let dbTableName;
2329
+ if (typeof dbNameOrTableOptions === "string") {
2330
+ dbTableName = dbNameOrTableOptions;
2331
+ } else {
2332
+ options = dbNameOrTableOptions;
2333
+ }
2334
+ if (!options) {
2335
+ options = {};
2336
+ }
2337
+ if (!options.name) {
2338
+ options.name = dbTableName ?? _.snakeCase(className);
2339
+ }
2340
+ const metadataStorage = getMetadataStorage();
2341
+ const modelMetadata = new ModelMetadata({
2342
+ name: className,
2343
+ type: classObject,
2344
+ tableName: options.name,
2345
+ readonly: options.readonly ?? false,
2346
+ connection: options.connection
2347
+ });
2348
+ metadataStorage.models.push(modelMetadata);
2349
+ };
2350
+ }
2351
+
2352
+ function updateDateColumn(dbColumnNameOrOptions, options) {
2353
+ return function updateDateColumnDecorator(object, propertyName) {
2354
+ let dbColumnName;
2355
+ if (typeof dbColumnNameOrOptions === "string") {
2356
+ dbColumnName = dbColumnNameOrOptions;
2357
+ } else {
2358
+ options = dbColumnNameOrOptions;
2359
+ }
2360
+ if (dbColumnNameOrOptions) {
2361
+ if (!options) {
2362
+ options = {};
2363
+ }
2364
+ if (!dbColumnName) {
2365
+ dbColumnName = options.name ?? _.snakeCase(propertyName);
2366
+ }
2367
+ const metadataStorage = getMetadataStorage();
2368
+ metadataStorage.columns.push(
2369
+ new ColumnTypeMetadata({
2370
+ target: object.constructor.name,
2371
+ name: dbColumnName,
2372
+ propertyName,
2373
+ updateDate: true,
2374
+ required: options.required,
2375
+ type: options.type
2376
+ })
2377
+ );
2378
+ } else {
2379
+ const metadataStorage = getMetadataStorage();
2380
+ metadataStorage.columnModifiers.push({
2381
+ target: object.constructor.name,
2382
+ name: dbColumnName ?? _.snakeCase(propertyName),
2383
+ propertyName,
2384
+ updateDate: true,
2385
+ required: options ? options.required : void 0,
2386
+ type: options ? options.type : "datetime"
2387
+ });
2388
+ }
2389
+ };
2390
+ }
2391
+
2392
+ function versionColumn(dbColumnNameOrOptions, options) {
2393
+ return function versionColumnDecorator(object, propertyName) {
2394
+ let dbColumnName;
2395
+ if (typeof dbColumnNameOrOptions === "string") {
2396
+ dbColumnName = dbColumnNameOrOptions;
2397
+ } else {
2398
+ options = dbColumnNameOrOptions;
2399
+ }
2400
+ if (dbColumnNameOrOptions) {
2401
+ if (!options) {
2402
+ options = {};
2403
+ }
2404
+ if (!dbColumnName) {
2405
+ dbColumnName = options.name ?? _.snakeCase(propertyName);
2406
+ }
2407
+ const metadataStorage = getMetadataStorage();
2408
+ metadataStorage.columns.push(
2409
+ new ColumnTypeMetadata({
2410
+ target: object.constructor.name,
2411
+ name: dbColumnName,
2412
+ propertyName,
2413
+ version: true,
2414
+ required: options.required,
2415
+ type: options.type
2416
+ })
2417
+ );
2418
+ } else {
2419
+ const metadataStorage = getMetadataStorage();
2420
+ metadataStorage.columnModifiers.push({
2421
+ target: object.constructor.name,
2422
+ name: dbColumnName ?? _.snakeCase(propertyName),
2423
+ propertyName,
2424
+ version: true,
2425
+ required: options ? options.required : void 0,
2426
+ type: options ? options.type : void 0
2427
+ });
2428
+ }
2429
+ };
2430
+ }
2431
+
2432
+ class Entity {
2433
+ static beforeCreate(values) {
2434
+ return values;
2435
+ }
2436
+ static beforeUpdate(values) {
2437
+ return values;
2438
+ }
2439
+ }
2440
+
2441
+ function getInheritanceTree(model) {
2442
+ const tree = [model];
2443
+ function getRecursivePrototypesOf(parentEntity) {
2444
+ const proto = Object.getPrototypeOf(parentEntity);
2445
+ if (proto && proto.name && proto.name !== "Function") {
2446
+ tree.unshift(proto);
2447
+ getRecursivePrototypesOf(proto);
2448
+ }
2449
+ }
2450
+ getRecursivePrototypesOf(model);
2451
+ return tree;
2452
+ }
2453
+ function initialize({ models, pool, readonlyPool = pool, connections = {}, expose }) {
2454
+ if (!models.length) {
2455
+ throw new Error("Models need to be specified to read all model information from decorators");
2456
+ }
2457
+ const inheritanceTreesByModelName = {};
2458
+ const modelNames = [];
2459
+ for (const model of models) {
2460
+ inheritanceTreesByModelName[model.name] = getInheritanceTree(model);
2461
+ modelNames.push(model.name);
2462
+ }
2463
+ const metadataStorage = getMetadataStorage();
2464
+ const modelMetadataByModelName = {};
2465
+ for (const model of metadataStorage.models) {
2466
+ modelMetadataByModelName[model.name] = model;
2467
+ }
2468
+ const columnsByPropertyNameForModel = {};
2469
+ for (const column of metadataStorage.columns) {
2470
+ const columns = columnsByPropertyNameForModel[column.target] ?? {};
2471
+ columns[column.propertyName] = column;
2472
+ columnsByPropertyNameForModel[column.target] = columns;
2473
+ }
2474
+ const columnModifiersByPropertyNameForModel = {};
2475
+ for (const columnModifier of metadataStorage.columnModifiers) {
2476
+ const columnModifiersForModel = columnModifiersByPropertyNameForModel[columnModifier.target] ?? {};
2477
+ const columnModifiersForProperty = columnModifiersForModel[columnModifier.propertyName] ?? [];
2478
+ columnModifiersForProperty.push(columnModifier);
2479
+ columnModifiersForModel[columnModifier.propertyName] = columnModifiersForProperty;
2480
+ columnModifiersByPropertyNameForModel[columnModifier.target] = columnModifiersForModel;
2481
+ }
2482
+ for (const model of models) {
2483
+ let modelMetadata;
2484
+ let inheritedColumnsByPropertyName = {};
2485
+ const inheritedColumnModifiersByPropertyName = /* @__PURE__ */ new Map();
2486
+ for (const inheritedClass of inheritanceTreesByModelName[model.name] ?? []) {
2487
+ modelMetadata = modelMetadataByModelName[inheritedClass.name] ?? modelMetadata;
2488
+ const columnsByPropertyName = columnsByPropertyNameForModel[inheritedClass.name] ?? {};
2489
+ inheritedColumnsByPropertyName = {
2490
+ ...inheritedColumnsByPropertyName,
2491
+ ...columnsByPropertyName
2492
+ };
2493
+ for (const [propertyName] of Object.entries(columnsByPropertyName)) {
2494
+ inheritedColumnModifiersByPropertyName.delete(propertyName);
2495
+ }
2496
+ const columnModifiersByPropertyName = columnModifiersByPropertyNameForModel[inheritedClass.name] ?? {};
2497
+ for (const [propertyName, columnModifiers] of Object.entries(columnModifiersByPropertyName)) {
2498
+ inheritedColumnModifiersByPropertyName.set(propertyName, [...inheritedColumnModifiersByPropertyName.get(propertyName) ?? [], ...columnModifiers ?? []]);
2499
+ }
2500
+ }
2501
+ if (!modelMetadata) {
2502
+ throw new Error(`Unable to find @table() on ${model.name}`);
2503
+ }
2504
+ modelMetadataByModelName[model.name] = new ModelMetadata({
2505
+ ...modelMetadata,
2506
+ name: model.name,
2507
+ type: model
2508
+ });
2509
+ columnsByPropertyNameForModel[model.name] = inheritedColumnsByPropertyName;
2510
+ columnModifiersByPropertyNameForModel[model.name] = Object.fromEntries(inheritedColumnModifiersByPropertyName);
2511
+ }
2512
+ for (const [modelName, columnModifiersByPropertyName] of Object.entries(columnModifiersByPropertyNameForModel)) {
2513
+ const columnsByPropertyName = columnsByPropertyNameForModel[modelName] ?? {};
2514
+ for (const [propertyName, columnModifiers] of Object.entries(columnModifiersByPropertyName)) {
2515
+ const column = columnsByPropertyName[propertyName];
2516
+ if (column) {
2517
+ for (const columnModifier of columnModifiers) {
2518
+ Object.assign(column, _.omit(columnModifier, ["target", "name", "propertyName", "type", "model"]));
2519
+ }
2520
+ } else {
2521
+ let columnDetails = {
2522
+ target: modelName,
2523
+ propertyName
2524
+ };
2525
+ for (const columnModifier of columnModifiers) {
2526
+ columnDetails = {
2527
+ ...columnDetails,
2528
+ ...columnModifier
2529
+ };
2530
+ }
2531
+ if (!columnDetails.name) {
2532
+ throw new Error(`Missing column name for ${modelName}#${propertyName}`);
2533
+ }
2534
+ if (!columnDetails.type && !columnDetails.model) {
2535
+ throw new Error(`Missing column type for ${modelName}#${propertyName}`);
2536
+ }
2537
+ if (columnDetails.model) {
2538
+ columnsByPropertyName[propertyName] = new ColumnModelMetadata({
2539
+ ...columnDetails,
2540
+ name: columnDetails.name,
2541
+ model: columnDetails.model
2542
+ });
2543
+ } else if (columnDetails.type) {
2544
+ columnsByPropertyName[propertyName] = new ColumnTypeMetadata({
2545
+ ...columnDetails,
2546
+ name: columnDetails.name,
2547
+ type: columnDetails.type
2548
+ });
2549
+ }
2550
+ }
2551
+ }
2552
+ columnsByPropertyNameForModel[modelName] = columnsByPropertyName;
2553
+ }
2554
+ const repositoriesByModelNameLowered = {};
2555
+ const repositoriesByModelName = {};
2556
+ for (const modelName of modelNames) {
2557
+ const model = modelMetadataByModelName[modelName];
2558
+ if (!model) {
2559
+ throw new Error(`Unable to find @table() on ${modelName}`);
2560
+ }
2561
+ const columnsByPropertyName = columnsByPropertyNameForModel[modelName];
2562
+ if (!columnsByPropertyName) {
2563
+ throw new Error(`Did not find any columns decorated with @column. Model: ${modelName}`);
2564
+ }
2565
+ model.columns = Object.values(columnsByPropertyName);
2566
+ let modelPool = pool;
2567
+ let modelReadonlyPool = readonlyPool;
2568
+ if (model.connection) {
2569
+ const modelConnection = connections[model.connection];
2570
+ if (!modelConnection) {
2571
+ throw new Error(`Unable to find connection (${model.connection}) for entity: ${model.name}`);
2572
+ }
2573
+ modelPool = modelConnection.pool || pool;
2574
+ modelReadonlyPool = modelConnection.readonlyPool ?? modelPool;
2575
+ }
2576
+ let repository;
2577
+ if (model.readonly) {
2578
+ repository = new ReadonlyRepository({
2579
+ modelMetadata: model,
2580
+ type: model.type,
2581
+ repositoriesByModelNameLowered,
2582
+ pool: modelPool,
2583
+ readonlyPool: modelReadonlyPool
2584
+ });
2585
+ repositoriesByModelNameLowered[model.name.toLowerCase()] = repository;
2586
+ repositoriesByModelName[model.name] = repository;
2587
+ } else {
2588
+ repository = new Repository({
2589
+ modelMetadata: model,
2590
+ type: model.type,
2591
+ repositoriesByModelNameLowered,
2592
+ pool: modelPool,
2593
+ readonlyPool: modelReadonlyPool
2594
+ });
2595
+ repositoriesByModelNameLowered[model.name.toLowerCase()] = repository;
2596
+ repositoriesByModelName[model.name] = repository;
2597
+ }
2598
+ if (expose) {
2599
+ expose(repository, model);
2600
+ }
2601
+ }
2602
+ return repositoriesByModelName;
2603
+ }
2604
+
2605
+ export { ColumnBaseMetadata, ColumnCollectionMetadata, ColumnModelMetadata, ColumnTypeMetadata, Entity, ModelMetadata, ReadonlyRepository, Repository, column, createDateColumn, getMetadataStorage, initialize, primaryColumn, table, updateDateColumn, versionColumn };