@rws-framework/db 4.1.0 → 4.1.1
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/models/core/RWSModel.js +48 -5
- package/dist/models/utils/HydrateUtils.d.ts +4 -0
- package/dist/models/utils/HydrateUtils.js +44 -5
- package/dist/models/utils/ModelUtils.js +1 -1
- package/package.json +1 -1
- package/src/models/core/RWSModel.ts +61 -5
- package/src/models/utils/HydrateUtils.ts +59 -7
- package/src/models/utils/ModelUtils.ts +1 -1
|
@@ -422,8 +422,15 @@ class RWSModel {
|
|
|
422
422
|
// Check if it's already a full object with data or just an ID reference
|
|
423
423
|
if (relationData.id || Object.keys(relationData).length > 1) {
|
|
424
424
|
// Create new instance and hydrate ONLY basic fields, NO RELATIONS
|
|
425
|
+
// Respect ignored_keys from child model
|
|
426
|
+
const childIgnoredKeys = ModelClass._CUT_KEYS || [];
|
|
425
427
|
const relatedInstance = new ModelClass();
|
|
426
|
-
|
|
428
|
+
// Filter relationData to exclude ignored keys
|
|
429
|
+
const filteredData = { ...relationData };
|
|
430
|
+
for (const ignoredKey of childIgnoredKeys) {
|
|
431
|
+
delete filteredData[ignoredKey];
|
|
432
|
+
}
|
|
433
|
+
await relatedInstance._asyncFill(filteredData, false, false, true);
|
|
427
434
|
this[key] = relatedInstance;
|
|
428
435
|
}
|
|
429
436
|
}
|
|
@@ -441,6 +448,7 @@ class RWSModel {
|
|
|
441
448
|
// Handle singular inverse relation as a single object
|
|
442
449
|
if (typeof relationData === 'object' && relationData !== null &&
|
|
443
450
|
(relationData.id || Object.keys(relationData).length > 1)) {
|
|
451
|
+
const childIgnoredKeys = ModelClass._CUT_KEYS || [];
|
|
444
452
|
const relatedInstance = new ModelClass();
|
|
445
453
|
// Check relation metadata to identify foreign key fields that need to be preserved
|
|
446
454
|
const tempInstance = new ModelClass();
|
|
@@ -466,7 +474,12 @@ class RWSModel {
|
|
|
466
474
|
relatedInstance[foreignKeyField] = relationData[foreignKeyField];
|
|
467
475
|
}
|
|
468
476
|
}
|
|
469
|
-
|
|
477
|
+
// Filter relationData to exclude ignored keys
|
|
478
|
+
const filteredData = { ...relationData };
|
|
479
|
+
for (const ignoredKey of childIgnoredKeys) {
|
|
480
|
+
delete filteredData[ignoredKey];
|
|
481
|
+
}
|
|
482
|
+
await relatedInstance._asyncFill(filteredData, false, false, true);
|
|
470
483
|
this[key] = relatedInstance;
|
|
471
484
|
}
|
|
472
485
|
}
|
|
@@ -475,6 +488,7 @@ class RWSModel {
|
|
|
475
488
|
const relatedInstances = [];
|
|
476
489
|
for (const itemData of relationData) {
|
|
477
490
|
if (typeof itemData === 'object' && itemData !== null) {
|
|
491
|
+
const childIgnoredKeys = ModelClass._CUT_KEYS || [];
|
|
478
492
|
const relatedInstance = new ModelClass();
|
|
479
493
|
// Check relation metadata to identify foreign key fields that need to be preserved
|
|
480
494
|
const tempInstance = new ModelClass();
|
|
@@ -500,7 +514,12 @@ class RWSModel {
|
|
|
500
514
|
relatedInstance[foreignKeyField] = itemData[foreignKeyField];
|
|
501
515
|
}
|
|
502
516
|
}
|
|
503
|
-
|
|
517
|
+
// Filter itemData to exclude ignored keys
|
|
518
|
+
const filteredData = { ...itemData };
|
|
519
|
+
for (const ignoredKey of childIgnoredKeys) {
|
|
520
|
+
delete filteredData[ignoredKey];
|
|
521
|
+
}
|
|
522
|
+
await relatedInstance._asyncFill(filteredData, false, false, true);
|
|
504
523
|
relatedInstances.push(relatedInstance);
|
|
505
524
|
}
|
|
506
525
|
}
|
|
@@ -524,8 +543,32 @@ class RWSModel {
|
|
|
524
543
|
else {
|
|
525
544
|
where[pk] = this[pk];
|
|
526
545
|
}
|
|
527
|
-
//
|
|
528
|
-
const
|
|
546
|
+
// Get ignored keys from model's @RWSCollection decorator
|
|
547
|
+
const ignoredKeys = (this.constructor._CUT_KEYS || []);
|
|
548
|
+
let fields = undefined;
|
|
549
|
+
// Build fields list excluding ignored ones if there are ignored keys
|
|
550
|
+
if (ignoredKeys.length > 0) {
|
|
551
|
+
// Get proper database fields from model annotations
|
|
552
|
+
const annotations = await ModelUtils_1.ModelUtils.getModelAnnotations(this.constructor);
|
|
553
|
+
// Get scalar fields (TrackType decorated fields)
|
|
554
|
+
const scalarFields = ModelUtils_1.ModelUtils.getModelScalarFields(this);
|
|
555
|
+
// Get relation fields from annotations
|
|
556
|
+
const relationFields = Object.keys(annotations).filter(key => annotations[key].annotationType === 'Relation' ||
|
|
557
|
+
annotations[key].annotationType === 'InverseRelation');
|
|
558
|
+
// Combine all database fields
|
|
559
|
+
const allDbFields = [...scalarFields, ...relationFields];
|
|
560
|
+
// Filter out ignored keys
|
|
561
|
+
fields = allDbFields.filter(field => !ignoredKeys.includes(field));
|
|
562
|
+
// Always include id if not ignored
|
|
563
|
+
if (!fields.includes('id') && !ignoredKeys.includes('id')) {
|
|
564
|
+
fields.push('id');
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
// Find the fresh data from database with field filtering
|
|
568
|
+
const freshData = await FindUtils_1.FindUtils.findOneBy(this.constructor, {
|
|
569
|
+
conditions: where,
|
|
570
|
+
fields: fields
|
|
571
|
+
});
|
|
529
572
|
if (!freshData) {
|
|
530
573
|
return null;
|
|
531
574
|
}
|
|
@@ -10,4 +10,8 @@ export declare class HydrateUtils {
|
|
|
10
10
|
static hydrateRelations(model: RWSModel<any>, relManyData: RelManyMetaType<IRWSModel>, relOneData: RelOneMetaType<IRWSModel>, seriesHydrationfields: string[], fullDataMode: boolean, data: {
|
|
11
11
|
[key: string]: any;
|
|
12
12
|
}, postLoadExecute?: boolean): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Get all database fields for a model excluding ignored ones
|
|
15
|
+
*/
|
|
16
|
+
private static getFieldsExcludingIgnored;
|
|
13
17
|
}
|
|
@@ -19,9 +19,11 @@ class HydrateUtils {
|
|
|
19
19
|
foreignKeyFields.add(relationMeta.hydrationField);
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
+
// Get ignored keys from model's @RWSCollection decorator
|
|
23
|
+
const ignoredKeys = (model).constructor._CUT_KEYS || [];
|
|
22
24
|
for (const key in data) {
|
|
23
25
|
if (data.hasOwnProperty(key)) {
|
|
24
|
-
if (!fullDataMode &&
|
|
26
|
+
if (!fullDataMode && ignoredKeys.includes(key)) {
|
|
25
27
|
continue;
|
|
26
28
|
}
|
|
27
29
|
// Skip relation property names
|
|
@@ -52,20 +54,25 @@ class HydrateUtils {
|
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
static async hydrateRelations(model, relManyData, relOneData, seriesHydrationfields, fullDataMode, data, postLoadExecute = false) {
|
|
57
|
+
const ignoredKeys = (model).constructor._CUT_KEYS || [];
|
|
55
58
|
// Handle many-to-many relations
|
|
56
59
|
for (const key in relManyData) {
|
|
57
|
-
if (!fullDataMode &&
|
|
60
|
+
if (!fullDataMode && ignoredKeys.includes(key)) {
|
|
58
61
|
continue;
|
|
59
62
|
}
|
|
60
63
|
const relMeta = relManyData[key];
|
|
61
64
|
const relationEnabled = !RelationUtils_1.RelationUtils.checkRelDisabled(model, relMeta.key);
|
|
62
65
|
if (relationEnabled) {
|
|
63
66
|
const pk = ModelUtils_1.ModelUtils.findPrimaryKeyFields(model.constructor);
|
|
67
|
+
// Get child model ignored keys to pass to find operations
|
|
68
|
+
const childIgnoredKeys = relMeta.inversionModel._CUT_KEYS || [];
|
|
69
|
+
const childFields = childIgnoredKeys.length > 0 ? await this.getFieldsExcludingIgnored(relMeta.inversionModel, childIgnoredKeys) : undefined;
|
|
64
70
|
if (relMeta.singular) {
|
|
65
71
|
model[relMeta.key] = await relMeta.inversionModel.findOneBy({
|
|
66
72
|
conditions: {
|
|
67
73
|
[relMeta.foreignKey]: data[pk]
|
|
68
74
|
},
|
|
75
|
+
fields: childFields,
|
|
69
76
|
allowRelations: false,
|
|
70
77
|
cancelPostLoad: !postLoadExecute
|
|
71
78
|
});
|
|
@@ -75,6 +82,7 @@ class HydrateUtils {
|
|
|
75
82
|
conditions: {
|
|
76
83
|
[relMeta.foreignKey]: data[pk]
|
|
77
84
|
},
|
|
85
|
+
fields: childFields,
|
|
78
86
|
allowRelations: false,
|
|
79
87
|
cancelPostLoad: !postLoadExecute
|
|
80
88
|
});
|
|
@@ -83,7 +91,7 @@ class HydrateUtils {
|
|
|
83
91
|
}
|
|
84
92
|
// Handle one-to-one relations
|
|
85
93
|
for (const key in relOneData) {
|
|
86
|
-
if (!fullDataMode &&
|
|
94
|
+
if (!fullDataMode && ignoredKeys.includes(key)) {
|
|
87
95
|
continue;
|
|
88
96
|
}
|
|
89
97
|
const relMeta = relOneData[key];
|
|
@@ -101,13 +109,19 @@ class HydrateUtils {
|
|
|
101
109
|
else {
|
|
102
110
|
where[pk] = data[relMeta.hydrationField];
|
|
103
111
|
}
|
|
104
|
-
|
|
112
|
+
// Get child model ignored keys to pass to find operation
|
|
113
|
+
const childIgnoredKeys = relMeta.model._CUT_KEYS || [];
|
|
114
|
+
const childFields = childIgnoredKeys.length > 0 ? await this.getFieldsExcludingIgnored(relMeta.model, childIgnoredKeys) : undefined;
|
|
115
|
+
model[relMeta.key] = await relMeta.model.findOneBy({
|
|
116
|
+
conditions: where,
|
|
117
|
+
fields: childFields
|
|
118
|
+
}, { allowRelations: false });
|
|
105
119
|
}
|
|
106
120
|
else if (relationEnabled && !data[relMeta.hydrationField] && data[relMeta.key]) {
|
|
107
121
|
const newRelModel = await relMeta.model.create(data[relMeta.key]);
|
|
108
122
|
model[relMeta.key] = await newRelModel.save();
|
|
109
123
|
}
|
|
110
|
-
const cutKeys =
|
|
124
|
+
const cutKeys = ignoredKeys;
|
|
111
125
|
const trackedField = Object.keys((await ModelUtils_1.ModelUtils.getModelAnnotations(model.constructor))).includes(relMeta.hydrationField);
|
|
112
126
|
if (!cutKeys.includes(relMeta.hydrationField) && !trackedField) {
|
|
113
127
|
cutKeys.push(relMeta.hydrationField);
|
|
@@ -115,5 +129,30 @@ class HydrateUtils {
|
|
|
115
129
|
// seriesHydrationfields.push(relMeta.hydrationField);
|
|
116
130
|
}
|
|
117
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Get all database fields for a model excluding ignored ones
|
|
134
|
+
*/
|
|
135
|
+
static async getFieldsExcludingIgnored(modelClass, ignoredKeys) {
|
|
136
|
+
if (!ignoredKeys || ignoredKeys.length === 0) {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
// Get proper database fields from model annotations
|
|
140
|
+
const tempInstance = new modelClass();
|
|
141
|
+
const annotations = await ModelUtils_1.ModelUtils.getModelAnnotations(modelClass);
|
|
142
|
+
// Get scalar fields (TrackType decorated fields)
|
|
143
|
+
const scalarFields = ModelUtils_1.ModelUtils.getModelScalarFields(tempInstance);
|
|
144
|
+
// Get relation fields from annotations
|
|
145
|
+
const relationFields = Object.keys(annotations).filter(key => annotations[key].annotationType === 'Relation' ||
|
|
146
|
+
annotations[key].annotationType === 'InverseRelation');
|
|
147
|
+
// Combine all database fields
|
|
148
|
+
const allDbFields = [...scalarFields, ...relationFields];
|
|
149
|
+
// Filter out ignored keys
|
|
150
|
+
const filteredFields = allDbFields.filter(field => !ignoredKeys.includes(field));
|
|
151
|
+
// Always include id if not ignored
|
|
152
|
+
if (!filteredFields.includes('id') && !ignoredKeys.includes('id')) {
|
|
153
|
+
filteredFields.push('id');
|
|
154
|
+
}
|
|
155
|
+
return filteredFields.length > 0 ? filteredFields : undefined;
|
|
156
|
+
}
|
|
118
157
|
}
|
|
119
158
|
exports.HydrateUtils = HydrateUtils;
|
|
@@ -55,7 +55,7 @@ class ModelUtils {
|
|
|
55
55
|
return baseClass.prototype.isPrototypeOf(constructor.prototype);
|
|
56
56
|
}
|
|
57
57
|
static getModelScalarFields(model) {
|
|
58
|
-
return FieldsHelper_1.FieldsHelper.getAllClassFields(model)
|
|
58
|
+
return FieldsHelper_1.FieldsHelper.getAllClassFields(model.constructor)
|
|
59
59
|
.filter((item) => item.indexOf('TrackType') === 0)
|
|
60
60
|
.map((item) => item.split(':').at(-1));
|
|
61
61
|
}
|
package/package.json
CHANGED
|
@@ -547,8 +547,17 @@ class RWSModel<T> implements IModel {
|
|
|
547
547
|
// Check if it's already a full object with data or just an ID reference
|
|
548
548
|
if (relationData.id || Object.keys(relationData).length > 1) {
|
|
549
549
|
// Create new instance and hydrate ONLY basic fields, NO RELATIONS
|
|
550
|
+
// Respect ignored_keys from child model
|
|
551
|
+
const childIgnoredKeys = (ModelClass as OpModelType<any>)._CUT_KEYS || [];
|
|
550
552
|
const relatedInstance = new ModelClass();
|
|
551
|
-
|
|
553
|
+
|
|
554
|
+
// Filter relationData to exclude ignored keys
|
|
555
|
+
const filteredData = { ...relationData };
|
|
556
|
+
for (const ignoredKey of childIgnoredKeys) {
|
|
557
|
+
delete filteredData[ignoredKey];
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
await relatedInstance._asyncFill(filteredData, false, false, true);
|
|
552
561
|
this[key] = relatedInstance;
|
|
553
562
|
}
|
|
554
563
|
}
|
|
@@ -568,6 +577,7 @@ class RWSModel<T> implements IModel {
|
|
|
568
577
|
// Handle singular inverse relation as a single object
|
|
569
578
|
if (typeof relationData === 'object' && relationData !== null &&
|
|
570
579
|
(relationData.id || Object.keys(relationData).length > 1)) {
|
|
580
|
+
const childIgnoredKeys = (ModelClass as OpModelType<any>)._CUT_KEYS || [];
|
|
571
581
|
const relatedInstance = new ModelClass();
|
|
572
582
|
|
|
573
583
|
// Check relation metadata to identify foreign key fields that need to be preserved
|
|
@@ -597,7 +607,13 @@ class RWSModel<T> implements IModel {
|
|
|
597
607
|
}
|
|
598
608
|
}
|
|
599
609
|
|
|
600
|
-
|
|
610
|
+
// Filter relationData to exclude ignored keys
|
|
611
|
+
const filteredData = { ...relationData };
|
|
612
|
+
for (const ignoredKey of childIgnoredKeys) {
|
|
613
|
+
delete filteredData[ignoredKey];
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
await relatedInstance._asyncFill(filteredData, false, false, true);
|
|
601
617
|
this[key] = relatedInstance;
|
|
602
618
|
}
|
|
603
619
|
} else if (Array.isArray(relationData) && relationData.length > 0) {
|
|
@@ -605,6 +621,7 @@ class RWSModel<T> implements IModel {
|
|
|
605
621
|
const relatedInstances = [];
|
|
606
622
|
for (const itemData of relationData) {
|
|
607
623
|
if (typeof itemData === 'object' && itemData !== null) {
|
|
624
|
+
const childIgnoredKeys = (ModelClass as OpModelType<any>)._CUT_KEYS || [];
|
|
608
625
|
const relatedInstance = new ModelClass();
|
|
609
626
|
|
|
610
627
|
// Check relation metadata to identify foreign key fields that need to be preserved
|
|
@@ -634,7 +651,13 @@ class RWSModel<T> implements IModel {
|
|
|
634
651
|
}
|
|
635
652
|
}
|
|
636
653
|
|
|
637
|
-
|
|
654
|
+
// Filter itemData to exclude ignored keys
|
|
655
|
+
const filteredData = { ...itemData };
|
|
656
|
+
for (const ignoredKey of childIgnoredKeys) {
|
|
657
|
+
delete filteredData[ignoredKey];
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
await relatedInstance._asyncFill(filteredData, false, false, true);
|
|
638
661
|
relatedInstances.push(relatedInstance);
|
|
639
662
|
}
|
|
640
663
|
}
|
|
@@ -663,8 +686,41 @@ class RWSModel<T> implements IModel {
|
|
|
663
686
|
where[pk as string] = this[pk as string]
|
|
664
687
|
}
|
|
665
688
|
|
|
666
|
-
//
|
|
667
|
-
const
|
|
689
|
+
// Get ignored keys from model's @RWSCollection decorator
|
|
690
|
+
const ignoredKeys = ((this.constructor as OpModelType<any>)._CUT_KEYS || []);
|
|
691
|
+
let fields: string[] | undefined = undefined;
|
|
692
|
+
|
|
693
|
+
// Build fields list excluding ignored ones if there are ignored keys
|
|
694
|
+
if (ignoredKeys.length > 0) {
|
|
695
|
+
// Get proper database fields from model annotations
|
|
696
|
+
const annotations = await ModelUtils.getModelAnnotations(this.constructor as OpModelType<any>);
|
|
697
|
+
|
|
698
|
+
// Get scalar fields (TrackType decorated fields)
|
|
699
|
+
const scalarFields = ModelUtils.getModelScalarFields(this);
|
|
700
|
+
|
|
701
|
+
// Get relation fields from annotations
|
|
702
|
+
const relationFields = Object.keys(annotations).filter(key =>
|
|
703
|
+
annotations[key].annotationType === 'Relation' ||
|
|
704
|
+
annotations[key].annotationType === 'InverseRelation'
|
|
705
|
+
);
|
|
706
|
+
|
|
707
|
+
// Combine all database fields
|
|
708
|
+
const allDbFields = [...scalarFields, ...relationFields];
|
|
709
|
+
|
|
710
|
+
// Filter out ignored keys
|
|
711
|
+
fields = allDbFields.filter(field => !ignoredKeys.includes(field));
|
|
712
|
+
|
|
713
|
+
// Always include id if not ignored
|
|
714
|
+
if (!fields.includes('id') && !ignoredKeys.includes('id')) {
|
|
715
|
+
fields.push('id');
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// Find the fresh data from database with field filtering
|
|
720
|
+
const freshData = await FindUtils.findOneBy(this.constructor as OpModelType<any>, {
|
|
721
|
+
conditions: where,
|
|
722
|
+
fields: fields
|
|
723
|
+
});
|
|
668
724
|
|
|
669
725
|
if (!freshData) {
|
|
670
726
|
return null;
|
|
@@ -5,6 +5,7 @@ import { TimeSeriesUtils } from "./TimeSeriesUtils";
|
|
|
5
5
|
import { RelationUtils } from "./RelationUtils";
|
|
6
6
|
import { OpModelType } from "..";
|
|
7
7
|
import { ModelUtils } from "./ModelUtils";
|
|
8
|
+
import { FieldsHelper } from "../../helper/FieldsHelper";
|
|
8
9
|
import chalk from 'chalk';
|
|
9
10
|
|
|
10
11
|
export class HydrateUtils {
|
|
@@ -20,9 +21,12 @@ export class HydrateUtils {
|
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
// Get ignored keys from model's @RWSCollection decorator
|
|
25
|
+
const ignoredKeys = ((model).constructor as OpModelType<any>)._CUT_KEYS || [];
|
|
26
|
+
|
|
23
27
|
for (const key in data) {
|
|
24
28
|
if (data.hasOwnProperty(key)) {
|
|
25
|
-
if (!fullDataMode &&
|
|
29
|
+
if (!fullDataMode && ignoredKeys.includes(key)) {
|
|
26
30
|
continue;
|
|
27
31
|
}
|
|
28
32
|
|
|
@@ -62,9 +66,11 @@ export class HydrateUtils {
|
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
static async hydrateRelations(model: RWSModel<any>, relManyData: RelManyMetaType<IRWSModel>, relOneData: RelOneMetaType<IRWSModel>, seriesHydrationfields: string[], fullDataMode: boolean, data: { [key: string]: any }, postLoadExecute = false) {
|
|
69
|
+
const ignoredKeys = ((model).constructor as OpModelType<any>)._CUT_KEYS || [];
|
|
70
|
+
|
|
65
71
|
// Handle many-to-many relations
|
|
66
72
|
for (const key in relManyData) {
|
|
67
|
-
if (!fullDataMode &&
|
|
73
|
+
if (!fullDataMode && ignoredKeys.includes(key)) {
|
|
68
74
|
continue;
|
|
69
75
|
}
|
|
70
76
|
|
|
@@ -72,16 +78,19 @@ export class HydrateUtils {
|
|
|
72
78
|
|
|
73
79
|
const relationEnabled = !RelationUtils.checkRelDisabled(model, relMeta.key);
|
|
74
80
|
|
|
75
|
-
|
|
76
|
-
|
|
77
81
|
if (relationEnabled) {
|
|
78
82
|
const pk = ModelUtils.findPrimaryKeyFields(model.constructor as OpModelType<any>) as string;
|
|
79
83
|
|
|
84
|
+
// Get child model ignored keys to pass to find operations
|
|
85
|
+
const childIgnoredKeys = (relMeta.inversionModel as OpModelType<any>)._CUT_KEYS || [];
|
|
86
|
+
const childFields = childIgnoredKeys.length > 0 ? await this.getFieldsExcludingIgnored(relMeta.inversionModel, childIgnoredKeys) : undefined;
|
|
87
|
+
|
|
80
88
|
if (relMeta.singular) {
|
|
81
89
|
model[relMeta.key] = await relMeta.inversionModel.findOneBy({
|
|
82
90
|
conditions: {
|
|
83
91
|
[relMeta.foreignKey]: data[pk]
|
|
84
92
|
},
|
|
93
|
+
fields: childFields,
|
|
85
94
|
allowRelations: false,
|
|
86
95
|
cancelPostLoad: !postLoadExecute
|
|
87
96
|
});
|
|
@@ -90,6 +99,7 @@ export class HydrateUtils {
|
|
|
90
99
|
conditions: {
|
|
91
100
|
[relMeta.foreignKey]: data[pk]
|
|
92
101
|
},
|
|
102
|
+
fields: childFields,
|
|
93
103
|
allowRelations: false,
|
|
94
104
|
cancelPostLoad: !postLoadExecute
|
|
95
105
|
});
|
|
@@ -99,7 +109,7 @@ export class HydrateUtils {
|
|
|
99
109
|
|
|
100
110
|
// Handle one-to-one relations
|
|
101
111
|
for (const key in relOneData) {
|
|
102
|
-
if (!fullDataMode &&
|
|
112
|
+
if (!fullDataMode && ignoredKeys.includes(key)) {
|
|
103
113
|
continue;
|
|
104
114
|
}
|
|
105
115
|
|
|
@@ -122,14 +132,21 @@ export class HydrateUtils {
|
|
|
122
132
|
where[pk as string] = data[relMeta.hydrationField]
|
|
123
133
|
}
|
|
124
134
|
|
|
125
|
-
|
|
135
|
+
// Get child model ignored keys to pass to find operation
|
|
136
|
+
const childIgnoredKeys = (relMeta.model as OpModelType<any>)._CUT_KEYS || [];
|
|
137
|
+
const childFields = childIgnoredKeys.length > 0 ? await this.getFieldsExcludingIgnored(relMeta.model, childIgnoredKeys) : undefined;
|
|
138
|
+
|
|
139
|
+
model[relMeta.key] = await relMeta.model.findOneBy({
|
|
140
|
+
conditions: where,
|
|
141
|
+
fields: childFields
|
|
142
|
+
}, { allowRelations: false });
|
|
126
143
|
}
|
|
127
144
|
else if (relationEnabled && !data[relMeta.hydrationField] && data[relMeta.key]) {
|
|
128
145
|
const newRelModel: RWSModel<any> = await relMeta.model.create(data[relMeta.key]);
|
|
129
146
|
model[relMeta.key] = await newRelModel.save();
|
|
130
147
|
}
|
|
131
148
|
|
|
132
|
-
const cutKeys =
|
|
149
|
+
const cutKeys = ignoredKeys;
|
|
133
150
|
|
|
134
151
|
const trackedField = Object.keys((await ModelUtils.getModelAnnotations(model.constructor as OpModelType<any>))).includes(relMeta.hydrationField);
|
|
135
152
|
|
|
@@ -140,4 +157,39 @@ export class HydrateUtils {
|
|
|
140
157
|
// seriesHydrationfields.push(relMeta.hydrationField);
|
|
141
158
|
}
|
|
142
159
|
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Get all database fields for a model excluding ignored ones
|
|
163
|
+
*/
|
|
164
|
+
private static async getFieldsExcludingIgnored(modelClass: OpModelType<any>, ignoredKeys: string[]): Promise<string[] | undefined> {
|
|
165
|
+
if (!ignoredKeys || ignoredKeys.length === 0) {
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Get proper database fields from model annotations
|
|
170
|
+
const tempInstance = new modelClass();
|
|
171
|
+
const annotations = await ModelUtils.getModelAnnotations(modelClass);
|
|
172
|
+
|
|
173
|
+
// Get scalar fields (TrackType decorated fields)
|
|
174
|
+
const scalarFields = ModelUtils.getModelScalarFields(tempInstance);
|
|
175
|
+
|
|
176
|
+
// Get relation fields from annotations
|
|
177
|
+
const relationFields = Object.keys(annotations).filter(key =>
|
|
178
|
+
annotations[key].annotationType === 'Relation' ||
|
|
179
|
+
annotations[key].annotationType === 'InverseRelation'
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
// Combine all database fields
|
|
183
|
+
const allDbFields = [...scalarFields, ...relationFields];
|
|
184
|
+
|
|
185
|
+
// Filter out ignored keys
|
|
186
|
+
const filteredFields = allDbFields.filter(field => !ignoredKeys.includes(field));
|
|
187
|
+
|
|
188
|
+
// Always include id if not ignored
|
|
189
|
+
if (!filteredFields.includes('id') && !ignoredKeys.includes('id')) {
|
|
190
|
+
filteredFields.push('id');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return filteredFields.length > 0 ? filteredFields : undefined;
|
|
194
|
+
}
|
|
143
195
|
}
|
|
@@ -70,7 +70,7 @@ export class ModelUtils {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
static getModelScalarFields(model: RWSModel<any>): string[] {
|
|
73
|
-
return FieldsHelper.getAllClassFields(model)
|
|
73
|
+
return FieldsHelper.getAllClassFields(model.constructor)
|
|
74
74
|
.filter((item: string) => item.indexOf('TrackType') === 0)
|
|
75
75
|
.map((item: string) => item.split(':').at(-1));
|
|
76
76
|
}
|