@rws-framework/db 3.3.7 → 3.3.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/helper/db/schema-generator.js +19 -8
- package/dist/models/interfaces/ITrackerOpts.d.ts +2 -0
- package/dist/models/types/RelationTypes.d.ts +1 -0
- package/dist/models/utils/HydrateUtils.js +16 -6
- package/dist/models/utils/RelationUtils.js +2 -1
- package/package.json +1 -1
- package/src/decorators/InverseRelation.ts +1 -1
- package/src/helper/db/schema-generator.ts +24 -9
- package/src/models/interfaces/ITrackerOpts.ts +3 -1
- package/src/models/types/RelationTypes.ts +2 -1
- package/src/models/utils/HydrateUtils.ts +16 -7
- package/src/models/utils/RelationUtils.ts +2 -1
|
@@ -93,10 +93,16 @@ datasource db {
|
|
|
93
93
|
const relationFieldName = modelMetadata.relationField ? modelMetadata.relationField : key.toLowerCase() + '_' + modelMetadata.relationField.toLowerCase();
|
|
94
94
|
const relatedToField = modelMetadata.relatedToField || 'id';
|
|
95
95
|
const bindingFieldExists = !!modelMetadatas[relationFieldName];
|
|
96
|
+
const relatedFieldMeta = relatedModelMetadatas[relatedToField];
|
|
97
|
+
const foundInverseRelation = Object.values(relatedModelMetadatas).find(item => item.metadata.foreignKey === relationFieldName && item.metadata.inversionModel._collection === modelName);
|
|
96
98
|
if (modelMetadata.required === false) {
|
|
97
99
|
requiredString = '?';
|
|
98
100
|
}
|
|
99
|
-
|
|
101
|
+
let cascadeStr = cascadeOpts.length ? `, ${cascadeOpts.join(', ')}` : '';
|
|
102
|
+
if (foundInverseRelation && foundInverseRelation.metadata.singular) {
|
|
103
|
+
cascadeStr = '';
|
|
104
|
+
requiredString = '?';
|
|
105
|
+
}
|
|
100
106
|
if (isMany) {
|
|
101
107
|
// Add an inverse field to the related model if it doesn't exist
|
|
102
108
|
section += `\t${key} ${relatedModel._collection}[] @relation(${relationName ? `"${relationName}", ` : ''}fields: [${relationFieldName}], references: [${relatedToField}]${mapName ? `, map: "${mapName}"` : ''}${cascadeStr})\n`;
|
|
@@ -104,7 +110,6 @@ datasource db {
|
|
|
104
110
|
else {
|
|
105
111
|
section += `\t${key} ${relatedModel._collection}${requiredString} @relation(${relationName ? `"${relationName}", ` : ''}fields: [${relationFieldName}], references: [${relatedToField}]${mapName ? `, map: "${mapName}"` : ''}${cascadeStr})\n`;
|
|
106
112
|
if (!bindingFieldExists) {
|
|
107
|
-
const relatedFieldMeta = relatedModelMetadatas[relatedToField];
|
|
108
113
|
if (!relatedFieldMeta.metadata.required) {
|
|
109
114
|
requiredString = '';
|
|
110
115
|
}
|
|
@@ -113,24 +118,29 @@ datasource db {
|
|
|
113
118
|
if (relationMeta.required === false) {
|
|
114
119
|
requiredString = '?';
|
|
115
120
|
}
|
|
121
|
+
let appendix = '';
|
|
122
|
+
if (foundInverseRelation && foundInverseRelation.metadata.singular) {
|
|
123
|
+
appendix = ' @unique';
|
|
124
|
+
requiredString = '?';
|
|
125
|
+
}
|
|
116
126
|
// Add relation field with appropriate type based on database
|
|
117
127
|
if (dbType === 'mongodb') {
|
|
118
|
-
section += `\t${relationFieldName} String${requiredString} @db.ObjectId\n`;
|
|
128
|
+
section += `\t${relationFieldName} String${requiredString} @db.ObjectId${appendix}\n`;
|
|
119
129
|
}
|
|
120
130
|
else if (dbType === 'mysql') {
|
|
121
131
|
// For MySQL, determine the type based on the related model's ID type
|
|
122
|
-
section += `\t${relationFieldName} ${relatedFieldType}${requiredString}\n`;
|
|
132
|
+
section += `\t${relationFieldName} ${relatedFieldType}${requiredString}${appendix}\n`;
|
|
123
133
|
}
|
|
124
134
|
else if (dbType === 'postgresql' || dbType === 'postgres') {
|
|
125
135
|
if (relatedFieldType === 'String') {
|
|
126
|
-
section += `\t${relationFieldName} ${relatedFieldType}${requiredString} @db.Uuid\n`;
|
|
136
|
+
section += `\t${relationFieldName} ${relatedFieldType}${requiredString} @db.Uuid${appendix}\n`;
|
|
127
137
|
}
|
|
128
138
|
else {
|
|
129
|
-
section += `\t${relationFieldName} ${relatedFieldType}${requiredString}\n`;
|
|
139
|
+
section += `\t${relationFieldName} ${relatedFieldType}${requiredString}${appendix}\n`;
|
|
130
140
|
}
|
|
131
141
|
}
|
|
132
142
|
else {
|
|
133
|
-
section += `\t${relationFieldName} String${requiredString}\n`;
|
|
143
|
+
section += `\t${relationFieldName} String${requiredString}${appendix}\n`;
|
|
134
144
|
}
|
|
135
145
|
}
|
|
136
146
|
}
|
|
@@ -145,11 +155,12 @@ datasource db {
|
|
|
145
155
|
const relationKey = [relatedModelName, modelName].join('_');
|
|
146
156
|
const relationIndex = relation_manager_1.RelationManager.getRelationCounter(relationKey, true);
|
|
147
157
|
const relationName = relation_manager_1.RelationManager.getShortenedRelationName(relatedModelName, modelName, relationIndex);
|
|
158
|
+
const singular = relationMeta.singular;
|
|
148
159
|
let relationTag = '';
|
|
149
160
|
if (relationMeta.relationName) {
|
|
150
161
|
relationTag = ` @relation("${relationMeta.relationName}")`;
|
|
151
162
|
}
|
|
152
|
-
section += `\t${key} ${relationMeta.inversionModel._collection}[]${relationTag}\n`;
|
|
163
|
+
section += `\t${key} ${relationMeta.inversionModel._collection}${singular ? '?' : '[]'}${relationTag}\n`;
|
|
153
164
|
relation_manager_1.RelationManager.completeRelation(relationKey, relationIndex, true);
|
|
154
165
|
}
|
|
155
166
|
else if (annotationType === 'InverseTimeSeries') {
|
|
@@ -48,12 +48,22 @@ class HydrateUtils {
|
|
|
48
48
|
const relationEnabled = !RelationUtils_1.RelationUtils.checkRelDisabled(model, relMeta.key);
|
|
49
49
|
if (relationEnabled) {
|
|
50
50
|
const pk = ModelUtils_1.ModelUtils.findPrimaryKeyFields(model.constructor);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
if (relMeta.singular) {
|
|
52
|
+
model[relMeta.key] = await relMeta.inversionModel.findOneBy({
|
|
53
|
+
conditions: {
|
|
54
|
+
[relMeta.foreignKey]: data[pk]
|
|
55
|
+
},
|
|
56
|
+
allowRelations: false
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
model[relMeta.key] = await relMeta.inversionModel.findBy({
|
|
61
|
+
conditions: {
|
|
62
|
+
[relMeta.foreignKey]: data[pk]
|
|
63
|
+
},
|
|
64
|
+
allowRelations: false
|
|
65
|
+
});
|
|
66
|
+
}
|
|
57
67
|
}
|
|
58
68
|
}
|
|
59
69
|
// Handle one-to-one relations
|
|
@@ -39,7 +39,8 @@ class RelationUtils {
|
|
|
39
39
|
relIds[key] = {
|
|
40
40
|
key: resolvedMetadata.key,
|
|
41
41
|
inversionModel: resolvedMetadata.inversionModel,
|
|
42
|
-
foreignKey: resolvedMetadata.foreignKey
|
|
42
|
+
foreignKey: resolvedMetadata.foreignKey,
|
|
43
|
+
singular: resolvedMetadata?.singular || false
|
|
43
44
|
};
|
|
44
45
|
}
|
|
45
46
|
}
|
package/package.json
CHANGED
|
@@ -59,7 +59,7 @@ function InverseRelation(inversionModel: () => OpModelType<RWSModel<any>>, sourc
|
|
|
59
59
|
|
|
60
60
|
const metaOpts: InverseRelationOpts = {
|
|
61
61
|
...relationOptions,
|
|
62
|
-
key,
|
|
62
|
+
key,
|
|
63
63
|
inversionModel: model,
|
|
64
64
|
foreignKey: relationOptions && relationOptions.foreignKey ? relationOptions.foreignKey : guessForeignKey(model, source, decoratorsData),
|
|
65
65
|
// Generate a unique relation name if one is not provided
|
|
@@ -125,12 +125,20 @@ datasource db {
|
|
|
125
125
|
|
|
126
126
|
const relatedToField = modelMetadata.relatedToField || 'id';
|
|
127
127
|
const bindingFieldExists = !!modelMetadatas[relationFieldName];
|
|
128
|
-
|
|
128
|
+
const relatedFieldMeta = relatedModelMetadatas[relatedToField];
|
|
129
|
+
|
|
130
|
+
const foundInverseRelation = Object.values(relatedModelMetadatas).find(item => item.metadata.foreignKey === relationFieldName && item.metadata.inversionModel._collection === modelName);
|
|
131
|
+
|
|
129
132
|
if(modelMetadata.required === false){
|
|
130
133
|
requiredString = '?';
|
|
131
134
|
}
|
|
132
135
|
|
|
133
|
-
|
|
136
|
+
let cascadeStr = cascadeOpts.length ? `, ${cascadeOpts.join(', ')}` : '' ;
|
|
137
|
+
|
|
138
|
+
if(foundInverseRelation && foundInverseRelation.metadata.singular){
|
|
139
|
+
cascadeStr = '';
|
|
140
|
+
requiredString = '?';
|
|
141
|
+
}
|
|
134
142
|
|
|
135
143
|
if (isMany) {
|
|
136
144
|
// Add an inverse field to the related model if it doesn't exist
|
|
@@ -138,7 +146,6 @@ datasource db {
|
|
|
138
146
|
} else {
|
|
139
147
|
section += `\t${key} ${relatedModel._collection}${requiredString} @relation(${relationName ? `"${relationName}", ` : ''}fields: [${relationFieldName}], references: [${relatedToField}]${mapName ? `, map: "${mapName}"` : ''}${cascadeStr})\n`;
|
|
140
148
|
if(!bindingFieldExists){
|
|
141
|
-
const relatedFieldMeta = relatedModelMetadatas[relatedToField];
|
|
142
149
|
|
|
143
150
|
if(!relatedFieldMeta.metadata.required){
|
|
144
151
|
requiredString = '';
|
|
@@ -150,21 +157,28 @@ datasource db {
|
|
|
150
157
|
if(relationMeta.required === false){
|
|
151
158
|
requiredString = '?';
|
|
152
159
|
}
|
|
160
|
+
|
|
161
|
+
let appendix = '';
|
|
162
|
+
|
|
163
|
+
if(foundInverseRelation && foundInverseRelation.metadata.singular){
|
|
164
|
+
appendix = ' @unique';
|
|
165
|
+
requiredString = '?';
|
|
166
|
+
}
|
|
153
167
|
|
|
154
168
|
// Add relation field with appropriate type based on database
|
|
155
169
|
if (dbType === 'mongodb') {
|
|
156
|
-
section += `\t${relationFieldName} String${requiredString} @db.ObjectId\n`;
|
|
170
|
+
section += `\t${relationFieldName} String${requiredString} @db.ObjectId${appendix}\n`;
|
|
157
171
|
} else if (dbType === 'mysql') {
|
|
158
172
|
// For MySQL, determine the type based on the related model's ID type
|
|
159
|
-
section += `\t${relationFieldName} ${relatedFieldType}${requiredString}\n`;
|
|
173
|
+
section += `\t${relationFieldName} ${relatedFieldType}${requiredString}${appendix}\n`;
|
|
160
174
|
} else if (dbType === 'postgresql' || dbType === 'postgres') {
|
|
161
175
|
if (relatedFieldType === 'String') {
|
|
162
|
-
section += `\t${relationFieldName} ${relatedFieldType}${requiredString} @db.Uuid\n`;
|
|
176
|
+
section += `\t${relationFieldName} ${relatedFieldType}${requiredString} @db.Uuid${appendix}\n`;
|
|
163
177
|
} else {
|
|
164
|
-
section += `\t${relationFieldName} ${relatedFieldType}${requiredString}\n`;
|
|
178
|
+
section += `\t${relationFieldName} ${relatedFieldType}${requiredString}${appendix}\n`;
|
|
165
179
|
}
|
|
166
180
|
} else {
|
|
167
|
-
section += `\t${relationFieldName} String${requiredString}\n`;
|
|
181
|
+
section += `\t${relationFieldName} String${requiredString}${appendix}\n`;
|
|
168
182
|
}
|
|
169
183
|
}
|
|
170
184
|
}
|
|
@@ -182,6 +196,7 @@ datasource db {
|
|
|
182
196
|
const relationIndex = RelationManager.getRelationCounter(relationKey, true);
|
|
183
197
|
|
|
184
198
|
const relationName = RelationManager.getShortenedRelationName(relatedModelName, modelName, relationIndex);
|
|
199
|
+
const singular: boolean = relationMeta.singular;
|
|
185
200
|
|
|
186
201
|
let relationTag = '';
|
|
187
202
|
|
|
@@ -189,7 +204,7 @@ datasource db {
|
|
|
189
204
|
relationTag = ` @relation("${relationMeta.relationName}")`;
|
|
190
205
|
}
|
|
191
206
|
|
|
192
|
-
section += `\t${key} ${relationMeta.inversionModel._collection}[]${relationTag}\n`;
|
|
207
|
+
section += `\t${key} ${relationMeta.inversionModel._collection}${singular ? '?' : '[]'}${relationTag}\n`;
|
|
193
208
|
|
|
194
209
|
RelationManager.completeRelation(relationKey, relationIndex, true);
|
|
195
210
|
} else if (annotationType === 'InverseTimeSeries') {
|
|
@@ -9,6 +9,8 @@ export interface ITrackerOpts extends IDbOpts {
|
|
|
9
9
|
relatedToField?: string,
|
|
10
10
|
relatedTo?: OpModelType<any>,
|
|
11
11
|
inversionModel?: OpModelType<any>,
|
|
12
|
-
relationName?: string
|
|
12
|
+
relationName?: string;
|
|
13
|
+
foreignKey?: string
|
|
13
14
|
noAuto?: boolean;
|
|
15
|
+
singular?: boolean;
|
|
14
16
|
}
|
|
@@ -61,13 +61,22 @@ export class HydrateUtils {
|
|
|
61
61
|
|
|
62
62
|
if (relationEnabled) {
|
|
63
63
|
const pk = ModelUtils.findPrimaryKeyFields(model.constructor as OpModelType<any>) as string;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
|
|
65
|
+
if(relMeta.singular){
|
|
66
|
+
model[relMeta.key] = await relMeta.inversionModel.findOneBy({
|
|
67
|
+
conditions: {
|
|
68
|
+
[relMeta.foreignKey]: data[pk]
|
|
69
|
+
},
|
|
70
|
+
allowRelations: false
|
|
71
|
+
});
|
|
72
|
+
} else {
|
|
73
|
+
model[relMeta.key] = await relMeta.inversionModel.findBy({
|
|
74
|
+
conditions: {
|
|
75
|
+
[relMeta.foreignKey]: data[pk]
|
|
76
|
+
},
|
|
77
|
+
allowRelations: false
|
|
78
|
+
});
|
|
79
|
+
}
|
|
71
80
|
}
|
|
72
81
|
}
|
|
73
82
|
|
|
@@ -47,7 +47,8 @@ export class RelationUtils {
|
|
|
47
47
|
relIds[key] = {
|
|
48
48
|
key: resolvedMetadata.key,
|
|
49
49
|
inversionModel: resolvedMetadata.inversionModel,
|
|
50
|
-
foreignKey: resolvedMetadata.foreignKey
|
|
50
|
+
foreignKey: resolvedMetadata.foreignKey,
|
|
51
|
+
singular: resolvedMetadata?.singular || false
|
|
51
52
|
};
|
|
52
53
|
}
|
|
53
54
|
}
|