@rws-framework/db 3.5.0 → 3.6.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.
@@ -15,7 +15,10 @@ declare class RWSModel<T> implements IModel {
15
15
  static _BANNED_KEYS: string[];
16
16
  static allModels: OpModelType<any>[];
17
17
  static _CUT_KEYS: string[];
18
+ private postLoadExecuted;
18
19
  constructor(data?: any);
20
+ isPostLoadExecuted(): boolean;
21
+ setPostLoadExecuted(): void;
19
22
  checkForInclusionWithThrow(): void;
20
23
  static checkForInclusionWithThrow(this: OpModelType<any>, checkModelType: string): void;
21
24
  checkForInclusion(): boolean;
@@ -27,7 +30,7 @@ declare class RWSModel<T> implements IModel {
27
30
  id: string | number;
28
31
  };
29
32
  };
30
- _asyncFill(data: any, fullDataMode?: boolean, allowRelations?: boolean): Promise<T>;
33
+ _asyncFill(data: any, fullDataMode?: boolean, allowRelations?: boolean, postLoadExecute?: boolean): Promise<T>;
31
34
  private getModelScalarFields;
32
35
  private getRelationOneMeta;
33
36
  static getRelationOneMeta(model: any, classFields: string[]): Promise<import("..").RelOneMetaType<import("../..").IRWSModel>>;
@@ -42,10 +45,11 @@ declare class RWSModel<T> implements IModel {
42
45
  annotationType: string;
43
46
  metadata: any;
44
47
  }>>;
45
- preUpdate(): void;
46
- postUpdate(): void;
47
- preCreate(): void;
48
- postCreate(): void;
48
+ preUpdate(): Promise<void>;
49
+ postLoad(): Promise<void>;
50
+ postUpdate(): Promise<void>;
51
+ preCreate(): Promise<void>;
52
+ postCreate(): Promise<void>;
49
53
  static isSubclass<T extends RWSModel<T>, C extends new () => T>(constructor: C, baseClass: new () => T): boolean;
50
54
  hasTimeSeries(): boolean;
51
55
  static checkTimeSeries(constructor: any): boolean;
@@ -68,6 +72,6 @@ declare class RWSModel<T> implements IModel {
68
72
  [k: string]: any;
69
73
  }): Promise<number>;
70
74
  static getDb(): DBService;
71
- reload(): Promise<T | null>;
75
+ reload(): Promise<RWSModel<T> | null>;
72
76
  }
73
77
  export { RWSModel };
