@rws-framework/db 3.3.2 → 3.3.3

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.
@@ -4,8 +4,6 @@ import { OpModelType } from '../interfaces/OpModelType';
4
4
  import { FindByType, IPaginationParams } from '../../types/FindParams';
5
5
  import { DBService } from '../../services/DBService';
6
6
  import { ISuperTagData } from '../../decorators/RWSCollection';
7
- import { RelManyMetaType, RelOneMetaType } from '../types/RelationTypes';
8
- import { IRWSModel } from '../../types/IRWSModel';
9
7
  declare class RWSModel<T> implements IModel {
10
8
  static services: IRWSModelServices;
11
9
  [key: string]: any;
@@ -32,9 +30,9 @@ declare class RWSModel<T> implements IModel {
32
30
  _asyncFill(data: any, fullDataMode?: boolean, allowRelations?: boolean): Promise<T>;
33
31
  private getModelScalarFields;
34
32
  private getRelationOneMeta;
35
- static getRelationOneMeta(model: any, classFields: string[]): Promise<RelOneMetaType<IRWSModel>>;
33
+ static getRelationOneMeta(model: any, classFields: string[]): Promise<import("..").RelOneMetaType<import("../..").IRWSModel>>;
36
34
  private getRelationManyMeta;
37
- static getRelationManyMeta(model: any, classFields: string[]): Promise<RelManyMetaType<IRWSModel>>;
35
+ static getRelationManyMeta(model: any, classFields: string[]): Promise<import("..").RelManyMetaType<import("../..").IRWSModel>>;
38
36
  static paginate<T extends RWSModel<T>>(this: OpModelType<T>, paginateParams: IPaginationParams, findParams?: FindByType): Promise<T[]>;
39
37
  toMongo(): Promise<any>;
40
38
  getCollection(): string | null;
@@ -16,6 +16,7 @@ const RelationUtils_1 = require("../utils/RelationUtils");
16
16
  const TimeSeriesUtils_1 = require("../utils/TimeSeriesUtils");
17
17
  const ModelUtils_1 = require("../utils/ModelUtils");
18
18
  const HydrateUtils_1 = require("../utils/HydrateUtils");
19
+ const FindUtils_1 = require("../utils/FindUtils");
19
20
  class RWSModel {
20
21
  static services = {};
21
22
  id;
@@ -119,29 +120,7 @@ class RWSModel {
119
120
  return RelationUtils_1.RelationUtils.getRelationManyMeta(model, classFields);
120
121
  }
121
122
  static async paginate(paginateParams, findParams) {
122
- const conditions = findParams?.conditions ?? {};
123
- const ordering = findParams?.ordering ?? null;
124
- const fields = findParams?.fields ?? null;
125
- const allowRelations = findParams?.allowRelations ?? true;
126
- const fullData = findParams?.fullData ?? false;
127
- const collection = Reflect.get(this, '_collection');
128
- this.checkForInclusionWithThrow(this.name);
129
- try {
130
- const dbData = await this.services.dbService.findBy(collection, conditions, fields, ordering, paginateParams);
131
- if (dbData.length) {
132
- const instanced = [];
133
- for (const data of dbData) {
134
- const inst = new this();
135
- instanced.push((await inst._asyncFill(data, fullData, allowRelations)));
136
- }
137
- return instanced;
138
- }
139
- return [];
140
- }
141
- catch (rwsError) {
142
- console.error(rwsError);
143
- throw rwsError;
144
- }
123
+ return await FindUtils_1.FindUtils.paginate(this, paginateParams, findParams);
145
124
  }
146
125
  async toMongo() {
147
126
  const data = {};
@@ -178,9 +157,11 @@ class RWSModel {
178
157
  async save() {
179
158
  const data = await this.toMongo();
180
159
  let updatedModelData = data;
181
- if (this.id) {
160
+ const entryExists = await ModelUtils_1.ModelUtils.entryExists(this);
161
+ if (entryExists) {
182
162
  this.preUpdate();
183
- updatedModelData = await this.dbService.update(data, this.getCollection());
163
+ const compoundId = ModelUtils_1.ModelUtils.findPrimaryKeyFields(this.constructor);
164
+ updatedModelData = await this.dbService.update(data, this.getCollection(), Array.isArray(compoundId) ? compoundId : null);
184
165
  await this._asyncFill(updatedModelData);
185
166
  this.postUpdate();
186
167
  }
@@ -239,59 +220,13 @@ class RWSModel {
239
220
  return await this.services.dbService.watchCollection(collection, preRun);
240
221
  }
241
222
  static async findOneBy(findParams) {
242
- const conditions = findParams?.conditions ?? {};
243
- const ordering = findParams?.ordering ?? null;
244
- const fields = findParams?.fields ?? null;
245
- const allowRelations = findParams?.allowRelations ?? true;
246
- const fullData = findParams?.fullData ?? false;
247
- this.checkForInclusionWithThrow('');
248
- const collection = Reflect.get(this, '_collection');
249
- const dbData = await this.services.dbService.findOneBy(collection, conditions, fields, ordering, allowRelations);
250
- if (dbData) {
251
- const inst = new this();
252
- return await inst._asyncFill(dbData, fullData, allowRelations);
253
- }
254
- return null;
223
+ return await FindUtils_1.FindUtils.findOneBy(this, findParams);
255
224
  }
256
225
  static async find(id, findParams = null) {
257
- const ordering = findParams?.ordering ?? null;
258
- const fields = findParams?.fields ?? null;
259
- const allowRelations = findParams?.allowRelations ?? true;
260
- const fullData = findParams?.fullData ?? false;
261
- const collection = Reflect.get(this, '_collection');
262
- this.checkForInclusionWithThrow(this.name);
263
- const dbData = await this.services.dbService.findOneBy(collection, { id }, fields, ordering, allowRelations);
264
- if (dbData) {
265
- const inst = new this();
266
- return await inst._asyncFill(dbData, fullData, allowRelations);
267
- }
268
- return null;
226
+ return await FindUtils_1.FindUtils.find(this, id, findParams);
269
227
  }
270
228
  static async findBy(findParams) {
271
- const conditions = findParams?.conditions ?? {};
272
- const ordering = findParams?.ordering ?? null;
273
- const fields = findParams?.fields ?? null;
274
- const allowRelations = findParams?.allowRelations ?? true;
275
- const fullData = findParams?.fullData ?? false;
276
- const collection = Reflect.get(this, '_collection');
277
- this.checkForInclusionWithThrow(this.name);
278
- try {
279
- const paginateParams = findParams?.pagination ? findParams?.pagination : undefined;
280
- const dbData = await this.services.dbService.findBy(collection, conditions, fields, ordering, paginateParams);
281
- if (dbData.length) {
282
- const instanced = [];
283
- for (const data of dbData) {
284
- const inst = new this();
285
- instanced.push((await inst._asyncFill(data, fullData, allowRelations)));
286
- }
287
- return instanced;
288
- }
289
- return [];
290
- }
291
- catch (rwsError) {
292
- console.error(rwsError);
293
- throw rwsError;
294
- }
229
+ return await FindUtils_1.FindUtils.findBy(this, findParams);
295
230
  }
296
231
  static async delete(conditions) {
297
232
  const collection = Reflect.get(this, '_collection');
@@ -0,0 +1,9 @@
1
+ import { RWSModel } from "../core/RWSModel";
2
+ import { OpModelType } from "..";
3
+ import { FindByType, IPaginationParams } from "../../types/FindParams";
4
+ export declare class FindUtils {
5
+ static findOneBy<T extends RWSModel<T>>(opModel: OpModelType<T>, findParams?: FindByType): Promise<T | null>;
6
+ static find<T extends RWSModel<T>>(opModel: OpModelType<T>, id: string | number, findParams?: Omit<FindByType, 'conditions'>): Promise<T | null>;
7
+ static findBy<T extends RWSModel<T>>(opModel: OpModelType<T>, findParams?: FindByType): Promise<T[]>;
8
+ static paginate<T extends RWSModel<T>>(opModel: OpModelType<T>, paginateParams: IPaginationParams, findParams?: FindByType): Promise<T[]>;
9
+ }
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FindUtils = void 0;
4
+ class FindUtils {
5
+ static async findOneBy(opModel, findParams) {
6
+ const conditions = findParams?.conditions ?? {};
7
+ const ordering = findParams?.ordering ?? null;
8
+ const fields = findParams?.fields ?? null;
9
+ const allowRelations = findParams?.allowRelations ?? true;
10
+ const fullData = findParams?.fullData ?? false;
11
+ opModel.checkForInclusionWithThrow('');
12
+ const collection = Reflect.get(opModel, '_collection');
13
+ const dbData = await opModel.services.dbService.findOneBy(collection, conditions, fields, ordering, allowRelations);
14
+ if (dbData) {
15
+ const inst = new opModel();
16
+ return await inst._asyncFill(dbData, fullData, allowRelations);
17
+ }
18
+ return null;
19
+ }
20
+ static async find(opModel, id, findParams = null) {
21
+ const ordering = findParams?.ordering ?? null;
22
+ const fields = findParams?.fields ?? null;
23
+ const allowRelations = findParams?.allowRelations ?? true;
24
+ const fullData = findParams?.fullData ?? false;
25
+ const collection = Reflect.get(opModel, '_collection');
26
+ opModel.checkForInclusionWithThrow(opModel.name);
27
+ const dbData = await opModel.services.dbService.findOneBy(collection, { id }, fields, ordering, allowRelations);
28
+ if (dbData) {
29
+ const inst = new opModel();
30
+ return await inst._asyncFill(dbData, fullData, allowRelations);
31
+ }
32
+ return null;
33
+ }
34
+ static async findBy(opModel, findParams) {
35
+ const conditions = findParams?.conditions ?? {};
36
+ const ordering = findParams?.ordering ?? null;
37
+ const fields = findParams?.fields ?? null;
38
+ const allowRelations = findParams?.allowRelations ?? true;
39
+ const fullData = findParams?.fullData ?? false;
40
+ const collection = Reflect.get(opModel, '_collection');
41
+ opModel.checkForInclusionWithThrow(opModel.name);
42
+ try {
43
+ const paginateParams = findParams?.pagination ? findParams?.pagination : undefined;
44
+ const dbData = await opModel.services.dbService.findBy(collection, conditions, fields, ordering, paginateParams);
45
+ if (dbData.length) {
46
+ const instanced = [];
47
+ for (const data of dbData) {
48
+ const inst = new opModel();
49
+ instanced.push((await inst._asyncFill(data, fullData, allowRelations)));
50
+ }
51
+ return instanced;
52
+ }
53
+ return [];
54
+ }
55
+ catch (rwsError) {
56
+ console.error(rwsError);
57
+ throw rwsError;
58
+ }
59
+ }
60
+ static async paginate(opModel, paginateParams, findParams) {
61
+ const conditions = findParams?.conditions ?? {};
62
+ const ordering = findParams?.ordering ?? null;
63
+ const fields = findParams?.fields ?? null;
64
+ const allowRelations = findParams?.allowRelations ?? true;
65
+ const fullData = findParams?.fullData ?? false;
66
+ const collection = Reflect.get(opModel, '_collection');
67
+ opModel.checkForInclusionWithThrow(opModel.name);
68
+ try {
69
+ const dbData = await opModel.services.dbService.findBy(collection, conditions, fields, ordering, paginateParams);
70
+ if (dbData.length) {
71
+ const instanced = [];
72
+ for (const data of dbData) {
73
+ const inst = new opModel();
74
+ instanced.push((await inst._asyncFill(data, fullData, allowRelations)));
75
+ }
76
+ return instanced;
77
+ }
78
+ return [];
79
+ }
80
+ catch (rwsError) {
81
+ console.error(rwsError);
82
+ throw rwsError;
83
+ }
84
+ }
85
+ }
86
+ exports.FindUtils = FindUtils;
@@ -1,4 +1,5 @@
1
1
  import { RWSModel } from "../core/RWSModel";
2
+ import { OpModelType } from "..";
2
3
  export declare class ModelUtils {
3
4
  static getModelAnnotations<T extends unknown>(constructor: new () => T): Promise<Record<string, {
4
5
  annotationType: string;
@@ -7,4 +8,6 @@ export declare class ModelUtils {
7
8
  static checkDbVariable(constructor: any, variable: string): Promise<boolean>;
8
9
  static isSubclass<T, C extends new () => T>(constructor: C, baseClass: new () => T): boolean;
9
10
  static getModelScalarFields(model: RWSModel<any>): string[];
11
+ static findPrimaryKeyFields(opModel: OpModelType<any>): string | string[];
12
+ static entryExists(model: RWSModel<any>): Promise<boolean>;
10
13
  }
@@ -59,5 +59,57 @@ class ModelUtils {
59
59
  .filter((item) => item.indexOf('TrackType') === 0)
60
60
  .map((item) => item.split(':').at(-1));
61
61
  }
62
+ static findPrimaryKeyFields(opModel) {
63
+ if (opModel._NO_ID) {
64
+ const foundSuperId = opModel._SUPER_TAGS.find(tag => tag.tagType === 'id');
65
+ if (foundSuperId) {
66
+ return foundSuperId.fields;
67
+ }
68
+ const foundSuperUnique = opModel._SUPER_TAGS.find(tag => tag.tagType === 'unique');
69
+ if (foundSuperUnique) {
70
+ return foundSuperUnique.fields;
71
+ }
72
+ }
73
+ return 'id';
74
+ }
75
+ static async entryExists(model) {
76
+ let entryHasData = true;
77
+ let compoundId = false;
78
+ const foundPrimaryKey = this.findPrimaryKeyFields(model.constructor);
79
+ if (Array.isArray(foundPrimaryKey)) {
80
+ compoundId = true;
81
+ for (const idKey of foundPrimaryKey) {
82
+ if (!Object.hasOwn(model, idKey)) {
83
+ entryHasData = false;
84
+ }
85
+ if (Object.hasOwn(model, idKey) && !model[idKey]) {
86
+ entryHasData = false;
87
+ }
88
+ }
89
+ }
90
+ else {
91
+ if (Object.hasOwn(model, foundPrimaryKey) && !model[foundPrimaryKey]) {
92
+ entryHasData = false;
93
+ }
94
+ if (!Object.hasOwn(model, foundPrimaryKey)) {
95
+ entryHasData = false;
96
+ }
97
+ }
98
+ if (!entryHasData) {
99
+ return false;
100
+ }
101
+ const constructor = model.constructor;
102
+ const conditions = {};
103
+ if (compoundId) {
104
+ for (const key of foundPrimaryKey) {
105
+ conditions[key] = model[key];
106
+ }
107
+ return (await constructor.findOneBy({ conditions }) !== null);
108
+ }
109
+ else {
110
+ conditions[foundPrimaryKey] = model[foundPrimaryKey];
111
+ }
112
+ return (await constructor.findOneBy({ conditions })) !== null;
113
+ }
62
114
  }
63
115
  exports.ModelUtils = ModelUtils;
@@ -21,7 +21,9 @@ declare class DBService {
21
21
  cloneDatabase(source: string, target: string): Promise<void>;
22
22
  watchCollection(collectionName: string, preRun: () => void): Promise<any>;
23
23
  insert(data: any, collection: string, isTimeSeries?: boolean): Promise<any>;
24
- update(data: any, collection: string): Promise<IModel>;
24
+ update(data: any, collection: string, compoundId?: {
25
+ [key: string]: any;
26
+ }): Promise<IModel>;
25
27
  findOneBy(collection: string, conditions: any, fields?: string[] | null, ordering?: {
26
28
  [fieldName: string]: string;
27
29
  }, allowRelations?: boolean): Promise<IModel | null>;
@@ -101,17 +101,24 @@ class DBService {
101
101
  result = await prismaCollection.create({ data });
102
102
  return await this.findOneBy(collection, { id: result.id });
103
103
  }
104
- async update(data, collection) {
105
- const model_id = data.id;
106
- delete data['id'];
104
+ async update(data, collection, compoundId = null) {
107
105
  const prismaCollection = this.getCollectionHandler(collection);
106
+ const where = compoundId ? compoundId : {
107
+ id: data.id,
108
+ };
109
+ if (!compoundId) {
110
+ delete data['id'];
111
+ }
112
+ else {
113
+ for (const cKey in compoundId) {
114
+ delete data[cKey];
115
+ }
116
+ }
108
117
  await prismaCollection.update({
109
- where: {
110
- id: model_id,
111
- },
118
+ where,
112
119
  data: data,
113
120
  });
114
- return await this.findOneBy(collection, { id: model_id });
121
+ return await this.findOneBy(collection, where);
115
122
  }
116
123
  async findOneBy(collection, conditions, fields = null, ordering = null, allowRelations = true) {
117
124
  const params = { where: conditions };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rws-framework/db",
3
3
  "private": false,
4
- "version": "3.3.2",
4
+ "version": "3.3.3",
5
5
  "description": "",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -1,7 +1,7 @@
1
1
  import { IModel } from '../interfaces/IModel';
2
2
  import { IRWSModelServices } from '../interfaces/IRWSModelServices';
3
3
  import { OpModelType } from '../interfaces/OpModelType';
4
- import { TrackType, ITrackerMetaOpts } from '../../decorators';
4
+ import { TrackType } from '../../decorators';
5
5
  import { FieldsHelper } from '../../helper/FieldsHelper';
6
6
  import { FindByType, IPaginationParams } from '../../types/FindParams';
7
7
  import { RelationUtils } from '../utils/RelationUtils';
@@ -11,9 +11,8 @@ import { ModelUtils } from '../utils/ModelUtils';
11
11
  // import timeSeriesModel from './TimeSeriesModel';
12
12
  import { DBService } from '../../services/DBService';
13
13
  import { ISuperTagData } from '../../decorators/RWSCollection';
14
- import { RelManyMetaType, RelOneMetaType } from '../types/RelationTypes';
15
- import { IRWSModel } from '../../types/IRWSModel';
16
14
  import { HydrateUtils } from '../utils/HydrateUtils';
15
+ import { FindUtils } from '../utils/FindUtils';
17
16
 
18
17
  class RWSModel<T> implements IModel {
19
18
  static services: IRWSModelServices = {};
@@ -153,33 +152,7 @@ class RWSModel<T> implements IModel {
153
152
  paginateParams: IPaginationParams,
154
153
  findParams?: FindByType
155
154
  ): Promise<T[]> {
156
- const conditions = findParams?.conditions ?? {};
157
- const ordering = findParams?.ordering ?? null;
158
- const fields = findParams?.fields ?? null;
159
- const allowRelations = findParams?.allowRelations ?? true;
160
- const fullData = findParams?.fullData ?? false;
161
-
162
- const collection = Reflect.get(this, '_collection');
163
- this.checkForInclusionWithThrow(this.name);
164
- try {
165
- const dbData = await this.services.dbService.findBy(collection, conditions, fields, ordering, paginateParams);
166
- if (dbData.length) {
167
- const instanced: T[] = [];
168
-
169
- for (const data of dbData) {
170
- const inst: T = new (this as { new(): T })();
171
- instanced.push((await inst._asyncFill(data, fullData,allowRelations)) as T);
172
- }
173
-
174
- return instanced;
175
- }
176
-
177
- return [];
178
- } catch (rwsError: Error | any) {
179
- console.error(rwsError);
180
-
181
- throw rwsError;
182
- }
155
+ return await FindUtils.paginate(this, paginateParams, findParams);
183
156
  }
184
157
 
185
158
  public async toMongo(): Promise<any> {
@@ -227,11 +200,16 @@ class RWSModel<T> implements IModel {
227
200
 
228
201
  async save(): Promise<this> {
229
202
  const data = await this.toMongo();
230
- let updatedModelData = data;
231
- if (this.id) {
203
+ let updatedModelData = data;
204
+
205
+ const entryExists = await ModelUtils.entryExists(this);
206
+
207
+ if (entryExists) {
232
208
  this.preUpdate();
233
209
 
234
- updatedModelData = await this.dbService.update(data, this.getCollection());
210
+ const compoundId = ModelUtils.findPrimaryKeyFields(this.constructor as OpModelType<any>);
211
+
212
+ updatedModelData = await this.dbService.update(data, this.getCollection(), Array.isArray(compoundId) ? compoundId : null);
235
213
 
236
214
  await this._asyncFill(updatedModelData);
237
215
  this.postUpdate();
@@ -316,25 +294,7 @@ class RWSModel<T> implements IModel {
316
294
  this: OpModelType<T>,
317
295
  findParams?: FindByType
318
296
  ): Promise<T | null> {
319
- const conditions = findParams?.conditions ?? {};
320
- const ordering = findParams?.ordering ?? null;
321
- const fields = findParams?.fields ?? null;
322
- const allowRelations = findParams?.allowRelations ?? true;
323
- const fullData = findParams?.fullData ?? false;
324
-
325
- this.checkForInclusionWithThrow('');
326
-
327
-
328
- const collection = Reflect.get(this, '_collection');
329
- const dbData = await this.services.dbService.findOneBy(collection, conditions, fields, ordering, allowRelations);
330
-
331
-
332
- if (dbData) {
333
- const inst: T = new (this as { new(): T })();
334
- return await inst._asyncFill(dbData, fullData, allowRelations);
335
- }
336
-
337
- return null;
297
+ return await FindUtils.findOneBy(this, findParams);
338
298
  }
339
299
 
340
300
  public static async find<T extends RWSModel<T>>(
@@ -342,58 +302,14 @@ class RWSModel<T> implements IModel {
342
302
  id: string | number,
343
303
  findParams: Omit<FindByType, 'conditions'> = null
344
304
  ): Promise<T | null> {
345
- const ordering = findParams?.ordering ?? null;
346
- const fields = findParams?.fields ?? null;
347
- const allowRelations = findParams?.allowRelations ?? true;
348
- const fullData = findParams?.fullData ?? false;
349
-
350
- const collection = Reflect.get(this, '_collection');
351
- this.checkForInclusionWithThrow(this.name);
352
-
353
- const dbData = await this.services.dbService.findOneBy(collection, { id }, fields, ordering, allowRelations);
354
-
355
- if (dbData) {
356
- const inst: T = new (this as { new(): T })();
357
- return await inst._asyncFill(dbData, fullData, allowRelations);
358
- }
359
-
360
- return null;
305
+ return await FindUtils.find(this, id, findParams)
361
306
  }
362
307
 
363
308
  public static async findBy<T extends RWSModel<T>>(
364
309
  this: OpModelType<T>,
365
310
  findParams?: FindByType
366
311
  ): Promise<T[]> {
367
- const conditions = findParams?.conditions ?? {};
368
- const ordering = findParams?.ordering ?? null;
369
- const fields = findParams?.fields ?? null;
370
- const allowRelations = findParams?.allowRelations ?? true;
371
- const fullData = findParams?.fullData ?? false;
372
-
373
- const collection = Reflect.get(this, '_collection');
374
- this.checkForInclusionWithThrow(this.name);
375
- try {
376
- const paginateParams = findParams?.pagination ? findParams?.pagination : undefined;
377
- const dbData = await this.services.dbService.findBy(collection, conditions, fields, ordering, paginateParams);
378
-
379
- if (dbData.length) {
380
- const instanced: T[] = [];
381
-
382
- for (const data of dbData) {
383
- const inst: T = new (this as { new(): T })();
384
-
385
- instanced.push((await inst._asyncFill(data, fullData,allowRelations)) as T);
386
- }
387
-
388
- return instanced;
389
- }
390
-
391
- return [];
392
- } catch (rwsError: Error | any) {
393
- console.error(rwsError);
394
-
395
- throw rwsError;
396
- }
312
+ return await FindUtils.findBy(this, findParams);
397
313
  }
398
314
 
399
315
  public static async delete<T extends RWSModel<T>>(
@@ -0,0 +1,128 @@
1
+ import { RWSModel } from "../core/RWSModel";
2
+ import { RelManyMetaType, RelOneMetaType } from "../types/RelationTypes";
3
+ import { IRWSModel } from "../../types/IRWSModel";
4
+ import { TimeSeriesUtils } from "./TimeSeriesUtils";
5
+ import { RelationUtils } from "./RelationUtils";
6
+ import { OpModelType } from "..";
7
+ import { ModelUtils } from "./ModelUtils";
8
+ import { FindByType, IPaginationParams } from "../../types/FindParams";
9
+
10
+ export class FindUtils {
11
+ public static async findOneBy<T extends RWSModel<T>>(
12
+ opModel: OpModelType<T>,
13
+ findParams?: FindByType
14
+ ): Promise<T | null> {
15
+ const conditions = findParams?.conditions ?? {};
16
+ const ordering = findParams?.ordering ?? null;
17
+ const fields = findParams?.fields ?? null;
18
+ const allowRelations = findParams?.allowRelations ?? true;
19
+ const fullData = findParams?.fullData ?? false;
20
+
21
+ opModel.checkForInclusionWithThrow('');
22
+
23
+
24
+ const collection = Reflect.get(opModel, '_collection');
25
+ const dbData = await opModel.services.dbService.findOneBy(collection, conditions, fields, ordering, allowRelations);
26
+
27
+
28
+ if (dbData) {
29
+ const inst: T = new (opModel as { new(): T })();
30
+ return await inst._asyncFill(dbData, fullData, allowRelations);
31
+ }
32
+
33
+ return null;
34
+ }
35
+
36
+ public static async find<T extends RWSModel<T>>(
37
+ opModel: OpModelType<T>,
38
+ id: string | number,
39
+ findParams: Omit<FindByType, 'conditions'> = null
40
+ ): Promise<T | null> {
41
+ const ordering = findParams?.ordering ?? null;
42
+ const fields = findParams?.fields ?? null;
43
+ const allowRelations = findParams?.allowRelations ?? true;
44
+ const fullData = findParams?.fullData ?? false;
45
+
46
+ const collection = Reflect.get(opModel, '_collection');
47
+ opModel.checkForInclusionWithThrow(opModel.name);
48
+
49
+ const dbData = await opModel.services.dbService.findOneBy(collection, { id }, fields, ordering, allowRelations);
50
+
51
+ if (dbData) {
52
+ const inst: T = new (opModel as { new(): T })();
53
+ return await inst._asyncFill(dbData, fullData, allowRelations);
54
+ }
55
+
56
+ return null;
57
+ }
58
+
59
+ public static async findBy<T extends RWSModel<T>>(
60
+ opModel: OpModelType<T>,
61
+ findParams?: FindByType
62
+ ): Promise<T[]> {
63
+ const conditions = findParams?.conditions ?? {};
64
+ const ordering = findParams?.ordering ?? null;
65
+ const fields = findParams?.fields ?? null;
66
+ const allowRelations = findParams?.allowRelations ?? true;
67
+ const fullData = findParams?.fullData ?? false;
68
+
69
+ const collection = Reflect.get(opModel, '_collection');
70
+ opModel.checkForInclusionWithThrow(opModel.name);
71
+ try {
72
+ const paginateParams = findParams?.pagination ? findParams?.pagination : undefined;
73
+ const dbData = await opModel.services.dbService.findBy(collection, conditions, fields, ordering, paginateParams);
74
+
75
+ if (dbData.length) {
76
+ const instanced: T[] = [];
77
+
78
+ for (const data of dbData) {
79
+ const inst: T = new (opModel as { new(): T })();
80
+
81
+ instanced.push((await inst._asyncFill(data, fullData, allowRelations)) as T);
82
+ }
83
+
84
+ return instanced;
85
+ }
86
+
87
+ return [];
88
+ } catch (rwsError: Error | any) {
89
+ console.error(rwsError);
90
+
91
+ throw rwsError;
92
+ }
93
+ }
94
+
95
+ public static async paginate<T extends RWSModel<T>>(
96
+ opModel: OpModelType<T>,
97
+ paginateParams: IPaginationParams,
98
+ findParams?: FindByType
99
+ ): Promise<T[]> {
100
+ const conditions = findParams?.conditions ?? {};
101
+ const ordering = findParams?.ordering ?? null;
102
+ const fields = findParams?.fields ?? null;
103
+ const allowRelations = findParams?.allowRelations ?? true;
104
+ const fullData = findParams?.fullData ?? false;
105
+
106
+ const collection = Reflect.get(opModel, '_collection');
107
+ opModel.checkForInclusionWithThrow(opModel.name);
108
+ try {
109
+ const dbData = await opModel.services.dbService.findBy(collection, conditions, fields, ordering, paginateParams);
110
+ if (dbData.length) {
111
+ const instanced: T[] = [];
112
+
113
+ for (const data of dbData) {
114
+ const inst: T = new (opModel as { new(): T })();
115
+ instanced.push((await inst._asyncFill(data, fullData, allowRelations)) as T);
116
+ }
117
+
118
+ return instanced;
119
+ }
120
+
121
+ return [];
122
+ } catch (rwsError: Error | any) {
123
+ console.error(rwsError);
124
+
125
+ throw rwsError;
126
+ }
127
+ }
128
+ }
@@ -1,5 +1,8 @@
1
1
  import { RWSModel } from "../core/RWSModel";
2
2
  import { FieldsHelper } from '../../helper/FieldsHelper';
3
+ import { OpModelType } from "..";
4
+ import { ISuperTagData } from "../../decorators/RWSCollection";
5
+ import { FindByType } from "../../types/FindParams";
3
6
 
4
7
  export class ModelUtils {
5
8
  static async getModelAnnotations<T extends unknown>(constructor: new () => T): Promise<Record<string, {annotationType: string, metadata: any}>> {
@@ -71,4 +74,71 @@ export class ModelUtils {
71
74
  .filter((item: string) => item.indexOf('TrackType') === 0)
72
75
  .map((item: string) => item.split(':').at(-1));
73
76
  }
77
+
78
+ static findPrimaryKeyFields(opModel: OpModelType<any>): string | string[]
79
+ {
80
+ if(opModel._NO_ID){
81
+ const foundSuperId: ISuperTagData = opModel._SUPER_TAGS.find(tag => tag.tagType === 'id');
82
+
83
+ if(foundSuperId){
84
+ return foundSuperId.fields;
85
+ }
86
+
87
+ const foundSuperUnique: ISuperTagData = opModel._SUPER_TAGS.find(tag => tag.tagType === 'unique');
88
+
89
+ if(foundSuperUnique){
90
+ return foundSuperUnique.fields;
91
+ }
92
+ }
93
+
94
+ return 'id';
95
+ }
96
+
97
+ static async entryExists(model: RWSModel<any>): Promise<boolean>
98
+ {
99
+ let entryHasData = true;
100
+ let compoundId = false;
101
+
102
+ const foundPrimaryKey = this.findPrimaryKeyFields(model.constructor as OpModelType<any>);
103
+
104
+ if(Array.isArray(foundPrimaryKey)){
105
+ compoundId = true;
106
+ for(const idKey of foundPrimaryKey){
107
+ if(!Object.hasOwn(model, idKey)){
108
+ entryHasData = false;
109
+ }
110
+
111
+ if(Object.hasOwn(model, idKey) && !model[idKey]){
112
+ entryHasData = false;
113
+ }
114
+ }
115
+ }else{
116
+ if(Object.hasOwn(model, foundPrimaryKey) && !model[foundPrimaryKey]){
117
+ entryHasData = false;
118
+ }
119
+
120
+ if(!Object.hasOwn(model, foundPrimaryKey)){
121
+ entryHasData = false;
122
+ }
123
+ }
124
+
125
+ if(!entryHasData){
126
+ return false;
127
+ }
128
+
129
+ const constructor = model.constructor as OpModelType<any>;
130
+ const conditions: FindByType['conditions'] = {};
131
+
132
+ if(compoundId){
133
+ for(const key of foundPrimaryKey){
134
+ conditions[key] = model[key];
135
+ }
136
+
137
+ return (await constructor.findOneBy({ conditions }) !== null);
138
+ }else{
139
+ conditions[foundPrimaryKey as string] = model[foundPrimaryKey as string];
140
+ }
141
+
142
+ return (await constructor.findOneBy({ conditions })) !== null;
143
+ }
74
144
  }
@@ -137,22 +137,30 @@ class DBService {
137
137
  return await this.findOneBy(collection, { id: result.id });
138
138
  }
139
139
 
140
- async update(data: any, collection: string): Promise<IModel>
141
- {
142
- const model_id: string = data.id;
143
- delete data['id'];
140
+ async update(data: any, collection: string, compoundId: {[key: string]: any} = null): Promise<IModel>
141
+ {
144
142
 
145
143
  const prismaCollection = this.getCollectionHandler(collection);
146
144
 
145
+ const where = compoundId ? compoundId : {
146
+ id: data.id,
147
+ };
148
+
149
+ if(!compoundId){
150
+ delete data['id'];
151
+ }else{
152
+ for(const cKey in compoundId){
153
+ delete data[cKey];
154
+ }
155
+ }
156
+
147
157
  await prismaCollection.update({
148
- where: {
149
- id: model_id,
150
- },
158
+ where,
151
159
  data: data,
152
160
  });
153
161
 
154
162
 
155
- return await this.findOneBy(collection, { id: model_id });
163
+ return await this.findOneBy(collection, where);
156
164
  }
157
165
 
158
166