@rws-framework/db 2.1.7 → 2.1.9

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,9 @@ class DbHelper {
51
51
  fs_1.default.writeFileSync(schemaPath, template);
52
52
  process.env.DB_URL = dbUrl;
53
53
  const endPrisma = 'npx prisma';
54
+ const clientPath = path_1.default.join(console_1.rwsPath.findRootWorkspacePath(), 'node_modules', '.prisma', 'client');
54
55
  await console_1.rwsShell.runCommand(`${endPrisma} generate --schema=${schemaPath}`, process.cwd());
55
- // leaveFile = true;
56
+ leaveFile = true;
56
57
  log(chalk_1.default.green('[RWS Init]') + ' prisma schema generated from ', schemaPath);
57
58
  if (!leaveFile) {
58
59
  fs_1.default.unlinkSync(schemaPath);
@@ -60,6 +61,7 @@ class DbHelper {
60
61
  }
61
62
  }
62
63
  static async generateModelSections(model) {
64
+ var _a, _b;
63
65
  let section = '';
64
66
  const modelMetadatas = await _model_1.RWSModel.getModelAnnotations(model);
65
67
  const modelName = model._collection;
@@ -73,14 +75,30 @@ class DbHelper {
73
75
  continue;
74
76
  }
75
77
  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`;
78
+ const relationMeta = modelMetadata;
79
+ const relatedModel = relationMeta.relatedTo;
80
+ const isMany = relationMeta.many;
81
+ const cascadeOpts = [];
82
+ if ((_a = relationMeta.cascade) === null || _a === void 0 ? void 0 : _a.onDelete) {
83
+ cascadeOpts.push(`onDelete: ${relationMeta.cascade.onDelete}`);
84
+ }
85
+ if ((_b = relationMeta.cascade) === null || _b === void 0 ? void 0 : _b.onUpdate) {
86
+ cascadeOpts.push(`onUpdate: ${relationMeta.cascade.onUpdate}`);
87
+ }
88
+ if (isMany) {
89
+ // Handle many-to-many or one-to-many relation
90
+ section += `\t${key} ${relatedModel._collection}[] @relation("${modelName}_${relatedModel._collection}")\n`;
91
+ }
92
+ else {
93
+ // Handle one-to-one or many-to-one relation
94
+ section += `\t${key} ${relatedModel._collection}${requiredString} @relation("${modelName}_${relatedModel._collection}", fields: [${modelMetadata.relationField}], references: [${modelMetadata.relatedToField || 'id'}], ${cascadeOpts.join(', ')})\n`;
95
+ section += `\t${modelMetadata.relationField} String${requiredString} @db.ObjectId\n`;
96
+ }
80
97
  }
81
98
  else if (annotationType === 'InverseRelation') {
99
+ const relationMeta = modelMetadata;
82
100
  // Handle inverse relation (one-to-many or one-to-one)
83
- section += `\t${key} ${modelMetadata.inversionModel._collection}[] @relation("${modelMetadata.inversionModel._collection}_${modelName}")\n`;
101
+ section += `\t${key} ${relationMeta.inversionModel._collection}[] @relation("${relationMeta.relationName ? relationMeta.relationName : `${relationMeta.inversionModel._collection}_${modelName}`}")\n`;
84
102
  }
85
103
  else if (annotationType === 'InverseTimeSeries') {
86
104
  section += `\t${key} String[] @db.ObjectId\n`;
@@ -105,6 +123,9 @@ class DbHelper {
105
123
  if (input == 'Date') {
106
124
  return 'DateTime';
107
125
  }
126
+ if (input == 'Array') {
127
+ return 'Json';
128
+ }
108
129
  const firstChar = input.charAt(0).toUpperCase();
109
130
  const restOfString = input.slice(1);
110
131
  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.9",
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,11 @@ export class DbHelper {
65
67
  fs.writeFileSync(schemaPath, template);
66
68
  process.env.DB_URL = dbUrl;
67
69
  const endPrisma = 'npx prisma';
70
+
71
+ const clientPath = path.join(rwsPath.findRootWorkspacePath(), 'node_modules', '.prisma', 'client');
68
72
  await rwsShell.runCommand(`${endPrisma} generate --schema=${schemaPath}`, process.cwd());
69
73
 
70
- // leaveFile = true;
74
+ leaveFile = true;
71
75
  log(chalk.green('[RWS Init]') + ' prisma schema generated from ', schemaPath);
72
76
 
73
77
  if(!leaveFile){
@@ -86,22 +90,43 @@ export class DbHelper {
86
90
  section += '\tid String @map("_id") @id @default(auto()) @db.ObjectId\n';
87
91
 
88
92
  for (const key in modelMetadatas) {
89
- const modelMetadata: IMetaOpts = modelMetadatas[key].metadata;
93
+ const modelMetadata = modelMetadatas[key].metadata;
90
94
  const requiredString = modelMetadata.required ? '' : '?';
91
95
  const annotationType: string = modelMetadatas[key].annotationType;
92
96
 
93
97
  if(key === 'id'){
94
98
  continue;
95
99
  }
100
+
96
101
 
97
102
  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'){
103
+ const relationMeta = modelMetadata as IRelationOpts
104
+
105
+ const relatedModel = relationMeta.relatedTo as OpModelType<any>;
106
+ const isMany = relationMeta.many;
107
+ const cascadeOpts = [];
108
+
109
+ if (relationMeta.cascade?.onDelete) {
110
+ cascadeOpts.push(`onDelete: ${relationMeta.cascade.onDelete}`);
111
+ }
112
+
113
+ if (relationMeta.cascade?.onUpdate) {
114
+ cascadeOpts.push(`onUpdate: ${relationMeta.cascade.onUpdate}`);
115
+ }
116
+
117
+ if (isMany) {
118
+ // Handle many-to-many or one-to-many relation
119
+ section += `\t${key} ${relatedModel._collection}[] @relation("${modelName}_${relatedModel._collection}")\n`;
120
+ } else {
121
+ // Handle one-to-one or many-to-one relation
122
+ section += `\t${key} ${relatedModel._collection}${requiredString} @relation("${modelName}_${relatedModel._collection}", fields: [${modelMetadata.relationField}], references: [${modelMetadata.relatedToField || 'id'}], ${cascadeOpts.join(', ')})\n`;
123
+ section += `\t${modelMetadata.relationField} String${requiredString} @db.ObjectId\n`;
124
+ }
125
+ } else if (annotationType === 'InverseRelation'){
126
+ const relationMeta = modelMetadata as InverseRelationOpts;
127
+
103
128
  // Handle inverse relation (one-to-many or one-to-one)
104
- section += `\t${key} ${modelMetadata.inversionModel._collection}[] @relation("${modelMetadata.inversionModel._collection}_${modelName}")\n`;
129
+ section += `\t${key} ${relationMeta.inversionModel._collection}[] @relation("${ relationMeta.relationName ? relationMeta.relationName : `${relationMeta.inversionModel._collection}_${modelName}`}")\n`;
105
130
  } else if (annotationType === 'InverseTimeSeries'){
106
131
  section += `\t${key} String[] @db.ObjectId\n`;
107
132
  } else if (annotationType === 'TrackType'){
@@ -129,6 +154,10 @@ export class DbHelper {
129
154
  if(input == 'Date'){
130
155
  return 'DateTime';
131
156
  }
157
+
158
+ if(input == 'Array'){
159
+ return 'Json';
160
+ }
132
161
 
133
162
 
134
163
  const firstChar = input.charAt(0).toUpperCase();