@rws-framework/db 3.0.0 → 3.1.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.
Files changed (45) hide show
  1. package/README.md +74 -136
  2. package/dist/decorators/IdType.d.ts +0 -0
  3. package/dist/decorators/IdType.js +0 -0
  4. package/dist/decorators/InverseRelation.js +30 -2
  5. package/dist/decorators/TypeFunctions.d.ts +0 -0
  6. package/dist/decorators/TypeFunctions.js +0 -0
  7. package/dist/helper/DbHelper.d.ts +1 -0
  8. package/dist/helper/DbHelper.js +6 -0
  9. package/dist/helper/db/index.d.ts +0 -0
  10. package/dist/helper/db/index.js +0 -0
  11. package/dist/helper/db/relation-manager.d.ts +0 -0
  12. package/dist/helper/db/relation-manager.js +0 -0
  13. package/dist/helper/db/schema-generator.d.ts +0 -0
  14. package/dist/helper/db/schema-generator.js +16 -1
  15. package/dist/helper/db/type-converter.d.ts +0 -0
  16. package/dist/helper/db/type-converter.js +0 -0
  17. package/dist/helper/db/utils.d.ts +1 -1
  18. package/dist/helper/db/utils.js +11 -13
  19. package/dist/models/core/RWSModel.d.ts +5 -3
  20. package/dist/models/core/RWSModel.js +5 -66
  21. package/dist/models/interfaces/IDbOpts.d.ts +0 -0
  22. package/dist/models/interfaces/IDbOpts.js +0 -0
  23. package/dist/models/interfaces/IIdOpts.d.ts +0 -0
  24. package/dist/models/interfaces/IIdOpts.js +0 -0
  25. package/dist/models/interfaces/IIdTypeOpts.d.ts +0 -0
  26. package/dist/models/interfaces/IIdTypeOpts.js +0 -0
  27. package/dist/models/interfaces/ITrackerOpts.d.ts +0 -0
  28. package/dist/models/interfaces/ITrackerOpts.js +0 -0
  29. package/dist/models/interfaces/OpModelType.d.ts +1 -1
  30. package/dist/models/utils/HydrateUtils.d.ts +13 -0
  31. package/dist/models/utils/HydrateUtils.js +81 -0
  32. package/package.json +1 -1
  33. package/src/decorators/InverseRelation.ts +43 -2
  34. package/src/helper/DbHelper.ts +9 -0
  35. package/src/helper/db/index.ts +0 -0
  36. package/src/helper/db/relation-manager.ts +0 -0
  37. package/src/helper/db/schema-generator.ts +23 -3
  38. package/src/helper/db/type-converter.ts +0 -0
  39. package/src/helper/db/utils.ts +15 -15
  40. package/src/models/core/RWSModel.ts +15 -84
  41. package/src/models/interfaces/IDbOpts.ts +0 -0
  42. package/src/models/interfaces/IIdTypeOpts.ts +0 -0
  43. package/src/models/interfaces/ITrackerOpts.ts +0 -0
  44. package/src/models/interfaces/OpModelType.ts +1 -1
  45. package/src/models/utils/HydrateUtils.ts +102 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Models
2
2
 
3
- RWS models are converted to Prisma schemas and are wrapping around generated PrismaClient providing complete typing and better Relation handling + TimeSeries in future minor versions.
3
+ RWS models are converted to Prisma schemas and are wrapping around generated PrismaClient providing complete typing and better Relation handling + TimeSeries in future versions.
4
4
 
5
5
  ## Models index file
6
6
 
@@ -21,11 +21,7 @@ export const models = [ User, ApiKey];
21
21
  import ApiKey from './ApiKey';
22
22
  import IApiKey from './interfaces/IApiKey';
23
23
 
