bigal 12.1.5 → 13.0.0-beta1
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.
- package/.devcontainer/devcontainer.json +16 -0
- package/.husky/pre-commit +4 -0
- package/.prettierrc.cjs +34 -0
- package/CHANGELOG.md +5 -0
- package/dist/index.cjs +2626 -0
- package/dist/index.d.cts +892 -0
- package/dist/index.d.mts +892 -0
- package/dist/index.d.ts +892 -0
- package/dist/index.mjs +2605 -0
- package/eslint.config.mjs +25 -0
- package/package.json +45 -36
- package/tsconfig.build.json +7 -0
- package/Entity.d.ts +0 -16
- package/Entity.js +0 -13
- package/Entity.js.map +0 -1
- package/IReadonlyRepository.d.ts +0 -36
- package/IReadonlyRepository.js +0 -3
- package/IReadonlyRepository.js.map +0 -1
- package/IRepository.d.ts +0 -99
- package/IRepository.js +0 -3
- package/IRepository.js.map +0 -1
- package/ReadonlyRepository.d.ts +0 -69
- package/ReadonlyRepository.js +0 -687
- package/ReadonlyRepository.js.map +0 -1
- package/Repository.d.ts +0 -69
- package/Repository.js +0 -171
- package/Repository.js.map +0 -1
- package/SqlHelper.d.ts +0 -144
- package/SqlHelper.js +0 -1081
- package/SqlHelper.js.map +0 -1
- package/decorators/ColumnBaseOptions.d.ts +0 -10
- package/decorators/ColumnBaseOptions.js +0 -3
- package/decorators/ColumnBaseOptions.js.map +0 -1
- package/decorators/ColumnCollectionOptions.d.ts +0 -15
- package/decorators/ColumnCollectionOptions.js +0 -3
- package/decorators/ColumnCollectionOptions.js.map +0 -1
- package/decorators/ColumnModelOptions.d.ts +0 -7
- package/decorators/ColumnModelOptions.js +0 -3
- package/decorators/ColumnModelOptions.js.map +0 -1
- package/decorators/ColumnTypeOptions.d.ts +0 -21
- package/decorators/ColumnTypeOptions.js +0 -3
- package/decorators/ColumnTypeOptions.js.map +0 -1
- package/decorators/TableOptions.d.ts +0 -14
- package/decorators/TableOptions.js +0 -3
- package/decorators/TableOptions.js.map +0 -1
- package/decorators/column.d.ts +0 -9
- package/decorators/column.js +0 -93
- package/decorators/column.js.map +0 -1
- package/decorators/createDateColumn.d.ts +0 -6
- package/decorators/createDateColumn.js +0 -50
- package/decorators/createDateColumn.js.map +0 -1
- package/decorators/index.d.ts +0 -6
- package/decorators/index.js +0 -23
- package/decorators/index.js.map +0 -1
- package/decorators/primaryColumn.d.ts +0 -8
- package/decorators/primaryColumn.js +0 -66
- package/decorators/primaryColumn.js.map +0 -1
- package/decorators/table.d.ts +0 -5
- package/decorators/table.js +0 -40
- package/decorators/table.js.map +0 -1
- package/decorators/updateDateColumn.d.ts +0 -6
- package/decorators/updateDateColumn.js +0 -51
- package/decorators/updateDateColumn.js.map +0 -1
- package/decorators/versionColumn.d.ts +0 -6
- package/decorators/versionColumn.js +0 -51
- package/decorators/versionColumn.js.map +0 -1
- package/errors/QueryError.d.ts +0 -8
- package/errors/QueryError.js +0 -13
- package/errors/QueryError.js.map +0 -1
- package/errors/index.d.ts +0 -1
- package/errors/index.js +0 -18
- package/errors/index.js.map +0 -1
- package/index.d.ts +0 -35
- package/index.js +0 -220
- package/index.js.map +0 -1
- package/metadata/ColumnBaseMetadata.d.ts +0 -93
- package/metadata/ColumnBaseMetadata.js +0 -19
- package/metadata/ColumnBaseMetadata.js.map +0 -1
- package/metadata/ColumnCollectionMetadata.d.ts +0 -36
- package/metadata/ColumnCollectionMetadata.js +0 -63
- package/metadata/ColumnCollectionMetadata.js.map +0 -1
- package/metadata/ColumnMetadata.d.ts +0 -4
- package/metadata/ColumnMetadata.js +0 -3
- package/metadata/ColumnMetadata.js.map +0 -1
- package/metadata/ColumnModelMetadata.d.ts +0 -18
- package/metadata/ColumnModelMetadata.js +0 -43
- package/metadata/ColumnModelMetadata.js.map +0 -1
- package/metadata/ColumnModifierMetadata.d.ts +0 -46
- package/metadata/ColumnModifierMetadata.js +0 -3
- package/metadata/ColumnModifierMetadata.js.map +0 -1
- package/metadata/ColumnTypeMetadata.d.ts +0 -43
- package/metadata/ColumnTypeMetadata.js +0 -26
- package/metadata/ColumnTypeMetadata.js.map +0 -1
- package/metadata/MetadataStorage.d.ts +0 -13
- package/metadata/MetadataStorage.js +0 -19
- package/metadata/MetadataStorage.js.map +0 -1
- package/metadata/ModelMetadata.d.ts +0 -36
- package/metadata/ModelMetadata.js +0 -81
- package/metadata/ModelMetadata.js.map +0 -1
- package/metadata/index.d.ts +0 -10
- package/metadata/index.js +0 -33
- package/metadata/index.js.map +0 -1
- package/query/Comparer.d.ts +0 -1
- package/query/Comparer.js +0 -3
- package/query/Comparer.js.map +0 -1
- package/query/CountArgs.d.ts +0 -7
- package/query/CountArgs.js +0 -3
- package/query/CountArgs.js.map +0 -1
- package/query/CountResult.d.ts +0 -5
- package/query/CountResult.js +0 -3
- package/query/CountResult.js.map +0 -1
- package/query/CreateOptions.d.ts +0 -9
- package/query/CreateOptions.js +0 -3
- package/query/CreateOptions.js.map +0 -1
- package/query/CreateUpdateOptions.d.ts +0 -4
- package/query/CreateUpdateOptions.js +0 -3
- package/query/CreateUpdateOptions.js.map +0 -1
- package/query/DeleteOptions.d.ts +0 -12
- package/query/DeleteOptions.js +0 -3
- package/query/DeleteOptions.js.map +0 -1
- package/query/DestroyResult.d.ts +0 -5
- package/query/DestroyResult.js +0 -3
- package/query/DestroyResult.js.map +0 -1
- package/query/DoNotReturnRecords.d.ts +0 -3
- package/query/DoNotReturnRecords.js +0 -3
- package/query/DoNotReturnRecords.js.map +0 -1
- package/query/FindArgs.d.ts +0 -6
- package/query/FindArgs.js +0 -3
- package/query/FindArgs.js.map +0 -1
- package/query/FindOneArgs.d.ts +0 -11
- package/query/FindOneArgs.js +0 -3
- package/query/FindOneArgs.js.map +0 -1
- package/query/FindOneResult.d.ts +0 -12
- package/query/FindOneResult.js +0 -3
- package/query/FindOneResult.js.map +0 -1
- package/query/FindResult.d.ts +0 -15
- package/query/FindResult.js +0 -3
- package/query/FindResult.js.map +0 -1
- package/query/OnConflictOptions.d.ts +0 -25
- package/query/OnConflictOptions.js +0 -3
- package/query/OnConflictOptions.js.map +0 -1
- package/query/PaginateOptions.d.ts +0 -4
- package/query/PaginateOptions.js +0 -3
- package/query/PaginateOptions.js.map +0 -1
- package/query/PopulateArgs.d.ts +0 -13
- package/query/PopulateArgs.js +0 -3
- package/query/PopulateArgs.js.map +0 -1
- package/query/ReturnSelect.d.ts +0 -5
- package/query/ReturnSelect.js +0 -3
- package/query/ReturnSelect.js.map +0 -1
- package/query/Sort.d.ts +0 -15
- package/query/Sort.js +0 -3
- package/query/Sort.js.map +0 -1
- package/query/WhereQuery.d.ts +0 -21
- package/query/WhereQuery.js +0 -3
- package/query/WhereQuery.js.map +0 -1
- package/query/index.d.ts +0 -15
- package/query/index.js +0 -32
- package/query/index.js.map +0 -1
- package/types/ClassLike.d.ts +0 -8
- package/types/ClassLike.js +0 -3
- package/types/ClassLike.js.map +0 -1
- package/types/CreateUpdateParams.d.ts +0 -9
- package/types/CreateUpdateParams.js +0 -3
- package/types/CreateUpdateParams.js.map +0 -1
- package/types/EntityPrimitiveOrId.d.ts +0 -2
- package/types/EntityPrimitiveOrId.js +0 -3
- package/types/EntityPrimitiveOrId.js.map +0 -1
- package/types/ExcludeEntityCollections.d.ts +0 -5
- package/types/ExcludeEntityCollections.js +0 -3
- package/types/ExcludeEntityCollections.js.map +0 -1
- package/types/ExcludeFunctions.d.ts +0 -4
- package/types/ExcludeFunctions.js +0 -3
- package/types/ExcludeFunctions.js.map +0 -1
- package/types/GetValueType.d.ts +0 -1
- package/types/GetValueType.js +0 -3
- package/types/GetValueType.js.map +0 -1
- package/types/IncludeFunctions.d.ts +0 -4
- package/types/IncludeFunctions.js +0 -3
- package/types/IncludeFunctions.js.map +0 -1
- package/types/IsValueOfType.d.ts +0 -1
- package/types/IsValueOfType.js +0 -3
- package/types/IsValueOfType.js.map +0 -1
- package/types/OmitEntityCollections.d.ts +0 -7
- package/types/OmitEntityCollections.js +0 -3
- package/types/OmitEntityCollections.js.map +0 -1
- package/types/OmitFunctions.d.ts +0 -7
- package/types/OmitFunctions.js +0 -3
- package/types/OmitFunctions.js.map +0 -1
- package/types/PickAsType.d.ts +0 -3
- package/types/PickAsType.js +0 -3
- package/types/PickAsType.js.map +0 -1
- package/types/PickByValueType.d.ts +0 -5
- package/types/PickByValueType.js +0 -3
- package/types/PickByValueType.js.map +0 -1
- package/types/PickFunctions.d.ts +0 -4
- package/types/PickFunctions.js +0 -3
- package/types/PickFunctions.js.map +0 -1
- package/types/Populated.d.ts +0 -9
- package/types/Populated.js +0 -3
- package/types/Populated.js.map +0 -1
- package/types/QueryResult.d.ts +0 -9
- package/types/QueryResult.js +0 -3
- package/types/QueryResult.js.map +0 -1
- package/types/QueryResultOptionalPopulated.d.ts +0 -9
- package/types/QueryResultOptionalPopulated.js +0 -3
- package/types/QueryResultOptionalPopulated.js.map +0 -1
- package/types/QueryResultPopulated.d.ts +0 -9
- package/types/QueryResultPopulated.js +0 -3
- package/types/QueryResultPopulated.js.map +0 -1
- package/types/index.d.ts +0 -17
- package/types/index.js +0 -34
- 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 };
|