@entity-access/entity-access 1.0.251 → 1.0.253

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.
Files changed (102) hide show
  1. package/.vscode/launch.json +2 -1
  2. package/dist/common/symbols/symbols.d.ts +1 -0
  3. package/dist/common/symbols/symbols.d.ts.map +1 -1
  4. package/dist/common/symbols/symbols.js +1 -0
  5. package/dist/common/symbols/symbols.js.map +1 -1
  6. package/dist/compiler/QueryCompiler.d.ts +3 -3
  7. package/dist/decorators/ForeignKey.d.ts +8 -7
  8. package/dist/decorators/ForeignKey.d.ts.map +1 -1
  9. package/dist/decorators/ForeignKey.js +43 -8
  10. package/dist/decorators/ForeignKey.js.map +1 -1
  11. package/dist/decorators/IColumn.d.ts +6 -3
  12. package/dist/decorators/IColumn.d.ts.map +1 -1
  13. package/dist/decorators/Relate.d.ts.map +1 -1
  14. package/dist/decorators/Relate.js +8 -6
  15. package/dist/decorators/Relate.js.map +1 -1
  16. package/dist/entity-query/EntityType.d.ts +5 -1
  17. package/dist/entity-query/EntityType.d.ts.map +1 -1
  18. package/dist/entity-query/EntityType.js +57 -25
  19. package/dist/entity-query/EntityType.js.map +1 -1
  20. package/dist/migrations/postgres/PostgresAutomaticMigrations.js +1 -1
  21. package/dist/migrations/postgres/PostgresAutomaticMigrations.js.map +1 -1
  22. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js +1 -1
  23. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js.map +1 -1
  24. package/dist/model/EntityModel.js +2 -2
  25. package/dist/model/EntityModel.js.map +1 -1
  26. package/dist/model/EntitySource.d.ts +6 -1
  27. package/dist/model/EntitySource.d.ts.map +1 -1
  28. package/dist/model/EntitySource.js.map +1 -1
  29. package/dist/model/SourceExpression.d.ts +1 -22
  30. package/dist/model/SourceExpression.d.ts.map +1 -1
  31. package/dist/model/SourceExpression.js +116 -98
  32. package/dist/model/SourceExpression.js.map +1 -1
  33. package/dist/model/changes/ChangeEntry.d.ts.map +1 -1
  34. package/dist/model/changes/ChangeEntry.js +62 -25
  35. package/dist/model/changes/ChangeEntry.js.map +1 -1
  36. package/dist/model/changes/ChangeSet.d.ts +2 -1
  37. package/dist/model/changes/ChangeSet.d.ts.map +1 -1
  38. package/dist/model/changes/ChangeSet.js +4 -3
  39. package/dist/model/changes/ChangeSet.js.map +1 -1
  40. package/dist/model/identity/IdentityMap.d.ts +23 -0
  41. package/dist/model/identity/IdentityMap.d.ts.map +1 -0
  42. package/dist/model/identity/IdentityMap.js +113 -0
  43. package/dist/model/identity/IdentityMap.js.map +1 -0
  44. package/dist/model/identity/RelationMapper.d.ts +2 -3
  45. package/dist/model/identity/RelationMapper.d.ts.map +1 -1
  46. package/dist/model/identity/RelationMapper.js +60 -27
  47. package/dist/model/identity/RelationMapper.js.map +1 -1
  48. package/dist/model/identity/SearchIndex.d.ts +17 -0
  49. package/dist/model/identity/SearchIndex.d.ts.map +1 -0
  50. package/dist/model/identity/SearchIndex.js +109 -0
  51. package/dist/model/identity/SearchIndex.js.map +1 -0
  52. package/dist/model/verification/VerificationSession.d.ts +1 -1
  53. package/dist/model/verification/VerificationSession.d.ts.map +1 -1
  54. package/dist/model/verification/VerificationSession.js +18 -16
  55. package/dist/model/verification/VerificationSession.js.map +1 -1
  56. package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
  57. package/dist/query/ast/ExpressionToSql.js +74 -52
  58. package/dist/query/ast/ExpressionToSql.js.map +1 -1
  59. package/dist/query/expander/QueryExpander.d.ts.map +1 -1
  60. package/dist/query/expander/QueryExpander.js +41 -10
  61. package/dist/query/expander/QueryExpander.js.map +1 -1
  62. package/dist/query/parser/ArrowToExpression.d.ts +16 -5
  63. package/dist/query/parser/ArrowToExpression.d.ts.map +1 -1
  64. package/dist/query/parser/ArrowToExpression.js +45 -25
  65. package/dist/query/parser/ArrowToExpression.js.map +1 -1
  66. package/dist/tests/db-tests/tests/multi-fk-tests.d.ts +3 -0
  67. package/dist/tests/db-tests/tests/multi-fk-tests.d.ts.map +1 -0
  68. package/dist/tests/db-tests/tests/multi-fk-tests.js +38 -0
  69. package/dist/tests/db-tests/tests/multi-fk-tests.js.map +1 -0
  70. package/dist/tests/expressions/left-joins/child-joins.js +7 -7
  71. package/dist/tests/model/ShoppingContext.d.ts +9 -0
  72. package/dist/tests/model/ShoppingContext.d.ts.map +1 -1
  73. package/dist/tests/model/ShoppingContext.js +34 -0
  74. package/dist/tests/model/ShoppingContext.js.map +1 -1
  75. package/dist/tests/security/tests/include-items.d.ts.map +1 -1
  76. package/dist/tests/security/tests/include-items.js +1 -0
  77. package/dist/tests/security/tests/include-items.js.map +1 -1
  78. package/dist/tsconfig.tsbuildinfo +1 -1
  79. package/package.json +1 -1
  80. package/src/common/symbols/symbols.ts +2 -1
  81. package/src/decorators/ForeignKey.ts +66 -28
  82. package/src/decorators/IColumn.ts +4 -3
  83. package/src/decorators/Relate.ts +8 -6
  84. package/src/entity-query/EntityType.ts +60 -26
  85. package/src/migrations/postgres/PostgresAutomaticMigrations.ts +1 -1
  86. package/src/migrations/sql-server/SqlServerAutomaticMigrations.ts +1 -1
  87. package/src/model/EntityModel.ts +2 -2
  88. package/src/model/EntitySource.ts +6 -1
  89. package/src/model/SourceExpression.ts +132 -132
  90. package/src/model/changes/ChangeEntry.ts +68 -25
  91. package/src/model/changes/ChangeSet.ts +4 -3
  92. package/src/model/identity/IdentityMap.ts +126 -0
  93. package/src/model/identity/RelationMapper.ts +71 -27
  94. package/src/model/identity/SearchIndex.ts +120 -0
  95. package/src/model/verification/VerificationSession.ts +19 -16
  96. package/src/query/ast/ExpressionToSql.ts +77 -61
  97. package/src/query/expander/QueryExpander.ts +52 -28
  98. package/src/query/parser/ArrowToExpression.ts +50 -26
  99. package/src/tests/db-tests/tests/multi-fk-tests.ts +46 -0
  100. package/src/tests/expressions/left-joins/child-joins.ts +7 -7
  101. package/src/tests/model/ShoppingContext.ts +32 -0
  102. package/src/tests/security/tests/include-items.ts +1 -0
