@reldens/storage 0.79.0 → 0.81.0
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/lib/entities-generator.js +1 -1
- package/lib/entity-templates/objection-js-model.template +1 -1
- package/lib/generators/models-generation.js +26 -1
- package/lib/prisma/prisma-data-server.js +1 -1
- package/lib/prisma/prisma-driver.js +187 -490
- package/lib/prisma/prisma-metadata-loader.js +126 -0
- package/lib/prisma/prisma-relation-resolver.js +267 -0
- package/lib/prisma/prisma-schema-generator.js +182 -182
- package/lib/prisma/prisma-type-caster.js +231 -0
- package/package.json +1 -1
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const { BaseDriver } = require('../base-driver');
|
|
8
|
+
const { PrismaTypeCaster } = require('./prisma-type-caster');
|
|
9
|
+
const { PrismaMetadataLoader } = require('./prisma-metadata-loader');
|
|
10
|
+
const { PrismaRelationResolver } = require('./prisma-relation-resolver');
|
|
8
11
|
const { Logger, sc } = require('@reldens/utils');
|
|
9
|
-
const { Prisma } = require('@prisma/client');
|
|
10
12
|
|
|
11
13
|
class PrismaDriver extends BaseDriver
|
|
12
14
|
{
|
|
@@ -24,302 +26,59 @@ class PrismaDriver extends BaseDriver
|
|
|
24
26
|
}
|
|
25
27
|
this.prisma = props.prisma;
|
|
26
28
|
this.model = props.model;
|
|
27
|
-
this.
|
|
28
|
-
this.optionalFields = [];
|
|
29
|
-
this.fieldTypes = {};
|
|
30
|
-
this.fieldDefaults = {};
|
|
31
|
-
this.idFieldType = 'String';
|
|
32
|
-
this.referenceFields = {};
|
|
33
|
-
this.relationMetadata = {};
|
|
34
|
-
this.foreignKeyMappings = {};
|
|
35
|
-
this.jsonFields = new Set();
|
|
29
|
+
this.initHelpers();
|
|
36
30
|
this.initModelMetadata();
|
|
37
31
|
}
|
|
38
32
|
|
|
39
|
-
|
|
40
|
-
{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
getDmmf()
|
|
65
|
-
{
|
|
66
|
-
try {
|
|
67
|
-
if(this.prisma._dmmf){
|
|
68
|
-
return this.prisma._dmmf.datamodel;
|
|
69
|
-
}
|
|
70
|
-
if(this.prisma._getDmmf && sc.isFunction(this.prisma._getDmmf)){
|
|
71
|
-
return this.prisma._getDmmf().datamodel;
|
|
72
|
-
}
|
|
73
|
-
if(this.prisma._runtimeDataModel){
|
|
74
|
-
return this.prisma._runtimeDataModel;
|
|
75
|
-
}
|
|
76
|
-
if(Prisma.dmmf && Prisma.dmmf.datamodel){
|
|
77
|
-
return Prisma.dmmf.datamodel;
|
|
78
|
-
}
|
|
79
|
-
return null;
|
|
80
|
-
} catch(error) {
|
|
81
|
-
Logger.warning('Failed to access DMMF: '+error.message);
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
processFieldMetadata(field)
|
|
87
|
-
{
|
|
88
|
-
this.fieldTypes[field.name] = field.type;
|
|
89
|
-
if('Json' === field.type){
|
|
90
|
-
this.jsonFields.add(field.name);
|
|
91
|
-
}
|
|
92
|
-
if(field.isId){
|
|
93
|
-
this.idFieldType = field.type;
|
|
94
|
-
}
|
|
95
|
-
if(field.hasDefaultValue){
|
|
96
|
-
this.fieldDefaults[field.name] = field.default;
|
|
97
|
-
}
|
|
98
|
-
if(field.isRequired && !field.hasDefaultValue && !field.isId && 'object' !== field.kind){
|
|
99
|
-
this.requiredFields.push(field.name);
|
|
100
|
-
}
|
|
101
|
-
if(field.isOptional || field.hasDefaultValue){
|
|
102
|
-
this.optionalFields.push(field.name);
|
|
103
|
-
}
|
|
104
|
-
if(field.kind === 'scalar' && field.isList === false){
|
|
105
|
-
let isNumericType = this.isNumericFieldType(field.type);
|
|
106
|
-
let isReferenceField = field.relationFromFields && 0 < field.relationFromFields.length;
|
|
107
|
-
if(isNumericType || isReferenceField){
|
|
108
|
-
this.referenceFields[field.name] = field.type;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
if('object' === field.kind){
|
|
112
|
-
let relationType = field.isList ? 'many' : 'one';
|
|
113
|
-
this.relationMetadata[field.name] = {
|
|
114
|
-
type: relationType,
|
|
115
|
-
model: field.type,
|
|
116
|
-
isList: field.isList,
|
|
117
|
-
isOptional: field.isOptional
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
if('object' === field.kind && sc.hasOwn(field, 'relationFromFields') && sc.isArray(field.relationFromFields)){
|
|
121
|
-
for(let foreignKeyField of field.relationFromFields){
|
|
122
|
-
this.foreignKeyMappings[foreignKeyField] = field.name;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
getAllRelations()
|
|
128
|
-
{
|
|
129
|
-
return Object.keys(this.relationMetadata || {});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
isNumericFieldType(fieldType)
|
|
133
|
-
{
|
|
134
|
-
return ('Int' === fieldType || 'BigInt' === fieldType || 'Float' === fieldType || 'Decimal' === fieldType);
|
|
33
|
+
initHelpers()
|
|
34
|
+
{
|
|
35
|
+
this.metadataLoader = new PrismaMetadataLoader({
|
|
36
|
+
prisma: this.prisma,
|
|
37
|
+
rawModel: this.rawModel
|
|
38
|
+
});
|
|
39
|
+
this.typeCaster = new PrismaTypeCaster({
|
|
40
|
+
idFieldType: 'String',
|
|
41
|
+
jsonFields: new Set(),
|
|
42
|
+
fieldTypes: {},
|
|
43
|
+
fieldDefaults: {},
|
|
44
|
+
requiredFields: [],
|
|
45
|
+
optionalFields: [],
|
|
46
|
+
rawModel: this.rawModel
|
|
47
|
+
});
|
|
48
|
+
this.relationResolver = new PrismaRelationResolver({
|
|
49
|
+
relationMetadata: {},
|
|
50
|
+
relationAliases: {},
|
|
51
|
+
metadataLoader: this.metadataLoader
|
|
52
|
+
});
|
|
135
53
|
}
|
|
136
54
|
|
|
137
|
-
|
|
138
|
-
{
|
|
139
|
-
return 'Boolean' === fieldType;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
isDateTimeFieldType(fieldType)
|
|
143
|
-
{
|
|
144
|
-
return 'DateTime' === fieldType || 'Date' === fieldType;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
isJsonFieldType(fieldType)
|
|
148
|
-
{
|
|
149
|
-
return 'Json' === fieldType;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
isJsonFieldByName(fieldName)
|
|
153
|
-
{
|
|
154
|
-
if(this.jsonFields.has(fieldName)){
|
|
155
|
-
return true;
|
|
156
|
-
}
|
|
157
|
-
if(!this.rawModel || !this.rawModel.properties){
|
|
158
|
-
return false;
|
|
159
|
-
}
|
|
160
|
-
return 'json' === sc.get(this.rawModel.properties[fieldName], 'dbType', '');
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
isStringFieldType(fieldType)
|
|
164
|
-
{
|
|
165
|
-
return 'String' === fieldType;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
castValue(value, fieldType, fieldName = null)
|
|
169
|
-
{
|
|
170
|
-
if('id' === fieldName){
|
|
171
|
-
return this.castToIdType(value);
|
|
172
|
-
}
|
|
173
|
-
if(this.isNullOrEmpty(value)){
|
|
174
|
-
if(sc.hasOwn(this.fieldDefaults, fieldName)){
|
|
175
|
-
return undefined;
|
|
176
|
-
}
|
|
177
|
-
if(-1 !== this.optionalFields.indexOf(fieldName)){
|
|
178
|
-
return null;
|
|
179
|
-
}
|
|
180
|
-
if(-1 !== this.requiredFields.indexOf(fieldName)){
|
|
181
|
-
Logger.warning('Required field '+fieldName+' cannot be null or empty');
|
|
182
|
-
return undefined;
|
|
183
|
-
}
|
|
184
|
-
return null;
|
|
185
|
-
}
|
|
186
|
-
if(this.isJsonFieldByName(fieldName)){
|
|
187
|
-
return this.castToJsonType(value);
|
|
188
|
-
}
|
|
189
|
-
if(this.isNumericFieldType(fieldType)){
|
|
190
|
-
return this.castToNumericType(value, fieldType);
|
|
191
|
-
}
|
|
192
|
-
if(this.isBooleanFieldType(fieldType)){
|
|
193
|
-
return this.castToBooleanType(value);
|
|
194
|
-
}
|
|
195
|
-
if(this.isDateTimeFieldType(fieldType)){
|
|
196
|
-
return this.castToDateType(value);
|
|
197
|
-
}
|
|
198
|
-
if(this.isStringFieldType(fieldType)){
|
|
199
|
-
return this.castToStringType(value);
|
|
200
|
-
}
|
|
201
|
-
return value;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
isNullOrEmpty(value)
|
|
205
|
-
{
|
|
206
|
-
return null === value || undefined === value || '' === value;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
castToIdType(value)
|
|
210
|
-
{
|
|
211
|
-
if(this.isNullOrEmpty(value)){
|
|
212
|
-
return value;
|
|
213
|
-
}
|
|
214
|
-
if(this.isNumericFieldType(this.idFieldType)){
|
|
215
|
-
let numeric = Number(value);
|
|
216
|
-
if(!isNaN(numeric)){
|
|
217
|
-
return ('Int' === this.idFieldType || 'BigInt' === this.idFieldType) ? Math.floor(numeric) : numeric;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
return String(value);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
castToNumericType(value, fieldType)
|
|
224
|
-
{
|
|
225
|
-
if(this.isNullOrEmpty(value)){
|
|
226
|
-
return null;
|
|
227
|
-
}
|
|
228
|
-
let numericValue = Number(value);
|
|
229
|
-
if(isNaN(numericValue)){
|
|
230
|
-
Logger.warning('Cannot convert value to numeric: '+value);
|
|
231
|
-
return null;
|
|
232
|
-
}
|
|
233
|
-
if('Int' === fieldType || 'BigInt' === fieldType){
|
|
234
|
-
return Math.floor(numericValue);
|
|
235
|
-
}
|
|
236
|
-
return numericValue;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
castToBooleanType(value)
|
|
240
|
-
{
|
|
241
|
-
if(this.isNullOrEmpty(value)){
|
|
242
|
-
return null;
|
|
243
|
-
}
|
|
244
|
-
if('boolean' === typeof value){
|
|
245
|
-
return value;
|
|
246
|
-
}
|
|
247
|
-
if('number' === typeof value){
|
|
248
|
-
return 0 !== value;
|
|
249
|
-
}
|
|
250
|
-
if('string' === typeof value){
|
|
251
|
-
let lowerValue = value.toLowerCase();
|
|
252
|
-
if('true' === lowerValue || '1' === lowerValue || 'yes' === lowerValue){
|
|
253
|
-
return true;
|
|
254
|
-
}
|
|
255
|
-
if('false' === lowerValue || '0' === lowerValue || 'no' === lowerValue){
|
|
256
|
-
return false;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
return Boolean(value);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
castToDateType(dateValue)
|
|
263
|
-
{
|
|
264
|
-
if(dateValue instanceof Date){
|
|
265
|
-
return dateValue;
|
|
266
|
-
}
|
|
267
|
-
if(this.isNullOrEmpty(dateValue)){
|
|
268
|
-
return null;
|
|
269
|
-
}
|
|
270
|
-
let dateString = String(dateValue);
|
|
271
|
-
if(dateString.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/)){
|
|
272
|
-
return new Date(dateString.replace(' ', 'T') + 'Z');
|
|
273
|
-
}
|
|
274
|
-
if(dateString.match(/^\d{4}-\d{2}-\d{2}$/)){
|
|
275
|
-
return new Date(dateString + 'T00:00:00Z');
|
|
276
|
-
}
|
|
277
|
-
try {
|
|
278
|
-
let parsedDate = new Date(dateString);
|
|
279
|
-
if(isNaN(parsedDate.getTime())){
|
|
280
|
-
Logger.warning('Invalid date value: '+dateString);
|
|
281
|
-
return null;
|
|
282
|
-
}
|
|
283
|
-
return parsedDate;
|
|
284
|
-
} catch(error) {
|
|
285
|
-
Logger.warning('Failed to convert date value: '+dateString);
|
|
286
|
-
return null;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
castToJsonType(value)
|
|
291
|
-
{
|
|
292
|
-
if(this.isNullOrEmpty(value)){
|
|
293
|
-
return Prisma.DbNull;
|
|
294
|
-
}
|
|
295
|
-
if('object' === typeof value){
|
|
296
|
-
return value;
|
|
297
|
-
}
|
|
298
|
-
if('string' === typeof value){
|
|
299
|
-
if(value.startsWith('%') && value.endsWith('%')){
|
|
300
|
-
return value;
|
|
301
|
-
}
|
|
302
|
-
try {
|
|
303
|
-
return JSON.parse(value);
|
|
304
|
-
} catch(error) {
|
|
305
|
-
return value;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
return value;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
castToStringType(value)
|
|
55
|
+
initModelMetadata()
|
|
312
56
|
{
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
if('string' === typeof value){
|
|
317
|
-
if('null' === value){
|
|
318
|
-
return null;
|
|
319
|
-
}
|
|
320
|
-
return value;
|
|
57
|
+
let metadata = this.metadataLoader.loadModelMetadata(this.tableName());
|
|
58
|
+
if(!metadata){
|
|
59
|
+
return;
|
|
321
60
|
}
|
|
322
|
-
|
|
61
|
+
this.requiredFields = metadata.requiredFields;
|
|
62
|
+
this.optionalFields = metadata.optionalFields;
|
|
63
|
+
this.fieldTypes = metadata.fieldTypes;
|
|
64
|
+
this.fieldDefaults = metadata.fieldDefaults;
|
|
65
|
+
this.idFieldType = metadata.idFieldType;
|
|
66
|
+
this.referenceFields = metadata.referenceFields;
|
|
67
|
+
this.relationMetadata = metadata.relationMetadata;
|
|
68
|
+
this.foreignKeyMappings = metadata.foreignKeyMappings;
|
|
69
|
+
this.jsonFields = metadata.jsonFields;
|
|
70
|
+
this.typeCaster.updateMetadata({
|
|
71
|
+
idFieldType: this.idFieldType,
|
|
72
|
+
jsonFields: this.jsonFields,
|
|
73
|
+
fieldTypes: this.fieldTypes,
|
|
74
|
+
fieldDefaults: this.fieldDefaults,
|
|
75
|
+
requiredFields: this.requiredFields,
|
|
76
|
+
optionalFields: this.optionalFields
|
|
77
|
+
});
|
|
78
|
+
this.relationResolver.updateMetadata({
|
|
79
|
+
relationMetadata: this.relationMetadata
|
|
80
|
+
});
|
|
81
|
+
this.relationAliases = this.relationResolver.buildRelationAliases(this.tableName());
|
|
323
82
|
}
|
|
324
83
|
|
|
325
84
|
databaseName()
|
|
@@ -347,6 +106,11 @@ class PrismaDriver extends BaseDriver
|
|
|
347
106
|
return this.rawModel[propertyName] || null;
|
|
348
107
|
}
|
|
349
108
|
|
|
109
|
+
getAllRelations()
|
|
110
|
+
{
|
|
111
|
+
return this.relationResolver.getAllRelations();
|
|
112
|
+
}
|
|
113
|
+
|
|
350
114
|
prepareData(params)
|
|
351
115
|
{
|
|
352
116
|
let data = {};
|
|
@@ -356,7 +120,7 @@ class PrismaDriver extends BaseDriver
|
|
|
356
120
|
data[key] = params[key];
|
|
357
121
|
continue;
|
|
358
122
|
}
|
|
359
|
-
let castedValue = this.castValue(params[key], fieldType, key);
|
|
123
|
+
let castedValue = this.typeCaster.castValue(params[key], fieldType, key);
|
|
360
124
|
if(undefined !== castedValue){
|
|
361
125
|
data[key] = castedValue;
|
|
362
126
|
}
|
|
@@ -372,9 +136,9 @@ class PrismaDriver extends BaseDriver
|
|
|
372
136
|
if(sc.hasOwn(this.foreignKeyMappings, key)){
|
|
373
137
|
let relationName = this.foreignKeyMappings[key];
|
|
374
138
|
let value = params[key];
|
|
375
|
-
if(!this.isNullOrEmpty(value)){
|
|
139
|
+
if(!this.typeCaster.isNullOrEmpty(value)){
|
|
376
140
|
relations[relationName] = {
|
|
377
|
-
connect: {id: this.castToIdType(value)}
|
|
141
|
+
connect: {id: this.typeCaster.castToIdType(value)}
|
|
378
142
|
};
|
|
379
143
|
continue;
|
|
380
144
|
}
|
|
@@ -387,14 +151,14 @@ class PrismaDriver extends BaseDriver
|
|
|
387
151
|
}
|
|
388
152
|
let fieldType = this.fieldTypes[key];
|
|
389
153
|
if(!fieldType){
|
|
390
|
-
if(!this.isNullOrEmpty(params[key])){
|
|
154
|
+
if(!this.typeCaster.isNullOrEmpty(params[key])){
|
|
391
155
|
data[key] = params[key];
|
|
392
156
|
}
|
|
393
157
|
continue;
|
|
394
158
|
}
|
|
395
|
-
let castedValue = this.castValue(params[key], fieldType, key);
|
|
159
|
+
let castedValue = this.typeCaster.castValue(params[key], fieldType, key);
|
|
396
160
|
if(undefined !== castedValue){
|
|
397
|
-
if(this.isJsonFieldType(fieldType) && null === castedValue){
|
|
161
|
+
if(this.typeCaster.isJsonFieldType(fieldType) && null === castedValue){
|
|
398
162
|
continue;
|
|
399
163
|
}
|
|
400
164
|
data[key] = castedValue;
|
|
@@ -447,60 +211,69 @@ class PrismaDriver extends BaseDriver
|
|
|
447
211
|
{
|
|
448
212
|
if(sc.isArray(value)){
|
|
449
213
|
if('id' === key){
|
|
450
|
-
return value.map(id => this.castToIdType(id));
|
|
214
|
+
return value.map(id => this.typeCaster.castToIdType(id)).filter(id => null !== id);
|
|
451
215
|
}
|
|
452
216
|
let fieldType = this.fieldTypes[key];
|
|
453
217
|
if(fieldType){
|
|
454
|
-
return value.map(val => this.castValue(val, fieldType, key)).filter(val => undefined !== val);
|
|
218
|
+
return value.map(val => this.typeCaster.castValue(val, fieldType, key)).filter(val => undefined !== val);
|
|
455
219
|
}
|
|
456
220
|
return value;
|
|
457
221
|
}
|
|
458
222
|
if('id' === key){
|
|
459
|
-
return this.castToIdType(value);
|
|
223
|
+
return this.typeCaster.castToIdType(value);
|
|
460
224
|
}
|
|
461
225
|
let fieldType = this.fieldTypes[key];
|
|
462
226
|
if(fieldType){
|
|
463
|
-
let castedValue = this.castValue(value, fieldType, key);
|
|
227
|
+
let castedValue = this.typeCaster.castValue(value, fieldType, key);
|
|
464
228
|
return undefined !== castedValue ? castedValue : value;
|
|
465
229
|
}
|
|
466
230
|
return value;
|
|
467
231
|
}
|
|
468
232
|
|
|
469
|
-
|
|
233
|
+
applyOperator(value, operator, fieldName = null)
|
|
470
234
|
{
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
if(sc.isArray(result)){
|
|
475
|
-
return result.map(item => this.transformSingleResult(item, includeConfig));
|
|
235
|
+
let upperOperator = operator ? operator.toUpperCase() : '';
|
|
236
|
+
if('LIKE' === upperOperator){
|
|
237
|
+
return this.handleLikeOperator(value, fieldName);
|
|
476
238
|
}
|
|
477
|
-
|
|
239
|
+
let operatorsMap = {
|
|
240
|
+
'=': value,
|
|
241
|
+
'!=': {not: value},
|
|
242
|
+
'>': {gt: value},
|
|
243
|
+
'>=': {gte: value},
|
|
244
|
+
'<': {lt: value},
|
|
245
|
+
'<=': {lte: value},
|
|
246
|
+
'IN': {in: value},
|
|
247
|
+
'NOT IN': {notIn: value}
|
|
248
|
+
};
|
|
249
|
+
return operatorsMap[upperOperator] || value;
|
|
478
250
|
}
|
|
479
251
|
|
|
480
|
-
|
|
252
|
+
handleLikeOperator(value, fieldName)
|
|
481
253
|
{
|
|
482
|
-
|
|
483
|
-
|
|
254
|
+
let cleanValue = String(value).replace(/%/g, '');
|
|
255
|
+
if(this.typeCaster.isJsonFieldByName(fieldName) || this.isJsonField(fieldName)){
|
|
256
|
+
return this.handleJsonTextSearch(cleanValue);
|
|
484
257
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
if(!
|
|
488
|
-
|
|
489
|
-
}
|
|
490
|
-
let relationMeta = this.relationMetadata[relationName];
|
|
491
|
-
if(!relationMeta){
|
|
492
|
-
continue;
|
|
493
|
-
}
|
|
494
|
-
let relationValue = transformed[relationName];
|
|
495
|
-
if('one' === relationMeta.type && sc.isArray(relationValue)){
|
|
496
|
-
transformed[relationName] = 0 < relationValue.length ? relationValue[0] : null;
|
|
497
|
-
continue;
|
|
498
|
-
}
|
|
499
|
-
if('many' === relationMeta.type && !sc.isArray(relationValue)){
|
|
500
|
-
transformed[relationName] = relationValue ? [relationValue] : [];
|
|
258
|
+
if('id' === fieldName || sc.hasOwn(this.referenceFields, fieldName)){
|
|
259
|
+
let numericValue = Number(cleanValue);
|
|
260
|
+
if(!isNaN(numericValue)){
|
|
261
|
+
return numericValue;
|
|
501
262
|
}
|
|
502
263
|
}
|
|
503
|
-
return
|
|
264
|
+
return {contains: cleanValue};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
handleJsonTextSearch(searchValue)
|
|
268
|
+
{
|
|
269
|
+
return {
|
|
270
|
+
string_contains: searchValue
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
isJsonField(fieldName)
|
|
275
|
+
{
|
|
276
|
+
return this.jsonFields && this.jsonFields.has(fieldName);
|
|
504
277
|
}
|
|
505
278
|
|
|
506
279
|
async create(params)
|
|
@@ -526,26 +299,37 @@ class PrismaDriver extends BaseDriver
|
|
|
526
299
|
this.ensureRequiredFields(preparedData);
|
|
527
300
|
let createData = {data: preparedData};
|
|
528
301
|
if(0 < relations.length){
|
|
529
|
-
let
|
|
530
|
-
createData.include =
|
|
302
|
+
let includeData = this.relationResolver.buildIncludeObjectWithMapping(relations);
|
|
303
|
+
createData.include = includeData.include;
|
|
531
304
|
for(let relation of relations){
|
|
532
|
-
|
|
305
|
+
let normalizedRelation = this.relationResolver.normalizeRelationName(relation);
|
|
306
|
+
if(!sc.hasOwn(params, relation) && !sc.hasOwn(params, normalizedRelation)){
|
|
533
307
|
continue;
|
|
534
308
|
}
|
|
535
|
-
let relationData = params
|
|
309
|
+
let relationData = sc.get(params, relation, sc.get(params, normalizedRelation, null));
|
|
536
310
|
if(sc.isArray(relationData)){
|
|
537
|
-
createData.data[
|
|
538
|
-
connect: relationData.map(item => ({id: this.castToIdType(item.id)}))
|
|
311
|
+
createData.data[normalizedRelation] = {
|
|
312
|
+
connect: relationData.map(item => ({id: this.typeCaster.castToIdType(item.id)}))
|
|
539
313
|
};
|
|
540
314
|
continue;
|
|
541
315
|
}
|
|
542
|
-
createData.data[
|
|
543
|
-
connect: {id: this.castToIdType(relationData.id)}
|
|
316
|
+
createData.data[normalizedRelation] = {
|
|
317
|
+
connect: {id: this.typeCaster.castToIdType(relationData.id)}
|
|
544
318
|
};
|
|
545
319
|
}
|
|
320
|
+
try {
|
|
321
|
+
return this.relationResolver.transformRelationResults(
|
|
322
|
+
await this.model.create(createData),
|
|
323
|
+
includeData.include,
|
|
324
|
+
includeData.mapping
|
|
325
|
+
);
|
|
326
|
+
} catch(error) {
|
|
327
|
+
Logger.error('Create with relations error: '+error.message);
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
546
330
|
}
|
|
547
331
|
try {
|
|
548
|
-
return
|
|
332
|
+
return await this.model.create(createData);
|
|
549
333
|
} catch(error) {
|
|
550
334
|
Logger.error('Create with relations error: '+error.message);
|
|
551
335
|
return false;
|
|
@@ -584,7 +368,7 @@ class PrismaDriver extends BaseDriver
|
|
|
584
368
|
|
|
585
369
|
async updateById(id, params)
|
|
586
370
|
{
|
|
587
|
-
let castedId = this.castToIdType(id);
|
|
371
|
+
let castedId = this.typeCaster.castToIdType(id);
|
|
588
372
|
let found = await this.loadById(castedId);
|
|
589
373
|
if(!found){
|
|
590
374
|
return false;
|
|
@@ -606,7 +390,7 @@ class PrismaDriver extends BaseDriver
|
|
|
606
390
|
let preparedData = this.prepareDataWithRelations(params);
|
|
607
391
|
let existing = false;
|
|
608
392
|
if(params.id){
|
|
609
|
-
let castedId = this.castToIdType(params.id);
|
|
393
|
+
let castedId = this.typeCaster.castToIdType(params.id);
|
|
610
394
|
existing = await this.loadById(castedId);
|
|
611
395
|
if(existing){
|
|
612
396
|
let patch = Object.assign({}, preparedData);
|
|
@@ -627,7 +411,7 @@ class PrismaDriver extends BaseDriver
|
|
|
627
411
|
if(existing){
|
|
628
412
|
try {
|
|
629
413
|
return await this.model.update({
|
|
630
|
-
where: {id: this.castToIdType(existing.id)},
|
|
414
|
+
where: {id: this.typeCaster.castToIdType(existing.id)},
|
|
631
415
|
data: preparedData
|
|
632
416
|
});
|
|
633
417
|
} catch(error) {
|
|
@@ -654,7 +438,7 @@ class PrismaDriver extends BaseDriver
|
|
|
654
438
|
|
|
655
439
|
async deleteById(id)
|
|
656
440
|
{
|
|
657
|
-
let castedId = this.castToIdType(id);
|
|
441
|
+
let castedId = this.typeCaster.castToIdType(id);
|
|
658
442
|
let found = await this.loadById(castedId);
|
|
659
443
|
if(!found){
|
|
660
444
|
return false;
|
|
@@ -692,7 +476,7 @@ class PrismaDriver extends BaseDriver
|
|
|
692
476
|
where: processedFilters
|
|
693
477
|
};
|
|
694
478
|
if(0 < relations.length){
|
|
695
|
-
query.include = this.
|
|
479
|
+
query.include = this.relationResolver.buildIncludeObjectWithMapping(relations).include;
|
|
696
480
|
}
|
|
697
481
|
try {
|
|
698
482
|
return await this.model.count(query);
|
|
@@ -714,22 +498,13 @@ class PrismaDriver extends BaseDriver
|
|
|
714
498
|
|
|
715
499
|
async loadAllWithRelations(relations)
|
|
716
500
|
{
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
query.include = includeConfig;
|
|
725
|
-
}
|
|
726
|
-
try {
|
|
727
|
-
let results = await this.model.findMany(query);
|
|
728
|
-
return this.transformRelationResults(results, includeConfig);
|
|
729
|
-
} catch(error) {
|
|
730
|
-
Logger.error('Load all with relations error: '+error.message);
|
|
731
|
-
return [];
|
|
732
|
-
}
|
|
501
|
+
return this.executeQueryWithRelations(
|
|
502
|
+
(q) => this.model.findMany(q),
|
|
503
|
+
this.buildQueryOptions(),
|
|
504
|
+
relations,
|
|
505
|
+
'Load all with relations error: ',
|
|
506
|
+
[]
|
|
507
|
+
);
|
|
733
508
|
}
|
|
734
509
|
|
|
735
510
|
async load(filters)
|
|
@@ -747,24 +522,15 @@ class PrismaDriver extends BaseDriver
|
|
|
747
522
|
|
|
748
523
|
async loadWithRelations(filters, relations)
|
|
749
524
|
{
|
|
750
|
-
if(!sc.isArray(relations) || 0 === relations.length){
|
|
751
|
-
relations = this.getAllRelations();
|
|
752
|
-
}
|
|
753
|
-
let processedFilters = this.processFilters(filters);
|
|
754
525
|
let query = this.buildQueryOptions();
|
|
755
|
-
query.where =
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
return this.transformRelationResults(results, includeConfig);
|
|
764
|
-
} catch(error) {
|
|
765
|
-
Logger.error('Load with relations error: '+error.message);
|
|
766
|
-
return [];
|
|
767
|
-
}
|
|
526
|
+
query.where = this.processFilters(filters);
|
|
527
|
+
return this.executeQueryWithRelations(
|
|
528
|
+
(q) => this.model.findMany(q),
|
|
529
|
+
query,
|
|
530
|
+
relations,
|
|
531
|
+
'Load with relations error: ',
|
|
532
|
+
[]
|
|
533
|
+
);
|
|
768
534
|
}
|
|
769
535
|
|
|
770
536
|
async loadBy(field, fieldValue, operator = null)
|
|
@@ -782,29 +548,20 @@ class PrismaDriver extends BaseDriver
|
|
|
782
548
|
|
|
783
549
|
async loadByWithRelations(field, fieldValue, relations, operator = null)
|
|
784
550
|
{
|
|
785
|
-
if(!sc.isArray(relations) || 0 === relations.length){
|
|
786
|
-
relations = this.getAllRelations();
|
|
787
|
-
}
|
|
788
|
-
let filter = this.createSingleFilter(field, fieldValue, operator);
|
|
789
551
|
let query = this.buildQueryOptions();
|
|
790
|
-
query.where =
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
return this.transformRelationResults(results, includeConfig);
|
|
799
|
-
} catch(error) {
|
|
800
|
-
Logger.error('Load by with relations error: '+error.message);
|
|
801
|
-
return [];
|
|
802
|
-
}
|
|
552
|
+
query.where = this.createSingleFilter(field, fieldValue, operator);
|
|
553
|
+
return this.executeQueryWithRelations(
|
|
554
|
+
(q) => this.model.findMany(q),
|
|
555
|
+
query,
|
|
556
|
+
relations,
|
|
557
|
+
'Load by with relations error: ',
|
|
558
|
+
[]
|
|
559
|
+
);
|
|
803
560
|
}
|
|
804
561
|
|
|
805
562
|
async loadById(id)
|
|
806
563
|
{
|
|
807
|
-
let castedId = this.castToIdType(id);
|
|
564
|
+
let castedId = this.typeCaster.castToIdType(id);
|
|
808
565
|
try {
|
|
809
566
|
return await this.model.findUnique({
|
|
810
567
|
where: {id: castedId}
|
|
@@ -817,30 +574,21 @@ class PrismaDriver extends BaseDriver
|
|
|
817
574
|
|
|
818
575
|
async loadByIdWithRelations(id, relations)
|
|
819
576
|
{
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
let includeConfig = {};
|
|
828
|
-
if(0 < relations.length){
|
|
829
|
-
includeConfig = this.buildIncludeObject(relations);
|
|
830
|
-
query.include = includeConfig;
|
|
831
|
-
}
|
|
832
|
-
try {
|
|
833
|
-
let result = await this.model.findUnique(query);
|
|
834
|
-
return this.transformRelationResults(result, includeConfig);
|
|
835
|
-
} catch(error) {
|
|
836
|
-
Logger.error('Load by ID with relations error: '+error.message);
|
|
837
|
-
return null;
|
|
838
|
-
}
|
|
577
|
+
return this.executeQueryWithRelations(
|
|
578
|
+
(q) => this.model.findUnique(q),
|
|
579
|
+
{where: {id: this.typeCaster.castToIdType(id)}},
|
|
580
|
+
relations,
|
|
581
|
+
'Load by ID with relations error: ',
|
|
582
|
+
null
|
|
583
|
+
);
|
|
839
584
|
}
|
|
840
585
|
|
|
841
586
|
async loadByIds(ids)
|
|
842
587
|
{
|
|
843
|
-
let castedIds = ids.map(id => this.castToIdType(id));
|
|
588
|
+
let castedIds = ids.map(id => this.typeCaster.castToIdType(id)).filter(id => null !== id);
|
|
589
|
+
if(0 === castedIds.length){
|
|
590
|
+
return [];
|
|
591
|
+
}
|
|
844
592
|
try {
|
|
845
593
|
return await this.model.findMany({
|
|
846
594
|
where: {
|
|
@@ -868,24 +616,15 @@ class PrismaDriver extends BaseDriver
|
|
|
868
616
|
|
|
869
617
|
async loadOneWithRelations(filters, relations)
|
|
870
618
|
{
|
|
871
|
-
if(!sc.isArray(relations) || 0 === relations.length){
|
|
872
|
-
relations = this.getAllRelations();
|
|
873
|
-
}
|
|
874
|
-
let processedFilters = this.processFilters(filters);
|
|
875
619
|
let query = this.buildQueryOptions(false);
|
|
876
|
-
query.where =
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
return this.transformRelationResults(result, includeConfig);
|
|
885
|
-
} catch(error) {
|
|
886
|
-
Logger.error('Load one with relations error: '+error.message);
|
|
887
|
-
return null;
|
|
888
|
-
}
|
|
620
|
+
query.where = this.processFilters(filters);
|
|
621
|
+
return this.executeQueryWithRelations(
|
|
622
|
+
(q) => this.model.findFirst(q),
|
|
623
|
+
query,
|
|
624
|
+
relations,
|
|
625
|
+
'Load one with relations error: ',
|
|
626
|
+
null
|
|
627
|
+
);
|
|
889
628
|
}
|
|
890
629
|
|
|
891
630
|
async loadOneBy(field, fieldValue, operator = null)
|
|
@@ -903,24 +642,15 @@ class PrismaDriver extends BaseDriver
|
|
|
903
642
|
|
|
904
643
|
async loadOneByWithRelations(field, fieldValue, relations, operator = null)
|
|
905
644
|
{
|
|
906
|
-
if(!sc.isArray(relations) || 0 === relations.length){
|
|
907
|
-
relations = this.getAllRelations();
|
|
908
|
-
}
|
|
909
|
-
let filter = this.createSingleFilter(field, fieldValue, operator);
|
|
910
645
|
let query = this.buildQueryOptions(false);
|
|
911
|
-
query.where =
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
return this.transformRelationResults(result, includeConfig);
|
|
920
|
-
} catch(error) {
|
|
921
|
-
Logger.error('Load one by with relations error: '+error.message);
|
|
922
|
-
return null;
|
|
923
|
-
}
|
|
646
|
+
query.where = this.createSingleFilter(field, fieldValue, operator);
|
|
647
|
+
return this.executeQueryWithRelations(
|
|
648
|
+
(q) => this.model.findFirst(q),
|
|
649
|
+
query,
|
|
650
|
+
relations,
|
|
651
|
+
'Load one by with relations error: ',
|
|
652
|
+
null
|
|
653
|
+
);
|
|
924
654
|
}
|
|
925
655
|
|
|
926
656
|
buildQueryOptions(useLimit = true)
|
|
@@ -958,54 +688,21 @@ class PrismaDriver extends BaseDriver
|
|
|
958
688
|
return this.processFilters(filter);
|
|
959
689
|
}
|
|
960
690
|
|
|
961
|
-
|
|
691
|
+
async executeQueryWithRelations(modelMethod, query, relations, errorMessage, defaultReturn)
|
|
962
692
|
{
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
return this.handleLikeOperator(value, fieldName);
|
|
966
|
-
}
|
|
967
|
-
let operatorsMap = {
|
|
968
|
-
'=': value,
|
|
969
|
-
'!=': {not: value},
|
|
970
|
-
'>': {gt: value},
|
|
971
|
-
'>=': {gte: value},
|
|
972
|
-
'<': {lt: value},
|
|
973
|
-
'<=': {lte: value},
|
|
974
|
-
'IN': {in: value},
|
|
975
|
-
'NOT IN': {notIn: value}
|
|
976
|
-
};
|
|
977
|
-
return operatorsMap[upperOperator] || value;
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
handleLikeOperator(value, fieldName)
|
|
981
|
-
{
|
|
982
|
-
let cleanValue = String(value).replace(/%/g, '');
|
|
983
|
-
if(this.isJsonFieldByName(fieldName) || this.isJsonField(fieldName)){
|
|
984
|
-
return this.handleJsonTextSearch(cleanValue);
|
|
693
|
+
if(!sc.isArray(relations) || 0 === relations.length){
|
|
694
|
+
relations = this.getAllRelations();
|
|
985
695
|
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
return numericValue;
|
|
990
|
-
}
|
|
696
|
+
let includeData = this.relationResolver.buildIncludeObjectWithMapping(relations);
|
|
697
|
+
if(0 < Object.keys(includeData.include).length){
|
|
698
|
+
query.include = includeData.include;
|
|
991
699
|
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
return {
|
|
998
|
-
string_contains: searchValue
|
|
999
|
-
};
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
buildIncludeObject(relations)
|
|
1003
|
-
{
|
|
1004
|
-
let include = {};
|
|
1005
|
-
for(let relation of relations){
|
|
1006
|
-
include[relation] = true;
|
|
700
|
+
try {
|
|
701
|
+
return this.relationResolver.transformRelationResults(await modelMethod(query), includeData.include, includeData.mapping);
|
|
702
|
+
} catch(error) {
|
|
703
|
+
Logger.error(errorMessage+error.message);
|
|
704
|
+
return defaultReturn;
|
|
1007
705
|
}
|
|
1008
|
-
return include;
|
|
1009
706
|
}
|
|
1010
707
|
|
|
1011
708
|
}
|