@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.
- package/dist/decorators/IdType.js +6 -0
- package/dist/decorators/InverseRelation.js +3 -4
- package/dist/decorators/Relation.js +4 -3
- package/dist/decorators/TrackType.js +2 -2
- package/dist/helper/DbHelper.d.ts +1 -1
- package/dist/helper/DbHelper.js +4 -4
- package/dist/helper/db/relation-manager.js +1 -1
- package/dist/helper/db/schema-generator.js +73 -26
- package/dist/helper/db/type-converter.d.ts +2 -1
- package/dist/helper/db/type-converter.js +33 -9
- package/dist/helper/db/utils.d.ts +7 -0
- package/dist/helper/db/utils.js +80 -26
- package/dist/models/core/RWSModel.js +29 -32
- package/dist/models/interfaces/IDbOpts.d.ts +3 -0
- package/dist/models/interfaces/IIdTypeOpts.d.ts +2 -0
- package/dist/models/interfaces/ITrackerOpts.d.ts +1 -0
- package/dist/models/utils/HydrateUtils.js +0 -1
- package/dist/models/utils/ModelUtils.js +8 -1
- package/dist/models/utils/PaginationUtils.js +5 -6
- package/dist/services/DBService.js +7 -8
- package/exec/console.js +0 -2
- package/package.json +1 -1
- package/src/decorators/IdType.ts +10 -1
- package/src/decorators/InverseRelation.ts +2 -2
- package/src/decorators/Relation.ts +6 -4
- package/src/helper/DbHelper.ts +1 -1
- package/src/helper/db/schema-generator.ts +104 -36
- package/src/helper/db/type-converter.ts +41 -8
- package/src/helper/db/utils.ts +114 -40
- package/src/models/interfaces/IDbOpts.ts +3 -0
- package/src/models/interfaces/IIdTypeOpts.ts +2 -0
- package/src/models/interfaces/ITrackerOpts.ts +1 -0
- package/src/models/utils/HydrateUtils.ts +0 -2
- package/src/models/utils/ModelUtils.ts +10 -1
- 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
|
-
|
|
114
|
-
const
|
|
115
|
-
const
|
|
116
|
-
const
|
|
117
|
-
const
|
|
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
|
-
|
|
235
|
-
const
|
|
236
|
-
const
|
|
237
|
-
const
|
|
238
|
-
const
|
|
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
|
-
|
|
251
|
-
const
|
|
252
|
-
const
|
|
253
|
-
const
|
|
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
|
-
|
|
266
|
-
const
|
|
267
|
-
const
|
|
268
|
-
const
|
|
269
|
-
const
|
|
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 =
|
|
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
|
}
|
|
@@ -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 =
|
|
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
|
-
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
package/src/decorators/IdType.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
68
|
-
|
|
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
|
|
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
|
|
41
|
-
|
|
42
|
+
relationOptions.relationName :
|
|
43
|
+
null
|
|
42
44
|
};
|
|
43
45
|
|
|
44
46
|
if(relationOptions.required){
|
package/src/helper/DbHelper.ts
CHANGED
|
@@ -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:
|
|
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
|
|
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 =
|
|
105
|
-
|
|
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}]
|
|
120
|
-
} else {
|
|
121
|
-
section += `\t${key} ${relatedModel._collection}${requiredString} @relation("${relationName}", fields: [${relationFieldName}], references: [${relatedToField}]
|
|
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
|
-
|
|
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}[]
|
|
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
|
|
206
|
+
} else {
|
|
184
207
|
const trackMeta = modelMetadata as ITrackerMetaOpts;
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
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(
|
|
213
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
304
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
|
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
|
-
}
|
|
89
|
-
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if(tag){
|
|
122
|
+
tags.push(tag);
|
|
90
123
|
}
|
|
91
124
|
|
|
92
125
|
if (metadata.dbOptions.mysql.useUuid && metadata.tags?.includes('id')) {
|