@@ -82,8 +82,27 @@ export default class EntityType {
82
82
 
83
83
  const existing = this.fieldMap.get(c.name);
84
84
  if (existing) {
85
- c.fkRelation = existing.fkRelation;
86
- c.fkRelation.fkColumn = c;
85
+ const fkRelation = c.fkRelation = existing.fkRelation;
86
+ if(fkRelation) {
87
+ fkRelation.fkMap = [{ fkColumn: c, relatedKeyColumn: null }];
88
+ // if(!fkRelation.fkMap?.length) {
89
+ // fkRelation.fkMap = [{ fkColumn: c, relatedKeyColumn: null}];
90
+ // } else {
91
+ // if(fkRelation.fkMap.length === 1) {
92
+ // fkRelation.fkMap[0].fkColumn = c;
93
+ // }
94
+ // }
95
+ }
96
+ // if (fkRelation?.fkMap) {
97
+ // if (!c.fkRelation.fkMap.length) {
98
+ // c.fkRelation.fkMap = [{ fkColumn: c, relatedKeyColumn: null }];
99
+ // } else {
100
+ // c.fkRelation.fkMap[0].fkColumn = c;
101
+ // }
102
+ // } else {
103
+ // c
104
+ // }
105
+ // c.fkRelation.fkColumn = c;
87
106
  }
88
107
 
89
108
  this.fieldMap.set(c.name, c);
@@ -109,26 +128,29 @@ export default class EntityType {
109
128
  }
110
129
 
111
130
 
112
- addRelation(relation: IEntityRelation, getInverseModel?: (t) => EntityType) {
131
+ addRelation(relation: IEntityRelation & { fkName?: string }, getInverseModel?: (t) => EntityType) {
113
132
  // we will also set fk to the corresponding column
114
133
  this.relations.push(relation);
115
134
  this.relationMap.set(relation.name, relation);
116
135
 
117
- // find fk...
118
- let fkColumn = this.fieldMap.get(relation.foreignKey);
119
- if(!fkColumn) {
120
- fkColumn = {
121
- name: relation.foreignKey,
122
- // columnName: relation.foreignKey,
123
- fkRelation: relation,
124
- dataType: "BigInt"
125
- };
126
- this.fieldMap.set(relation.foreignKey, fkColumn);
127
- }
128
- fkColumn.fkRelation = relation;
129
- relation.fkColumn = fkColumn;
130
- if (fkColumn.dataType === "Double") {
131
- fkColumn.dataType = "BigInt";
136
+ if (!relation.fkMap) {
137
+ // find fk...
138
+ let fkColumn = this.fieldMap.get(relation.fkName);
139
+ if(!fkColumn) {
140
+ fkColumn = {
141
+ name: relation.fkName,
142
+ // columnName: relation.foreignKey,
143
+ fkRelation: relation,
144
+ dataType: "BigInt"
145
+ };
146
+ this.fieldMap.set(relation.fkName, fkColumn);
147
+ relation.fkMap = [ { fkColumn, relatedKeyColumn: null} ];
148
+ }
149
+ fkColumn.fkRelation = relation;
150
+ // relation.fkColumn = fkColumn;
151
+ if (fkColumn.dataType === "Double") {
152
+ fkColumn.dataType = "BigInt";
153
+ }
132
154
  }
133
155
 
134
156
  if (!getInverseModel) {
@@ -137,14 +159,23 @@ export default class EntityType {
137
159
 
138
160
  // let us set inverse relations...
139
161
  const relatedType = getInverseModel(relation.relatedTypeClass);
162
+
163
+ relation.fkMap[0].relatedKeyColumn ??= relatedType.keys[0];
164
+ relation.fkMap = [ ... relation.fkMap.map((x) => ({ ... x}))];
165
+ for (const iterator of relation.fkMap) {
166
+ iterator.fkColumn = this.getField(iterator.fkColumn.name);
167
+ // iterator.fkColumn.fkRelation = relation;
168
+ iterator.relatedKeyColumn = relatedType.getField(iterator.relatedKeyColumn.name);
169
+ iterator.relatedKeyColumn.entityType = relatedType;
170
+ }
171
+
140
172
  relation.relatedEntity = relatedType;
141
173
  const inverseRelation: IEntityRelation = {
142
174
  name: relation.relatedName,
143
- foreignKey: "",
144
175
  relatedName: relation.name,
145
176
  relatedTypeClass: this.typeClass,
146
- dotNotCreateIndex: true,
147
- fkColumn,
177
+ doNotCreateIndex: true,
178
+ fkMap: null,
148
179
  isInverseRelation: true,
149
180
  isCollection: relation.singleInverseRelation ? false : true,
150
181
  relatedRelation: relation,
@@ -158,11 +189,14 @@ export default class EntityType {
158
189
 
159
190
  let { foreignKeyConstraint } = relation;
160
191
  if(foreignKeyConstraint) {
161
- foreignKeyConstraint = { ... foreignKeyConstraint};
162
- relation.foreignKeyConstraint = foreignKeyConstraint;
163
- foreignKeyConstraint.name ||= `FK_${this.name}_${fkColumn.name}_${this.typeClass.name}_${relatedType.keys[0].name}`;
164
- foreignKeyConstraint.column = fkColumn;
165
- foreignKeyConstraint.refColumns = relatedType.keys;
192
+ if (relation.fkMap.length === 1) {
193
+ const { fkColumn } = relation.fkMap[0];
194
+ foreignKeyConstraint = { ... foreignKeyConstraint};
195
+ relation.foreignKeyConstraint = foreignKeyConstraint;
196
+ foreignKeyConstraint.name ||= `FK_${this.name}_${fkColumn.name}_${this.typeClass.name}_${relatedType.keys[0].name}`;
197
+ foreignKeyConstraint.column = fkColumn;
198
+ foreignKeyConstraint.refColumns = relatedType.keys;
199
+ }
166
200
  }
167
201
  return relation;
168
202
  }
@@ -26,7 +26,7 @@ export default class PostgresAutomaticMigrations extends PostgresMigrations {
26
26
  await this.createIndexes(context, type, nonKeyColumns.filter((x) =>
27
27
  x.fkRelation
28
28
  && (!x.key || type.keys.indexOf(x) !== 0)
29
- && !x.fkRelation?.dotNotCreateIndex));
29
+ && !x.fkRelation?.doNotCreateIndex));
30
30
 
31
31
  }
32
32
 
@@ -26,7 +26,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
26
26
  await this.createIndexes(context, type, nonKeyColumns.filter((x) =>
27
27
  x.fkRelation
28
28
  && (!x.key || type.keys.indexOf(x) !== 0)
29
- && !x.fkRelation?.dotNotCreateIndex));
29
+ && !x.fkRelation?.doNotCreateIndex));
30
30
 
31
31
  }
32
32
 
@@ -23,8 +23,8 @@ const getOrCreateModel = (map: Map<any, EntityType>, type: IClassOf<any>, naming
23
23
  ? column.columnName
24
24
  : (namingConvention
25
25
  ? namingConvention(column.columnName) : column.columnName);
26
- t.addColumn(column);
27
26
  column.entityType = t;
27
+ t.addColumn(column);
28
28
  }
29
29
  t.indexes.push(... original.indexes.map((i) => ({ ... i, columns: [ ... i.columns.map((c) => ( { ... c}))] })));
30
30
  // sort keys...
@@ -38,7 +38,7 @@ const getOrCreateModel = (map: Map<any, EntityType>, type: IClassOf<any>, naming
38
38
  if (iterator.isInverseRelation) {
39
39
  continue;
40
40
  }
41
- const relation: IEntityRelation = { ... iterator, fkColumn: void 0, relatedEntity: void 0,type: t };
41
+ const relation: IEntityRelation = { ... iterator, relatedEntity: void 0,type: t };
42
42
  t.addRelation(relation, (tc) => getOrCreateModel(map, tc, namingConvention));
43
43
  }
44
44
  return t;
@@ -28,8 +28,13 @@ export type ISaveDirect<T> = {
28
28
  keys: Partial<T>,
29
29
  changes: Partial<T>,
30
30
  // select?: Partial<T>,
31
- mode: "selectOrInsert" | "insert",
31
+ mode: "selectOrInsert",
32
32
  updateAfterSelect?: never
33
+ } | {
34
+ keys?: never,
35
+ mode: "insert",
36
+ changes: Partial<T>,
37
+ updateAfterSelect?: never,
33
38
  } | {
34
39
  keys?: Partial<T>,
35
40
  changes: Partial<T>,
@@ -1,132 +1,132 @@
1
- import { modelSymbol } from "../common/symbols/symbols.js";
2
- import EntityType from "../entity-query/EntityType.js";
3
- import { Expression, JoinExpression, ParameterExpression, SelectStatement } from "../query/ast/Expressions.js";
4
- import { ITextQueryFragment, QueryParameter } from "../query/ast/IStringTransformer.js";
5
- import EntityContext from "./EntityContext.js";
6
-
7
- const sourceSymbol = Symbol("source");
8
-
9
- export class SourceExpression {
10
-
11
- public static create(p: Partial<SourceExpression>) {
12
- return new SourceExpression(p);
13
- }
14
-
15
- alias: ParameterExpression;
16
- parameter?: ParameterExpression;
17
- context: EntityContext;
18
- model?: EntityType;
19
- include?: EntityType[];
20
- select: SelectStatement;
21
- parent?: SourceExpression;
22
-
23
- private map: Map<string,SourceExpression>;
24
- private paramMap: Map<string, SourceExpression>;
25
-
26
- private constructor(p: Partial<SourceExpression>) {
27
- Object.setPrototypeOf(p, SourceExpression.prototype);
28
- const r = p as SourceExpression;
29
- if (r.parent) {
30
- r.map = r.parent.map;
31
- r.paramMap = r.parent.paramMap;
32
- } else {
33
- r.paramMap = new Map();
34
- r.map = new Map();
35
- }
36
- return r;
37
- }
38
-
39
- copy() {
40
- const r = { ... this } as SourceExpression;
41
- Object.setPrototypeOf(r, Object.getPrototypeOf(this));
42
- r.map = new Map(this.map.entries());
43
- r.paramMap = new Map(this.paramMap.entries());
44
- r.select = Expression.clone(this.select);
45
- return r;
46
- }
47
-
48
- addJoin(property: string) {
49
- const { select } = this;
50
- select.joins ??= [];
51
-
52
- const relation = this.model.getProperty(property);
53
- const model = this.context.model.register(relation.relation.relatedTypeClass)[modelSymbol];
54
-
55
- for (const iterator of select.joins) {
56
- if (model === iterator.model) {
57
- return iterator[sourceSymbol] as SourceExpression;
58
- }
59
- }
60
- const column = relation.relation.fkColumn;
61
- const parameter = ParameterExpression.create({ name: this.parameter + "." + property, model });
62
- const source = this.addSource(model, parameter);
63
- const join = JoinExpression.create({
64
- as: source.alias,
65
- joinType: column.nullable ? "LEFT" : "INNER",
66
- model,
67
- source: Expression.identifier(model.name),
68
- where: Expression.logicalAnd(
69
- Expression.member(
70
- this.alias,
71
- column.columnName),
72
- Expression.member(
73
- source.alias,
74
- model.keys[0].columnName)
75
- )
76
- });
77
- select.joins.push(join);
78
- join[sourceSymbol] = source;
79
- return source;
80
- }
81
-
82
- addSource(model: EntityType, parameter: ParameterExpression) {
83
-
84
- const { context } = this;
85
- const source = SourceExpression.create({
86
- model,
87
- parameter,
88
- context,
89
- parent: this
90
- });
91
-
92
- source.map = this.map;
93
- source.paramMap = this.paramMap;
94
-
95
- let id = 0;
96
- let alias: string;
97
- do {
98
- alias = model.name[0] + id++;
99
- const exists = this.map.get(alias);
100
- if (exists === null || exists === void 0) {
101
- break;
102
- }
103
- }while (true);
104
- source.alias = ParameterExpression.create({ name: alias, model });
105
- this.map.set(alias, source);
106
- this.paramMap.set(parameter.name, source);
107
- return source;
108
- }
109
-
110
- flatten(chain: string[]): ITextQueryFragment {
111
- const [start, ... others ] = chain;
112
- if (start === this.parameter.name) {
113
- return this.prepareNames(others);
114
- }
115
- const mapped = this.paramMap.get(start);
116
- if (mapped) {
117
- return mapped.prepareNames(others);
118
- }
119
- throw new Error("Not found");
120
- }
121
-
122
- prepareNames([property , ... others]: string[]): ITextQueryFragment {
123
- const p = this.model.getProperty(property);
124
- if (others.length === 0) {
125
- return `${ QueryParameter.create(() => this.alias.name)}.${p.field.columnName}`;
126
- }
127
-
128
- // this must be a navigation...
129
- const source = this.addJoin(property);
130
- return source.prepareNames(others);
131
- }
132
- }
1
+ // import { modelSymbol } from "../common/symbols/symbols.js";
2
+ // import EntityType from "../entity-query/EntityType.js";
3
+ // import { Expression, JoinExpression, ParameterExpression, SelectStatement } from "../query/ast/Expressions.js";
4
+ // import { ITextQueryFragment, QueryParameter } from "../query/ast/IStringTransformer.js";
5
+ // import EntityContext from "./EntityContext.js";
6
+
7
+ // const sourceSymbol = Symbol("source");
8
+
9
+ // export class SourceExpression {
10
+
11
+ // public static create(p: Partial<SourceExpression>) {
12
+ // return new SourceExpression(p);
13
+ // }
14
+
15
+ // alias: ParameterExpression;
16
+ // parameter?: ParameterExpression;
17
+ // context: EntityContext;
18
+ // model?: EntityType;
19
+ // include?: EntityType[];
20
+ // select: SelectStatement;
21
+ // parent?: SourceExpression;
22
+
23
+ // private map: Map<string,SourceExpression>;
24
+ // private paramMap: Map<string, SourceExpression>;
25
+
26
+ // private constructor(p: Partial<SourceExpression>) {
27
+ // Object.setPrototypeOf(p, SourceExpression.prototype);
28
+ // const r = p as SourceExpression;
29
+ // if (r.parent) {
30
+ // r.map = r.parent.map;
31
+ // r.paramMap = r.parent.paramMap;
32
+ // } else {
33
+ // r.paramMap = new Map();
34
+ // r.map = new Map();
35
+ // }
36
+ // return r;
37
+ // }
38
+
39
+ // copy() {
40
+ // const r = { ... this } as SourceExpression;
41
+ // Object.setPrototypeOf(r, Object.getPrototypeOf(this));
42
+ // r.map = new Map(this.map.entries());
43
+ // r.paramMap = new Map(this.paramMap.entries());
44
+ // r.select = Expression.clone(this.select);
45
+ // return r;
46
+ // }
47
+
48
+ // addJoin(property: string) {
49
+ // const { select } = this;
50
+ // select.joins ??= [];
51
+
52
+ // const relation = this.model.getProperty(property);
53
+ // const model = this.context.model.register(relation.relation.relatedTypeClass)[modelSymbol];
54
+
55
+ // for (const iterator of select.joins) {
56
+ // if (model === iterator.model) {
57
+ // return iterator[sourceSymbol] as SourceExpression;
58
+ // }
59
+ // }
60
+ // const column = relation.relation.fkColumn;
61
+ // const parameter = ParameterExpression.create({ name: this.parameter + "." + property, model });
62
+ // const source = this.addSource(model, parameter);
63
+ // const join = JoinExpression.create({
64
+ // as: source.alias,
65
+ // joinType: column.nullable ? "LEFT" : "INNER",
66
+ // model,
67
+ // source: Expression.identifier(model.name),
68
+ // where: Expression.logicalAnd(
69
+ // Expression.member(
70
+ // this.alias,
71
+ // column.columnName),
72
+ // Expression.member(
73
+ // source.alias,
74
+ // model.keys[0].columnName)
75
+ // )
76
+ // });
77
+ // select.joins.push(join);
78
+ // join[sourceSymbol] = source;
79
+ // return source;
80
+ // }
81
+
82
+ // addSource(model: EntityType, parameter: ParameterExpression) {
83
+
84
+ // const { context } = this;
85
+ // const source = SourceExpression.create({
86
+ // model,
87
+ // parameter,
88
+ // context,
89
+ // parent: this
90
+ // });
91
+
92
+ // source.map = this.map;
93
+ // source.paramMap = this.paramMap;
94
+
95
+ // let id = 0;
96
+ // let alias: string;
97
+ // do {
98
+ // alias = model.name[0] + id++;
99
+ // const exists = this.map.get(alias);
100
+ // if (exists === null || exists === void 0) {
101
+ // break;
102
+ // }
103
+ // }while (true);
104
+ // source.alias = ParameterExpression.create({ name: alias, model });
105
+ // this.map.set(alias, source);
106
+ // this.paramMap.set(parameter.name, source);
107
+ // return source;
108
+ // }
109
+
110
+ // flatten(chain: string[]): ITextQueryFragment {
111
+ // const [start, ... others ] = chain;
112
+ // if (start === this.parameter.name) {
113
+ // return this.prepareNames(others);
114
+ // }
115
+ // const mapped = this.paramMap.get(start);
116
+ // if (mapped) {
117
+ // return mapped.prepareNames(others);
118
+ // }
119
+ // throw new Error("Not found");
120
+ // }
121
+
122
+ // prepareNames([property , ... others]: string[]): ITextQueryFragment {
123
+ // const p = this.model.getProperty(property);
124
+ // if (others.length === 0) {
125
+ // return `${ QueryParameter.create(() => this.alias.name)}.${p.field.columnName}`;
126
+ // }
127
+
128
+ // // this must be a navigation...
129
+ // const source = this.addJoin(property);
130
+ // return source.prepareNames(others);
131
+ // }
132
+ // }
@@ -168,14 +168,16 @@ export default class ChangeEntry<T = any> implements IChanges {
168
168
  // this is tricky as we need to build inverse query...
169
169
  const { relatedRelation } = relation;
170
170
  const filter = [];
171
- for (const iterator of this.type.keys) {
172
- filter.push(`x.${relatedRelation.name}.${iterator.name} === p.${iterator.name}`);
171
+ for (const { fkColumn, relatedKeyColumn } of relatedRelation.fkMap) {
172
+ filter.push(`x.${relatedRelation.name}.${fkColumn.name} === p.${relatedKeyColumn.name}`);
173
173
  }
174
174
 
175
175
  await context.model.register(relatedEntity.typeClass)
176
176
  .where(this.entity, `(p) => (x) => ${filter.join(" && ")}` as any)
177
177
  .toArray();
178
178
 
179
+ return;
180
+
179
181
  }
180
182
 
181
183
  if (this.entity[relation.name]) {
@@ -183,9 +185,13 @@ export default class ChangeEntry<T = any> implements IChanges {
183
185
  }
184
186
 
185
187
 
186
- const key = relatedEntity.keys[0];
188
+ // need to setup inverse key check
189
+ // const key = relatedEntity.keys[0];
187
190
  const keys = {} as any;
188
- keys[key.name] = this.entity[relation.fkColumn.name];
191
+ // keys[key.name] = this.entity[relation.fkColumn.name];
192
+ for (const { fkColumn, relatedKeyColumn } of relation.fkMap) {
193
+ keys[relatedKeyColumn.name] = this.entity[fkColumn.name];
194
+ }
189
195
  this.entity[relation.name] = await context.model.register(relatedEntity.typeClass).loadByKeys(keys);
190
196
  }
191
197
 
@@ -281,7 +287,7 @@ export default class ChangeEntry<T = any> implements IChanges {
281
287
  }
282
288
 
283
289
  // if related has key defined.. set it...
284
- const rKey = iterator.relatedEntity.keys[0];
290
+ // const rKey = iterator.relatedEntity.keys[0];
285
291
 
286
292
  // lets set the prototype...
287
293
  const prototype = iterator.relatedTypeClass.prototype;
@@ -290,38 +296,75 @@ export default class ChangeEntry<T = any> implements IChanges {
290
296
  }
291
297
  const relatedChanges = this.changeSet.getEntry(related);
292
298
 
293
- const keyValue = related[rKey.name];
294
- if (keyValue === void 0) {
299
+ for (const { fkColumn, relatedKeyColumn } of iterator.fkMap) {
300
+ const keyValue = related[relatedKeyColumn.name];
301
+ if (keyValue === void 0) {
295
302
 
296
- if(relatedChanges.dependents.has(this)) {
297
- continue;
298
- }
299
- relatedChanges.dependents.add(this);
303
+ if(relatedChanges.dependents.has(this)) {
304
+ continue;
305
+ }
306
+ relatedChanges.dependents.add(this);
300
307
 
301
- this.order++;
308
+ this.order++;
302
309
 
303
- for (const d of this.dependents) {
304
- d.order++;
305
- }
310
+ for (const d of this.dependents) {
311
+ d.order++;
312
+ }
306
313
 
307
- const fk = iterator;
308
- if (!fk.fkColumn.columnName) {
309
- throw new EntityAccessError(`Configuration error, fk not set for ${fk.name}`);
310
- }
311
- relatedChanges.pending.push(() => {
312
- this.entity[fk.fkColumn.name] = related[rKey.name];
313
- });
314
- if (this.status !== "inserted") {
315
- this.modified.set(iterator, { column: iterator.fkColumn, oldValue: void 0, newValue: void 0});
314
+ if (!fkColumn.columnName) {
315
+ throw new EntityAccessError(`Configuration error, fk not set for ${fkColumn.name}`);
316
+ }
317
+ relatedChanges.pending.push(() => {
318
+ this.entity[fkColumn.name] = related[relatedKeyColumn.name];
319
+ });
320
+ if (this.status !== "inserted") {
321
+ this.modified.set(iterator, { column: fkColumn, oldValue: void 0, newValue: void 0});
322
+ }
316
323
  }
317
324
  continue;
318
325
  }
319
326
 
327
+ // const keyValue = related[rKey.name];
328
+ // if (keyValue === void 0) {
329
+
330
+ // if(relatedChanges.dependents.has(this)) {
331
+ // continue;
332
+ // }
333
+ // relatedChanges.dependents.add(this);
334
+
335
+ // this.order++;
336
+
337
+ // for (const d of this.dependents) {
338
+ // d.order++;
339
+ // }
340
+
341
+ // const fk = iterator;
342
+ // if (!fk.fkMap?.length) {
343
+ // throw new EntityAccessError(`Configuration error, fk not set for ${fk.name}`);
344
+ // }
345
+ // relatedChanges.pending.push(() => {
346
+ // for (const { fkColumn, relatedKeyColumn } of fk.fkMap) {
347
+ // this.entity[fkColumn.name] = related[relatedKeyColumn.name];
348
+ // }
349
+ // // this.entity[fk.fkColumn.name] = related[rKey.name];
350
+ // });
351
+ // if (this.status !== "inserted") {
352
+ // for (const { fkColumn } of fk.fkMap) {
353
+ // this.modified.set(iterator, { column: fkColumn, oldValue: void 0, newValue: void 0});
354
+ // }
355
+ // // this.modified.set(iterator, { column: iterator.fkColumn, oldValue: void 0, newValue: void 0});
356
+ // }
357
+ // continue;
358
+ // }
359
+
320
360
  if(!relatedChanges.dependents.has(this)) {
321
361
  relatedChanges.dependents.add(this);
322
362
  this.order += relatedChanges.order;
323
363
  }
324
- this.entity[iterator.fkColumn.name] = related[rKey.name];
364
+ for (const { fkColumn, relatedKeyColumn } of iterator.fkMap) {
365
+ this.entity[fkColumn.name] = related[relatedKeyColumn.name];
366
+ }
367
+ // this.entity[iterator.fkColumn.name] = related[rKey.name];
325
368
  }
326
369
  }
327
370
 
@@ -3,6 +3,7 @@ import EntityAccessError from "../../common/EntityAccessError.js";
3
3
  import EventSet from "../../common/EventSet.js";
4
4
  import SchemaRegistry from "../../decorators/SchemaRegistry.js";
5
5
  import EntityContext from "../EntityContext.js";
6
+ import IdentityMap from "../identity/IdentityMap.js";
6
7
  import IdentityService, { identityMapSymbol } from "../identity/IdentityService.js";
7
8
  import ChangeEntry, { privateUpdateEntry, getContext } from "./ChangeEntry.js";
8
9
 
@@ -26,7 +27,7 @@ export default class ChangeSet {
26
27
  /**
27
28
  * This will provide new entity for same key
28
29
  */
29
- private identityMap: Map<string,any> = new Map();
30
+ private identityMap = new IdentityMap();
30
31
 
31
32
  private nextId = 1;
32
33
 
@@ -70,7 +71,7 @@ export default class ChangeSet {
70
71
  this.entryMap.delete(entry.entity);
71
72
  return;
72
73
  }
73
- this.identityMap.set(jsonKey, entry.entity);
74
+ this.identityMap.set(jsonKey, entry.entity, entry.type);
74
75
  }
75
76
  }
76
77
 
@@ -101,7 +102,7 @@ export default class ChangeSet {
101
102
  return entry.updateValues(original);
102
103
  }
103
104
  } else {
104
- this.identityMap.set(jsonKey, entity);
105
+ this.identityMap.set(jsonKey, entity, type);
105
106
  }
106
107
  }
107
108
  entry = new ChangeEntry({