@rws-framework/db 3.2.0 → 3.3.1

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.
@@ -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
  }
@@ -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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rws-framework/db",
3
3
  "private": false,
4
- "version": "3.2.0",
4
+ "version": "3.3.1",
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;
@@ -39,8 +39,8 @@ function Relation(theModel: () => OpModelType<RWSModel<any>>, relationOptions: P
39
39
  key,
40
40
  // Generate a unique relation name if one is not provided
41
41
  relationName: relationOptions.relationName ?
42
- relationOptions.relationName.toLowerCase() :
43
- `${target.constructor.name.toLowerCase()}_${key}_${relatedTo._collection.toLowerCase()}`
42
+ relationOptions.relationName :
43
+ null
44
44
  };
45
45
 
46
46
  if(relationOptions.required){
@@ -46,7 +46,7 @@ export class DbHelper {
46
46
  static async migrateDBModels(configService: IDbConfigHandler, dbService: DBService, leaveFile = false): Promise<void> {
47
47
  process.env = { ...process.env, [this.dbUrlVarName]: configService.get('db_url') };
48
48
 
49
- const [_, schemaPath] = DbUtils.getSchemaDir();
49
+ const [_, schemaPath] = DbUtils.getProcessedSchemaDir();
50
50
 
51
51
  await rwsShell.runCommand(`${DbUtils.detectInstaller()} prisma migrate dev --create-only --schema=${schemaPath}`, process.cwd());
52
52
  }
@@ -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,6 +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 _EXECUTE_PRISMA_CMD = true;
19
+ const _REMOVE_SCHEMA_FILE = true;
18
20
 
19
21
  /**
20
22
  * Handles Prisma schema generation
@@ -56,13 +58,28 @@ datasource db {
56
58
  const dbType = configService.get('db_type') || 'mongodb';
57
59
  const modelName: string = (model as any)._collection;
58
60
 
59
- 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
+
60
76
 
61
77
  if(
62
- !model._NO_ID
63
- ){
64
- section += `\t${DbUtils.generateId(dbType, modelMetadatas)}\n`;
65
- }
78
+ !model._NO_ID && !hasIdType
79
+ ){
80
+ section += `\t${DbUtils.generateId(dbType, modelMetadatas)}\n`;
81
+ idGenerated = true;
82
+ }
66
83
 
67
84
  for (const key in modelMetadatas) {
68
85
  const modelMetadata = modelMetadatas[key].metadata;
@@ -71,16 +88,15 @@ datasource db {
71
88
 
72
89
  let indexedId = false;
73
90
 
74
- if(model._NO_ID){
91
+ if(model._NO_ID || hasIdType){
75
92
  indexedId = true;
76
93
  requiredString = '';
77
- }
78
-
94
+ }
79
95
 
80
96
  if (key === 'id' && !indexedId) {
81
97
  continue;
82
98
  }
83
-
99
+
84
100
  if (annotationType === 'Relation') {
85
101
  const relationMeta = modelMetadata as IRelationOpts;
86
102
 
@@ -100,8 +116,9 @@ datasource db {
100
116
  const relationKey = [modelName, relatedModelName].join('_');
101
117
 
102
118
  const relationIndex = RelationManager.getRelationCounter(relationKey);
103
- const relationName = RelationManager.getShortenedRelationName(modelName, relatedModelName, relationIndex);
104
- const mapName = relationName;
119
+ const relationName = relationMeta.relationName ? relationMeta.relationName : null;
120
+
121
+ const mapName = relationMeta.mappingName ? relationMeta.mappingName : null;
105
122
 
106
123
  const relatedModelMetadatas: Record<string, { annotationType: string, metadata: ITrackerMetaOpts }> = await RWSModel.getModelAnnotations(relatedModel);
107
124
  const relationFieldName = modelMetadata.relationField ? modelMetadata.relationField : key.toLowerCase() + '_' + modelMetadata.relationField.toLowerCase();
@@ -111,19 +128,19 @@ datasource db {
111
128
 
112
129
  if(modelMetadata.required === false){
113
130
  requiredString = '?';
114
- }
131
+ }
115
132
 
116
133
  const cascadeStr = cascadeOpts.length ? `, ${cascadeOpts.join(', ')}` : '' ;
117
134
 
118
135
  if (isMany) {
119
136
  // Add an inverse field to the related model if it doesn't exist
120
- section += `\t${key} ${relatedModel._collection}[] @relation("${relationName}", fields: [${relationFieldName}], references: [${relatedToField}], map: "${mapName}"${cascadeStr})\n`;
121
- } else {
122
- section += `\t${key} ${relatedModel._collection}${requiredString} @relation("${relationName}", fields: [${relationFieldName}], references: [${relatedToField}], map: "${mapName}"${cascadeStr})\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`;
123
140
  if(!bindingFieldExists){
124
141
  const relatedFieldMeta = relatedModelMetadatas[relatedToField];
125
142
 
126
- if(!relatedFieldMeta.metadata.required){
143
+ if(!relatedFieldMeta.metadata.required){
127
144
  requiredString = '';
128
145
  }
129
146
 
@@ -163,10 +180,15 @@ datasource db {
163
180
  const relationKey = [relatedModelName, modelName].join('_');
164
181
  const relationIndex = RelationManager.getRelationCounter(relationKey, true);
165
182
 
166
- const relationName = RelationManager.getShortenedRelationName(relatedModelName, modelName, relationIndex);
167
- const mapName = relationName;
183
+ const relationName = RelationManager.getShortenedRelationName(relatedModelName, modelName, relationIndex);
184
+
185
+ let relationTag = '';
168
186
 
169
- section += `\t${key} ${relationMeta.inversionModel._collection}[] @relation("${relationName}", map: "${mapName}")\n`;
187
+ if(relationMeta.relationName){
188
+ relationTag = ` @relation("${relationMeta.relationName}")`;
189
+ }
190
+
191
+ section += `\t${key} ${relationMeta.inversionModel._collection}[]${relationTag}\n`;
170
192
 
171
193
  RelationManager.completeRelation(relationKey, relationIndex, true);
172
194
  } else if (annotationType === 'InverseTimeSeries') {
@@ -181,14 +203,22 @@ datasource db {
181
203
  } else {
182
204
  section += `\t${key} String[]\n`;
183
205
  }
184
- } else if (annotationType === 'TrackType') {
206
+ } else {
185
207
  const trackMeta = modelMetadata as ITrackerMetaOpts;
186
- const tags: string[] = trackMeta.tags.map((item: string) => '@' + item);
187
-
188
- 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
+ ){
189
219
  continue;
190
220
  }
191
-
221
+
192
222
  if(trackMeta.unique){
193
223
  const fieldDetail: string | null = typeof trackMeta.unique === 'string' ? trackMeta.unique : null;
194
224
  tags.push(`@unique(${fieldDetail ? `map: "${fieldDetail}"` : ''})`);
@@ -210,8 +240,21 @@ datasource db {
210
240
  const dbSpecificTags = TypeConverter.processTypeOptions(trackMeta as { tags: string[], dbOptions: IDbOpts['dbOptions'] }, dbType);
211
241
  tags.push(...dbSpecificTags);
212
242
 
243
+ const isIdTypeField = modelMetadatas[key].annotationType === 'IdType';
244
+ const fieldInUniqueSuperTag = model._SUPER_TAGS.some(st => st.tagType === 'unique' && st.fields.includes(key));
213
245
 
214
- section += `\t${key} ${TypeConverter.toConfigCase(trackMeta, dbType, key === 'id')}${requiredString} ${tags.join(' ')}\n`;
246
+ if(isIdTypeField){
247
+ requiredString = '';
248
+ }
249
+
250
+ let trackField = `${key} ${TypeConverter.toConfigCase(trackMeta, dbType, key === 'id', isOverrideBehavior)}${requiredString} ${tags.join(' ')}`;
251
+
252
+ if(isIdTypeField){
253
+ trackField += DbUtils.addIdPart(dbType, DbUtils.doesUseUuid(modelMetadatas), trackMeta.noAuto);
254
+ idGenerated = true;
255
+ }
256
+
257
+ section += `\t${trackField}\n`;
215
258
  }
216
259
  }
217
260
 
@@ -319,13 +362,14 @@ datasource db {
319
362
 
320
363
  fs.writeFileSync(schemaPath, template);
321
364
 
365
+ if(_EXECUTE_PRISMA_CMD)
322
366
  await rwsShell.runCommand(`${DbUtils.detectInstaller()} prisma generate --schema=${schemaPath}`, process.cwd());
323
367
 
324
- leaveFile = false;
368
+
325
369
  console.log(chalk.green('[RWS Init]') + ' prisma schema generated from ', schemaPath);
326
370
 
327
- if (!leaveFile) {
328
- // fs.unlinkSync(schemaPath);
371
+ if (_REMOVE_SCHEMA_FILE) {
372
+ fs.unlinkSync(schemaPath);
329
373
  }
330
374
  }
331
375
  }
@@ -339,7 +383,7 @@ datasource db {
339
383
  static async pushDBModels(configService: IDbConfigHandler, dbService: DBService, leaveFile = false): Promise<void> {
340
384
  process.env = { ...process.env, [this.dbUrlVarName]: configService.get('db_url') };
341
385
 
342
- const [_, schemaPath] = DbUtils.getSchemaDir();
386
+ const [_, schemaPath] = DbUtils.getProcessedSchemaDir();
343
387
 
344
388
  await rwsShell.runCommand(`${DbUtils.detectInstaller()} prisma db push --schema=${schemaPath}`, process.cwd());
345
389
  }
@@ -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,7 +11,7 @@ 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
 
@@ -36,6 +38,10 @@ export class TypeConverter {
36
38
  }
37
39
  }
38
40
 
41
+ if (input == 'BigInt') {
42
+ input = 'BigInt';
43
+ }
44
+
39
45
  if (input == 'Object') {
40
46
  input = 'Json';
41
47
  }
@@ -63,9 +69,9 @@ export class TypeConverter {
63
69
  const restOfString = input.slice(1);
64
70
  let resultField = firstChar + restOfString;
65
71
 
66
- if(isId){
67
- return dbType === 'mongodb' ? 'String' : 'Int';
68
- }
72
+ if(isId && !isIdOverride){
73
+ return DbUtils.getDefaultPrismaType(dbType, false);
74
+ }
69
75
 
70
76
  const trackerModelType = modelType as ITrackerMetaOpts;
71
77
 
@@ -5,6 +5,7 @@ import { IDbConfigParams } from '../../types/DbConfigHandler';
5
5
  import { IIdMetaOpts, IIdTypeOpts } from '../../decorators/IdType';
6
6
  import { TypeConverter } from './type-converter';
7
7
  import { IDbOpts } from '../../models/interfaces/IDbOpts';
8
+ import { ITrackerMetaOpts } from '../../models/_model';
8
9
 
9
10
  const workspaceRoot = rwsPath.findRootWorkspacePath();
10
11
  const moduleDir = path.resolve(workspaceRoot, 'node_modules', '@rws-framework', 'db');
@@ -23,6 +24,13 @@ export class DbUtils {
23
24
  return [schemaDir, schemaPath];
24
25
  }
25
26
 
27
+ static getProcessedSchemaDir(): [string, string] {
28
+ const schemaDir = path.join(workspaceRoot, 'node_modules','.prisma', 'client');
29
+ const schemaPath = path.join(schemaDir, 'schema.prisma');
30
+
31
+ return [schemaDir, schemaPath];
32
+ }
33
+
26
34
  /**
27
35
  * Detect the package installer (yarn or npx)
28
36
  */
@@ -41,78 +49,151 @@ export class DbUtils {
41
49
  dbType: IDbConfigParams['db_type'],
42
50
  modelMeta: Record<string, { annotationType: string, metadata: IIdMetaOpts }>,
43
51
  optional = false
44
- ): string {
45
- let useUuid = false;
52
+ ): string {
53
+ let useUuid = this.doesUseUuid(modelMeta);
46
54
  let field = 'id';
47
55
  const tags: string[] = [];
48
56
 
49
57
  for (const key in modelMeta) {
50
- const modelMetadata: IIdMetaOpts = modelMeta[key].metadata;
51
- const annotationType: string = modelMeta[key].annotationType;
58
+ const modelMetadata: IIdMetaOpts = modelMeta[key].metadata;
59
+ const annotationType: string = modelMeta[key].annotationType;
52
60
 
53
- if(key !== 'id'){
54
- if(annotationType == 'IdType'){
61
+ if (key !== 'id') {
62
+ if (annotationType == 'IdType') {
55
63
  const dbSpecificTags = TypeConverter.processTypeOptions({ tags: [], dbOptions: modelMetadata.dbOptions }, dbType);
56
- tags.push(...dbSpecificTags);
57
-
58
- field = key;
64
+ tags.push(...dbSpecificTags);
65
+
66
+ field = key;
67
+ }
68
+ }
69
+ }
70
+
71
+ const idPrismaType = this.getDefaultPrismaType(dbType, useUuid);
72
+
73
+ let reqStr = '';
74
+
75
+ if (optional) {
76
+ reqStr = '?';
77
+ }
78
+
79
+ let idString: string = `${field} ${idPrismaType}${reqStr}`;
80
+
81
+ idString += this.addIdPart(dbType, useUuid, modelMeta[field].metadata.noAuto);
82
+
83
+ if(dbType === 'mongodb'){
84
+ tags.push('@map("_id")');
85
+ tags.push('@db.ObjectId');
86
+ }
87
+
88
+ if (tags.length) {
89
+ idString += ' ' + tags.join(' ');
90
+ }
91
+
92
+ if (!idString) {
93
+ throw new Error(`DB type "${dbType}" is not supported!`);
94
+ }
95
+
96
+
97
+ return idString;
98
+ }
99
+
100
+ static getDefaultPrismaType(dbType: IDbConfigParams['db_type'], useUuid: boolean): string
101
+ {
102
+ let idPrismaType = 'String';
103
+
104
+ switch (dbType) {
105
+ case 'mysql':
106
+ if (useUuid) {
107
+ idPrismaType = 'String';
108
+ } else {
109
+ idPrismaType = 'Int';
110
+ }
111
+
112
+ break;
59
113
 
60
- if(modelMetadata.dbOptions?.mysql?.useUuid){
114
+ case 'postgresql':
115
+ case 'postgres':
116
+ if (useUuid) {
117
+ idPrismaType = 'String';
118
+ } else {
119
+ idPrismaType = 'Int';
120
+ }
121
+
122
+ break;
123
+
124
+ case 'sqlite':
125
+ if (useUuid) {
126
+ idPrismaType = 'String';
127
+ } else {
128
+ idPrismaType = 'Int';
129
+ }
130
+
131
+ break;
132
+ }
133
+
134
+ return idPrismaType;
135
+ }
136
+
137
+ static doesUseUuid(modelMeta: Record<string, { annotationType: string, metadata: IIdMetaOpts }>): boolean
138
+ {
139
+ let useUuid = false;
140
+
141
+ for (const key in modelMeta) {
142
+ const modelMetadata: IIdMetaOpts = modelMeta[key].metadata;
143
+ const annotationType: string = modelMeta[key].annotationType;
144
+
145
+ if (key !== 'id') {
146
+ if (annotationType == 'IdType') {
147
+ if (modelMetadata.dbOptions?.mysql?.useUuid) {
61
148
  useUuid = true;
62
149
  }
63
150
 
64
- if(modelMetadata.dbOptions?.postgres?.useUuid){
151
+ if (modelMetadata.dbOptions?.postgres?.useUuid) {
65
152
  useUuid = true;
66
153
  }
67
154
 
68
- if(modelMetadata.type.name === 'String'){
155
+ if (modelMetadata.type.name === 'String') {
69
156
  useUuid = true;
70
157
  }
71
158
  }
72
159
  }
73
160
  }
74
161
 
75
- let idString: string;
76
-
77
- let reqStr = '';
162
+ return useUuid;
163
+ }
78
164
 
79
- if(optional){
80
- reqStr = '?';
165
+ static addIdPart(dbType: IDbConfigParams['db_type'], useUuid: boolean, noAuto: boolean = false): string
166
+ {
167
+ let idString = ` @id${!noAuto ? ` @default(${this.generateIdDefault(dbType, useUuid)})` : ''}`;
168
+
169
+ if(dbType === 'mongodb'){
170
+ idString += ' @map("_id")';
171
+ idString += ' @db.ObjectId';
81
172
  }
82
173
 
174
+ return idString;
175
+ }
176
+
177
+ static generateIdDefault(dbType: IDbConfigParams['db_type'], useUuid: boolean): string
178
+ {
83
179
  switch (dbType) {
84
180
  case 'mongodb':
85
- idString = `${field} String${reqStr} @id @default(auto()) @map("_id") @db.ObjectId`;
86
- break;
181
+ return `auto()`;
87
182
 
88
183
  case 'mysql':
89
- idString = useUuid
90
- ? `${field} String${reqStr} @id @default(uuid())`
91
- : `${field} Int${reqStr} @id @default(autoincrement())`;
92
- break;
184
+ return useUuid
185
+ ? `uuid()`
186
+ : `autoincrement()`;
93
187
 
94
188
  case 'postgresql':
95
189
  case 'postgres':
96
- idString = useUuid
97
- ? `${field} String${reqStr} @id @default(uuid())`
98
- : `${field} Int${reqStr} @id @default(autoincrement())`;
99
- break;
190
+ return useUuid
191
+ ? `uuid()`
192
+ : `autoincrement()`;
100
193
 
101
194
  case 'sqlite':
102
- idString = `${field} Int${reqStr} @id @default(autoincrement())`;
103
- break;
104
- }
105
-
106
- if(tags.length){
107
- idString += ' '+tags.join(' ');
108
- }
109
-
110
- if(!idString){
111
- throw new Error(`DB type "${dbType}" is not supported!`);
195
+ return 'autoincrement()';
112
196
  }
113
-
114
-
115
- return idString;
116
197
  }
117
198
  }
118
199
 
@@ -1,4 +1,6 @@
1
1
  import { IDbOpts } from "./IDbOpts";
2
2
 
3
3
  export interface IIdTypeOpts extends IDbOpts {
4
+ unique?: boolean | string;
5
+ noAuto?: boolean;
4
6
  }
@@ -10,4 +10,5 @@ export interface ITrackerOpts extends IDbOpts {
10
10
  relatedTo?: OpModelType<any>,
11
11
  inversionModel?: OpModelType<any>,
12
12
  relationName?: string
13
+ noAuto?: boolean;
13
14
  }
@@ -6,9 +6,18 @@ export class ModelUtils {
6
6
  const annotationsData: Record<string, {annotationType: string, metadata: any}> = {};
7
7
 
8
8
  const metadataKeys = Reflect.getMetadataKeys(constructor.prototype);
9
+
10
+ const filteredMetaKeys = metadataKeys.filter((metaKey) => {
11
+ const [annotationType, annotatedField] = metaKey.split(':');
12
+ if(annotationType === 'TrackType' && annotatedField === 'id' && metadataKeys.includes('IdType:' + annotatedField)){
13
+ return false;
14
+ }
15
+
16
+ return true;
17
+ });
9
18
 
10
19
  // Process all metadata keys and collect promises
11
- const metadataPromises = metadataKeys.map(async (fullKey: string) => {
20
+ const metadataPromises = filteredMetaKeys.map(async (fullKey: string) => {
12
21
  const [annotationType, propertyKey] = fullKey.split(':');
13
22
  const metadata = Reflect.getMetadata(fullKey, constructor.prototype);
14
23
 
package/tsconfig.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "baseUrl": ".",
4
4
  "experimentalDecorators": true,
5
5
  "emitDecoratorMetadata": true,
6
- "target": "ES2018",
6
+ "target": "ES2022",
7
7
  "module": "commonjs",
8
8
  "moduleResolution": "node",
9
9
  "strict": true,