@getstrata/core 0.5.99 → 0.5.100
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/CHANGELOG.md +10 -0
- package/dist/core/database/model.d.ts +2 -0
- package/dist/core/database/relationships.d.ts +4 -2
- package/dist/entries/database/model.js +85 -23
- package/dist/entries/database/relationships.js +85 -21
- package/dist/entries/database/repositoryQuery.js +214 -6
- package/dist/index.js +93 -31
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @getstrata/core changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.100
|
|
4
|
+
|
|
5
|
+
HiroApp dogfood of 0.5.99: eager `with()` / nested `load("a.b")` missed related rows when a Postgres int4 PK arrived as a JS `number` and an int8 FK as a `bigint`. Map matching used `===`.
|
|
6
|
+
|
|
7
|
+
- Relation indexers and eager attach compare keys with `relationMatchKey` (`1`, `1n`, `"1"` match).
|
|
8
|
+
- Sequential `load("position")` / `application.position()` already used SQL `get()` and were unaffected.
|
|
9
|
+
- `registerModelRepository(User, users)` already names `User` and `$morphClass`. Do not also call `registerModelClass("User", User)`. `registerModelClass` is only for an alias that is neither `constructor.name` nor `$morphClass`.
|
|
10
|
+
|
|
11
|
+
Still non-conforming (honest): Bun cannot infer `morphTo()` method names. `hashed` cast is a no-op. `Factory.has()` without a bound model still needs an explicit FK.
|
|
12
|
+
|
|
3
13
|
## 0.5.99
|
|
4
14
|
|
|
5
15
|
HiroApp dogfood of 0.5.98 found lookalike APIs. This release matches Laravel call shape and SQL, not just export names.
|
|
@@ -25,6 +25,7 @@ type ModelObserver = {
|
|
|
25
25
|
deleting?: (model: AnyModel) => unknown;
|
|
26
26
|
deleted?: (model: AnyModel) => unknown;
|
|
27
27
|
};
|
|
28
|
+
/** Alias for `hasMany("Name")` when `Name` is not `constructor.name` or `$morphClass`. */
|
|
28
29
|
declare function registerModelClass(name: string, model: object): void;
|
|
29
30
|
declare function hydrateValue(value: unknown, cast: CastType): unknown;
|
|
30
31
|
declare function dehydrateValue(value: unknown, cast: CastType): unknown;
|
|
@@ -135,6 +136,7 @@ declare class Model<TEntity extends object, PrimaryKey extends keyof TEntity & s
|
|
|
135
136
|
setLoaded(name: string, value: unknown): this;
|
|
136
137
|
mergeAttributes(patch: Partial<TEntity>): this;
|
|
137
138
|
}
|
|
139
|
+
/** Binds a Model class to its table/connection and names it for `hasMany("User")`. */
|
|
138
140
|
declare function registerModelRepository<TModelClass>(model: TModelClass, repository: object): TModelClass;
|
|
139
141
|
export { BelongsToManyRelationQuery, BelongsToRelationQuery, HasManyRelationQuery, HasOneRelationQuery, MorphManyRelationQuery, MorphOneRelationQuery, MorphToRelationQuery, } from "./relationQuery.ts";
|
|
140
142
|
export type { CastType, GlobalScopeFn, ModelClassType, ModelConstructor };
|
|
@@ -48,6 +48,8 @@ declare function belongsToMany<TParent, TRelated, Pivot extends object, ParentKe
|
|
|
48
48
|
foreignPivotKey: ForeignPivotKey;
|
|
49
49
|
relatedPivotKey: RelatedPivotKey;
|
|
50
50
|
}): BelongsToManyRelation<TParent, TRelated, Pivot, ParentKey, RelatedKey, ForeignPivotKey, RelatedPivotKey>;
|
|
51
|
+
declare function relationMatchKey(value: unknown): string;
|
|
52
|
+
declare function getByRelationKey<K, V>(map: ReadonlyMap<K, V>, key: unknown): V | undefined;
|
|
51
53
|
declare function indexHasManyRelation<TParent, TChild, LocalKey extends keyof TParent & string, ForeignKey extends keyof TChild & string>(parents: readonly TParent[], children: readonly TChild[], relation: HasManyRelation<TParent, TChild, LocalKey, ForeignKey>): Map<TParent[LocalKey], TChild[]>;
|
|
52
54
|
declare function indexHasOneRelation<TParent, TChild, LocalKey extends keyof TParent & string, ForeignKey extends keyof TChild & string>(parents: readonly TParent[], children: readonly TChild[], relation: HasOneRelation<TParent, TChild, LocalKey, ForeignKey>): Map<TParent[LocalKey], TChild | undefined>;
|
|
53
55
|
declare function indexBelongsToRelation<TChild, TParent, ForeignKey extends keyof TChild & string, OwnerKey extends keyof TParent & string>(children: readonly TChild[], parents: readonly TParent[], relation: BelongsToRelation<TChild, TParent, ForeignKey, OwnerKey>): Map<TChild[ForeignKey], TParent>;
|
|
@@ -95,6 +97,6 @@ declare function morphTo<TChild, MorphTypeKey extends keyof TChild & string = ke
|
|
|
95
97
|
}): MorphToRelation<TChild, MorphTypeKey, MorphIdKey>;
|
|
96
98
|
declare function indexMorphManyRelation<TParent, TChild, LocalKey extends keyof TParent & string, MorphTypeKey extends keyof TChild & string, MorphIdKey extends keyof TChild & string>(parents: readonly TParent[], children: readonly TChild[], relation: MorphManyRelation<TParent, TChild, LocalKey, MorphTypeKey, MorphIdKey>): Map<TParent[LocalKey], TChild[]>;
|
|
97
99
|
declare function indexMorphOneRelation<TParent, TChild, LocalKey extends keyof TParent & string, MorphTypeKey extends keyof TChild & string, MorphIdKey extends keyof TChild & string>(parents: readonly TParent[], children: readonly TChild[], relation: MorphOneRelation<TParent, TChild, LocalKey, MorphTypeKey, MorphIdKey>): Map<TParent[LocalKey], TChild | undefined>;
|
|
98
|
-
declare function indexMorphToRelation<TChild, TParent extends object, MorphTypeKey extends keyof TChild & string, MorphIdKey extends keyof TChild & string,
|
|
100
|
+
declare function indexMorphToRelation<TChild, TParent extends object, MorphTypeKey extends keyof TChild & string, MorphIdKey extends keyof TChild & string, _OwnerKey extends keyof TParent & string = keyof TParent & string>(children: readonly TChild[], parentsByType: ReadonlyMap<string, ReadonlyMap<unknown, TParent>>, relation: MorphToRelation<TChild, MorphTypeKey, MorphIdKey>): Map<TChild[MorphIdKey], TParent>;
|
|
99
101
|
export type { BelongsToManyRelation, BelongsToRelation, HasManyRelation, HasOneRelation, MorphManyRelation, MorphOneRelation, MorphToRelation, };
|
|
100
|
-
export { belongsTo, belongsToMany, hasMany, hasOne, indexBelongsToManyRelation, indexBelongsToRelation, indexHasManyRelation, indexHasOneRelation, indexMorphManyRelation, indexMorphOneRelation, indexMorphToRelation, morphMany, morphOne, morphTo, };
|
|
102
|
+
export { belongsTo, belongsToMany, getByRelationKey, hasMany, hasOne, indexBelongsToManyRelation, indexBelongsToRelation, indexHasManyRelation, indexHasOneRelation, indexMorphManyRelation, indexMorphOneRelation, indexMorphToRelation, morphMany, morphOne, morphTo, relationMatchKey, };
|
|
@@ -982,26 +982,67 @@ function belongsToMany(definition) {
|
|
|
982
982
|
...definition
|
|
983
983
|
};
|
|
984
984
|
}
|
|
985
|
+
function relationMatchKey(value) {
|
|
986
|
+
if (value === null || value === undefined) {
|
|
987
|
+
return "";
|
|
988
|
+
}
|
|
989
|
+
if (typeof value === "bigint") {
|
|
990
|
+
return value.toString();
|
|
991
|
+
}
|
|
992
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
993
|
+
return String(value);
|
|
994
|
+
}
|
|
995
|
+
if (typeof value === "string" && /^-?\d+$/.test(value)) {
|
|
996
|
+
return BigInt(value).toString();
|
|
997
|
+
}
|
|
998
|
+
return String(value);
|
|
999
|
+
}
|
|
1000
|
+
function getByRelationKey(map, key) {
|
|
1001
|
+
if (map.has(key)) {
|
|
1002
|
+
return map.get(key);
|
|
1003
|
+
}
|
|
1004
|
+
const want = relationMatchKey(key);
|
|
1005
|
+
if (want === "") {
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
1008
|
+
for (const [existing, value] of map) {
|
|
1009
|
+
if (relationMatchKey(existing) === want) {
|
|
1010
|
+
return value;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
985
1015
|
function indexHasManyRelation(parents, children, relation) {
|
|
986
1016
|
const groups = new Map;
|
|
1017
|
+
const originalKeys = new Map;
|
|
987
1018
|
for (const parent of parents) {
|
|
988
|
-
|
|
1019
|
+
const key = relationMatchKey(parent[relation.localKey]);
|
|
1020
|
+
if (!groups.has(key)) {
|
|
1021
|
+
groups.set(key, []);
|
|
1022
|
+
originalKeys.set(key, parent[relation.localKey]);
|
|
1023
|
+
}
|
|
989
1024
|
}
|
|
990
1025
|
for (const child of children) {
|
|
991
|
-
const
|
|
992
|
-
const group = groups.get(key);
|
|
1026
|
+
const group = groups.get(relationMatchKey(child[relation.foreignKey]));
|
|
993
1027
|
if (!group) {
|
|
994
1028
|
continue;
|
|
995
1029
|
}
|
|
996
1030
|
group.push(child);
|
|
997
1031
|
}
|
|
998
|
-
|
|
1032
|
+
const result = new Map;
|
|
1033
|
+
for (const [key, group] of groups) {
|
|
1034
|
+
const original = originalKeys.get(key);
|
|
1035
|
+
if (original !== undefined) {
|
|
1036
|
+
result.set(original, group);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
return result;
|
|
999
1040
|
}
|
|
1000
1041
|
function indexHasOneRelation(parents, children, relation) {
|
|
1001
1042
|
const grouped = indexHasManyRelation(parents, children, relation);
|
|
1002
1043
|
const result = new Map;
|
|
1003
1044
|
for (const parent of parents) {
|
|
1004
|
-
const matches = grouped
|
|
1045
|
+
const matches = getByRelationKey(grouped, parent[relation.localKey]) ?? [];
|
|
1005
1046
|
result.set(parent[relation.localKey], matches[0]);
|
|
1006
1047
|
}
|
|
1007
1048
|
return result;
|
|
@@ -1009,12 +1050,12 @@ function indexHasOneRelation(parents, children, relation) {
|
|
|
1009
1050
|
function indexBelongsToRelation(children, parents, relation) {
|
|
1010
1051
|
const parentsById = new Map;
|
|
1011
1052
|
for (const parent of parents) {
|
|
1012
|
-
parentsById.set(parent[relation.ownerKey], parent);
|
|
1053
|
+
parentsById.set(relationMatchKey(parent[relation.ownerKey]), parent);
|
|
1013
1054
|
}
|
|
1014
1055
|
const result = new Map;
|
|
1015
1056
|
for (const child of children) {
|
|
1016
1057
|
const foreignKey = child[relation.foreignKey];
|
|
1017
|
-
const parent = parentsById.get(foreignKey);
|
|
1058
|
+
const parent = parentsById.get(relationMatchKey(foreignKey));
|
|
1018
1059
|
if (parent) {
|
|
1019
1060
|
result.set(foreignKey, parent);
|
|
1020
1061
|
}
|
|
@@ -1024,23 +1065,33 @@ function indexBelongsToRelation(children, parents, relation) {
|
|
|
1024
1065
|
function indexBelongsToManyRelation(parents, pivotRows, relatedRows, relation) {
|
|
1025
1066
|
const relatedById = new Map;
|
|
1026
1067
|
for (const related of relatedRows) {
|
|
1027
|
-
relatedById.set(related[relation.relatedKey], related);
|
|
1068
|
+
relatedById.set(relationMatchKey(related[relation.relatedKey]), related);
|
|
1028
1069
|
}
|
|
1029
1070
|
const groups = new Map;
|
|
1071
|
+
const originalKeys = new Map;
|
|
1030
1072
|
for (const parent of parents) {
|
|
1031
|
-
|
|
1073
|
+
const key = relationMatchKey(parent[relation.parentKey]);
|
|
1074
|
+
if (!groups.has(key)) {
|
|
1075
|
+
groups.set(key, []);
|
|
1076
|
+
originalKeys.set(key, parent[relation.parentKey]);
|
|
1077
|
+
}
|
|
1032
1078
|
}
|
|
1033
1079
|
for (const pivot of pivotRows) {
|
|
1034
|
-
const
|
|
1035
|
-
const
|
|
1036
|
-
const group = groups.get(parentId);
|
|
1037
|
-
const related = relatedById.get(relatedId);
|
|
1080
|
+
const group = groups.get(relationMatchKey(pivot[relation.foreignPivotKey]));
|
|
1081
|
+
const related = relatedById.get(relationMatchKey(pivot[relation.relatedPivotKey]));
|
|
1038
1082
|
if (!group || !related) {
|
|
1039
1083
|
continue;
|
|
1040
1084
|
}
|
|
1041
1085
|
group.push(related);
|
|
1042
1086
|
}
|
|
1043
|
-
|
|
1087
|
+
const result = new Map;
|
|
1088
|
+
for (const [key, group] of groups) {
|
|
1089
|
+
const original = originalKeys.get(key);
|
|
1090
|
+
if (original !== undefined) {
|
|
1091
|
+
result.set(original, group);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
return result;
|
|
1044
1095
|
}
|
|
1045
1096
|
function morphMany(definition) {
|
|
1046
1097
|
return {
|
|
@@ -1062,27 +1113,38 @@ function morphTo(definition) {
|
|
|
1062
1113
|
}
|
|
1063
1114
|
function indexMorphManyRelation(parents, children, relation) {
|
|
1064
1115
|
const groups = new Map;
|
|
1116
|
+
const originalKeys = new Map;
|
|
1065
1117
|
for (const parent of parents) {
|
|
1066
|
-
|
|
1118
|
+
const key = relationMatchKey(parent[relation.localKey]);
|
|
1119
|
+
if (!groups.has(key)) {
|
|
1120
|
+
groups.set(key, []);
|
|
1121
|
+
originalKeys.set(key, parent[relation.localKey]);
|
|
1122
|
+
}
|
|
1067
1123
|
}
|
|
1068
1124
|
for (const child of children) {
|
|
1069
1125
|
if (child[relation.morphTypeKey] !== relation.morphType) {
|
|
1070
1126
|
continue;
|
|
1071
1127
|
}
|
|
1072
|
-
const
|
|
1073
|
-
const group = groups.get(key);
|
|
1128
|
+
const group = groups.get(relationMatchKey(child[relation.morphIdKey]));
|
|
1074
1129
|
if (!group) {
|
|
1075
1130
|
continue;
|
|
1076
1131
|
}
|
|
1077
1132
|
group.push(child);
|
|
1078
1133
|
}
|
|
1079
|
-
|
|
1134
|
+
const result = new Map;
|
|
1135
|
+
for (const [key, group] of groups) {
|
|
1136
|
+
const original = originalKeys.get(key);
|
|
1137
|
+
if (original !== undefined) {
|
|
1138
|
+
result.set(original, group);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
return result;
|
|
1080
1142
|
}
|
|
1081
1143
|
function indexMorphOneRelation(parents, children, relation) {
|
|
1082
1144
|
const grouped = indexMorphManyRelation(parents, children, relation);
|
|
1083
1145
|
const result = new Map;
|
|
1084
1146
|
for (const parent of parents) {
|
|
1085
|
-
const matches = grouped
|
|
1147
|
+
const matches = getByRelationKey(grouped, parent[relation.localKey]) ?? [];
|
|
1086
1148
|
result.set(parent[relation.localKey], matches[0]);
|
|
1087
1149
|
}
|
|
1088
1150
|
return result;
|
|
@@ -1095,7 +1157,7 @@ function indexMorphToRelation(children, parentsByType, relation) {
|
|
|
1095
1157
|
if (!parents) {
|
|
1096
1158
|
continue;
|
|
1097
1159
|
}
|
|
1098
|
-
const parent = parents
|
|
1160
|
+
const parent = getByRelationKey(parents, child[relation.morphIdKey]);
|
|
1099
1161
|
if (parent) {
|
|
1100
1162
|
result.set(child[relation.morphIdKey], parent);
|
|
1101
1163
|
}
|
|
@@ -1762,7 +1824,7 @@ class Model {
|
|
|
1762
1824
|
}
|
|
1763
1825
|
async loadHasMany(as, relation, childRepository, options = {}) {
|
|
1764
1826
|
const grouped = await childRepository.withConnection(this.repository.getConnection()).loadHasManyForParents([this.attributes], relation, options);
|
|
1765
|
-
const loaded = grouped
|
|
1827
|
+
const loaded = getByRelationKey(grouped, this.attributes[relation.localKey]) ?? [];
|
|
1766
1828
|
return Object.assign(this, { [as]: loaded });
|
|
1767
1829
|
}
|
|
1768
1830
|
async loadHasOne(as, relation, childRepository, options = {}) {
|
|
@@ -1772,7 +1834,7 @@ class Model {
|
|
|
1772
1834
|
}
|
|
1773
1835
|
async loadBelongsTo(as, relation, parentRepository, options = {}) {
|
|
1774
1836
|
const grouped = await this.repository.loadBelongsToForParents([this.attributes], relation, parentRepository, options);
|
|
1775
|
-
const loaded = grouped
|
|
1837
|
+
const loaded = getByRelationKey(grouped, this.attributes[relation.foreignKey]);
|
|
1776
1838
|
return Object.assign(this, { [as]: loaded });
|
|
1777
1839
|
}
|
|
1778
1840
|
async loadBelongsToMany(as, relation, relatedRepository, options = {}) {
|
|
@@ -1792,7 +1854,7 @@ class Model {
|
|
|
1792
1854
|
}
|
|
1793
1855
|
});
|
|
1794
1856
|
const grouped = indexBelongsToManyRelation([this.attributes], pivotRows, relatedRows, relation);
|
|
1795
|
-
const loaded = grouped
|
|
1857
|
+
const loaded = getByRelationKey(grouped, parentId) ?? [];
|
|
1796
1858
|
return Object.assign(this, { [as]: loaded });
|
|
1797
1859
|
}
|
|
1798
1860
|
hasMany(related, foreignKey, localKey) {
|
|
@@ -24,26 +24,67 @@ function belongsToMany(definition) {
|
|
|
24
24
|
...definition
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
function relationMatchKey(value) {
|
|
28
|
+
if (value === null || value === undefined) {
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
if (typeof value === "bigint") {
|
|
32
|
+
return value.toString();
|
|
33
|
+
}
|
|
34
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
35
|
+
return String(value);
|
|
36
|
+
}
|
|
37
|
+
if (typeof value === "string" && /^-?\d+$/.test(value)) {
|
|
38
|
+
return BigInt(value).toString();
|
|
39
|
+
}
|
|
40
|
+
return String(value);
|
|
41
|
+
}
|
|
42
|
+
function getByRelationKey(map, key) {
|
|
43
|
+
if (map.has(key)) {
|
|
44
|
+
return map.get(key);
|
|
45
|
+
}
|
|
46
|
+
const want = relationMatchKey(key);
|
|
47
|
+
if (want === "") {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
for (const [existing, value] of map) {
|
|
51
|
+
if (relationMatchKey(existing) === want) {
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
27
57
|
function indexHasManyRelation(parents, children, relation) {
|
|
28
58
|
const groups = new Map;
|
|
59
|
+
const originalKeys = new Map;
|
|
29
60
|
for (const parent of parents) {
|
|
30
|
-
|
|
61
|
+
const key = relationMatchKey(parent[relation.localKey]);
|
|
62
|
+
if (!groups.has(key)) {
|
|
63
|
+
groups.set(key, []);
|
|
64
|
+
originalKeys.set(key, parent[relation.localKey]);
|
|
65
|
+
}
|
|
31
66
|
}
|
|
32
67
|
for (const child of children) {
|
|
33
|
-
const
|
|
34
|
-
const group = groups.get(key);
|
|
68
|
+
const group = groups.get(relationMatchKey(child[relation.foreignKey]));
|
|
35
69
|
if (!group) {
|
|
36
70
|
continue;
|
|
37
71
|
}
|
|
38
72
|
group.push(child);
|
|
39
73
|
}
|
|
40
|
-
|
|
74
|
+
const result = new Map;
|
|
75
|
+
for (const [key, group] of groups) {
|
|
76
|
+
const original = originalKeys.get(key);
|
|
77
|
+
if (original !== undefined) {
|
|
78
|
+
result.set(original, group);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
41
82
|
}
|
|
42
83
|
function indexHasOneRelation(parents, children, relation) {
|
|
43
84
|
const grouped = indexHasManyRelation(parents, children, relation);
|
|
44
85
|
const result = new Map;
|
|
45
86
|
for (const parent of parents) {
|
|
46
|
-
const matches = grouped
|
|
87
|
+
const matches = getByRelationKey(grouped, parent[relation.localKey]) ?? [];
|
|
47
88
|
result.set(parent[relation.localKey], matches[0]);
|
|
48
89
|
}
|
|
49
90
|
return result;
|
|
@@ -51,12 +92,12 @@ function indexHasOneRelation(parents, children, relation) {
|
|
|
51
92
|
function indexBelongsToRelation(children, parents, relation) {
|
|
52
93
|
const parentsById = new Map;
|
|
53
94
|
for (const parent of parents) {
|
|
54
|
-
parentsById.set(parent[relation.ownerKey], parent);
|
|
95
|
+
parentsById.set(relationMatchKey(parent[relation.ownerKey]), parent);
|
|
55
96
|
}
|
|
56
97
|
const result = new Map;
|
|
57
98
|
for (const child of children) {
|
|
58
99
|
const foreignKey = child[relation.foreignKey];
|
|
59
|
-
const parent = parentsById.get(foreignKey);
|
|
100
|
+
const parent = parentsById.get(relationMatchKey(foreignKey));
|
|
60
101
|
if (parent) {
|
|
61
102
|
result.set(foreignKey, parent);
|
|
62
103
|
}
|
|
@@ -66,23 +107,33 @@ function indexBelongsToRelation(children, parents, relation) {
|
|
|
66
107
|
function indexBelongsToManyRelation(parents, pivotRows, relatedRows, relation) {
|
|
67
108
|
const relatedById = new Map;
|
|
68
109
|
for (const related of relatedRows) {
|
|
69
|
-
relatedById.set(related[relation.relatedKey], related);
|
|
110
|
+
relatedById.set(relationMatchKey(related[relation.relatedKey]), related);
|
|
70
111
|
}
|
|
71
112
|
const groups = new Map;
|
|
113
|
+
const originalKeys = new Map;
|
|
72
114
|
for (const parent of parents) {
|
|
73
|
-
|
|
115
|
+
const key = relationMatchKey(parent[relation.parentKey]);
|
|
116
|
+
if (!groups.has(key)) {
|
|
117
|
+
groups.set(key, []);
|
|
118
|
+
originalKeys.set(key, parent[relation.parentKey]);
|
|
119
|
+
}
|
|
74
120
|
}
|
|
75
121
|
for (const pivot of pivotRows) {
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
const group = groups.get(parentId);
|
|
79
|
-
const related = relatedById.get(relatedId);
|
|
122
|
+
const group = groups.get(relationMatchKey(pivot[relation.foreignPivotKey]));
|
|
123
|
+
const related = relatedById.get(relationMatchKey(pivot[relation.relatedPivotKey]));
|
|
80
124
|
if (!group || !related) {
|
|
81
125
|
continue;
|
|
82
126
|
}
|
|
83
127
|
group.push(related);
|
|
84
128
|
}
|
|
85
|
-
|
|
129
|
+
const result = new Map;
|
|
130
|
+
for (const [key, group] of groups) {
|
|
131
|
+
const original = originalKeys.get(key);
|
|
132
|
+
if (original !== undefined) {
|
|
133
|
+
result.set(original, group);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return result;
|
|
86
137
|
}
|
|
87
138
|
function morphMany(definition) {
|
|
88
139
|
return {
|
|
@@ -104,27 +155,38 @@ function morphTo(definition) {
|
|
|
104
155
|
}
|
|
105
156
|
function indexMorphManyRelation(parents, children, relation) {
|
|
106
157
|
const groups = new Map;
|
|
158
|
+
const originalKeys = new Map;
|
|
107
159
|
for (const parent of parents) {
|
|
108
|
-
|
|
160
|
+
const key = relationMatchKey(parent[relation.localKey]);
|
|
161
|
+
if (!groups.has(key)) {
|
|
162
|
+
groups.set(key, []);
|
|
163
|
+
originalKeys.set(key, parent[relation.localKey]);
|
|
164
|
+
}
|
|
109
165
|
}
|
|
110
166
|
for (const child of children) {
|
|
111
167
|
if (child[relation.morphTypeKey] !== relation.morphType) {
|
|
112
168
|
continue;
|
|
113
169
|
}
|
|
114
|
-
const
|
|
115
|
-
const group = groups.get(key);
|
|
170
|
+
const group = groups.get(relationMatchKey(child[relation.morphIdKey]));
|
|
116
171
|
if (!group) {
|
|
117
172
|
continue;
|
|
118
173
|
}
|
|
119
174
|
group.push(child);
|
|
120
175
|
}
|
|
121
|
-
|
|
176
|
+
const result = new Map;
|
|
177
|
+
for (const [key, group] of groups) {
|
|
178
|
+
const original = originalKeys.get(key);
|
|
179
|
+
if (original !== undefined) {
|
|
180
|
+
result.set(original, group);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
122
184
|
}
|
|
123
185
|
function indexMorphOneRelation(parents, children, relation) {
|
|
124
186
|
const grouped = indexMorphManyRelation(parents, children, relation);
|
|
125
187
|
const result = new Map;
|
|
126
188
|
for (const parent of parents) {
|
|
127
|
-
const matches = grouped
|
|
189
|
+
const matches = getByRelationKey(grouped, parent[relation.localKey]) ?? [];
|
|
128
190
|
result.set(parent[relation.localKey], matches[0]);
|
|
129
191
|
}
|
|
130
192
|
return result;
|
|
@@ -137,7 +199,7 @@ function indexMorphToRelation(children, parentsByType, relation) {
|
|
|
137
199
|
if (!parents) {
|
|
138
200
|
continue;
|
|
139
201
|
}
|
|
140
|
-
const parent = parents
|
|
202
|
+
const parent = getByRelationKey(parents, child[relation.morphIdKey]);
|
|
141
203
|
if (parent) {
|
|
142
204
|
result.set(child[relation.morphIdKey], parent);
|
|
143
205
|
}
|
|
@@ -147,6 +209,7 @@ function indexMorphToRelation(children, parentsByType, relation) {
|
|
|
147
209
|
export {
|
|
148
210
|
belongsTo,
|
|
149
211
|
belongsToMany,
|
|
212
|
+
getByRelationKey,
|
|
150
213
|
hasMany,
|
|
151
214
|
hasOne,
|
|
152
215
|
indexBelongsToManyRelation,
|
|
@@ -158,5 +221,6 @@ export {
|
|
|
158
221
|
indexMorphToRelation,
|
|
159
222
|
morphMany,
|
|
160
223
|
morphOne,
|
|
161
|
-
morphTo
|
|
224
|
+
morphTo,
|
|
225
|
+
relationMatchKey
|
|
162
226
|
};
|
|
@@ -422,6 +422,214 @@ function buildDeleteByIdQuery(table, id) {
|
|
|
422
422
|
};
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
+
// ../../src/core/database/relationships.ts
|
|
426
|
+
function hasMany(definition) {
|
|
427
|
+
return {
|
|
428
|
+
type: "hasMany",
|
|
429
|
+
...definition
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
function hasOne(definition) {
|
|
433
|
+
return {
|
|
434
|
+
type: "hasOne",
|
|
435
|
+
...definition
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
function belongsTo(definition) {
|
|
439
|
+
return {
|
|
440
|
+
type: "belongsTo",
|
|
441
|
+
...definition
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
function belongsToMany(definition) {
|
|
445
|
+
return {
|
|
446
|
+
type: "belongsToMany",
|
|
447
|
+
...definition
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
function relationMatchKey(value) {
|
|
451
|
+
if (value === null || value === undefined) {
|
|
452
|
+
return "";
|
|
453
|
+
}
|
|
454
|
+
if (typeof value === "bigint") {
|
|
455
|
+
return value.toString();
|
|
456
|
+
}
|
|
457
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
458
|
+
return String(value);
|
|
459
|
+
}
|
|
460
|
+
if (typeof value === "string" && /^-?\d+$/.test(value)) {
|
|
461
|
+
return BigInt(value).toString();
|
|
462
|
+
}
|
|
463
|
+
return String(value);
|
|
464
|
+
}
|
|
465
|
+
function getByRelationKey(map, key) {
|
|
466
|
+
if (map.has(key)) {
|
|
467
|
+
return map.get(key);
|
|
468
|
+
}
|
|
469
|
+
const want = relationMatchKey(key);
|
|
470
|
+
if (want === "") {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
for (const [existing, value] of map) {
|
|
474
|
+
if (relationMatchKey(existing) === want) {
|
|
475
|
+
return value;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
function indexHasManyRelation(parents, children, relation) {
|
|
481
|
+
const groups = new Map;
|
|
482
|
+
const originalKeys = new Map;
|
|
483
|
+
for (const parent of parents) {
|
|
484
|
+
const key = relationMatchKey(parent[relation.localKey]);
|
|
485
|
+
if (!groups.has(key)) {
|
|
486
|
+
groups.set(key, []);
|
|
487
|
+
originalKeys.set(key, parent[relation.localKey]);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
for (const child of children) {
|
|
491
|
+
const group = groups.get(relationMatchKey(child[relation.foreignKey]));
|
|
492
|
+
if (!group) {
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
group.push(child);
|
|
496
|
+
}
|
|
497
|
+
const result = new Map;
|
|
498
|
+
for (const [key, group] of groups) {
|
|
499
|
+
const original = originalKeys.get(key);
|
|
500
|
+
if (original !== undefined) {
|
|
501
|
+
result.set(original, group);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
return result;
|
|
505
|
+
}
|
|
506
|
+
function indexHasOneRelation(parents, children, relation) {
|
|
507
|
+
const grouped = indexHasManyRelation(parents, children, relation);
|
|
508
|
+
const result = new Map;
|
|
509
|
+
for (const parent of parents) {
|
|
510
|
+
const matches = getByRelationKey(grouped, parent[relation.localKey]) ?? [];
|
|
511
|
+
result.set(parent[relation.localKey], matches[0]);
|
|
512
|
+
}
|
|
513
|
+
return result;
|
|
514
|
+
}
|
|
515
|
+
function indexBelongsToRelation(children, parents, relation) {
|
|
516
|
+
const parentsById = new Map;
|
|
517
|
+
for (const parent of parents) {
|
|
518
|
+
parentsById.set(relationMatchKey(parent[relation.ownerKey]), parent);
|
|
519
|
+
}
|
|
520
|
+
const result = new Map;
|
|
521
|
+
for (const child of children) {
|
|
522
|
+
const foreignKey = child[relation.foreignKey];
|
|
523
|
+
const parent = parentsById.get(relationMatchKey(foreignKey));
|
|
524
|
+
if (parent) {
|
|
525
|
+
result.set(foreignKey, parent);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
return result;
|
|
529
|
+
}
|
|
530
|
+
function indexBelongsToManyRelation(parents, pivotRows, relatedRows, relation) {
|
|
531
|
+
const relatedById = new Map;
|
|
532
|
+
for (const related of relatedRows) {
|
|
533
|
+
relatedById.set(relationMatchKey(related[relation.relatedKey]), related);
|
|
534
|
+
}
|
|
535
|
+
const groups = new Map;
|
|
536
|
+
const originalKeys = new Map;
|
|
537
|
+
for (const parent of parents) {
|
|
538
|
+
const key = relationMatchKey(parent[relation.parentKey]);
|
|
539
|
+
if (!groups.has(key)) {
|
|
540
|
+
groups.set(key, []);
|
|
541
|
+
originalKeys.set(key, parent[relation.parentKey]);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
for (const pivot of pivotRows) {
|
|
545
|
+
const group = groups.get(relationMatchKey(pivot[relation.foreignPivotKey]));
|
|
546
|
+
const related = relatedById.get(relationMatchKey(pivot[relation.relatedPivotKey]));
|
|
547
|
+
if (!group || !related) {
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
group.push(related);
|
|
551
|
+
}
|
|
552
|
+
const result = new Map;
|
|
553
|
+
for (const [key, group] of groups) {
|
|
554
|
+
const original = originalKeys.get(key);
|
|
555
|
+
if (original !== undefined) {
|
|
556
|
+
result.set(original, group);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return result;
|
|
560
|
+
}
|
|
561
|
+
function morphMany(definition) {
|
|
562
|
+
return {
|
|
563
|
+
type: "morphMany",
|
|
564
|
+
...definition
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
function morphOne(definition) {
|
|
568
|
+
return {
|
|
569
|
+
type: "morphOne",
|
|
570
|
+
...definition
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
function morphTo(definition) {
|
|
574
|
+
return {
|
|
575
|
+
type: "morphTo",
|
|
576
|
+
...definition
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
function indexMorphManyRelation(parents, children, relation) {
|
|
580
|
+
const groups = new Map;
|
|
581
|
+
const originalKeys = new Map;
|
|
582
|
+
for (const parent of parents) {
|
|
583
|
+
const key = relationMatchKey(parent[relation.localKey]);
|
|
584
|
+
if (!groups.has(key)) {
|
|
585
|
+
groups.set(key, []);
|
|
586
|
+
originalKeys.set(key, parent[relation.localKey]);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
for (const child of children) {
|
|
590
|
+
if (child[relation.morphTypeKey] !== relation.morphType) {
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
593
|
+
const group = groups.get(relationMatchKey(child[relation.morphIdKey]));
|
|
594
|
+
if (!group) {
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
group.push(child);
|
|
598
|
+
}
|
|
599
|
+
const result = new Map;
|
|
600
|
+
for (const [key, group] of groups) {
|
|
601
|
+
const original = originalKeys.get(key);
|
|
602
|
+
if (original !== undefined) {
|
|
603
|
+
result.set(original, group);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
return result;
|
|
607
|
+
}
|
|
608
|
+
function indexMorphOneRelation(parents, children, relation) {
|
|
609
|
+
const grouped = indexMorphManyRelation(parents, children, relation);
|
|
610
|
+
const result = new Map;
|
|
611
|
+
for (const parent of parents) {
|
|
612
|
+
const matches = getByRelationKey(grouped, parent[relation.localKey]) ?? [];
|
|
613
|
+
result.set(parent[relation.localKey], matches[0]);
|
|
614
|
+
}
|
|
615
|
+
return result;
|
|
616
|
+
}
|
|
617
|
+
function indexMorphToRelation(children, parentsByType, relation) {
|
|
618
|
+
const result = new Map;
|
|
619
|
+
for (const child of children) {
|
|
620
|
+
const morphType = String(child[relation.morphTypeKey]);
|
|
621
|
+
const parents = parentsByType.get(morphType);
|
|
622
|
+
if (!parents) {
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
const parent = getByRelationKey(parents, child[relation.morphIdKey]);
|
|
626
|
+
if (parent) {
|
|
627
|
+
result.set(child[relation.morphIdKey], parent);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
return result;
|
|
631
|
+
}
|
|
632
|
+
|
|
425
633
|
// ../../src/core/database/whereBuilder.ts
|
|
426
634
|
class WhereBuilder {
|
|
427
635
|
nodes = [];
|
|
@@ -652,7 +860,7 @@ class RepositoryQuery {
|
|
|
652
860
|
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadHasManyForParents(rows, relation2, load.options);
|
|
653
861
|
result = result.map((row) => ({
|
|
654
862
|
...row,
|
|
655
|
-
[load.as]: grouped2
|
|
863
|
+
[load.as]: getByRelationKey(grouped2, row[relation2.localKey]) ?? []
|
|
656
864
|
}));
|
|
657
865
|
continue;
|
|
658
866
|
}
|
|
@@ -661,7 +869,7 @@ class RepositoryQuery {
|
|
|
661
869
|
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadMorphManyForParents(rows, relation2, load.options);
|
|
662
870
|
result = result.map((row) => ({
|
|
663
871
|
...row,
|
|
664
|
-
[load.as]: grouped2
|
|
872
|
+
[load.as]: getByRelationKey(grouped2, row[relation2.localKey]) ?? []
|
|
665
873
|
}));
|
|
666
874
|
continue;
|
|
667
875
|
}
|
|
@@ -670,7 +878,7 @@ class RepositoryQuery {
|
|
|
670
878
|
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadMorphOneForParents(rows, relation2, load.options);
|
|
671
879
|
result = result.map((row) => ({
|
|
672
880
|
...row,
|
|
673
|
-
[load.as]: grouped2
|
|
881
|
+
[load.as]: getByRelationKey(grouped2, row[relation2.localKey])
|
|
674
882
|
}));
|
|
675
883
|
continue;
|
|
676
884
|
}
|
|
@@ -679,7 +887,7 @@ class RepositoryQuery {
|
|
|
679
887
|
const grouped2 = await this.repository.loadBelongsToManyForParents(rows, relation2, load.repository, load.options);
|
|
680
888
|
result = result.map((row) => ({
|
|
681
889
|
...row,
|
|
682
|
-
[load.as]: grouped2
|
|
890
|
+
[load.as]: getByRelationKey(grouped2, row[relation2.parentKey]) ?? []
|
|
683
891
|
}));
|
|
684
892
|
continue;
|
|
685
893
|
}
|
|
@@ -688,7 +896,7 @@ class RepositoryQuery {
|
|
|
688
896
|
const grouped2 = await this.repository.loadMorphToForChildren(rows, relation2, load.morphRepositories ?? new Map, load.options);
|
|
689
897
|
result = result.map((row) => ({
|
|
690
898
|
...row,
|
|
691
|
-
[load.as]: grouped2
|
|
899
|
+
[load.as]: getByRelationKey(grouped2, row[relation2.morphIdKey])
|
|
692
900
|
}));
|
|
693
901
|
continue;
|
|
694
902
|
}
|
|
@@ -696,7 +904,7 @@ class RepositoryQuery {
|
|
|
696
904
|
const grouped = await this.repository.loadBelongsToForParents(rows, relation, load.repository, load.options);
|
|
697
905
|
result = result.map((row) => ({
|
|
698
906
|
...row,
|
|
699
|
-
[load.as]: grouped
|
|
907
|
+
[load.as]: getByRelationKey(grouped, row[relation.foreignKey])
|
|
700
908
|
}));
|
|
701
909
|
}
|
|
702
910
|
return result;
|
package/dist/index.js
CHANGED
|
@@ -2084,26 +2084,67 @@ function belongsToMany(definition) {
|
|
|
2084
2084
|
...definition
|
|
2085
2085
|
};
|
|
2086
2086
|
}
|
|
2087
|
+
function relationMatchKey(value) {
|
|
2088
|
+
if (value === null || value === undefined) {
|
|
2089
|
+
return "";
|
|
2090
|
+
}
|
|
2091
|
+
if (typeof value === "bigint") {
|
|
2092
|
+
return value.toString();
|
|
2093
|
+
}
|
|
2094
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2095
|
+
return String(value);
|
|
2096
|
+
}
|
|
2097
|
+
if (typeof value === "string" && /^-?\d+$/.test(value)) {
|
|
2098
|
+
return BigInt(value).toString();
|
|
2099
|
+
}
|
|
2100
|
+
return String(value);
|
|
2101
|
+
}
|
|
2102
|
+
function getByRelationKey(map, key) {
|
|
2103
|
+
if (map.has(key)) {
|
|
2104
|
+
return map.get(key);
|
|
2105
|
+
}
|
|
2106
|
+
const want = relationMatchKey(key);
|
|
2107
|
+
if (want === "") {
|
|
2108
|
+
return;
|
|
2109
|
+
}
|
|
2110
|
+
for (const [existing, value] of map) {
|
|
2111
|
+
if (relationMatchKey(existing) === want) {
|
|
2112
|
+
return value;
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
return;
|
|
2116
|
+
}
|
|
2087
2117
|
function indexHasManyRelation(parents, children, relation) {
|
|
2088
2118
|
const groups = new Map;
|
|
2119
|
+
const originalKeys = new Map;
|
|
2089
2120
|
for (const parent of parents) {
|
|
2090
|
-
|
|
2121
|
+
const key = relationMatchKey(parent[relation.localKey]);
|
|
2122
|
+
if (!groups.has(key)) {
|
|
2123
|
+
groups.set(key, []);
|
|
2124
|
+
originalKeys.set(key, parent[relation.localKey]);
|
|
2125
|
+
}
|
|
2091
2126
|
}
|
|
2092
2127
|
for (const child of children) {
|
|
2093
|
-
const
|
|
2094
|
-
const group = groups.get(key);
|
|
2128
|
+
const group = groups.get(relationMatchKey(child[relation.foreignKey]));
|
|
2095
2129
|
if (!group) {
|
|
2096
2130
|
continue;
|
|
2097
2131
|
}
|
|
2098
2132
|
group.push(child);
|
|
2099
2133
|
}
|
|
2100
|
-
|
|
2134
|
+
const result = new Map;
|
|
2135
|
+
for (const [key, group] of groups) {
|
|
2136
|
+
const original = originalKeys.get(key);
|
|
2137
|
+
if (original !== undefined) {
|
|
2138
|
+
result.set(original, group);
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
return result;
|
|
2101
2142
|
}
|
|
2102
2143
|
function indexHasOneRelation(parents, children, relation) {
|
|
2103
2144
|
const grouped = indexHasManyRelation(parents, children, relation);
|
|
2104
2145
|
const result = new Map;
|
|
2105
2146
|
for (const parent of parents) {
|
|
2106
|
-
const matches = grouped
|
|
2147
|
+
const matches = getByRelationKey(grouped, parent[relation.localKey]) ?? [];
|
|
2107
2148
|
result.set(parent[relation.localKey], matches[0]);
|
|
2108
2149
|
}
|
|
2109
2150
|
return result;
|
|
@@ -2111,12 +2152,12 @@ function indexHasOneRelation(parents, children, relation) {
|
|
|
2111
2152
|
function indexBelongsToRelation(children, parents, relation) {
|
|
2112
2153
|
const parentsById = new Map;
|
|
2113
2154
|
for (const parent of parents) {
|
|
2114
|
-
parentsById.set(parent[relation.ownerKey], parent);
|
|
2155
|
+
parentsById.set(relationMatchKey(parent[relation.ownerKey]), parent);
|
|
2115
2156
|
}
|
|
2116
2157
|
const result = new Map;
|
|
2117
2158
|
for (const child of children) {
|
|
2118
2159
|
const foreignKey = child[relation.foreignKey];
|
|
2119
|
-
const parent = parentsById.get(foreignKey);
|
|
2160
|
+
const parent = parentsById.get(relationMatchKey(foreignKey));
|
|
2120
2161
|
if (parent) {
|
|
2121
2162
|
result.set(foreignKey, parent);
|
|
2122
2163
|
}
|
|
@@ -2126,23 +2167,33 @@ function indexBelongsToRelation(children, parents, relation) {
|
|
|
2126
2167
|
function indexBelongsToManyRelation(parents, pivotRows, relatedRows, relation) {
|
|
2127
2168
|
const relatedById = new Map;
|
|
2128
2169
|
for (const related of relatedRows) {
|
|
2129
|
-
relatedById.set(related[relation.relatedKey], related);
|
|
2170
|
+
relatedById.set(relationMatchKey(related[relation.relatedKey]), related);
|
|
2130
2171
|
}
|
|
2131
2172
|
const groups = new Map;
|
|
2173
|
+
const originalKeys = new Map;
|
|
2132
2174
|
for (const parent of parents) {
|
|
2133
|
-
|
|
2175
|
+
const key = relationMatchKey(parent[relation.parentKey]);
|
|
2176
|
+
if (!groups.has(key)) {
|
|
2177
|
+
groups.set(key, []);
|
|
2178
|
+
originalKeys.set(key, parent[relation.parentKey]);
|
|
2179
|
+
}
|
|
2134
2180
|
}
|
|
2135
2181
|
for (const pivot of pivotRows) {
|
|
2136
|
-
const
|
|
2137
|
-
const
|
|
2138
|
-
const group = groups.get(parentId);
|
|
2139
|
-
const related = relatedById.get(relatedId);
|
|
2182
|
+
const group = groups.get(relationMatchKey(pivot[relation.foreignPivotKey]));
|
|
2183
|
+
const related = relatedById.get(relationMatchKey(pivot[relation.relatedPivotKey]));
|
|
2140
2184
|
if (!group || !related) {
|
|
2141
2185
|
continue;
|
|
2142
2186
|
}
|
|
2143
2187
|
group.push(related);
|
|
2144
2188
|
}
|
|
2145
|
-
|
|
2189
|
+
const result = new Map;
|
|
2190
|
+
for (const [key, group] of groups) {
|
|
2191
|
+
const original = originalKeys.get(key);
|
|
2192
|
+
if (original !== undefined) {
|
|
2193
|
+
result.set(original, group);
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
return result;
|
|
2146
2197
|
}
|
|
2147
2198
|
function morphMany(definition) {
|
|
2148
2199
|
return {
|
|
@@ -2164,27 +2215,38 @@ function morphTo(definition) {
|
|
|
2164
2215
|
}
|
|
2165
2216
|
function indexMorphManyRelation(parents, children, relation) {
|
|
2166
2217
|
const groups = new Map;
|
|
2218
|
+
const originalKeys = new Map;
|
|
2167
2219
|
for (const parent of parents) {
|
|
2168
|
-
|
|
2220
|
+
const key = relationMatchKey(parent[relation.localKey]);
|
|
2221
|
+
if (!groups.has(key)) {
|
|
2222
|
+
groups.set(key, []);
|
|
2223
|
+
originalKeys.set(key, parent[relation.localKey]);
|
|
2224
|
+
}
|
|
2169
2225
|
}
|
|
2170
2226
|
for (const child of children) {
|
|
2171
2227
|
if (child[relation.morphTypeKey] !== relation.morphType) {
|
|
2172
2228
|
continue;
|
|
2173
2229
|
}
|
|
2174
|
-
const
|
|
2175
|
-
const group = groups.get(key);
|
|
2230
|
+
const group = groups.get(relationMatchKey(child[relation.morphIdKey]));
|
|
2176
2231
|
if (!group) {
|
|
2177
2232
|
continue;
|
|
2178
2233
|
}
|
|
2179
2234
|
group.push(child);
|
|
2180
2235
|
}
|
|
2181
|
-
|
|
2236
|
+
const result = new Map;
|
|
2237
|
+
for (const [key, group] of groups) {
|
|
2238
|
+
const original = originalKeys.get(key);
|
|
2239
|
+
if (original !== undefined) {
|
|
2240
|
+
result.set(original, group);
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
return result;
|
|
2182
2244
|
}
|
|
2183
2245
|
function indexMorphOneRelation(parents, children, relation) {
|
|
2184
2246
|
const grouped = indexMorphManyRelation(parents, children, relation);
|
|
2185
2247
|
const result = new Map;
|
|
2186
2248
|
for (const parent of parents) {
|
|
2187
|
-
const matches = grouped
|
|
2249
|
+
const matches = getByRelationKey(grouped, parent[relation.localKey]) ?? [];
|
|
2188
2250
|
result.set(parent[relation.localKey], matches[0]);
|
|
2189
2251
|
}
|
|
2190
2252
|
return result;
|
|
@@ -2197,7 +2259,7 @@ function indexMorphToRelation(children, parentsByType, relation) {
|
|
|
2197
2259
|
if (!parents) {
|
|
2198
2260
|
continue;
|
|
2199
2261
|
}
|
|
2200
|
-
const parent = parents
|
|
2262
|
+
const parent = getByRelationKey(parents, child[relation.morphIdKey]);
|
|
2201
2263
|
if (parent) {
|
|
2202
2264
|
result.set(child[relation.morphIdKey], parent);
|
|
2203
2265
|
}
|
|
@@ -2435,7 +2497,7 @@ class RepositoryQuery {
|
|
|
2435
2497
|
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadHasManyForParents(rows, relation2, load.options);
|
|
2436
2498
|
result = result.map((row) => ({
|
|
2437
2499
|
...row,
|
|
2438
|
-
[load.as]: grouped2
|
|
2500
|
+
[load.as]: getByRelationKey(grouped2, row[relation2.localKey]) ?? []
|
|
2439
2501
|
}));
|
|
2440
2502
|
continue;
|
|
2441
2503
|
}
|
|
@@ -2444,7 +2506,7 @@ class RepositoryQuery {
|
|
|
2444
2506
|
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadMorphManyForParents(rows, relation2, load.options);
|
|
2445
2507
|
result = result.map((row) => ({
|
|
2446
2508
|
...row,
|
|
2447
|
-
[load.as]: grouped2
|
|
2509
|
+
[load.as]: getByRelationKey(grouped2, row[relation2.localKey]) ?? []
|
|
2448
2510
|
}));
|
|
2449
2511
|
continue;
|
|
2450
2512
|
}
|
|
@@ -2453,7 +2515,7 @@ class RepositoryQuery {
|
|
|
2453
2515
|
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadMorphOneForParents(rows, relation2, load.options);
|
|
2454
2516
|
result = result.map((row) => ({
|
|
2455
2517
|
...row,
|
|
2456
|
-
[load.as]: grouped2
|
|
2518
|
+
[load.as]: getByRelationKey(grouped2, row[relation2.localKey])
|
|
2457
2519
|
}));
|
|
2458
2520
|
continue;
|
|
2459
2521
|
}
|
|
@@ -2462,7 +2524,7 @@ class RepositoryQuery {
|
|
|
2462
2524
|
const grouped2 = await this.repository.loadBelongsToManyForParents(rows, relation2, load.repository, load.options);
|
|
2463
2525
|
result = result.map((row) => ({
|
|
2464
2526
|
...row,
|
|
2465
|
-
[load.as]: grouped2
|
|
2527
|
+
[load.as]: getByRelationKey(grouped2, row[relation2.parentKey]) ?? []
|
|
2466
2528
|
}));
|
|
2467
2529
|
continue;
|
|
2468
2530
|
}
|
|
@@ -2471,7 +2533,7 @@ class RepositoryQuery {
|
|
|
2471
2533
|
const grouped2 = await this.repository.loadMorphToForChildren(rows, relation2, load.morphRepositories ?? new Map, load.options);
|
|
2472
2534
|
result = result.map((row) => ({
|
|
2473
2535
|
...row,
|
|
2474
|
-
[load.as]: grouped2
|
|
2536
|
+
[load.as]: getByRelationKey(grouped2, row[relation2.morphIdKey])
|
|
2475
2537
|
}));
|
|
2476
2538
|
continue;
|
|
2477
2539
|
}
|
|
@@ -2479,7 +2541,7 @@ class RepositoryQuery {
|
|
|
2479
2541
|
const grouped = await this.repository.loadBelongsToForParents(rows, relation, load.repository, load.options);
|
|
2480
2542
|
result = result.map((row) => ({
|
|
2481
2543
|
...row,
|
|
2482
|
-
[load.as]: grouped
|
|
2544
|
+
[load.as]: getByRelationKey(grouped, row[relation.foreignKey])
|
|
2483
2545
|
}));
|
|
2484
2546
|
}
|
|
2485
2547
|
return result;
|
|
@@ -2770,7 +2832,7 @@ class BaseRepository {
|
|
|
2770
2832
|
const grouped = await this.loadMorphManyForParents(parents, relation, options);
|
|
2771
2833
|
const result = new Map;
|
|
2772
2834
|
for (const parent of parents) {
|
|
2773
|
-
const matches = grouped
|
|
2835
|
+
const matches = getByRelationKey(grouped, parent[relation.localKey]) ?? [];
|
|
2774
2836
|
result.set(parent[relation.localKey], matches[0]);
|
|
2775
2837
|
}
|
|
2776
2838
|
return result;
|
|
@@ -2799,7 +2861,7 @@ class BaseRepository {
|
|
|
2799
2861
|
}, options);
|
|
2800
2862
|
const indexed = new Map;
|
|
2801
2863
|
for (const parent of parents) {
|
|
2802
|
-
indexed.set(parent[ownerKey], parent);
|
|
2864
|
+
indexed.set(relationMatchKey(parent[ownerKey]), parent);
|
|
2803
2865
|
}
|
|
2804
2866
|
parentsByType.set(morphType, indexed);
|
|
2805
2867
|
}
|
|
@@ -4313,7 +4375,7 @@ class Model {
|
|
|
4313
4375
|
}
|
|
4314
4376
|
async loadHasMany(as, relation, childRepository, options = {}) {
|
|
4315
4377
|
const grouped = await childRepository.withConnection(this.repository.getConnection()).loadHasManyForParents([this.attributes], relation, options);
|
|
4316
|
-
const loaded = grouped
|
|
4378
|
+
const loaded = getByRelationKey(grouped, this.attributes[relation.localKey]) ?? [];
|
|
4317
4379
|
return Object.assign(this, { [as]: loaded });
|
|
4318
4380
|
}
|
|
4319
4381
|
async loadHasOne(as, relation, childRepository, options = {}) {
|
|
@@ -4323,7 +4385,7 @@ class Model {
|
|
|
4323
4385
|
}
|
|
4324
4386
|
async loadBelongsTo(as, relation, parentRepository, options = {}) {
|
|
4325
4387
|
const grouped = await this.repository.loadBelongsToForParents([this.attributes], relation, parentRepository, options);
|
|
4326
|
-
const loaded = grouped
|
|
4388
|
+
const loaded = getByRelationKey(grouped, this.attributes[relation.foreignKey]);
|
|
4327
4389
|
return Object.assign(this, { [as]: loaded });
|
|
4328
4390
|
}
|
|
4329
4391
|
async loadBelongsToMany(as, relation, relatedRepository, options = {}) {
|
|
@@ -4343,7 +4405,7 @@ class Model {
|
|
|
4343
4405
|
}
|
|
4344
4406
|
});
|
|
4345
4407
|
const grouped = indexBelongsToManyRelation([this.attributes], pivotRows, relatedRows, relation);
|
|
4346
|
-
const loaded = grouped
|
|
4408
|
+
const loaded = getByRelationKey(grouped, parentId) ?? [];
|
|
4347
4409
|
return Object.assign(this, { [as]: loaded });
|
|
4348
4410
|
}
|
|
4349
4411
|
hasMany(related, foreignKey, localKey) {
|