@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.
@@ -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>>, foreignKey?: string): (target: any, key: string) => void;
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, foreignKey = null) {
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?: string;
6
- relationField?: string;
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>>, required?: boolean, relationField?: string, relatedToField?: string): (target: any, key: string) => void;
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
- function Relation(theModel, required = false, relationField = null, relatedToField = 'id') {
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 = { required, relatedTo, relatedToField };
10
- if (!relationField) {
11
- metaOpts.relationField = relatedTo._collection + '_id';
12
- }
13
- else {
14
- metaOpts.relationField = relationField;
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
@@ -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 SCHEMA BUILD', chalk_1.default.blue('Building DB Model'), model.name);
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
- await console_1.rwsShell.runCommand(`${endPrisma} generate --schema=${schemaPath}`, process.cwd());
55
- // leaveFile = true;
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 relatedModel = modelMetadata.relatedTo;
77
- // Handle direct relation (many-to-one or one-to-one)
78
- section += `\t${key} ${relatedModel._collection}${requiredString} @relation("${modelName}_${relatedModel._collection}", fields: [${modelMetadata.relationField}], references: [${modelMetadata.relatedToField}], onDelete: Cascade)\n`;
79
- section += `\t${modelMetadata.relationField} String${requiredString} @db.ObjectId\n`;
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} ${modelMetadata.inversionModel._collection}[] @relation("${modelMetadata.inversionModel._collection}_${modelName}")\n`;
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rws-framework/db",
3
3
  "private": false,
4
- "version": "2.1.7",
4
+ "version": "2.1.8",
5
5
  "description": "",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -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>>, foreignKey: string = null) {
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?: string
7
- relationField?: string
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>>, required: boolean = false, relationField: string = null, relatedToField: string = 'id') {
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
- const metaOpts: IRelationOpts = {required, relatedTo, relatedToField};
18
- if(!relationField){
19
- metaOpts.relationField = relatedTo._collection + '_id';
20
- } else{
21
- metaOpts.relationField = relationField;
22
- }
23
- metaOpts.key = key;
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
 
@@ -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 SCHEMA BUILD', chalk.blue('Building DB Model'), model.name);
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
- // leaveFile = true;
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: IMetaOpts = modelMetadatas[key].metadata;
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 relatedModel = modelMetadata.relatedTo as OpModelType<any>;
99
- // Handle direct relation (many-to-one or one-to-one)
100
- section += `\t${key} ${relatedModel._collection}${requiredString} @relation("${modelName}_${relatedModel._collection}", fields: [${modelMetadata.relationField}], references: [${modelMetadata.relatedToField}], onDelete: Cascade)\n`;
101
- section += `\t${modelMetadata.relationField} String${requiredString} @db.ObjectId\n`;
102
- } else if (annotationType === 'InverseRelation'){
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} ${modelMetadata.inversionModel._collection}[] @relation("${modelMetadata.inversionModel._collection}_${modelName}")\n`;
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();