24
- @RWSCollection('users', {
25
- relations: {
26
- transcriptions: true,
27
- apiKeys: true
28
- },
24
+ @RWSCollection('users', {
29
25
  ignored_keys: ['passwd']
30
26
  })
31
27
  class User extends RWSModel<User> implements IUser {
@@ -68,20 +64,26 @@ export default User;
68
64
 
69
65
  ***Basic many to one relation***
70
66
  ```typescript
71
- import { RWSModel, TrackType, Relation } from '@rws-framework/db';
67
+ import { RWSCollection, RWSModel, TrackType, Relation } from '@rws-framework/db';
72
68
 
73
69
  import 'reflect-metadata';
74
70
  import User from './User';
71
+ import SomeModel from './SomeModel';
75
72
  import IApiKey from './interfaces/IApiKey';
76
73
 
74
+ @RWSCollection('user_api_keys', {
75
+ relations: {
76
+ dummyIgnoredHydrationRelation: false // ignoring this relation on hydration - will be null
77
+ }
78
+ })
77
79
  class ApiKey extends RWSModel<ApiKey> implements IApiKey {
78
- static _RELATIONS = {
79
- user: true,
80
- };
81
80
 
82
- @Relation(() => User, true) // second attribute is required = false
81
+ @Relation(() => User, { requried: false }) // second attribute is required = false
83
82
  user: User;
84
83
 
84
+ @Relation(() => SomeModel) // relation to be ignored by
85
+ dummyIgnoredHydrationRelation: SomeModel;
86
+
85
87
  @TrackType(Object)
86
88
  keyval: string;
87
89
 
@@ -111,29 +113,52 @@ export default ApiKey;
111
113
 
112
114
  ```typescript
113
115
  import 'reflect-metadata';
116
+ import { RWSModel, OpModelType } from '../models/_model';
114
117
 
115
- import { RWSModel, OpModelType } from '@rws-framework/db';
118
+ export type CascadingSetup = 'Cascade' | 'Restrict' | 'NoAction' | 'SetNull';
116
119
 
117
- interface IRelationOpts {
120
+ export interface IRelationOpts {
118
121
  required?: boolean
119
- key?: string
120
- relationField?: string
121
- relatedToField?: string
122
- relatedTo: OpModelType<Model<any>>
122
+ key: string
123
+ relationField: string //name of field that will hold the relation key value
124
+ relatedToField?: string //name of related field (id by default)
125
+ mappingName?: string
126
+ relatedTo: OpModelType<RWSModel<any>>
127
+ many?: boolean // is it one-to-many or many-to-one
128
+ embed?: boolean // @deprecated for mongo - new decorator for embeds incoming
129
+ useUuid?: boolean //for sql dbs - if you're using some text based id
130
+ relationName?: string
131
+ cascade?: {
132
+ onDelete?: CascadingSetup,
133
+ onUpdate?: CascadingSetup
134
+ }
123
135
  }
136
+
137
+ const _DEFAULTS: Partial<IRelationOpts> = { required: false, many: false, embed: false, cascade: { onDelete: 'SetNull', onUpdate: 'Cascade' }};
124
138
 
125
- function Relation(theModel: () => OpModelType<RWSModel<any>>, required: boolean = false, relationField: string = null, relatedToField: string = 'id') {
139
+ function Relation(theModel: () => OpModelType<RWSModel<any>>, relationOptions: Partial<IRelationOpts> = _DEFAULTS) {
126
140
  return function(target: any, key: string) {
127
141
  // Store the promise in metadata immediately
128
- const metadataPromise = Promise.resolve().then(() => {
142
+
143
+ const metadataPromise = Promise.resolve().then(() => {
129
144
  const relatedTo = theModel();
130
- const metaOpts: IRelationOpts = {required, relatedTo, relatedToField};
131
- if(!relationField){
132
- metaOpts.relationField = relatedTo._collection + '_id';
133
- } else{
134
- metaOpts.relationField = relationField;
135
- }
136
- metaOpts.key = key;
145
+
146
+ const metaOpts: IRelationOpts = {
147
+ ...relationOptions,
148
+ cascade: relationOptions.cascade || _DEFAULTS.cascade,
149
+ relatedTo,
150
+ relationField: relationOptions.relationField ? relationOptions.relationField : relatedTo._collection + '_id',
151
+ key,
152
+ // Generate a unique relation name if one is not provided
153
+ relationName: relationOptions.relationName ?
154
+ relationOptions.relationName.toLowerCase() :
155
+ `${target.constructor.name.toLowerCase()}_${key}_${relatedTo._collection.toLowerCase()}`
156
+ };
157
+
158
+ if(relationOptions.required){
159
+ metaOpts.cascade.onDelete = 'Restrict';
160
+ }
161
+
137
162
  return metaOpts;
138
163
  });
139
164
 
@@ -147,33 +172,41 @@ function Relation(theModel: () => OpModelType<RWSModel<any>>, required: boolean
147
172
 
148
173
 
149
174
  export default Relation;
150
- export {IRelationOpts};
175
+
176
+
151
177
  ```
152
178
 
153
179
  ***Inverse relation decorator*** (one-to-many)
154
180
  ```typescript
155
181
  import 'reflect-metadata';
156
- import { RWSModel, OpModelType } from '@rws-framework/db';
182
+ import { RWSModel, OpModelType } from '../models/_model';
157
183
 
158
- interface InverseRelationOpts{
184
+ export interface InverseRelationOpts {
159
185
  key: string,
160
- inversionModel: OpModelType<RWSModel<any>>,
161
- foreignKey: string
162
- }
186
+ inversionModel: OpModelType<RWSModel<any>>
187
+ foreignKey: string
188
+ singular?: boolean
189
+ relationName?: string
190
+ mappingName?: string
191
+ }
163
192
 
164
- function InverseRelation(inversionModel: () => OpModelType<RWSModel<any>>, sourceModel: () => OpModelType<RWSModel<any>>, foreignKey: string = null) {
165
- return function(target: any, key: string) {
166
- // Store the promise in metadata immediately
193
+ function InverseRelation(inversionModel: () => OpModelType<RWSModel<any>>, sourceModel: () => OpModelType<RWSModel<any>>, relationOptions: Partial<InverseRelationOpts> = null) {
194
+ return function (target: any, key: string) {
167
195
  const metadataPromise = Promise.resolve().then(() => {
168
196
  const model = inversionModel();
169
197
  const source = sourceModel();
170
-
198
+
171
199
  const metaOpts: InverseRelationOpts = {
200
+ ...relationOptions,
172
201
  key,
173
202
  inversionModel: model,
174
- foreignKey: foreignKey ? foreignKey : `${source._collection}_id`
175
- };
176
-
203
+ foreignKey: relationOptions && relationOptions.foreignKey ? relationOptions.foreignKey : `${source._collection}_id`,
204
+ // Generate a unique relation name if one is not provided
205
+ relationName: relationOptions && relationOptions.relationName ?
206
+ relationOptions.relationName.toLowerCase() :
207
+ `${model._collection}_${key}_${source._collection}`.toLowerCase()
208
+ };
209
+
177
210
  return metaOpts;
178
211
  });
179
212
 
@@ -186,7 +219,7 @@ interface InverseRelationOpts{
186
219
  }
187
220
 
188
221
  export default InverseRelation;
189
- export {InverseRelationOpts};
222
+
190
223
  ```
191
224
 
192
225
 
@@ -307,99 +340,4 @@ bunx rws-db "mongodb://user:pass@localhost:27017/databaseName?authSource=admin&r
307
340
 
308
341
  Code for RWS to prisma conversion from "@rws-framework/server" package:
309
342
 
310
- ```typescript
311
- static async generateModelSections(model: OpModelType<any>): Promise<string> {
312
- let section = '';
313
- const modelMetadatas: Record<string, {annotationType: string, metadata: any}> = await RWSModel.getModelAnnotations(model);
314
-
315
- const modelName: string = (model as any)._collection;
316
-
317
- section += `model ${modelName} {\n`;
318
- section += '\tid String @map("_id") @id @default(auto()) @db.ObjectId\n';
319
-
320
- for (const key in modelMetadatas) {
321
- const modelMetadata = modelMetadatas[key].metadata;
322
- let requiredString = modelMetadata.required ? '' : '?';
323
- const annotationType: string = modelMetadatas[key].annotationType;
324
-
325
- if(key === 'id'){
326
- continue;
327
- }
328
-
329
-
330
- if(annotationType === 'Relation'){
331
- const relationMeta = modelMetadata as IRelationOpts
332
-
333
- const relatedModel = relationMeta.relatedTo as OpModelType<any>;
334
- const isMany = relationMeta.many;
335
- const cascadeOpts = [];
336
-
337
- if (relationMeta.cascade?.onDelete) {
338
- cascadeOpts.push(`onDelete: ${relationMeta.cascade.onDelete}`);
339
- }
340
-
341
- if (relationMeta.cascade?.onUpdate) {
342
- cascadeOpts.push(`onUpdate: ${relationMeta.cascade.onUpdate}`);
343
- }
344
-
345
- if (isMany) {
346
- // Handle many-to-many or one-to-many relation
347
- section += `\t${key} ${relatedModel._collection}[] @relation("${modelName}_${relatedModel._collection}")\n`;
348
- } else {
349
- // Handle one-to-one or many-to-one relation
350
- section += `\t${key} ${relatedModel._collection}${requiredString} @relation("${modelName}_${relatedModel._collection}", fields: [${modelMetadata.relationField}], references: [${modelMetadata.relatedToField || 'id'}], ${cascadeOpts.join(', ')})\n`;
351
- section += `\t${modelMetadata.relationField} String${requiredString} @db.ObjectId\n`;
352
- }
353
- } else if (annotationType === 'InverseRelation'){
354
- const relationMeta = modelMetadata as InverseRelationOpts;
355
-
356
- // Handle inverse relation (one-to-many or one-to-one)
357
- section += `\t${key} ${relationMeta.inversionModel._collection}[] @relation("${ relationMeta.relationName ? relationMeta.relationName : `${relationMeta.inversionModel._collection}_${modelName}`}")\n`;
358
- } else if (annotationType === 'InverseTimeSeries'){
359
- section += `\t${key} String[] @db.ObjectId\n`;
360
- } else if (annotationType === 'TrackType'){
361
- const tags: string[] = modelMetadata.tags.map((item: string) => '@' + item);
362
-
363
- if(modelMetadata.isArray || modelMetadata.type.name === 'Array'){
364
- requiredString = '';
365
- }
366
- section += `\t${key} ${DbHelper.toConfigCase(modelMetadata)}${requiredString} ${tags.join(' ')}\n`;
367
- }
368
- }
369
-
370
- section += '}\n';
371
- return section;
372
- }
373
-
374
- static toConfigCase(modelType: IMetaOpts): string {
375
- const type = modelType.type;
376
- let input = type.name;
377
-
378
-
379
- if(input == 'Number'){
380
- input = 'Int';
381
- }
382
-
383
- if(input == 'Object'){
384
- input = 'Json';
385
- }
386
-
387
- if(input == 'Date'){
388
- input = 'DateTime';
389
- }
390
-
391
- if(input == 'Array'){
392
- input = 'Json[]';
393
- }
394
-
395
- const firstChar = input.charAt(0).toUpperCase();
396
- const restOfString = input.slice(1);
397
- let resultField = firstChar + restOfString;
398
-
399
- if(modelType.isArray){
400
- resultField += '[]';
401
- }
402
-
403
- return resultField;
404
- }
405
- ```
343
+ [The repo file](https://github.com/rws-framework/db/blob/master/src/helper/DbHelper.ts)
File without changes
File without changes
@@ -1,16 +1,44 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  require("reflect-metadata");
4
+ const ModelUtils_1 = require("../models/utils/ModelUtils");
5
+ function guessForeignKey(inversionModel, bindingModel, decoratorsData) {
6
+ var _a;
7
+ let key = null;
8
+ let defaultKey = `${bindingModel._collection}_id`;
9
+ const relDecorators = {};
10
+ const trackDecorators = {};
11
+ if (Object.keys(trackDecorators).includes(key)) {
12
+ return key;
13
+ }
14
+ for (const decKey of Object.keys(decoratorsData)) {
15
+ const dec = decoratorsData[decKey];
16
+ if (dec.annotationType === 'Relation') {
17
+ relDecorators[decKey] = dec;
18
+ }
19
+ if (dec.annotationType === 'TrackType') {
20
+ trackDecorators[decKey] = dec;
21
+ }
22
+ }
23
+ for (const relKey of Object.keys(relDecorators)) {
24
+ const prodMeta = (_a = relDecorators[relKey]) === null || _a === void 0 ? void 0 : _a.metadata;
25
+ if (prodMeta && prodMeta.relatedTo._collection === bindingModel._collection) {
26
+ return prodMeta.relationField;
27
+ }
28
+ }
29
+ return key;
30
+ }
4
31
  function InverseRelation(inversionModel, sourceModel, relationOptions = null) {
5
32
  return function (target, key) {
6
- const metadataPromise = Promise.resolve().then(() => {
33
+ const metadataPromise = Promise.resolve().then(async () => {
7
34
  const model = inversionModel();
8
35
  const source = sourceModel();
36
+ const decoratorsData = await ModelUtils_1.ModelUtils.getModelAnnotations(model);
9
37
  const metaOpts = {
10
38
  ...relationOptions,
11
39
  key,
12
40
  inversionModel: model,
13
- foreignKey: relationOptions && relationOptions.foreignKey ? relationOptions.foreignKey : `${source._collection}_id`,
41
+ foreignKey: relationOptions && relationOptions.foreignKey ? relationOptions.foreignKey : guessForeignKey(model, source, decoratorsData),
14
42
  // Generate a unique relation name if one is not provided
15
43
  relationName: relationOptions && relationOptions.relationName ?
16
44
  relationOptions.relationName.toLowerCase() :
File without changes
File without changes
@@ -27,6 +27,7 @@ export declare class DbHelper {
27
27
  * @param leaveFile Whether to leave the schema file after generation
28
28
  */
29
29
  static pushDBModels(configService: IDbConfigHandler, dbService: DBService, leaveFile?: boolean): Promise<void>;
30
+ static migrateDBModels(configService: IDbConfigHandler, dbService: DBService, leaveFile?: boolean): Promise<void>;
30
31
  /**
31
32
  * Generate model sections for the schema
32
33
  * @param model The model to generate a section for
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DbHelper = void 0;
4
+ const console_1 = require("@rws-framework/console");
4
5
  const db_1 = require("./db");
5
6
  /**
6
7
  * Database helper class
@@ -27,6 +28,11 @@ class DbHelper {
27
28
  static async pushDBModels(configService, dbService, leaveFile = false) {
28
29
  return db_1.SchemaGenerator.pushDBModels(configService, dbService, leaveFile);
29
30
  }
31
+ static async migrateDBModels(configService, dbService, leaveFile = false) {
32
+ process.env = { ...process.env, [this.dbUrlVarName]: configService.get('db_url') };
33
+ const [_, schemaPath] = db_1.DbUtils.getSchemaDir();
34
+ await console_1.rwsShell.runCommand(`${db_1.DbUtils.detectInstaller()} prisma migrate dev --create-only --schema=${schemaPath}`, process.cwd());
35
+ }
30
36
  /**
31
37
  * Generate model sections for the schema
32
38
  * @param model The model to generate a section for
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -47,7 +47,7 @@ datasource db {
47
47
  const modelName = model._collection;
48
48
  section += `model ${modelName} {\n`;
49
49
  if (!model._NO_ID) {
50
- section += `\t${utils_1.DbUtils.generateId(dbType, modelMetadatas, false)}\n`;
50
+ section += `\t${utils_1.DbUtils.generateId(dbType, modelMetadatas)}\n`;
51
51
  }
52
52
  for (const key in modelMetadatas) {
53
53
  const modelMetadata = modelMetadatas[key].metadata;
@@ -81,6 +81,9 @@ datasource db {
81
81
  const relationFieldName = modelMetadata.relationField ? modelMetadata.relationField : key.toLowerCase() + '_' + modelMetadata.relationField.toLowerCase();
82
82
  const relatedToField = modelMetadata.relatedToField || 'id';
83
83
  const bindingFieldExists = !!modelMetadatas[relationFieldName];
84
+ if (modelMetadata.required === false) {
85
+ requiredString = '?';
86
+ }
84
87
  if (isMany) {
85
88
  // Add an inverse field to the related model if it doesn't exist
86
89
  section += `\t${key} ${relatedModel._collection}[] @relation("${relationName}", fields: [${relationFieldName}], references: [${relatedToField}], map: "${mapName}", ${cascadeOpts.join(', ')})\n`;
@@ -151,16 +154,28 @@ datasource db {
151
154
  else if (annotationType === 'TrackType') {
152
155
  const trackMeta = modelMetadata;
153
156
  const tags = trackMeta.tags.map((item) => '@' + item);
157
+ if (key === 'id' && model._NO_ID && !model._SUPER_TAGS.some(tag => tag.tagType === 'id' && tag.fields.includes('id'))) {
158
+ continue;
159
+ }
154
160
  if (trackMeta.unique) {
155
161
  const fieldDetail = typeof trackMeta.unique === 'string' ? trackMeta.unique : null;
156
162
  tags.push(`@unique(${fieldDetail ? `map: "${fieldDetail}"` : ''})`);
157
163
  }
164
+ if (!trackMeta.required) {
165
+ requiredString = '?';
166
+ }
158
167
  if (trackMeta.isArray || trackMeta.type.name === 'Array') {
159
168
  requiredString = '';
160
169
  }
170
+ if (model._SUPER_TAGS.some(tag => tag.tagType === 'id' && tag.fields.includes(key))) {
171
+ requiredString = '';
172
+ }
161
173
  // Process any database-specific options from the metadata
162
174
  const dbSpecificTags = type_converter_1.TypeConverter.processTypeOptions(trackMeta, dbType);
163
175
  tags.push(...dbSpecificTags);
176
+ if (modelName === 'category_translation' && key === 'meta_keywords') {
177
+ console.log({ requiredString, trackMeta });
178
+ }
164
179
  section += `\t${key} ${type_converter_1.TypeConverter.toConfigCase(trackMeta, dbType, key === 'id')}${requiredString} ${tags.join(' ')}\n`;
165
180
  }
166
181
  }
File without changes
File without changes
@@ -18,7 +18,7 @@ export declare class DbUtils {
18
18
  static generateId(dbType: IDbConfigParams['db_type'], modelMeta: Record<string, {
19
19
  annotationType: string;
20
20
  metadata: IIdMetaOpts;
21
- }>, debug?: boolean): string;
21
+ }>, optional?: boolean): string;
22
22
  }
23
23
  export declare const workspaceRootPath: string;
24
24
  export declare const moduleDirPath: string;
@@ -34,7 +34,7 @@ class DbUtils {
34
34
  /**
35
35
  * Generate an ID field based on the database type
36
36
  */
37
- static generateId(dbType, modelMeta, debug = false) {
37
+ static generateId(dbType, modelMeta, optional = false) {
38
38
  var _a, _b, _c, _d;
39
39
  let useUuid = false;
40
40
  let field = 'id';
@@ -46,9 +46,6 @@ class DbUtils {
46
46
  if (annotationType == 'IdType') {
47
47
  const dbSpecificTags = type_converter_1.TypeConverter.processTypeOptions({ tags: [], dbOptions: modelMetadata.dbOptions }, dbType);
48
48
  tags.push(...dbSpecificTags);
49
- if (debug) {
50
- console.log({ modelMetadata: modelMetadata.dbOptions });
51
- }
52
49
  field = key;
53
50
  if ((_b = (_a = modelMetadata.dbOptions) === null || _a === void 0 ? void 0 : _a.mysql) === null || _b === void 0 ? void 0 : _b.useUuid) {
54
51
  useUuid = true;
@@ -63,23 +60,27 @@ class DbUtils {
63
60
  }
64
61
  }
65
62
  let idString;
63
+ let reqStr = '';
64
+ if (optional) {
65
+ reqStr = '?';
66
+ }
66
67
  switch (dbType) {
67
68
  case 'mongodb':
68
- idString = `${field} String @id @default(auto()) @map("_id") @db.ObjectId`;
69
+ idString = `${field} String${reqStr} @id @default(auto()) @map("_id") @db.ObjectId`;
69
70
  break;
70
71
  case 'mysql':
71
72
  idString = useUuid
72
- ? `${field} String @id @default(uuid())`
73
- : `${field} Int @id @default(autoincrement())`;
73
+ ? `${field} String${reqStr} @id @default(uuid())`
74
+ : `${field} Int${reqStr} @id @default(autoincrement())`;
74
75
  break;
75
76
  case 'postgresql':
76
77
  case 'postgres':
77
78
  idString = useUuid
78
- ? `${field} String @id @default(uuid())`
79
- : `${field} Int @id @default(autoincrement())`;
79
+ ? `${field} String${reqStr} @id @default(uuid())`
80
+ : `${field} Int${reqStr} @id @default(autoincrement())`;
80
81
  break;
81
82
  case 'sqlite':
82
- idString = `${field} Int @id @default(autoincrement())`;
83
+ idString = `${field} Int${reqStr} @id @default(autoincrement())`;
83
84
  break;
84
85
  }
85
86
  if (tags.length) {
@@ -88,9 +89,6 @@ class DbUtils {
88
89
  if (!idString) {
89
90
  throw new Error(`DB type "${dbType}" is not supported!`);
90
91
  }
91
- if (debug) {
92
- console.log({ idString, useUuid });
93
- }
94
92
  return idString;
95
93
  }
96
94
  }
@@ -4,6 +4,8 @@ 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';
7
9
  declare class RWSModel<T> implements IModel {
8
10
  static services: IRWSModelServices;
9
11
  [key: string]: any;
@@ -30,9 +32,9 @@ declare class RWSModel<T> implements IModel {
30
32
  _asyncFill(data: any, fullDataMode?: boolean, allowRelations?: boolean): Promise<T>;
31
33
  private getModelScalarFields;
32
34
  private getRelationOneMeta;
33
- static getRelationOneMeta(model: any, classFields: string[]): Promise<import("..").RelOneMetaType<import("../..").IRWSModel>>;
35
+ static getRelationOneMeta(model: any, classFields: string[]): Promise<RelOneMetaType<IRWSModel>>;
34
36
  private getRelationManyMeta;
35
- static getRelationManyMeta(model: any, classFields: string[]): Promise<import("..").RelManyMetaType<import("../..").IRWSModel>>;
37
+ static getRelationManyMeta(model: any, classFields: string[]): Promise<RelManyMetaType<IRWSModel>>;
36
38
  static paginate<T extends RWSModel<T>>(this: OpModelType<T>, paginateParams: IPaginationParams, findParams?: FindByType): Promise<T[]>;
37
39
  toMongo(): Promise<any>;
38
40
  getCollection(): string | null;
@@ -54,7 +56,7 @@ declare class RWSModel<T> implements IModel {
54
56
  sanitizeDBData(data: any): any;
55
57
  static watchCollection<T extends RWSModel<T>>(this: OpModelType<T>, preRun: () => void): Promise<any>;
56
58
  static findOneBy<T extends RWSModel<T>>(this: OpModelType<T>, findParams?: FindByType): Promise<T | null>;
57
- static find<T extends RWSModel<T>>(this: OpModelType<T>, id: string, findParams?: Omit<FindByType, 'conditions'>): Promise<T | null>;
59
+ static find<T extends RWSModel<T>>(this: OpModelType<T>, id: string | number, findParams?: Omit<FindByType, 'conditions'>): Promise<T | null>;
58
60
  static findBy<T extends RWSModel<T>>(this: OpModelType<T>, findParams?: FindByType): Promise<T[]>;
59
61
  static delete<T extends RWSModel<T>>(this: OpModelType<T>, conditions: any): Promise<void>;
60
62
  delete<T extends RWSModel<T>>(): Promise<void>;
@@ -15,6 +15,7 @@ const FieldsHelper_1 = require("../../helper/FieldsHelper");
15
15
  const RelationUtils_1 = require("../utils/RelationUtils");
16
16
  const TimeSeriesUtils_1 = require("../utils/TimeSeriesUtils");
17
17
  const ModelUtils_1 = require("../utils/ModelUtils");
18
+ const HydrateUtils_1 = require("../utils/HydrateUtils");
18
19
  class RWSModel {
19
20
  constructor(data = null) {
20
21
  if (!this.getCollection()) {
@@ -76,7 +77,6 @@ class RWSModel {
76
77
  }
77
78
  async _asyncFill(data, fullDataMode = false, allowRelations = true) {
78
79
  const collections_to_models = {};
79
- const timeSeriesIds = TimeSeriesUtils_1.TimeSeriesUtils.getTimeSeriesModelFields(this);
80
80
  const classFields = FieldsHelper_1.FieldsHelper.getAllClassFields(this.constructor);
81
81
  // Get both relation metadata types asynchronously
82
82
  const [relOneData, relManyData] = await Promise.all([
@@ -88,72 +88,10 @@ class RWSModel {
88
88
  });
89
89
  const seriesHydrationfields = [];
90
90
  if (allowRelations) {
91
- // Handle many-to-many relations
92
- for (const key in relManyData) {
93
- if (!fullDataMode && this.constructor._CUT_KEYS.includes(key)) {
94
- continue;
95
- }
96
- const relMeta = relManyData[key];
97
- const relationEnabled = !RelationUtils_1.RelationUtils.checkRelDisabled(this, relMeta.key);
98
- if (relationEnabled) {
99
- this[relMeta.key] = await relMeta.inversionModel.findBy({
100
- conditions: {
101
- [relMeta.foreignKey]: data.id
102
- },
103
- allowRelations: false
104
- });
105
- }
106
- }
107
- // Handle one-to-one relations
108
- for (const key in relOneData) {
109
- if (!fullDataMode && this.constructor._CUT_KEYS.includes(key)) {
110
- continue;
111
- }
112
- const relMeta = relOneData[key];
113
- const relationEnabled = !RelationUtils_1.RelationUtils.checkRelDisabled(this, relMeta.key);
114
- if (!data[relMeta.hydrationField] && relMeta.required) {
115
- throw new Error(`Relation field "${relMeta.hydrationField}" is required in model ${this.constructor.name}.`);
116
- }
117
- if (relationEnabled && data[relMeta.hydrationField]) {
118
- this[relMeta.key] = await relMeta.model.find(data[relMeta.hydrationField], { allowRelations: false });
119
- }
120
- else if (relationEnabled && !data[relMeta.hydrationField] && data[relMeta.key]) {
121
- const newRelModel = await relMeta.model.create(data[relMeta.key]);
122
- this[relMeta.key] = await newRelModel.save();
123
- }
124
- const cutKeys = this.constructor._CUT_KEYS;
125
- if (!cutKeys.includes(relMeta.hydrationField)) {
126
- cutKeys.push(relMeta.hydrationField);
127
- }
128
- }
91
+ await HydrateUtils_1.HydrateUtils.hydrateRelations(this, relManyData, relOneData, seriesHydrationfields, fullDataMode, data);
129
92
  }
130
93
  // Process regular fields and time series
131
- for (const key in data) {
132
- if (data.hasOwnProperty(key)) {
133
- if (!fullDataMode && this.constructor._CUT_KEYS.includes(key)) {
134
- continue;
135
- }
136
- if (Object.keys(relOneData).includes(key)) {
137
- continue;
138
- }
139
- if (seriesHydrationfields.includes(key)) {
140
- continue;
141
- }
142
- const timeSeriesMetaData = timeSeriesIds[key];
143
- if (timeSeriesMetaData) {
144
- this[key] = data[key];
145
- const seriesModel = collections_to_models[timeSeriesMetaData.collection];
146
- const dataModels = await seriesModel.findBy({
147
- id: { in: data[key] }
148
- });
149
- seriesHydrationfields.push(timeSeriesMetaData.hydrationField);
150
- this[timeSeriesMetaData.hydrationField] = dataModels;
151
- }
152
- else {
153
- this[key] = data[key];
154
- }
155
- }
156
- }
94
+ await HydrateUtils_1.HydrateUtils.hydrateDataFields(this, collections_to_models, relOneData, seriesHydrationfields, fullDataMode, data);
157
95
  return this;
158
96
  }
159
97
  getModelScalarFields(model) {
@@ -333,7 +271,8 @@ class RWSModel {
333
271
  const collection = Reflect.get(this, '_collection');
334
272
  this.checkForInclusionWithThrow(this.name);
335
273
  try {
336
- const dbData = await this.services.dbService.findBy(collection, conditions, fields, ordering);
274
+ const paginateParams = (findParams === null || findParams === void 0 ? void 0 : findParams.pagination) ? findParams === null || findParams === void 0 ? void 0 : findParams.pagination : undefined;
275
+ const dbData = await this.services.dbService.findBy(collection, conditions, fields, ordering, paginateParams);
337
276
  if (dbData.length) {
338
277
  const instanced = [];
339
278
  for (const data of dbData) {
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes