@rws-framework/db 3.1.0 → 3.3.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 (35) hide show
  1. package/dist/decorators/IdType.js +6 -0
  2. package/dist/decorators/InverseRelation.js +3 -4
  3. package/dist/decorators/Relation.js +4 -3
  4. package/dist/decorators/TrackType.js +2 -2
  5. package/dist/helper/DbHelper.d.ts +1 -1
  6. package/dist/helper/DbHelper.js +4 -4
  7. package/dist/helper/db/relation-manager.js +1 -1
  8. package/dist/helper/db/schema-generator.js +73 -26
  9. package/dist/helper/db/type-converter.d.ts +2 -1
  10. package/dist/helper/db/type-converter.js +33 -9
  11. package/dist/helper/db/utils.d.ts +7 -0
  12. package/dist/helper/db/utils.js +80 -26
  13. package/dist/models/core/RWSModel.js +29 -32
  14. package/dist/models/interfaces/IDbOpts.d.ts +3 -0
  15. package/dist/models/interfaces/IIdTypeOpts.d.ts +2 -0
  16. package/dist/models/interfaces/ITrackerOpts.d.ts +1 -0
  17. package/dist/models/utils/HydrateUtils.js +0 -1
  18. package/dist/models/utils/ModelUtils.js +8 -1
  19. package/dist/models/utils/PaginationUtils.js +5 -6
  20. package/dist/services/DBService.js +7 -8
  21. package/exec/console.js +0 -2
  22. package/package.json +1 -1
  23. package/src/decorators/IdType.ts +10 -1
  24. package/src/decorators/InverseRelation.ts +2 -2
  25. package/src/decorators/Relation.ts +6 -4
  26. package/src/helper/DbHelper.ts +1 -1
  27. package/src/helper/db/schema-generator.ts +104 -36
  28. package/src/helper/db/type-converter.ts +41 -8
  29. package/src/helper/db/utils.ts +114 -40
  30. package/src/models/interfaces/IDbOpts.ts +3 -0
  31. package/src/models/interfaces/IIdTypeOpts.ts +2 -0
  32. package/src/models/interfaces/ITrackerOpts.ts +1 -0
  33. package/src/models/utils/HydrateUtils.ts +0 -2
  34. package/src/models/utils/ModelUtils.ts +10 -1
  35. package/tsconfig.json +1 -1
@@ -17,6 +17,15 @@ const TimeSeriesUtils_1 = require("../utils/TimeSeriesUtils");
17
17
  const ModelUtils_1 = require("../utils/ModelUtils");
18
18
  const HydrateUtils_1 = require("../utils/HydrateUtils");