@@ -27,6 +27,7 @@ class RWSModel {
27
27
  static _BANNED_KEYS = ['_collection'];
28
28
  static allModels = [];
29
29
  static _CUT_KEYS = [];
30
+ postLoadExecuted = false;
30
31
  constructor(data = null) {
31
32
  if (!this.getCollection()) {
32
33
  throw new Error('Model must have a collection defined');
@@ -43,6 +44,12 @@ class RWSModel {
43
44
  throw new Error('Time Series not supported in synchronous constructor. Use `await Model.create(data)` static method to instantiate this model.');
44
45
  }
45
46
  }
47
+ isPostLoadExecuted() {
48
+ return this.postLoadExecuted;
49
+ }
50
+ setPostLoadExecuted() {
51
+ this.postLoadExecuted = true;
52
+ }
46
53
  checkForInclusionWithThrow() {
47
54
  const constructor = this.constructor;
48
55
  if (!constructor.checkForInclusion(constructor.name)) {
@@ -85,7 +92,7 @@ class RWSModel {
85
92
  bindRelation(key, relatedModel) {
86
93
  return RelationUtils_1.RelationUtils.bindRelation(relatedModel);
87
94
  }
88
- async _asyncFill(data, fullDataMode = false, allowRelations = true) {
95
+ async _asyncFill(data, fullDataMode = false, allowRelations = true, postLoadExecute = true) {
89
96
  const collections_to_models = {};
90
97
  const classFields = FieldsHelper_1.FieldsHelper.getAllClassFields(this.constructor);
91
98
  // Get both relation metadata types asynchronously
@@ -102,6 +109,10 @@ class RWSModel {
102
109
  }
103
110
  // Process regular fields and time series
104
111
  await HydrateUtils_1.HydrateUtils.hydrateDataFields(this, collections_to_models, relOneData, seriesHydrationfields, fullDataMode, data);
112
+ if (!this.isPostLoadExecuted() && postLoadExecute) {
113
+ await this.postLoad();
114
+ this.setPostLoadExecuted();
115
+ }
105
116
  return this;
106
117
  }
107
118
  getModelScalarFields(model) {
@@ -159,34 +170,37 @@ class RWSModel {
159
170
  let updatedModelData = data;
160
171
  const entryExists = await ModelUtils_1.ModelUtils.entryExists(this);
161
172
  if (entryExists) {
162
- this.preUpdate();
173
+ await this.preUpdate();
163
174
  const pk = ModelUtils_1.ModelUtils.findPrimaryKeyFields(this.constructor);
164
175
  updatedModelData = await this.dbService.update(data, this.getCollection(), pk);
165
176
  await this._asyncFill(updatedModelData);
166
- this.postUpdate();
177
+ await this.postUpdate();
167
178
  }
168
179
  else {
169
- this.preCreate();
180
+ await this.preCreate();
170
181
  const isTimeSeries = false; //this instanceof timeSeriesModel;
171
182
  updatedModelData = await this.dbService.insert(data, this.getCollection(), isTimeSeries);
172
183
  await this._asyncFill(updatedModelData);
173
- this.postCreate();
184
+ await this.postCreate();
174
185
  }
175
186
  return this;
176
187
  }
177
188
  static async getModelAnnotations(constructor) {
178
189
  return ModelUtils_1.ModelUtils.getModelAnnotations(constructor);
179
190
  }
180
- preUpdate() {
191
+ async preUpdate() {
192
+ return;
193
+ }
194
+ async postLoad() {
181
195
  return;
182
196
  }
183
- postUpdate() {
197
+ async postUpdate() {
184
198
  return;
185
199
  }
186
- preCreate() {
200
+ async preCreate() {
187
201
  return;
188
202
  }
189
- postCreate() {
203
+ async postCreate() {
190
204
  return;
191
205
  }
192
206
  static isSubclass(constructor, baseClass) {
@@ -1,11 +1,21 @@
1
1
  import { IDbConfigHandler } from '../../types/DbConfigHandler';
2
2
  import { DBService } from '../../services/DBService';
3
+ import { RWSModel } from '..';
3
4
  export interface IModel {
4
5
  [key: string]: any;
5
6
  id: string | number | null;
6
- save: () => void;
7
- getDb: () => DBService;
8
- getCollection: () => string | null;
9
7
  configService?: IDbConfigHandler;
10
8
  dbService?: DBService;
9
+ save: () => Promise<this>;
10
+ getDb: () => DBService;
11
+ getCollection: () => string | null;
12
+ reload: () => Promise<RWSModel<any>>;
13
+ delete: () => Promise<void>;
14
+ hasTimeSeries: () => boolean;
15
+ _asyncFill: (data: any, fullDataMode?: boolean, allowRelations?: boolean) => Promise<any>;
16
+ preUpdate: () => Promise<void>;
17
+ postUpdate: () => Promise<void>;
18
+ preCreate: () => Promise<void>;
19
+ postCreate: () => Promise<void>;
20
+ postLoad: () => Promise<void>;
11
21
  }
@@ -28,7 +28,18 @@ export interface OpModelType<T> {
28
28
  create<T extends RWSModel<T>>(this: new () => T, data: any): Promise<T>;
29
29
  getRelationOneMeta(model: any, classFields: string[]): Promise<RelOneMetaType<IRWSModel>>;
30
30
  getRelationManyMeta(model: any, classFields: string[]): Promise<RelManyMetaType<IRWSModel>>;
31
- getCollection(): string;
31
+ getCollection(): string | null;
32
32
  getDb(): DBService;
33
33
  setServices(services: IRWSModelServices): void;
34
+ watchCollection<T extends RWSModel<T>>(this: OpModelType<T>, preRun: () => void): Promise<any>;
35
+ count(where?: {
36
+ [k: string]: any;
37
+ }): Promise<number>;
38
+ isSubclass<T extends RWSModel<T>, C extends new () => T>(constructor: C, baseClass: new () => T): boolean;
39
+ getModelAnnotations<T extends unknown>(constructor: new () => T): Promise<Record<string, {
40
+ annotationType: string;
41
+ metadata: any;
42
+ }>>;
43
+ checkTimeSeries(constructor: any): boolean;
44
+ checkDbVariable(constructor: any, variable: string): Promise<boolean>;
34
45
  }
@@ -13,7 +13,8 @@ class FindUtils {
13
13
  const dbData = await opModel.services.dbService.findOneBy(collection, conditions, fields, ordering);
14
14
  if (dbData) {
15
15
  const inst = new opModel();
16
- return await inst._asyncFill(dbData, fullData, allowRelations);
16
+ const loaded = await inst._asyncFill(dbData, fullData, allowRelations, findParams.cancelPostLoad ? false : true);
17
+ return loaded;
17
18
  }
18
19
  return null;
19
20
  }
@@ -27,7 +28,8 @@ class FindUtils {
27
28
  const dbData = await opModel.services.dbService.findOneBy(collection, { id }, fields, ordering);
28
29
  if (dbData) {
29
30
  const inst = new opModel();
30
- return await inst._asyncFill(dbData, fullData, allowRelations);
31
+ const loaded = await inst._asyncFill(dbData, fullData, allowRelations, findParams.cancelPostLoad ? false : true);
32
+ return loaded;
31
33
  }
32
34
  return null;
33
35
  }
@@ -46,7 +48,7 @@ class FindUtils {
46
48
  const instanced = [];
47
49
  for (const data of dbData) {
48
50
  const inst = new opModel();
49
- instanced.push((await inst._asyncFill(data, fullData, allowRelations)));
51
+ instanced.push((await inst._asyncFill(data, fullData, allowRelations, findParams.cancelPostLoad ? false : true)));
50
52
  }
51
53
  return instanced;
52
54
  }
@@ -71,7 +73,7 @@ class FindUtils {
71
73
  const instanced = [];
72
74
  for (const data of dbData) {
73
75
  const inst = new opModel();
74
- instanced.push((await inst._asyncFill(data, fullData, allowRelations)));
76
+ instanced.push((await inst._asyncFill(data, fullData, allowRelations, findParams.cancelPostLoad ? false : true)));
75
77
  }
76
78
  return instanced;
77
79
  }
@@ -9,5 +9,5 @@ export declare class HydrateUtils {
9
9
  }): Promise<void>;
10
10
  static hydrateRelations(model: RWSModel<any>, relManyData: RelManyMetaType<IRWSModel>, relOneData: RelOneMetaType<IRWSModel>, seriesHydrationfields: string[], fullDataMode: boolean, data: {
11
11
  [key: string]: any;
12
- }): Promise<void>;
12
+ }, postLoadExecute?: boolean): Promise<void>;
13
13
  }
@@ -38,7 +38,7 @@ class HydrateUtils {
38
38
  }
39
39
  }
40
40
  }
41
- static async hydrateRelations(model, relManyData, relOneData, seriesHydrationfields, fullDataMode, data) {
41
+ static async hydrateRelations(model, relManyData, relOneData, seriesHydrationfields, fullDataMode, data, postLoadExecute = false) {
42
42
  // Handle many-to-many relations
43
43
  for (const key in relManyData) {
44
44
  if (!fullDataMode && model.constructor._CUT_KEYS.includes(key)) {
@@ -53,7 +53,8 @@ class HydrateUtils {
53
53
  conditions: {
54
54
  [relMeta.foreignKey]: data[pk]
55
55
  },
56
- allowRelations: false
56
+ allowRelations: false,
57
+ cancelPostLoad: !postLoadExecute
57
58
  });
58
59
  }
59
60
  else {
@@ -61,7 +62,8 @@ class HydrateUtils {
61
62
  conditions: {
62
63
  [relMeta.foreignKey]: data[pk]
63
64
  },
64
- allowRelations: false
65
+ allowRelations: false,
66
+ cancelPostLoad: !postLoadExecute
65
67
  });
66
68
  }
67
69
  }
@@ -207,7 +207,7 @@ class DBService {
207
207
  return this;
208
208
  }
209
209
  async count(opModel, where = {}) {
210
- return await this.getCollectionHandler(opModel._collection).count(where);
210
+ return await this.getCollectionHandler(opModel._collection).count({ where });
211
211
  }
212
212
  }
213
213
  exports.DBService = DBService;
@@ -7,6 +7,7 @@ export type FindByType = {
7
7
  allowRelations?: boolean;
8
8
  fullData?: boolean;
9
9
  pagination?: IPaginationParams;
10
+ cancelPostLoad?: boolean;
10
11
  };
11
12
  export interface IPaginationParams {
12
13
  page: number;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rws-framework/db",
3
3
  "private": false,
4
- "version": "3.5.0",
4
+ "version": "3.6.0",
5
5
  "description": "",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -28,6 +28,8 @@ class RWSModel<T> implements IModel {
28
28
  static allModels: OpModelType<any>[] = [];
29
29
  static _CUT_KEYS: string[] = [];
30
30
 
31
+ private postLoadExecuted: boolean = false;
32
+
31
33
  constructor(data: any = null) {
32
34
  if(!this.getCollection()){
33
35
  throw new Error('Model must have a collection defined');
@@ -45,7 +47,16 @@ class RWSModel<T> implements IModel {
45
47
  }else{
46
48
  throw new Error('Time Series not supported in synchronous constructor. Use `await Model.create(data)` static method to instantiate this model.');
47
49
  }
48
- }
50
+ }
51
+
52
+ isPostLoadExecuted(): boolean
53
+ {
54
+ return this.postLoadExecuted;
55
+ }
56
+
57
+ setPostLoadExecuted(){
58
+ this.postLoadExecuted = true;
59
+ }
49
60
 
50
61
  checkForInclusionWithThrow(): void {
51
62
  const constructor = this.constructor as OpModelType<any>;
@@ -98,7 +109,7 @@ class RWSModel<T> implements IModel {
98
109
  return RelationUtils.bindRelation(relatedModel);
99
110
  }
100
111
 
101
- public async _asyncFill(data: any, fullDataMode = false, allowRelations = true): Promise<T> {
112
+ public async _asyncFill(data: any, fullDataMode = false, allowRelations = true, postLoadExecute = true): Promise<T> {
102
113
  const collections_to_models: {[key: string]: any} = {};
103
114
  const classFields = FieldsHelper.getAllClassFields(this.constructor);
104
115
 
@@ -120,8 +131,13 @@ class RWSModel<T> implements IModel {
120
131
  }
121
132
 
122
133
  // Process regular fields and time series
123
- await HydrateUtils.hydrateDataFields(this, collections_to_models, relOneData, seriesHydrationfields, fullDataMode, data);
134
+ await HydrateUtils.hydrateDataFields(this, collections_to_models, relOneData, seriesHydrationfields, fullDataMode, data);
124
135
 
136
+ if(!this.isPostLoadExecuted() && postLoadExecute){
137
+ await this.postLoad();
138
+ this.setPostLoadExecuted();
139
+ }
140
+
125
141
  return this as any as T;
126
142
  }
127
143
 
@@ -205,16 +221,16 @@ class RWSModel<T> implements IModel {
205
221
  const entryExists = await ModelUtils.entryExists(this);
206
222
 
207
223
  if (entryExists) {
208
- this.preUpdate();
224
+ await this.preUpdate();
209
225
 
210
226
  const pk = ModelUtils.findPrimaryKeyFields(this.constructor as OpModelType<any>);
211
227
 
212
228
  updatedModelData = await this.dbService.update(data, this.getCollection(), pk);
213
229
 
214
230
  await this._asyncFill(updatedModelData);
215
- this.postUpdate();
231
+ await this.postUpdate();
216
232
  } else {
217
- this.preCreate();
233
+ await this.preCreate();
218
234
 
219
235
  const isTimeSeries = false;//this instanceof timeSeriesModel;
220
236
 
@@ -222,7 +238,7 @@ class RWSModel<T> implements IModel {
222
238
 
223
239
  await this._asyncFill(updatedModelData);
224
240
 
225
- this.postCreate();
241
+ await this.postCreate();
226
242
  }
227
243
 
228
244
  return this;
@@ -232,19 +248,23 @@ class RWSModel<T> implements IModel {
232
248
  return ModelUtils.getModelAnnotations(constructor);
233
249
  }
234
250
 
235
- public preUpdate(): void {
251
+ public async preUpdate(): Promise<void> {
252
+ return;
253
+ }
254
+
255
+ public async postLoad(): Promise<void> {
236
256
  return;
237
257
  }
238
258
 
239
- public postUpdate(): void {
259
+ public async postUpdate(): Promise<void> {
240
260
  return;
241
261
  }
242
262
 
243
- public preCreate(): void {
263
+ public async preCreate(): Promise<void> {
244
264
  return;
245
265
  }
246
266
 
247
- public postCreate(): void {
267
+ public async postCreate(): Promise<void> {
248
268
  return;
249
269
  }
250
270
 
@@ -370,9 +390,9 @@ class RWSModel<T> implements IModel {
370
390
  return this.services.dbService;
371
391
  }
372
392
 
373
- public async reload(): Promise<T | null>
393
+ public async reload(): Promise<RWSModel<T> | null>
374
394
  {
375
- const pk = ModelUtils.findPrimaryKeyFields(this.constructor as OpModelType<any>);
395
+ const pk = ModelUtils.findPrimaryKeyFields(this.constructor as OpModelType<T>);
376
396
  const where: any = {};
377
397
 
378
398
  if(Array.isArray(pk)){
@@ -1,12 +1,25 @@
1
1
  import { IDbConfigHandler } from '../../types/DbConfigHandler';
2
2
  import { DBService } from '../../services/DBService';
3
+ import { RWSModel } from '..';
3
4
 
4
5
  export interface IModel {
5
6
  [key: string]: any;
6
- id: string |number | null;
7
- save: () => void;
8
- getDb: () => DBService;
9
- getCollection: () => string | null;
7
+ id: string | number | null;
10
8
  configService?: IDbConfigHandler;
11
9
  dbService?: DBService;
10
+ // Core methods
11
+ save: () => Promise<this>;
12
+ getDb: () => DBService;
13
+ getCollection: () => string | null;
14
+ reload: () => Promise<RWSModel<any>>;
15
+ delete: () => Promise<void>;
16
+ hasTimeSeries: () => boolean;
17
+
18
+ _asyncFill: (data: any, fullDataMode?: boolean, allowRelations?: boolean) => Promise<any>;
19
+ // Lifecycle hooks
20
+ preUpdate: () => Promise<void>;
21
+ postUpdate: () => Promise<void>;
22
+ preCreate: () => Promise<void>;
23
+ postCreate: () => Promise<void>;
24
+ postLoad: () => Promise<void>;
12
25
  }
@@ -3,21 +3,21 @@ import { FindByType, IPaginationParams } from '../../types/FindParams';
3
3
  import { IRWSModelServices } from './IRWSModelServices';
4
4
  import { RelOneMetaType, RelManyMetaType } from '../types/RelationTypes';
5
5
  import { DBService } from '../../services/DBService';
6
-
7
- // Reference to the RWSModel class to avoid circular dependency
8
6
  import type { RWSModel } from '../core/RWSModel';
9
7
  import { ISuperTagData } from '../../decorators/RWSCollection';
10
8
 
11
9
  export interface OpModelType<T> {
12
10
  new(data?: any | null): T;
11
+ // Static properties
13
12
  services: IRWSModelServices;
14
13
  name: string;
15
14
  _collection: string;
16
15
  _NO_ID: boolean;
17
16
  _SUPER_TAGS: ISuperTagData[];
18
- _RELATIONS: {[key: string]: boolean};
17
+ _RELATIONS: { [key: string]: boolean };
19
18
  _CUT_KEYS: string[];
20
19
  allModels: OpModelType<any>[];
20
+ // Static methods
21
21
  loadModels: () => OpModelType<any>[];
22
22
  checkForInclusionWithThrow: (className: string) => void;
23
23
  checkForInclusion: (className: string) => boolean;
@@ -27,15 +27,15 @@ export interface OpModelType<T> {
27
27
  ): Promise<T | null>;
28
28
  find<T extends RWSModel<T>>(
29
29
  this: OpModelType<T>,
30
- id: string | number,
30
+ id: string | number,
31
31
  findParams?: Omit<FindByType, 'conditions'>
32
32
  ): Promise<T | null>;
33
33
  findBy<T extends RWSModel<T>>(
34
- this: OpModelType<T>,
34
+ this: OpModelType<T>,
35
35
  findParams?: FindByType
36
36
  ): Promise<T[]>;
37
37
  paginate<T extends RWSModel<T>>(
38
- this: OpModelType<T>,
38
+ this: OpModelType<T>,
39
39
  paginateParams?: IPaginationParams,
40
40
  findParams?: FindByType
41
41
  ): Promise<T[]>;
@@ -43,10 +43,33 @@ export interface OpModelType<T> {
43
43
  this: OpModelType<T>,
44
44
  conditions: any
45
45
  ): Promise<void>;
46
- create<T extends RWSModel<T>>(this: new () => T, data: any): Promise<T>;
47
- getRelationOneMeta(model: any, classFields: string[]): Promise<RelOneMetaType<IRWSModel>>;
48
- getRelationManyMeta(model: any, classFields: string[]): Promise<RelManyMetaType<IRWSModel>>;
49
- getCollection(): string;
46
+ create<T extends RWSModel<T>>(
47
+ this: new () => T,
48
+ data: any
49
+ ): Promise<T>;
50
+ getRelationOneMeta(
51
+ model: any,
52
+ classFields: string[]
53
+ ): Promise<RelOneMetaType<IRWSModel>>;
54
+ getRelationManyMeta(
55
+ model: any,
56
+ classFields: string[]
57
+ ): Promise<RelManyMetaType<IRWSModel>>;
58
+ getCollection(): string | null;
50
59
  getDb(): DBService;
51
60
  setServices(services: IRWSModelServices): void;
61
+ watchCollection<T extends RWSModel<T>>(
62
+ this: OpModelType<T>,
63
+ preRun: () => void
64
+ ): Promise<any>;
65
+ count(where?: { [k: string]: any }): Promise<number>;
66
+ isSubclass<T extends RWSModel<T>, C extends new () => T>(
67
+ constructor: C,
68
+ baseClass: new () => T
69
+ ): boolean;
70
+ getModelAnnotations<T extends unknown>(
71
+ constructor: new () => T
72
+ ): Promise<Record<string, { annotationType: string; metadata: any }>>;
73
+ checkTimeSeries(constructor: any): boolean;
74
+ checkDbVariable(constructor: any, variable: string): Promise<boolean>;
52
75
  }
@@ -27,7 +27,8 @@ export class FindUtils {
27
27
 
28
28
  if (dbData) {
29
29
  const inst: T = new (opModel as { new(): T })();
30
- return await inst._asyncFill(dbData, fullData, allowRelations);
30
+ const loaded = await inst._asyncFill(dbData, fullData, allowRelations, findParams.cancelPostLoad ? false : true);
31
+ return loaded as T;
31
32
  }
32
33
 
33
34
  return null;
@@ -50,7 +51,8 @@ export class FindUtils {
50
51
 
51
52
  if (dbData) {
52
53
  const inst: T = new (opModel as { new(): T })();
53
- return await inst._asyncFill(dbData, fullData, allowRelations);
54
+ const loaded = await inst._asyncFill(dbData, fullData, allowRelations, findParams.cancelPostLoad ? false : true);
55
+ return loaded as T;
54
56
  }
55
57
 
56
58
  return null;
@@ -78,7 +80,7 @@ export class FindUtils {
78
80
  for (const data of dbData) {
79
81
  const inst: T = new (opModel as { new(): T })();
80
82
 
81
- instanced.push((await inst._asyncFill(data, fullData, allowRelations)) as T);
83
+ instanced.push((await inst._asyncFill(data, fullData, allowRelations, findParams.cancelPostLoad ? false : true)) as T);
82
84
  }
83
85
 
84
86
  return instanced;
@@ -112,7 +114,7 @@ export class FindUtils {
112
114
 
113
115
  for (const data of dbData) {
114
116
  const inst: T = new (opModel as { new(): T })();
115
- instanced.push((await inst._asyncFill(data, fullData, allowRelations)) as T);
117
+ instanced.push((await inst._asyncFill(data, fullData, allowRelations, findParams.cancelPostLoad ? false : true)) as T);
116
118
  }
117
119
 
118
120
  return instanced;
@@ -8,119 +8,120 @@ import { ModelUtils } from "./ModelUtils";
8
8
  import chalk from 'chalk';
9
9
 
10
10
  export class HydrateUtils {
11
- static async hydrateDataFields(model: RWSModel<any>, collections_to_models: {[key: string]: any}, relOneData: RelOneMetaType<IRWSModel>, seriesHydrationfields: string[], fullDataMode: boolean, data: {[key: string] : any}){
11
+ static async hydrateDataFields(model: RWSModel<any>, collections_to_models: { [key: string]: any }, relOneData: RelOneMetaType<IRWSModel>, seriesHydrationfields: string[], fullDataMode: boolean, data: { [key: string]: any }) {
12
12
  const timeSeriesIds = TimeSeriesUtils.getTimeSeriesModelFields(model);
13
- for (const key in data) {
14
- if (data.hasOwnProperty(key)) {
15
- if(!fullDataMode && ((model).constructor as OpModelType<any>)._CUT_KEYS.includes(key)){
16
- continue;
17
- }
18
-
19
- if (Object.keys(relOneData).includes(key)) {
20
- continue;
21
- }
22
-
23
- if (seriesHydrationfields.includes(key)) {
24
- continue;
25
- }
26
-
27
-
28
- const timeSeriesMetaData = timeSeriesIds[key];
29
-
30
- if (timeSeriesMetaData) {
31
- model[key] = data[key];
32
- const seriesModel = collections_to_models[timeSeriesMetaData.collection];
33
-
34
- const dataModels = await seriesModel.findBy({
35
- id: { in: data[key] }
36
- });
37
-
38
- seriesHydrationfields.push(timeSeriesMetaData.hydrationField);
39
-
40
- model[timeSeriesMetaData.hydrationField] = dataModels;
41
- } else {
42
- model[key] = data[key];
43
- }
44
- }
45
- }
46
- }
47
-
48
- static async hydrateRelations(model: RWSModel<any>, relManyData: RelManyMetaType<IRWSModel>, relOneData: RelOneMetaType<IRWSModel>, seriesHydrationfields: string[], fullDataMode: boolean, data: {[key: string] : any})
49
- {
50
- // Handle many-to-many relations
51
- for (const key in relManyData) {
52
- if(!fullDataMode && (model as any).constructor._CUT_KEYS.includes(key)){
53
- continue;
54
- }
55
-
56
- const relMeta = relManyData[key];
57
-
58
- const relationEnabled = !RelationUtils.checkRelDisabled(model, relMeta.key);
59
-
60
-
61
-
62
- if (relationEnabled) {
63
- const pk = ModelUtils.findPrimaryKeyFields(model.constructor as OpModelType<any>) as string;
64
-
65
- if(relMeta.singular){
66
- model[relMeta.key] = await relMeta.inversionModel.findOneBy({
67
- conditions: {
68
- [relMeta.foreignKey]: data[pk]
69
- },
70
- allowRelations: false
71
- });
72
- } else {
73
- model[relMeta.key] = await relMeta.inversionModel.findBy({
74
- conditions: {
75
- [relMeta.foreignKey]: data[pk]
76
- },
77
- allowRelations: false
78
- });
79
- }
80
- }
81
- }
82
-
83
- // Handle one-to-one relations
84
- for (const key in relOneData) {
85
- if(!fullDataMode && ((model as any).constructor as OpModelType<any>)._CUT_KEYS.includes(key)){
86
- continue;
87
- }
88
-
89
- const relMeta = relOneData[key];
90
- const relationEnabled = !RelationUtils.checkRelDisabled(model, relMeta.key);
91
-
92
- if(!data[relMeta.hydrationField] && relMeta.required){
93
- throw new Error(`Relation field "${relMeta.hydrationField}" is required in model ${this.constructor.name}.`)
94
- }
95
-
96
- if (relationEnabled && data[relMeta.hydrationField]) {
97
- const pk = ModelUtils.findPrimaryKeyFields(relMeta.model);
98
-
99
- const where: any = {};
100
-
101
- if(Array.isArray(pk)){
102
- console.log(chalk.yellowBright(`Hydration field "${relMeta.hydrationField}" on model "${model.constructor.name}" leads to compound key. Ignoring.`));
103
- continue;
104
- }else{
105
- where[pk as string] = data[relMeta.hydrationField]
106
- }
107
-
108
- model[relMeta.key] = await relMeta.model.findOneBy({conditions: where}, { allowRelations: false });
109
- }
110
- else if(relationEnabled && !data[relMeta.hydrationField] && data[relMeta.key]){
111
- const newRelModel: RWSModel<any> = await relMeta.model.create(data[relMeta.key]);
112
- model[relMeta.key] = await newRelModel.save();
113
- }
114
-
115
- const cutKeys = ((model.constructor as OpModelType<any>)._CUT_KEYS as string[]);
116
-
117
- const trackedField = Object.keys((await ModelUtils.getModelAnnotations(model.constructor as OpModelType<any>))).includes(relMeta.hydrationField);
118
-
119
- if(!cutKeys.includes(relMeta.hydrationField) && !trackedField){
120
- cutKeys.push(relMeta.hydrationField)
121
- }
122
-
123
- // seriesHydrationfields.push(relMeta.hydrationField);
124
- }
125
- }
13
+ for (const key in data) {
14
+ if (data.hasOwnProperty(key)) {
15
+ if (!fullDataMode && ((model).constructor as OpModelType<any>)._CUT_KEYS.includes(key)) {
16
+ continue;
17
+ }
18
+
19
+ if (Object.keys(relOneData).includes(key)) {
20
+ continue;
21
+ }
22
+
23
+ if (seriesHydrationfields.includes(key)) {
24
+ continue;
25
+ }
26
+
27
+
28
+ const timeSeriesMetaData = timeSeriesIds[key];
29
+
30
+ if (timeSeriesMetaData) {
31
+ model[key] = data[key];
32
+ const seriesModel = collections_to_models[timeSeriesMetaData.collection];
33
+
34
+ const dataModels = await seriesModel.findBy({
35
+ id: { in: data[key] }
36
+ });
37
+
38
+ seriesHydrationfields.push(timeSeriesMetaData.hydrationField);
39
+
40
+ model[timeSeriesMetaData.hydrationField] = dataModels;
41
+ } else {
42
+ model[key] = data[key];
43
+ }
44
+ }
45
+ }
46
+ }
47
+
48
+ static async hydrateRelations(model: RWSModel<any>, relManyData: RelManyMetaType<IRWSModel>, relOneData: RelOneMetaType<IRWSModel>, seriesHydrationfields: string[], fullDataMode: boolean, data: { [key: string]: any }, postLoadExecute = false) {
49
+ // Handle many-to-many relations
50
+ for (const key in relManyData) {
51
+ if (!fullDataMode && (model as any).constructor._CUT_KEYS.includes(key)) {
52
+ continue;
53
+ }
54
+
55
+ const relMeta = relManyData[key];
56
+
57
+ const relationEnabled = !RelationUtils.checkRelDisabled(model, relMeta.key);
58
+
59
+
60
+
61
+ if (relationEnabled) {
62
+ const pk = ModelUtils.findPrimaryKeyFields(model.constructor as OpModelType<any>) as string;
63
+
64
+ if (relMeta.singular) {
65
+ model[relMeta.key] = await relMeta.inversionModel.findOneBy({
66
+ conditions: {
67
+ [relMeta.foreignKey]: data[pk]
68
+ },
69
+ allowRelations: false,
70
+ cancelPostLoad: !postLoadExecute
71
+ });
72
+ } else {
73
+ model[relMeta.key] = await relMeta.inversionModel.findBy({
74
+ conditions: {
75
+ [relMeta.foreignKey]: data[pk]
76
+ },
77
+ allowRelations: false,
78
+ cancelPostLoad: !postLoadExecute
79
+ });
80
+ }
81
+ }
82
+ }
83
+
84
+ // Handle one-to-one relations
85
+ for (const key in relOneData) {
86
+ if (!fullDataMode && ((model as any).constructor as OpModelType<any>)._CUT_KEYS.includes(key)) {
87
+ continue;
88
+ }
89
+
90
+ const relMeta = relOneData[key];
91
+ const relationEnabled = !RelationUtils.checkRelDisabled(model, relMeta.key);
92
+
93
+ if (!data[relMeta.hydrationField] && relMeta.required) {
94
+ throw new Error(`Relation field "${relMeta.hydrationField}" is required in model ${this.constructor.name}.`)
95
+ }
96
+
97
+ if (relationEnabled && data[relMeta.hydrationField]) {
98
+ const pk = ModelUtils.findPrimaryKeyFields(relMeta.model);
99
+
100
+ const where: any = {};
101
+
102
+ if (Array.isArray(pk)) {
103
+ console.log(chalk.yellowBright(`Hydration field "${relMeta.hydrationField}" on model "${model.constructor.name}" leads to compound key. Ignoring.`));
104
+ continue;
105
+ } else {
106
+ where[pk as string] = data[relMeta.hydrationField]
107
+ }
108
+
109
+ model[relMeta.key] = await relMeta.model.findOneBy({ conditions: where }, { allowRelations: false });
110
+ }
111
+ else if (relationEnabled && !data[relMeta.hydrationField] && data[relMeta.key]) {
112
+ const newRelModel: RWSModel<any> = await relMeta.model.create(data[relMeta.key]);
113
+ model[relMeta.key] = await newRelModel.save();
114
+ }
115
+
116
+ const cutKeys = ((model.constructor as OpModelType<any>)._CUT_KEYS as string[]);
117
+
118
+ const trackedField = Object.keys((await ModelUtils.getModelAnnotations(model.constructor as OpModelType<any>))).includes(relMeta.hydrationField);
119
+
120
+ if (!cutKeys.includes(relMeta.hydrationField) && !trackedField) {
121
+ cutKeys.push(relMeta.hydrationField)
122
+ }
123
+
124
+ // seriesHydrationfields.push(relMeta.hydrationField);
125
+ }
126
+ }
126
127
  }
@@ -290,7 +290,7 @@ class DBService {
290
290
  }
291
291
 
292
292
  public async count<T = any>(opModel: OpModelType<T>, where: {[k: string]: any} = {}): Promise<number>{
293
- return await this.getCollectionHandler(opModel._collection).count(where);
293
+ return await this.getCollectionHandler(opModel._collection).count({where});
294
294
  }
295
295
  }
296
296
 
@@ -5,6 +5,7 @@ export type FindByType = {
5
5
  allowRelations?: boolean
6
6
  fullData?: boolean
7
7
  pagination?: IPaginationParams
8
+ cancelPostLoad?: boolean
8
9
  }
9
10
 
10
11
  export interface IPaginationParams {