@rws-framework/db 2.1.7 → 2.1.8
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/InverseRelation.d.ts +3 -1
- package/dist/decorators/InverseRelation.js +3 -3
- package/dist/decorators/Relation.d.ts +10 -3
- package/dist/decorators/Relation.js +9 -9
- package/dist/helper/DbHelper.js +33 -8
- package/package.json +1 -1
- package/src/decorators/InverseRelation.ts +7 -5
- package/src/decorators/Relation.ts +21 -10
- package/src/helper/DbHelper.ts +43 -10
|
@@ -4,7 +4,9 @@ interface InverseRelationOpts {
|
|
|
4
4
|
key: string;
|
|
5
5
|
inversionModel: OpModelType<RWSModel<any>>;
|
|
6
6
|
foreignKey: string;
|
|
7
|
+
singular?: boolean;
|
|
8
|
+
relationName?: string;
|
|
7
9
|
}
|
|
8
|
-
declare function InverseRelation(inversionModel: () => OpModelType<RWSModel<any>>, sourceModel: () => OpModelType<RWSModel<any>>,
|
|
10
|
+
declare function InverseRelation(inversionModel: () => OpModelType<RWSModel<any>>, sourceModel: () => OpModelType<RWSModel<any>>, relationOptions?: Partial<InverseRelationOpts>): (target: any, key: string) => void;
|
|
9
11
|
export default InverseRelation;
|
|
10
12
|
export { InverseRelationOpts };
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
require("reflect-metadata");
|
|
4
|
-
function InverseRelation(inversionModel, sourceModel,
|
|
4
|
+
function InverseRelation(inversionModel, sourceModel, relationOptions = null) {
|
|
5
5
|
return function (target, key) {
|
|
6
|
-
// Store the promise in metadata immediately
|
|
7
6
|
const metadataPromise = Promise.resolve().then(() => {
|
|
8
7
|
const model = inversionModel();
|
|
9
8
|
const source = sourceModel();
|
|
10
9
|
const metaOpts = {
|
|
10
|
+
...relationOptions,
|
|
11
11
|
key,
|
|
12
12
|
inversionModel: model,
|
|
13
|
-
foreignKey: foreignKey ? foreignKey : `${source._collection}_id`
|
|
13
|
+
foreignKey: relationOptions && relationOptions.foreignKey ? relationOptions.foreignKey : `${source._collection}_id`
|
|
14
14
|
};
|
|
15
15
|
return metaOpts;
|
|
16
16
|
});
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
2
|
import { RWSModel, OpModelType } from '../models/_model';
|
|
3
|
+
type CascadingSetup = 'Cascade' | 'Restrict' | 'NoAction' | 'SetNull';
|
|
3
4
|
interface IRelationOpts {
|
|
4
5
|
required?: boolean;
|
|
5
|
-
key
|
|
6
|
-
relationField
|
|
6
|
+
key: string;
|
|
7
|
+
relationField: string;
|
|
7
8
|
relatedToField?: string;
|
|
8
9
|
relatedTo: OpModelType<RWSModel<any>>;
|
|
10
|
+
many?: boolean;
|
|
11
|
+
embed?: boolean;
|
|
12
|
+
cascade: {
|
|
13
|
+
onDelete: CascadingSetup;
|
|
14
|
+
onUpdate: CascadingSetup;
|
|
15
|
+
};
|
|
9
16
|
}
|
|
10
|
-
declare function Relation(theModel: () => OpModelType<RWSModel<any>>,
|
|
17
|
+
declare function Relation(theModel: () => OpModelType<RWSModel<any>>, relationOptions?: Partial<IRelationOpts>): (target: any, key: string) => void;
|
|
11
18
|
export default Relation;
|
|
12
19
|
export { IRelationOpts };
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
require("reflect-metadata");
|
|
4
|
-
|
|
4
|
+
const _DEFAULTS = { required: false, many: false, embed: false, cascade: { onDelete: 'SetNull', onUpdate: 'Cascade' } };
|
|
5
|
+
function Relation(theModel, relationOptions = _DEFAULTS) {
|
|
5
6
|
return function (target, key) {
|
|
6
7
|
// Store the promise in metadata immediately
|
|
7
8
|
const metadataPromise = Promise.resolve().then(() => {
|
|
8
9
|
const relatedTo = theModel();
|
|
9
|
-
const metaOpts = {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
metaOpts.key = key;
|
|
10
|
+
const metaOpts = {
|
|
11
|
+
...relationOptions,
|
|
12
|
+
cascade: relationOptions.cascade || _DEFAULTS.cascade,
|
|
13
|
+
relatedTo,
|
|
14
|
+
relationField: relationOptions.relationField ? relationOptions.relationField : relatedTo._collection + '_id',
|
|
15
|
+
key
|
|
16
|
+
};
|
|
17
17
|
return metaOpts;
|
|
18
18
|
});
|
|
19
19
|
// Store both the promise and the key information
|
package/dist/helper/DbHelper.js
CHANGED
|
@@ -29,7 +29,7 @@ class DbHelper {
|
|
|
29
29
|
for (const model of dbModels) {
|
|
30
30
|
const modelSection = await DbHelper.generateModelSections(model);
|
|
31
31
|
template += '\n\n' + modelSection;
|
|
32
|
-
log('RWS
|
|
32
|
+
log(chalk_1.default.green('[RWS]'), chalk_1.default.blue('Building DB Model'), model.name);
|
|
33
33
|
if (_model_1.RWSModel.isSubclass(model, TimeSeriesModel_1.default)) {
|
|
34
34
|
dbService.collectionExists(model._collection).then((exists) => {
|
|
35
35
|
if (exists) {
|
|
@@ -51,8 +51,13 @@ class DbHelper {
|
|
|
51
51
|
fs_1.default.writeFileSync(schemaPath, template);
|
|
52
52
|
process.env.DB_URL = dbUrl;
|
|
53
53
|
const endPrisma = 'npx prisma';
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
const clientPath = path_1.default.join(console_1.rwsPath.findRootWorkspacePath(), 'node_modules', '.prisma', 'client');
|
|
55
|
+
await console_1.rwsShell.runCommand(`${endPrisma} generate --schema=${schemaPath}`, process.cwd(), false, {
|
|
56
|
+
env: {
|
|
57
|
+
PRISMA_CLIENT_OUTPUT: clientPath
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
leaveFile = true;
|
|
56
61
|
log(chalk_1.default.green('[RWS Init]') + ' prisma schema generated from ', schemaPath);
|
|
57
62
|
if (!leaveFile) {
|
|
58
63
|
fs_1.default.unlinkSync(schemaPath);
|
|
@@ -60,6 +65,7 @@ class DbHelper {
|
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
static async generateModelSections(model) {
|
|
68
|
+
var _a, _b;
|
|
63
69
|
let section = '';
|
|
64
70
|
const modelMetadatas = await _model_1.RWSModel.getModelAnnotations(model);
|
|
65
71
|
const modelName = model._collection;
|
|
@@ -73,14 +79,30 @@ class DbHelper {
|
|
|
73
79
|
continue;
|
|
74
80
|
}
|
|
75
81
|
if (annotationType === 'Relation') {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
const relationMeta = modelMetadata;
|
|
83
|
+
const relatedModel = relationMeta.relatedTo;
|
|
84
|
+
const isMany = relationMeta.many;
|
|
85
|
+
const cascadeOpts = [];
|
|
86
|
+
if ((_a = relationMeta.cascade) === null || _a === void 0 ? void 0 : _a.onDelete) {
|
|
87
|
+
cascadeOpts.push(`onDelete: ${relationMeta.cascade.onDelete}`);
|
|
88
|
+
}
|
|
89
|
+
if ((_b = relationMeta.cascade) === null || _b === void 0 ? void 0 : _b.onUpdate) {
|
|
90
|
+
cascadeOpts.push(`onUpdate: ${relationMeta.cascade.onUpdate}`);
|
|
91
|
+
}
|
|
92
|
+
if (isMany) {
|
|
93
|
+
// Handle many-to-many or one-to-many relation
|
|
94
|
+
section += `\t${key} ${relatedModel._collection}[] @relation("${modelName}_${relatedModel._collection}")\n`;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// Handle one-to-one or many-to-one relation
|
|
98
|
+
section += `\t${key} ${relatedModel._collection}${requiredString} @relation("${modelName}_${relatedModel._collection}", fields: [${modelMetadata.relationField}], references: [${modelMetadata.relatedToField || 'id'}], ${cascadeOpts.join(', ')})\n`;
|
|
99
|
+
section += `\t${modelMetadata.relationField} String${requiredString} @db.ObjectId\n`;
|
|
100
|
+
}
|
|
80
101
|
}
|
|
81
102
|
else if (annotationType === 'InverseRelation') {
|
|
103
|
+
const relationMeta = modelMetadata;
|
|
82
104
|
// Handle inverse relation (one-to-many or one-to-one)
|
|
83
|
-
section += `\t${key} ${
|
|
105
|
+
section += `\t${key} ${relationMeta.inversionModel._collection}[] @relation("${relationMeta.relationName ? relationMeta.relationName : `${relationMeta.inversionModel._collection}_${modelName}`}")\n`;
|
|
84
106
|
}
|
|
85
107
|
else if (annotationType === 'InverseTimeSeries') {
|
|
86
108
|
section += `\t${key} String[] @db.ObjectId\n`;
|
|
@@ -105,6 +127,9 @@ class DbHelper {
|
|
|
105
127
|
if (input == 'Date') {
|
|
106
128
|
return 'DateTime';
|
|
107
129
|
}
|
|
130
|
+
if (input == 'Array') {
|
|
131
|
+
return 'Json';
|
|
132
|
+
}
|
|
108
133
|
const firstChar = input.charAt(0).toUpperCase();
|
|
109
134
|
const restOfString = input.slice(1);
|
|
110
135
|
return firstChar + restOfString;
|
package/package.json
CHANGED
|
@@ -4,20 +4,22 @@ import { RWSModel, OpModelType } from '../models/_model';
|
|
|
4
4
|
interface InverseRelationOpts{
|
|
5
5
|
key: string,
|
|
6
6
|
inversionModel: OpModelType<RWSModel<any>>,
|
|
7
|
-
foreignKey: string
|
|
7
|
+
foreignKey: string,
|
|
8
|
+
singular?: boolean
|
|
9
|
+
relationName?: string
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
function InverseRelation(inversionModel: () => OpModelType<RWSModel<any>>, sourceModel: () => OpModelType<RWSModel<any>>,
|
|
11
|
-
return function(target: any, key: string) {
|
|
12
|
-
// Store the promise in metadata immediately
|
|
12
|
+
function InverseRelation(inversionModel: () => OpModelType<RWSModel<any>>, sourceModel: () => OpModelType<RWSModel<any>>, relationOptions: Partial<InverseRelationOpts> = null) {
|
|
13
|
+
return function(target: any, key: string) {
|
|
13
14
|
const metadataPromise = Promise.resolve().then(() => {
|
|
14
15
|
const model = inversionModel();
|
|
15
16
|
const source = sourceModel();
|
|
16
17
|
|
|
17
18
|
const metaOpts: InverseRelationOpts = {
|
|
19
|
+
...relationOptions,
|
|
18
20
|
key,
|
|
19
21
|
inversionModel: model,
|
|
20
|
-
foreignKey: foreignKey ? foreignKey : `${source._collection}_id`
|
|
22
|
+
foreignKey: relationOptions && relationOptions.foreignKey ? relationOptions.foreignKey : `${source._collection}_id`
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
return metaOpts;
|
|
@@ -1,26 +1,37 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
2
|
import { RWSModel, OpModelType } from '../models/_model';
|
|
3
3
|
|
|
4
|
+
type CascadingSetup = 'Cascade' | 'Restrict' | 'NoAction' | 'SetNull';
|
|
5
|
+
|
|
4
6
|
interface IRelationOpts {
|
|
5
7
|
required?: boolean
|
|
6
|
-
key
|
|
7
|
-
relationField
|
|
8
|
+
key: string
|
|
9
|
+
relationField: string
|
|
8
10
|
relatedToField?: string
|
|
9
11
|
relatedTo: OpModelType<RWSModel<any>>
|
|
12
|
+
many?: boolean
|
|
13
|
+
embed?: boolean
|
|
14
|
+
cascade: {
|
|
15
|
+
onDelete: CascadingSetup,
|
|
16
|
+
onUpdate: CascadingSetup
|
|
17
|
+
}
|
|
10
18
|
}
|
|
19
|
+
|
|
20
|
+
const _DEFAULTS: Partial<IRelationOpts> = { required: false, many: false, embed: false, cascade: { onDelete: 'SetNull', onUpdate: 'Cascade' }};
|
|
11
21
|
|
|
12
|
-
function Relation(theModel: () => OpModelType<RWSModel<any>>,
|
|
22
|
+
function Relation(theModel: () => OpModelType<RWSModel<any>>, relationOptions: Partial<IRelationOpts> = _DEFAULTS) {
|
|
13
23
|
return function(target: any, key: string) {
|
|
14
24
|
// Store the promise in metadata immediately
|
|
15
25
|
const metadataPromise = Promise.resolve().then(() => {
|
|
16
26
|
const relatedTo = theModel();
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
|
|
28
|
+
const metaOpts: IRelationOpts = {
|
|
29
|
+
...relationOptions,
|
|
30
|
+
cascade: relationOptions.cascade || _DEFAULTS.cascade,
|
|
31
|
+
relatedTo,
|
|
32
|
+
relationField: relationOptions.relationField ? relationOptions.relationField : relatedTo._collection + '_id',
|
|
33
|
+
key
|
|
34
|
+
};
|
|
24
35
|
return metaOpts;
|
|
25
36
|
});
|
|
26
37
|
|
package/src/helper/DbHelper.ts
CHANGED
|
@@ -7,6 +7,8 @@ import { IDbConfigHandler } from '../types/DbConfigHandler';
|
|
|
7
7
|
import { IMetaOpts, OpModelType, RWSModel } from '../models/_model';
|
|
8
8
|
import TimeSeriesModel from '../models/TimeSeriesModel';
|
|
9
9
|
import { DBService } from '../services/DBService';
|
|
10
|
+
import { IRelationOpts } from '../decorators/Relation';
|
|
11
|
+
import { InverseRelationOpts } from '../decorators/InverseRelation';
|
|
10
12
|
|
|
11
13
|
const log = console.log;
|
|
12
14
|
const workspaceRoot = rwsPath.findRootWorkspacePath();
|
|
@@ -36,7 +38,7 @@ export class DbHelper {
|
|
|
36
38
|
|
|
37
39
|
template += '\n\n' + modelSection;
|
|
38
40
|
|
|
39
|
-
log('RWS
|
|
41
|
+
log(chalk.green('[RWS]'), chalk.blue('Building DB Model'), model.name);
|
|
40
42
|
|
|
41
43
|
if(RWSModel.isSubclass(model as any, TimeSeriesModel)){
|
|
42
44
|
dbService.collectionExists(model._collection).then((exists: boolean) => {
|
|
@@ -65,9 +67,15 @@ export class DbHelper {
|
|
|
65
67
|
fs.writeFileSync(schemaPath, template);
|
|
66
68
|
process.env.DB_URL = dbUrl;
|
|
67
69
|
const endPrisma = 'npx prisma';
|
|
68
|
-
await rwsShell.runCommand(`${endPrisma} generate --schema=${schemaPath}`, process.cwd());
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
const clientPath = path.join(rwsPath.findRootWorkspacePath(), 'node_modules', '.prisma', 'client');
|
|
72
|
+
await rwsShell.runCommand(`${endPrisma} generate --schema=${schemaPath}`, process.cwd(), false, {
|
|
73
|
+
env: {
|
|
74
|
+
PRISMA_CLIENT_OUTPUT: clientPath
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
leaveFile = true;
|
|
71
79
|
log(chalk.green('[RWS Init]') + ' prisma schema generated from ', schemaPath);
|
|
72
80
|
|
|
73
81
|
if(!leaveFile){
|
|
@@ -86,22 +94,43 @@ export class DbHelper {
|
|
|
86
94
|
section += '\tid String @map("_id") @id @default(auto()) @db.ObjectId\n';
|
|
87
95
|
|
|
88
96
|
for (const key in modelMetadatas) {
|
|
89
|
-
const modelMetadata
|
|
97
|
+
const modelMetadata = modelMetadatas[key].metadata;
|
|
90
98
|
const requiredString = modelMetadata.required ? '' : '?';
|
|
91
99
|
const annotationType: string = modelMetadatas[key].annotationType;
|
|
92
100
|
|
|
93
101
|
if(key === 'id'){
|
|
94
102
|
continue;
|
|
95
103
|
}
|
|
104
|
+
|
|
96
105
|
|
|
97
106
|
if(annotationType === 'Relation'){
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
107
|
+
const relationMeta = modelMetadata as IRelationOpts
|
|
108
|
+
|
|
109
|
+
const relatedModel = relationMeta.relatedTo as OpModelType<any>;
|
|
110
|
+
const isMany = relationMeta.many;
|
|
111
|
+
const cascadeOpts = [];
|
|
112
|
+
|
|
113
|
+
if (relationMeta.cascade?.onDelete) {
|
|
114
|
+
cascadeOpts.push(`onDelete: ${relationMeta.cascade.onDelete}`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (relationMeta.cascade?.onUpdate) {
|
|
118
|
+
cascadeOpts.push(`onUpdate: ${relationMeta.cascade.onUpdate}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (isMany) {
|
|
122
|
+
// Handle many-to-many or one-to-many relation
|
|
123
|
+
section += `\t${key} ${relatedModel._collection}[] @relation("${modelName}_${relatedModel._collection}")\n`;
|
|
124
|
+
} else {
|
|
125
|
+
// Handle one-to-one or many-to-one relation
|
|
126
|
+
section += `\t${key} ${relatedModel._collection}${requiredString} @relation("${modelName}_${relatedModel._collection}", fields: [${modelMetadata.relationField}], references: [${modelMetadata.relatedToField || 'id'}], ${cascadeOpts.join(', ')})\n`;
|
|
127
|
+
section += `\t${modelMetadata.relationField} String${requiredString} @db.ObjectId\n`;
|
|
128
|
+
}
|
|
129
|
+
} else if (annotationType === 'InverseRelation'){
|
|
130
|
+
const relationMeta = modelMetadata as InverseRelationOpts;
|
|
131
|
+
|
|
103
132
|
// Handle inverse relation (one-to-many or one-to-one)
|
|
104
|
-
section += `\t${key} ${
|
|
133
|
+
section += `\t${key} ${relationMeta.inversionModel._collection}[] @relation("${ relationMeta.relationName ? relationMeta.relationName : `${relationMeta.inversionModel._collection}_${modelName}`}")\n`;
|
|
105
134
|
} else if (annotationType === 'InverseTimeSeries'){
|
|
106
135
|
section += `\t${key} String[] @db.ObjectId\n`;
|
|
107
136
|
} else if (annotationType === 'TrackType'){
|
|
@@ -129,6 +158,10 @@ export class DbHelper {
|
|
|
129
158
|
if(input == 'Date'){
|
|
130
159
|
return 'DateTime';
|
|
131
160
|
}
|
|
161
|
+
|
|
162
|
+
if(input == 'Array'){
|
|
163
|
+
return 'Json';
|
|
164
|
+
}
|
|
132
165
|
|
|
133
166
|
|
|
134
167
|
const firstChar = input.charAt(0).toUpperCase();
|