19
19
  class RWSModel {
20
+ static services = {};
21
+ id;
22
+ static _collection = null;
23
+ static _RELATIONS = {};
24
+ static _NO_ID = false;
25
+ static _SUPER_TAGS = [];
26
+ static _BANNED_KEYS = ['_collection'];
27
+ static allModels = [];
28
+ static _CUT_KEYS = [];
20
29
  constructor(data = null) {
21
30
  if (!this.getCollection()) {
22
31
  throw new Error('Model must have a collection defined');
@@ -110,12 +119,11 @@ class RWSModel {
110
119
  return RelationUtils_1.RelationUtils.getRelationManyMeta(model, classFields);
111
120
  }
112
121
  static async paginate(paginateParams, findParams) {
113
- var _a, _b, _c, _d, _e;
114
- const conditions = (_a = findParams === null || findParams === void 0 ? void 0 : findParams.conditions) !== null && _a !== void 0 ? _a : {};
115
- const ordering = (_b = findParams === null || findParams === void 0 ? void 0 : findParams.ordering) !== null && _b !== void 0 ? _b : null;
116
- const fields = (_c = findParams === null || findParams === void 0 ? void 0 : findParams.fields) !== null && _c !== void 0 ? _c : null;
117
- const allowRelations = (_d = findParams === null || findParams === void 0 ? void 0 : findParams.allowRelations) !== null && _d !== void 0 ? _d : true;
118
- const fullData = (_e = findParams === null || findParams === void 0 ? void 0 : findParams.fullData) !== null && _e !== void 0 ? _e : false;
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;
119
127
  const collection = Reflect.get(this, '_collection');
120
128
  this.checkForInclusionWithThrow(this.name);
121
129
  try {
@@ -231,12 +239,11 @@ class RWSModel {
231
239
  return await this.services.dbService.watchCollection(collection, preRun);
232
240
  }
233
241
  static async findOneBy(findParams) {
234
- var _a, _b, _c, _d, _e;
235
- const conditions = (_a = findParams === null || findParams === void 0 ? void 0 : findParams.conditions) !== null && _a !== void 0 ? _a : {};
236
- const ordering = (_b = findParams === null || findParams === void 0 ? void 0 : findParams.ordering) !== null && _b !== void 0 ? _b : null;
237
- const fields = (_c = findParams === null || findParams === void 0 ? void 0 : findParams.fields) !== null && _c !== void 0 ? _c : null;
238
- const allowRelations = (_d = findParams === null || findParams === void 0 ? void 0 : findParams.allowRelations) !== null && _d !== void 0 ? _d : true;
239
- const fullData = (_e = findParams === null || findParams === void 0 ? void 0 : findParams.fullData) !== null && _e !== void 0 ? _e : false;
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;
240
247
  this.checkForInclusionWithThrow('');
241
248
  const collection = Reflect.get(this, '_collection');
242
249
  const dbData = await this.services.dbService.findOneBy(collection, conditions, fields, ordering, allowRelations);
@@ -247,11 +254,10 @@ class RWSModel {
247
254
  return null;
248
255
  }
249
256
  static async find(id, findParams = null) {
250
- var _a, _b, _c, _d;
251
- const ordering = (_a = findParams === null || findParams === void 0 ? void 0 : findParams.ordering) !== null && _a !== void 0 ? _a : null;
252
- const fields = (_b = findParams === null || findParams === void 0 ? void 0 : findParams.fields) !== null && _b !== void 0 ? _b : null;
253
- const allowRelations = (_c = findParams === null || findParams === void 0 ? void 0 : findParams.allowRelations) !== null && _c !== void 0 ? _c : true;
254
- const fullData = (_d = findParams === null || findParams === void 0 ? void 0 : findParams.fullData) !== null && _d !== void 0 ? _d : false;
257
+ const ordering = findParams?.ordering ?? null;
258
+ const fields = findParams?.fields ?? null;
259
+ const allowRelations = findParams?.allowRelations ?? true;
260
+ const fullData = findParams?.fullData ?? false;
255
261
  const collection = Reflect.get(this, '_collection');
256
262
  this.checkForInclusionWithThrow(this.name);
257
263
  const dbData = await this.services.dbService.findOneBy(collection, { id }, fields, ordering, allowRelations);
@@ -262,16 +268,15 @@ class RWSModel {
262
268
  return null;
263
269
  }
264
270
  static async findBy(findParams) {
265
- var _a, _b, _c, _d, _e;
266
- const conditions = (_a = findParams === null || findParams === void 0 ? void 0 : findParams.conditions) !== null && _a !== void 0 ? _a : {};
267
- const ordering = (_b = findParams === null || findParams === void 0 ? void 0 : findParams.ordering) !== null && _b !== void 0 ? _b : null;
268
- const fields = (_c = findParams === null || findParams === void 0 ? void 0 : findParams.fields) !== null && _c !== void 0 ? _c : null;
269
- const allowRelations = (_d = findParams === null || findParams === void 0 ? void 0 : findParams.allowRelations) !== null && _d !== void 0 ? _d : true;
270
- const fullData = (_e = findParams === null || findParams === void 0 ? void 0 : findParams.fullData) !== null && _e !== void 0 ? _e : false;
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;
271
276
  const collection = Reflect.get(this, '_collection');
272
277
  this.checkForInclusionWithThrow(this.name);
273
278
  try {
274
- const paginateParams = (findParams === null || findParams === void 0 ? void 0 : findParams.pagination) ? findParams === null || findParams === void 0 ? void 0 : findParams.pagination : undefined;
279
+ const paginateParams = findParams?.pagination ? findParams?.pagination : undefined;
275
280
  const dbData = await this.services.dbService.findBy(collection, conditions, fields, ordering, paginateParams);
276
281
  if (dbData.length) {
277
282
  const instanced = [];
@@ -327,14 +332,6 @@ class RWSModel {
327
332
  }
328
333
  }
329
334
  exports.RWSModel = RWSModel;
330
- RWSModel.services = {};
331
- RWSModel._collection = null;
332
- RWSModel._RELATIONS = {};
333
- RWSModel._NO_ID = false;
334
- RWSModel._SUPER_TAGS = [];
335
- RWSModel._BANNED_KEYS = ['_collection'];
336
- RWSModel.allModels = [];
337
- RWSModel._CUT_KEYS = [];
338
335
  __decorate([
339
336
  (0, decorators_1.TrackType)(String),
340
337
  __metadata("design:type", Object)
@@ -5,13 +5,16 @@ export interface IDbOpts {
5
5
  useText?: boolean;
6
6
  maxLength?: number;
7
7
  useUuid?: boolean;
8
+ params?: string[];
8
9
  };
9
10
  postgres?: {
10
11
  useText?: boolean;
11
12
  useUuid?: boolean;
13
+ params?: string[];
12
14
  };
13
15
  mongodb?: {
14
16
  customType?: string;
17
+ params?: string[];
15
18
  };
16
19
  };
17
20
  }
@@ -1,3 +1,5 @@
1
1
  import { IDbOpts } from "./IDbOpts";
2
2
  export interface IIdTypeOpts extends IDbOpts {
3
+ unique?: boolean | string;
4
+ noAuto?: boolean;
3
5
  }
@@ -9,4 +9,5 @@ export interface ITrackerOpts extends IDbOpts {
9
9
  relatedTo?: OpModelType<any>;
10
10
  inversionModel?: OpModelType<any>;
11
11
  relationName?: string;
12
+ noAuto?: boolean;
12
13
  }
@@ -41,7 +41,6 @@ class HydrateUtils {
41
41
  continue;
42
42
  }
43
43
  const relMeta = relManyData[key];
44
- // console.log({relMeta});
45
44
  const relationEnabled = !RelationUtils_1.RelationUtils.checkRelDisabled(model, relMeta.key);
46
45
  if (relationEnabled) {
47
46
  model[relMeta.key] = await relMeta.inversionModel.findBy({
@@ -6,8 +6,15 @@ class ModelUtils {
6
6
  static async getModelAnnotations(constructor) {
7
7
  const annotationsData = {};
8
8
  const metadataKeys = Reflect.getMetadataKeys(constructor.prototype);
9
+ const filteredMetaKeys = metadataKeys.filter((metaKey) => {
10
+ const [annotationType, annotatedField] = metaKey.split(':');
11
+ if (annotationType === 'TrackType' && annotatedField === 'id' && metadataKeys.includes('IdType:' + annotatedField)) {
12
+ return false;
13
+ }
14
+ return true;
15
+ });
9
16
  // Process all metadata keys and collect promises
10
- const metadataPromises = metadataKeys.map(async (fullKey) => {
17
+ const metadataPromises = filteredMetaKeys.map(async (fullKey) => {
11
18
  const [annotationType, propertyKey] = fullKey.split(':');
12
19
  const metadata = Reflect.getMetadata(fullKey, constructor.prototype);
13
20
  if (metadata) {
@@ -3,12 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PaginationUtils = void 0;
4
4
  class PaginationUtils {
5
5
  static async paginate(paginationParams = { page: 0, per_page: 50 }, findParams = {}) {
6
- var _a, _b, _c, _d, _e;
7
- const conditions = (_a = findParams === null || findParams === void 0 ? void 0 : findParams.conditions) !== null && _a !== void 0 ? _a : {};
8
- const ordering = (_b = findParams === null || findParams === void 0 ? void 0 : findParams.ordering) !== null && _b !== void 0 ? _b : null;
9
- const fields = (_c = findParams === null || findParams === void 0 ? void 0 : findParams.fields) !== null && _c !== void 0 ? _c : null;
10
- const allowRelations = (_d = findParams === null || findParams === void 0 ? void 0 : findParams.allowRelations) !== null && _d !== void 0 ? _d : true;
11
- const fullData = (_e = findParams === null || findParams === void 0 ? void 0 : findParams.fullData) !== null && _e !== void 0 ? _e : false;
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;
12
11
  const collection = Reflect.get(this, '_collection');
13
12
  this.checkForInclusionWithThrow(this.name);
14
13
  try {
@@ -8,10 +8,12 @@ const client_1 = require("@prisma/client");
8
8
  const mongodb_1 = require("mongodb");
9
9
  const chalk_1 = __importDefault(require("chalk"));
10
10
  class DBService {
11
+ configService;
12
+ client;
13
+ opts = null;
14
+ connected = false;
11
15
  constructor(configService) {
12
16
  this.configService = configService;
13
- this.opts = null;
14
- this.connected = false;
15
17
  }
16
18
  connectToDB(opts = null) {
17
19
  if (opts) {
@@ -50,15 +52,13 @@ class DBService {
50
52
  return client;
51
53
  }
52
54
  async createBaseMongoClient() {
53
- var _a;
54
- const dbUrl = ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.dbUrl) || this.configService.get('db_url');
55
+ const dbUrl = this.opts?.dbUrl || this.configService.get('db_url');
55
56
  const client = DBService.baseClientConstruct(dbUrl);
56
57
  await client.connect();
57
58
  return client;
58
59
  }
59
60
  async createBaseMongoClientDB() {
60
- var _a;
61
- const dbName = ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.dbName) || this.configService.get('db_name');
61
+ const dbName = this.opts?.dbName || this.configService.get('db_name');
62
62
  const client = await this.createBaseMongoClient();
63
63
  return [client, client.db(dbName)];
64
64
  }
@@ -151,8 +151,7 @@ class DBService {
151
151
  return retData;
152
152
  }
153
153
  async collectionExists(collection_name) {
154
- var _a;
155
- const dbUrl = ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.dbUrl) || this.configService.get('db_url');
154
+ const dbUrl = this.opts?.dbUrl || this.configService.get('db_url');
156
155
  const client = new mongodb_1.MongoClient(dbUrl);
157
156
  try {
158
157
  await client.connect();
package/exec/console.js CHANGED
@@ -15,8 +15,6 @@ const getCachedPath = (key) => path.resolve(rwsCliConfigDir, key);
15
15
 
16
16
  const currentCwd = path.resolve(__dirname);
17
17
 
18
- console.log({params})
19
-
20
18
 
21
19
  const commandString = `npx webpack --config db.rws.webpack.config.js --output-path ./build ${process.cwd()} ${params[2]}`;
22
20
  function needsCacheWarming(){
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rws-framework/db",
3
3
  "private": false,
4
- "version": "3.1.0",
4
+ "version": "3.3.0",
5
5
  "description": "",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -8,7 +8,16 @@ export interface IIdMetaOpts extends IIdTypeOpts {
8
8
 
9
9
  function IdType(type: any, opts: IIdTypeOpts | null = null, tags: string[] = []) {
10
10
  const metaOpts: IIdMetaOpts = { type, dbOptions: opts && opts.dbOptions ? opts.dbOptions : null };
11
- return function(target: any, key: string) {
11
+
12
+ if(opts && opts.dbOptions){
13
+ metaOpts.dbOptions = opts.dbOptions;
14
+ }
15
+
16
+ if(opts && opts.noAuto){
17
+ metaOpts.noAuto = opts.noAuto;
18
+ }
19
+
20
+ return function(target: any, key: string) {
12
21
  Reflect.defineMetadata(`IdType:${key}`, metaOpts, target);
13
22
  };
14
23
  }
@@ -64,8 +64,8 @@ function InverseRelation(inversionModel: () => OpModelType<RWSModel<any>>, sourc
64
64
  foreignKey: relationOptions && relationOptions.foreignKey ? relationOptions.foreignKey : guessForeignKey(model, source, decoratorsData),
65
65
  // Generate a unique relation name if one is not provided
66
66
  relationName: relationOptions && relationOptions.relationName ?
67
- relationOptions.relationName.toLowerCase() :
68
- `${model._collection}_${key}_${source._collection}`.toLowerCase()
67
+ relationOptions.relationName :
68
+ null
69
69
  };
70
70
 
71
71
  return metaOpts;
@@ -20,13 +20,15 @@ export interface IRelationOpts {
20
20
  }
21
21
  }
22
22
 
23
- const _DEFAULTS: Partial<IRelationOpts> = { required: false, many: false, embed: false, cascade: { onDelete: 'SetNull', onUpdate: 'Cascade' }};
23
+ const _DEFAULT_CASCADE = { onDelete: 'SetNull', onUpdate: 'Cascade' };
24
+
25
+ const _DEFAULTS: Partial<IRelationOpts> = { required: false, many: false, embed: false, cascade: null};
24
26
 
25
27
  function Relation(theModel: () => OpModelType<RWSModel<any>>, relationOptions: Partial<IRelationOpts> = _DEFAULTS) {
26
28
  return function(target: any, key: string) {
27
29
  // Store the promise in metadata immediately
28
30
 
29
- const metadataPromise = Promise.resolve().then(() => {
31
+ const metadataPromise = Promise.resolve().then(() => {
30
32
  const relatedTo = theModel();
31
33
 
32
34
  const metaOpts: IRelationOpts = {
@@ -37,8 +39,8 @@ function Relation(theModel: () => OpModelType<RWSModel<any>>, relationOptions: P
37
39
  key,
38
40
  // Generate a unique relation name if one is not provided
39
41
  relationName: relationOptions.relationName ?
40
- relationOptions.relationName.toLowerCase() :
41
- `${target.constructor.name.toLowerCase()}_${key}_${relatedTo._collection.toLowerCase()}`
42
+ relationOptions.relationName :
43
+ null
42
44
  };
43
45
 
44
46
  if(relationOptions.required){
@@ -101,7 +101,7 @@ export class DbHelper {
101
101
  /**
102
102
  * Convert a JavaScript type to a Prisma schema type
103
103
  */
104
- static toConfigCase(modelType: any, dbType: string = 'mongodb'): string {
104
+ static toConfigCase(modelType: any, dbType: IDbConfigParams['db_type'] = 'mongodb'): string {
105
105
  return TypeConverter.toConfigCase(modelType, dbType);
106
106
  }
107
107
 
@@ -15,7 +15,8 @@ import { RelationManager } from './relation-manager';
15
15
  import { ITrackerMetaOpts } from '../../decorators/TrackType';
16
16
  import { IDbOpts } from '../../models/interfaces/IDbOpts';
17
17
 
18
- const log = console.log;
18
+ const _EXECUTE_PRISMA_CMD = true;
19
+ const _REMOVE_SCHEMA_FILE = true;
19
20
 
20
21
  /**
21
22
  * Handles Prisma schema generation
@@ -57,13 +58,28 @@ datasource db {
57
58
  const dbType = configService.get('db_type') || 'mongodb';
58
59
  const modelName: string = (model as any)._collection;
59
60
 
60
- section += `model ${modelName} {\n`;
61
+ section += `model ${modelName} {\n`;
62
+
63
+ let hasIdType = false;
64
+ let idFieldName: string;
65
+
66
+ for(const someModelMetaKey in modelMetadatas){
67
+ const isIdTyped = modelMetadatas[someModelMetaKey].annotationType === 'IdType';
68
+ if(isIdTyped){
69
+ hasIdType = true;
70
+ idFieldName = someModelMetaKey;
71
+ }
72
+ }
73
+
74
+ let idGenerated = false;
75
+
61
76
 
62
77
  if(
63
- !model._NO_ID
64
- ){
65
- section += `\t${DbUtils.generateId(dbType, modelMetadatas)}\n`;
66
- }
78
+ !model._NO_ID && !hasIdType
79
+ ){
80
+ section += `\t${DbUtils.generateId(dbType, modelMetadatas)}\n`;
81
+ idGenerated = true;
82
+ }
67
83
 
68
84
  for (const key in modelMetadatas) {
69
85
  const modelMetadata = modelMetadatas[key].metadata;
@@ -72,16 +88,15 @@ datasource db {
72
88
 
73
89
  let indexedId = false;
74
90
 
75
- if(model._NO_ID){
91
+ if(model._NO_ID || hasIdType){
76
92
  indexedId = true;
77
93
  requiredString = '';
78
- }
79
-
94
+ }
80
95
 
81
96
  if (key === 'id' && !indexedId) {
82
97
  continue;
83
98
  }
84
-
99
+
85
100
  if (annotationType === 'Relation') {
86
101
  const relationMeta = modelMetadata as IRelationOpts;
87
102
 
@@ -101,8 +116,9 @@ datasource db {
101
116
  const relationKey = [modelName, relatedModelName].join('_');
102
117
 
103
118
  const relationIndex = RelationManager.getRelationCounter(relationKey);
104
- const relationName = RelationManager.getShortenedRelationName(modelName, relatedModelName, relationIndex);
105
- const mapName = relationName;
119
+ const relationName = relationMeta.relationName ? relationMeta.relationName : null;
120
+
121
+ const mapName = relationMeta.mappingName ? relationMeta.mappingName : null;
106
122
 
107
123
  const relatedModelMetadatas: Record<string, { annotationType: string, metadata: ITrackerMetaOpts }> = await RWSModel.getModelAnnotations(relatedModel);
108
124
  const relationFieldName = modelMetadata.relationField ? modelMetadata.relationField : key.toLowerCase() + '_' + modelMetadata.relationField.toLowerCase();
@@ -112,17 +128,19 @@ datasource db {
112
128
 
113
129
  if(modelMetadata.required === false){
114
130
  requiredString = '?';
115
- }
131
+ }
132
+
133
+ const cascadeStr = cascadeOpts.length ? `, ${cascadeOpts.join(', ')}` : '' ;
116
134
 
117
135
  if (isMany) {
118
136
  // Add an inverse field to the related model if it doesn't exist
119
- section += `\t${key} ${relatedModel._collection}[] @relation("${relationName}", fields: [${relationFieldName}], references: [${relatedToField}], map: "${mapName}", ${cascadeOpts.join(', ')})\n`;
120
- } else {
121
- section += `\t${key} ${relatedModel._collection}${requiredString} @relation("${relationName}", fields: [${relationFieldName}], references: [${relatedToField}], map: "${mapName}", ${cascadeOpts.join(', ')})\n`;
137
+ section += `\t${key} ${relatedModel._collection}[] @relation(${relationName ? `"${relationName}", ` : ''}fields: [${relationFieldName}], references: [${relatedToField}]${mapName ? `, map: "${mapName}"` : ''}${cascadeStr})\n`;
138
+ } else {
139
+ section += `\t${key} ${relatedModel._collection}${requiredString} @relation(${relationName ? `"${relationName}", ` : ''}fields: [${relationFieldName}], references: [${relatedToField}]${mapName ? `, map: "${mapName}"` : ''}${cascadeStr})\n`;
122
140
  if(!bindingFieldExists){
123
141
  const relatedFieldMeta = relatedModelMetadatas[relatedToField];
124
142
 
125
- if(!relatedFieldMeta.metadata.required){
143
+ if(!relatedFieldMeta.metadata.required){
126
144
  requiredString = '';
127
145
  }
128
146
 
@@ -162,10 +180,15 @@ datasource db {
162
180
  const relationKey = [relatedModelName, modelName].join('_');
163
181
  const relationIndex = RelationManager.getRelationCounter(relationKey, true);
164
182
 
165
- const relationName = RelationManager.getShortenedRelationName(relatedModelName, modelName, relationIndex);
166
- const mapName = relationName;
183
+ const relationName = RelationManager.getShortenedRelationName(relatedModelName, modelName, relationIndex);
184
+
185
+ let relationTag = '';
186
+
187
+ if(relationMeta.relationName){
188
+ relationTag = ` @relation("${relationMeta.relationName}")`;
189
+ }
167
190
 
168
- section += `\t${key} ${relationMeta.inversionModel._collection}[] @relation("${relationName}", map: "${mapName}")\n`;
191
+ section += `\t${key} ${relationMeta.inversionModel._collection}[]${relationTag}\n`;
169
192
 
170
193
  RelationManager.completeRelation(relationKey, relationIndex, true);
171
194
  } else if (annotationType === 'InverseTimeSeries') {
@@ -180,14 +203,22 @@ datasource db {
180
203
  } else {
181
204
  section += `\t${key} String[]\n`;
182
205
  }
183
- } else if (annotationType === 'TrackType') {
206
+ } else {
184
207
  const trackMeta = modelMetadata as ITrackerMetaOpts;
185
- const tags: string[] = trackMeta.tags.map((item: string) => '@' + item);
186
-
187
- if(key === 'id' && model._NO_ID && !model._SUPER_TAGS.some(tag => tag.tagType === 'id' && tag.fields.includes('id'))){
208
+ const trackTags = trackMeta.tags || [];
209
+ const tags: string[] = trackTags.map((item: string) => '@' + item);
210
+
211
+ const isNoIdBehavior = model._NO_ID || idFieldName;
212
+ const isOverrideBehavior = (hasIdType && annotationType === 'IdType' && key === 'id' && idFieldName === 'id')
213
+ ||
214
+ (model._NO_ID && model._SUPER_TAGS.some(a => a.fields.includes('id')) && key === 'id');
215
+
216
+ if(key === 'id' &&
217
+ isNoIdBehavior && !isOverrideBehavior
218
+ ){
188
219
  continue;
189
220
  }
190
-
221
+
191
222
  if(trackMeta.unique){
192
223
  const fieldDetail: string | null = typeof trackMeta.unique === 'string' ? trackMeta.unique : null;
193
224
  tags.push(`@unique(${fieldDetail ? `map: "${fieldDetail}"` : ''})`);
@@ -204,24 +235,60 @@ datasource db {
204
235
  if(model._SUPER_TAGS.some(tag => tag.tagType === 'id' && tag.fields.includes(key))){
205
236
  requiredString = '';
206
237
  }
207
-
238
+
208
239
  // Process any database-specific options from the metadata
209
240
  const dbSpecificTags = TypeConverter.processTypeOptions(trackMeta as { tags: string[], dbOptions: IDbOpts['dbOptions'] }, dbType);
210
241
  tags.push(...dbSpecificTags);
242
+
243
+ const isIdTypeField = modelMetadatas[key].annotationType === 'IdType';
244
+ const fieldInUniqueSuperTag = model._SUPER_TAGS.some(st => st.tagType === 'unique' && st.fields.includes(key));
211
245
 
212
- if(modelName === 'category_translation' && key === 'meta_keywords'){
213
- console.log({requiredString, trackMeta});
214
- }
246
+ if(isIdTypeField){
247
+ requiredString = '';
248
+ }
249
+
250
+ let trackField = `${key} ${TypeConverter.toConfigCase(trackMeta, dbType, key === 'id', isOverrideBehavior)}${requiredString} ${tags.join(' ')}`;
215
251
 
216
- section += `\t${key} ${TypeConverter.toConfigCase(trackMeta, dbType, key === 'id')}${requiredString} ${tags.join(' ')}\n`;
252
+ if(isIdTypeField){
253
+ trackField += DbUtils.addIdPart(dbType, DbUtils.doesUseUuid(modelMetadatas), trackMeta.noAuto);
254
+ idGenerated = true;
255
+ }
256
+
257
+ section += `\t${trackField}\n`;
217
258
  }
218
259
  }
219
260
 
261
+ if(model._SUPER_TAGS.length){
262
+ section += '\n';
263
+ }
264
+
220
265
  for(const superTag of model._SUPER_TAGS){
221
266
 
222
267
  const mapStr = superTag.map ? `, map: "${superTag.map}"` : '';
223
268
 
224
- section += `\t@@${superTag.tagType}([${superTag.fields.join(', ')}]${mapStr})\n`;
269
+ const superFields = [];
270
+
271
+ for(const superField of superTag.fields){
272
+ const fieldMetadata = modelMetadatas[superField]['metadata'];
273
+
274
+
275
+ let pushed = false;
276
+
277
+ if(fieldMetadata.dbOptions && fieldMetadata.dbOptions.mysql && fieldMetadata.dbOptions.mysql.useType){
278
+ switch(fieldMetadata.dbOptions.mysql.useType){
279
+ case 'db.LongText':
280
+ superFields.push(`${superField}(length: 255)`);
281
+ pushed = true;
282
+ break;
283
+ }
284
+ }
285
+
286
+ if(!pushed){
287
+ superFields.push(superField);
288
+ }
289
+ }
290
+
291
+ section += `\t@@${superTag.tagType}([${superFields.join(', ')}]${mapStr})\n`;
225
292
  }
226
293
 
227
294
  section += '}\n';
@@ -280,7 +347,7 @@ datasource db {
280
347
 
281
348
  template += '\n\n' + modelSection;
282
349
 
283
- log(chalk.green('[RWS]'), chalk.blue('Building DB Model'), model.name);
350
+ console.log(chalk.green('[RWS]'), chalk.blue('Building DB Model'), model.name);
284
351
  }
285
352
 
286
353
  const [schemaDir, schemaPath] = DbUtils.getSchemaDir();
@@ -295,13 +362,14 @@ datasource db {
295
362
 
296
363
  fs.writeFileSync(schemaPath, template);
297
364
 
365
+ if(_EXECUTE_PRISMA_CMD)
298
366
  await rwsShell.runCommand(`${DbUtils.detectInstaller()} prisma generate --schema=${schemaPath}`, process.cwd());
299
367
 
300
- leaveFile = false;
301
- log(chalk.green('[RWS Init]') + ' prisma schema generated from ', schemaPath);
368
+
369
+ console.log(chalk.green('[RWS Init]') + ' prisma schema generated from ', schemaPath);
302
370
 
303
- if (!leaveFile) {
304
- // fs.unlinkSync(schemaPath);
371
+ if (_REMOVE_SCHEMA_FILE) {
372
+ fs.unlinkSync(schemaPath);
305
373
  }
306
374
  }
307
375
  }
@@ -1,6 +1,8 @@
1
1
  import { IDbOpts } from '../../models/interfaces/IDbOpts';
2
2
  import { ITrackerMetaOpts } from '../../models/_model';
3
3
  import { IIdMetaOpts } from 'src/decorators/IdType';
4
+ import { DbUtils } from './utils';
5
+ import { IDbConfigParams } from 'src/types/DbConfigHandler';
4
6
 
5
7
  /**
6
8
  * Handles type conversion for database schema generation
@@ -9,14 +11,35 @@ export class TypeConverter {
9
11
  /**
10
12
  * Convert a JavaScript type to a Prisma schema type
11
13
  */
12
- static toConfigCase(modelType: ITrackerMetaOpts | IIdMetaOpts, dbType: string = 'mongodb', isId: boolean = false): string {
14
+ static toConfigCase(modelType: ITrackerMetaOpts | IIdMetaOpts, dbType: IDbConfigParams['db_type'] = 'mongodb', isId: boolean = false, isIdOverride: boolean = false): string {
13
15
  const type = modelType.type;
14
16
  let input = type.name;
15
17
 
16
18
 
17
19
  // Handle basic types
18
20
  if (input == 'Number') {
19
- input = 'Int';
21
+ let numberOverride = false;
22
+ if(modelType.dbOptions && modelType.dbOptions.mysql){
23
+ if(modelType.dbOptions.mysql.useType){
24
+ if(['db.Float'].includes(modelType.dbOptions.mysql.useType)){
25
+ input = 'Float';
26
+ numberOverride = true;
27
+ }
28
+
29
+ if(['db.Decimal'].includes(modelType.dbOptions.mysql.useType)){
30
+ input = 'Decimal';
31
+ numberOverride = true;
32
+ }
33
+ }
34
+ }
35
+
36
+ if(!numberOverride){
37
+ input = 'Int';
38
+ }
39
+ }
40
+
41
+ if (input == 'BigInt') {
42
+ input = 'BigInt';
20
43
  }
21
44
 
22
45
  if (input == 'Object') {
@@ -46,9 +69,9 @@ export class TypeConverter {
46
69
  const restOfString = input.slice(1);
47
70
  let resultField = firstChar + restOfString;
48
71
 
49
- if(isId){
50
- return dbType === 'mongodb' ? 'String' : 'Int';
51
- }
72
+ if(isId && !isIdOverride){
73
+ return DbUtils.getDefaultPrismaType(dbType, false);
74
+ }
52
75
 
53
76
  const trackerModelType = modelType as ITrackerMetaOpts;
54
77
 
@@ -64,7 +87,7 @@ export class TypeConverter {
64
87
  } else {
65
88
  resultField += '[]';
66
89
  }
67
- }
90
+ }
68
91
 
69
92
  return resultField;
70
93
  }
@@ -83,10 +106,20 @@ export class TypeConverter {
83
106
  if (metadata.dbOptions) {
84
107
  // Handle MySQL-specific options
85
108
  if (dbType === 'mysql' && metadata.dbOptions.mysql) {
109
+ let tag = null;
110
+
111
+ if (metadata.dbOptions.mysql.useType && !metadata.dbOptions.mysql.useText) {
112
+ const tagName = metadata.dbOptions.mysql.useType === 'VarChar' ? 'db.' + metadata.dbOptions.mysql.useType : metadata.dbOptions.mysql.useType;
113
+ let tagParams = tagName === 'db.VarChar' && metadata.dbOptions.mysql.maxLength ? metadata.dbOptions.mysql.maxLength : (metadata.dbOptions.mysql?.params?.join(', ') || '');
114
+ tag = `@${tagName}(${tagParams})`;
115
+ }
116
+
86
117
  if (metadata.dbOptions.mysql.useText) {
87
118
  tags.push('@db.Text');
88
- } else if (metadata.dbOptions.mysql.maxLength) {
89
- tags.push(`@db.VarChar(${metadata.dbOptions.mysql.maxLength})`);
119
+ }
120
+
121
+ if(tag){
122
+ tags.push(tag);
90
123
  }
91
124
 
92
125
  if (metadata.dbOptions.mysql.useUuid && metadata.tags?.includes('id')) {