@rws-framework/db 4.0.1 → 4.1.0
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.
|
@@ -15,6 +15,7 @@ declare class RWSModel<T> implements IModel {
|
|
|
15
15
|
static _BANNED_KEYS: string[];
|
|
16
16
|
static allModels: OpModelType<any>[];
|
|
17
17
|
static _CUT_KEYS: string[];
|
|
18
|
+
private _relationFields;
|
|
18
19
|
private postLoadExecuted;
|
|
19
20
|
constructor(data?: any);
|
|
20
21
|
isPostLoadExecuted(): boolean;
|
|
@@ -86,5 +87,6 @@ declare class RWSModel<T> implements IModel {
|
|
|
86
87
|
private hydratePrePopulatedRelations;
|
|
87
88
|
static getDb(): DBService;
|
|
88
89
|
reload(): Promise<RWSModel<T> | null>;
|
|
90
|
+
getPropertyValue(key: string): any;
|
|
89
91
|
}
|
|
90
92
|
export { RWSModel };
|
|
@@ -27,6 +27,8 @@ class RWSModel {
|
|
|
27
27
|
static _BANNED_KEYS = ['_collection'];
|
|
28
28
|
static allModels = [];
|
|
29
29
|
static _CUT_KEYS = [];
|
|
30
|
+
// Store relation foreign key fields for reload() functionality
|
|
31
|
+
_relationFields = {};
|
|
30
32
|
postLoadExecuted = false;
|
|
31
33
|
constructor(data = null) {
|
|
32
34
|
if (!this.getCollection()) {
|
|
@@ -440,6 +442,30 @@ class RWSModel {
|
|
|
440
442
|
if (typeof relationData === 'object' && relationData !== null &&
|
|
441
443
|
(relationData.id || Object.keys(relationData).length > 1)) {
|
|
442
444
|
const relatedInstance = new ModelClass();
|
|
445
|
+
// Check relation metadata to identify foreign key fields that need to be preserved
|
|
446
|
+
const tempInstance = new ModelClass();
|
|
447
|
+
const childClassFields = FieldsHelper_1.FieldsHelper.getAllClassFields(tempInstance.constructor);
|
|
448
|
+
const [childRelOneData, childRelManyData] = await Promise.all([
|
|
449
|
+
RelationUtils_1.RelationUtils.getRelationOneMeta(tempInstance, childClassFields),
|
|
450
|
+
RelationUtils_1.RelationUtils.getRelationManyMeta(tempInstance, childClassFields)
|
|
451
|
+
]);
|
|
452
|
+
// Store foreign key fields from relation metadata
|
|
453
|
+
for (const relKey in childRelOneData) {
|
|
454
|
+
const relMeta = childRelOneData[relKey];
|
|
455
|
+
const foreignKeyField = relMeta.hydrationField; // e.g., 'avatar_id', 'knowledge_id'
|
|
456
|
+
if (foreignKeyField && relationData[foreignKeyField] !== undefined) {
|
|
457
|
+
relatedInstance._relationFields[foreignKeyField] = relationData[foreignKeyField];
|
|
458
|
+
relatedInstance[foreignKeyField] = relationData[foreignKeyField];
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
for (const relKey in childRelManyData) {
|
|
462
|
+
const relMeta = childRelManyData[relKey];
|
|
463
|
+
const foreignKeyField = relMeta.foreignKey; // Use foreignKey for inverse relations
|
|
464
|
+
if (foreignKeyField && relationData[foreignKeyField] !== undefined) {
|
|
465
|
+
relatedInstance._relationFields[foreignKeyField] = relationData[foreignKeyField];
|
|
466
|
+
relatedInstance[foreignKeyField] = relationData[foreignKeyField];
|
|
467
|
+
}
|
|
468
|
+
}
|
|
443
469
|
await relatedInstance._asyncFill(relationData, false, false, true);
|
|
444
470
|
this[key] = relatedInstance;
|
|
445
471
|
}
|
|
@@ -450,6 +476,30 @@ class RWSModel {
|
|
|
450
476
|
for (const itemData of relationData) {
|
|
451
477
|
if (typeof itemData === 'object' && itemData !== null) {
|
|
452
478
|
const relatedInstance = new ModelClass();
|
|
479
|
+
// Check relation metadata to identify foreign key fields that need to be preserved
|
|
480
|
+
const tempInstance = new ModelClass();
|
|
481
|
+
const childClassFields = FieldsHelper_1.FieldsHelper.getAllClassFields(tempInstance.constructor);
|
|
482
|
+
const [childRelOneData, childRelManyData] = await Promise.all([
|
|
483
|
+
RelationUtils_1.RelationUtils.getRelationOneMeta(tempInstance, childClassFields),
|
|
484
|
+
RelationUtils_1.RelationUtils.getRelationManyMeta(tempInstance, childClassFields)
|
|
485
|
+
]);
|
|
486
|
+
// Store foreign key fields from relation metadata
|
|
487
|
+
for (const relKey in childRelOneData) {
|
|
488
|
+
const relMeta = childRelOneData[relKey];
|
|
489
|
+
const foreignKeyField = relMeta.hydrationField; // e.g., 'avatar_id', 'knowledge_id'
|
|
490
|
+
if (foreignKeyField && itemData[foreignKeyField] !== undefined) {
|
|
491
|
+
relatedInstance._relationFields[foreignKeyField] = itemData[foreignKeyField];
|
|
492
|
+
relatedInstance[foreignKeyField] = itemData[foreignKeyField];
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
for (const relKey in childRelManyData) {
|
|
496
|
+
const relMeta = childRelManyData[relKey];
|
|
497
|
+
const foreignKeyField = relMeta.foreignKey; // Use foreignKey for inverse relations
|
|
498
|
+
if (foreignKeyField && itemData[foreignKeyField] !== undefined) {
|
|
499
|
+
relatedInstance._relationFields[foreignKeyField] = itemData[foreignKeyField];
|
|
500
|
+
relatedInstance[foreignKeyField] = itemData[foreignKeyField];
|
|
501
|
+
}
|
|
502
|
+
}
|
|
453
503
|
await relatedInstance._asyncFill(itemData, false, false, true);
|
|
454
504
|
relatedInstances.push(relatedInstance);
|
|
455
505
|
}
|
|
@@ -481,10 +531,23 @@ class RWSModel {
|
|
|
481
531
|
}
|
|
482
532
|
// Convert the fresh instance back to plain data for hydration
|
|
483
533
|
const plainData = await freshData.toMongo();
|
|
534
|
+
// Preserve foreign key fields from _relationFields to ensure relations can be hydrated
|
|
535
|
+
for (const key in this._relationFields) {
|
|
536
|
+
if (plainData[key] === undefined) {
|
|
537
|
+
plainData[key] = this._relationFields[key];
|
|
538
|
+
}
|
|
539
|
+
}
|
|
484
540
|
// Hydrate current instance with fresh data including relations
|
|
485
541
|
await this._asyncFill(plainData, true, true, true);
|
|
486
542
|
return this;
|
|
487
543
|
}
|
|
544
|
+
// Helper method to get property with fallback to stored relation fields
|
|
545
|
+
getPropertyValue(key) {
|
|
546
|
+
if (this.hasOwnProperty(key) || this[key] !== undefined) {
|
|
547
|
+
return this[key];
|
|
548
|
+
}
|
|
549
|
+
return this._relationFields[key];
|
|
550
|
+
}
|
|
488
551
|
}
|
|
489
552
|
exports.RWSModel = RWSModel;
|
|
490
553
|
__decorate([
|
package/package.json
CHANGED
|
@@ -27,6 +27,9 @@ class RWSModel<T> implements IModel {
|
|
|
27
27
|
static _BANNED_KEYS = ['_collection'];
|
|
28
28
|
static allModels: OpModelType<any>[] = [];
|
|
29
29
|
static _CUT_KEYS: string[] = [];
|
|
30
|
+
|
|
31
|
+
// Store relation foreign key fields for reload() functionality
|
|
32
|
+
private _relationFields: Record<string, any> = {};
|
|
30
33
|
|
|
31
34
|
private postLoadExecuted: boolean = false;
|
|
32
35
|
|
|
@@ -566,6 +569,34 @@ class RWSModel<T> implements IModel {
|
|
|
566
569
|
if (typeof relationData === 'object' && relationData !== null &&
|
|
567
570
|
(relationData.id || Object.keys(relationData).length > 1)) {
|
|
568
571
|
const relatedInstance = new ModelClass();
|
|
572
|
+
|
|
573
|
+
// Check relation metadata to identify foreign key fields that need to be preserved
|
|
574
|
+
const tempInstance = new ModelClass();
|
|
575
|
+
const childClassFields = FieldsHelper.getAllClassFields(tempInstance.constructor);
|
|
576
|
+
const [childRelOneData, childRelManyData] = await Promise.all([
|
|
577
|
+
RelationUtils.getRelationOneMeta(tempInstance, childClassFields),
|
|
578
|
+
RelationUtils.getRelationManyMeta(tempInstance, childClassFields)
|
|
579
|
+
]);
|
|
580
|
+
|
|
581
|
+
// Store foreign key fields from relation metadata
|
|
582
|
+
for (const relKey in childRelOneData) {
|
|
583
|
+
const relMeta = childRelOneData[relKey];
|
|
584
|
+
const foreignKeyField = relMeta.hydrationField; // e.g., 'avatar_id', 'knowledge_id'
|
|
585
|
+
if (foreignKeyField && relationData[foreignKeyField] !== undefined) {
|
|
586
|
+
relatedInstance._relationFields[foreignKeyField] = relationData[foreignKeyField];
|
|
587
|
+
relatedInstance[foreignKeyField] = relationData[foreignKeyField];
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
for (const relKey in childRelManyData) {
|
|
592
|
+
const relMeta = childRelManyData[relKey];
|
|
593
|
+
const foreignKeyField = relMeta.foreignKey; // Use foreignKey for inverse relations
|
|
594
|
+
if (foreignKeyField && relationData[foreignKeyField] !== undefined) {
|
|
595
|
+
relatedInstance._relationFields[foreignKeyField] = relationData[foreignKeyField];
|
|
596
|
+
relatedInstance[foreignKeyField] = relationData[foreignKeyField];
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
569
600
|
await relatedInstance._asyncFill(relationData, false, false, true);
|
|
570
601
|
this[key] = relatedInstance;
|
|
571
602
|
}
|
|
@@ -575,6 +606,34 @@ class RWSModel<T> implements IModel {
|
|
|
575
606
|
for (const itemData of relationData) {
|
|
576
607
|
if (typeof itemData === 'object' && itemData !== null) {
|
|
577
608
|
const relatedInstance = new ModelClass();
|
|
609
|
+
|
|
610
|
+
// Check relation metadata to identify foreign key fields that need to be preserved
|
|
611
|
+
const tempInstance = new ModelClass();
|
|
612
|
+
const childClassFields = FieldsHelper.getAllClassFields(tempInstance.constructor);
|
|
613
|
+
const [childRelOneData, childRelManyData] = await Promise.all([
|
|
614
|
+
RelationUtils.getRelationOneMeta(tempInstance, childClassFields),
|
|
615
|
+
RelationUtils.getRelationManyMeta(tempInstance, childClassFields)
|
|
616
|
+
]);
|
|
617
|
+
|
|
618
|
+
// Store foreign key fields from relation metadata
|
|
619
|
+
for (const relKey in childRelOneData) {
|
|
620
|
+
const relMeta = childRelOneData[relKey];
|
|
621
|
+
const foreignKeyField = relMeta.hydrationField; // e.g., 'avatar_id', 'knowledge_id'
|
|
622
|
+
if (foreignKeyField && itemData[foreignKeyField] !== undefined) {
|
|
623
|
+
relatedInstance._relationFields[foreignKeyField] = itemData[foreignKeyField];
|
|
624
|
+
relatedInstance[foreignKeyField] = itemData[foreignKeyField];
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
for (const relKey in childRelManyData) {
|
|
629
|
+
const relMeta = childRelManyData[relKey];
|
|
630
|
+
const foreignKeyField = relMeta.foreignKey; // Use foreignKey for inverse relations
|
|
631
|
+
if (foreignKeyField && itemData[foreignKeyField] !== undefined) {
|
|
632
|
+
relatedInstance._relationFields[foreignKeyField] = itemData[foreignKeyField];
|
|
633
|
+
relatedInstance[foreignKeyField] = itemData[foreignKeyField];
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
578
637
|
await relatedInstance._asyncFill(itemData, false, false, true);
|
|
579
638
|
relatedInstances.push(relatedInstance);
|
|
580
639
|
}
|
|
@@ -614,11 +673,26 @@ class RWSModel<T> implements IModel {
|
|
|
614
673
|
// Convert the fresh instance back to plain data for hydration
|
|
615
674
|
const plainData = await freshData.toMongo();
|
|
616
675
|
|
|
676
|
+
// Preserve foreign key fields from _relationFields to ensure relations can be hydrated
|
|
677
|
+
for (const key in this._relationFields) {
|
|
678
|
+
if (plainData[key] === undefined) {
|
|
679
|
+
plainData[key] = this._relationFields[key];
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
617
683
|
// Hydrate current instance with fresh data including relations
|
|
618
684
|
await this._asyncFill(plainData, true, true, true);
|
|
619
685
|
|
|
620
686
|
return this;
|
|
621
687
|
}
|
|
688
|
+
|
|
689
|
+
// Helper method to get property with fallback to stored relation fields
|
|
690
|
+
getPropertyValue(key: string): any {
|
|
691
|
+
if (this.hasOwnProperty(key) || this[key] !== undefined) {
|
|
692
|
+
return this[key];
|
|
693
|
+
}
|
|
694
|
+
return this._relationFields[key];
|
|
695
|
+
}
|
|
622
696
|
}
|
|
623
697
|
|
|
624
698
|
export { RWSModel };
|