@cheetah.js/orm 0.1.13 → 0.1.15

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 (55) hide show
  1. package/dist/SqlBuilder.d.ts +19 -4
  2. package/dist/SqlBuilder.js +299 -81
  3. package/dist/SqlBuilder.js.map +1 -1
  4. package/dist/bun/index.js +225061 -0
  5. package/dist/bun/index.js.map +315 -0
  6. package/dist/cheetah.js +3 -5
  7. package/dist/cheetah.js.map +1 -1
  8. package/dist/common/email.vo.js +2 -6
  9. package/dist/common/email.vo.js.map +1 -1
  10. package/dist/common/uuid.js +2 -6
  11. package/dist/common/uuid.js.map +1 -1
  12. package/dist/common/value-object.js +3 -7
  13. package/dist/common/value-object.js.map +1 -1
  14. package/dist/constants.js +4 -7
  15. package/dist/constants.js.map +1 -1
  16. package/dist/decorators/entity.decorator.js +5 -9
  17. package/dist/decorators/entity.decorator.js.map +1 -1
  18. package/dist/decorators/index.decorator.js +4 -8
  19. package/dist/decorators/index.decorator.js.map +1 -1
  20. package/dist/decorators/one-many.decorator.js +10 -15
  21. package/dist/decorators/one-many.decorator.js.map +1 -1
  22. package/dist/decorators/primary-key.decorator.js +3 -7
  23. package/dist/decorators/primary-key.decorator.js.map +1 -1
  24. package/dist/decorators/property.decorator.js +13 -17
  25. package/dist/decorators/property.decorator.js.map +1 -1
  26. package/dist/domain/base-entity.js +12 -8
  27. package/dist/domain/base-entity.js.map +1 -1
  28. package/dist/domain/collection.js +2 -7
  29. package/dist/domain/collection.js.map +1 -1
  30. package/dist/domain/entities.js +7 -10
  31. package/dist/domain/entities.js.map +1 -1
  32. package/dist/domain/reference.js +1 -5
  33. package/dist/domain/reference.js.map +1 -1
  34. package/dist/driver/driver.interface.d.ts +17 -4
  35. package/dist/driver/driver.interface.js +1 -2
  36. package/dist/driver/pg-driver.js +4 -7
  37. package/dist/driver/pg-driver.js.map +1 -1
  38. package/dist/entry.js +5 -8
  39. package/dist/entry.js.map +1 -1
  40. package/dist/index.js +15 -31
  41. package/dist/index.js.map +1 -1
  42. package/dist/migration/diff-calculator.js +1 -5
  43. package/dist/migration/diff-calculator.js.map +1 -1
  44. package/dist/migration/migrator.d.ts +1 -1
  45. package/dist/migration/migrator.js +16 -43
  46. package/dist/migration/migrator.js.map +1 -1
  47. package/dist/orm.js +7 -10
  48. package/dist/orm.js.map +1 -1
  49. package/dist/orm.service.js +28 -58
  50. package/dist/orm.service.js.map +1 -1
  51. package/dist/utils.js +1 -5
  52. package/dist/utils.js.map +1 -1
  53. package/package.json +2 -2
  54. package/test/domain/base-entity.spec.ts +81 -39
  55. package/test/domain/relationship.spec.ts +173 -0
@@ -1,4 +1,4 @@
1
- import { AutoPath, FilterQuery, QueryOrderMap, ValueOrInstance } from './driver/driver.interface';
1
+ import { AutoPath, FilterQuery, QueryOrderMap, Statement, ValueOrInstance } from './driver/driver.interface';
2
2
  export declare class SqlBuilder<T> {
3
3
  private readonly driver;
4
4
  private entityStorage;
@@ -9,8 +9,10 @@ export declare class SqlBuilder<T> {
9
9
  private lastKeyNotOperator;
10
10
  private logger;
11
11
  private updatedColumns;
12
+ private originalColumns;
12
13
  constructor(model: new () => T);
13
14
  select(columns?: AutoPath<T, never, '*'>[]): SqlBuilder<T>;
15
+ setStrategy(strategy?: 'joined' | 'select'): SqlBuilder<T>;
14
16
  insert(values: Partial<{
15
17
  [K in keyof T]: ValueOrInstance<T[K]>;
16
18
  }>): SqlBuilder<T>;
@@ -23,14 +25,27 @@ export declare class SqlBuilder<T> {
23
25
  }) | QueryOrderMap<T>[]): SqlBuilder<T>;
24
26
  limit(limit: number | undefined): SqlBuilder<T>;
25
27
  offset(offset: number | undefined): SqlBuilder<T>;
26
- executeAndReturnFirst(): Promise<T | undefined>;
27
- executeAndReturnFirstOrFail(): Promise<T>;
28
- executeAndReturnAll(): Promise<T[]>;
28
+ load(load: string[]): SqlBuilder<T>;
29
+ private addJoinForRelationshipPath;
30
+ private getPrimaryKeyColumnName;
29
31
  execute(): Promise<{
30
32
  query: any;
31
33
  startTime: number;
32
34
  sql: string;
33
35
  }>;
36
+ executeAndReturnFirst(): Promise<T | undefined>;
37
+ executeAndReturnFirstOrFail(): Promise<T>;
38
+ executeAndReturnAll(): Promise<T[]>;
39
+ private handleSelectJoin;
40
+ getPathForSelectJoin(selectJoin: Statement<any>): string[] | null;
41
+ private setValueByPath;
42
+ private getPathForSelectJoinRecursive;
43
+ private findIdRecursively;
44
+ private generateColumns;
45
+ private extractAliasForColumns;
46
+ private filterInvalidColumns;
47
+ private includeUpdatedColumns;
48
+ private logExecution;
34
49
  startTransaction(): Promise<void>;
35
50
  commit(): Promise<void>;
36
51
  rollback(): Promise<void>;
@@ -1,10 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SqlBuilder = void 0;
4
- const entities_1 = require("./domain/entities");
5
- const orm_1 = require("./orm");
6
- const value_object_1 = require("./common/value-object");
7
- class SqlBuilder {
1
+ import { EntityStorage } from './domain/entities';
2
+ import { Orm } from './orm';
3
+ import { ValueObject } from './common/value-object';
4
+ import { BaseEntity } from '@cheetah.js/orm/domain/base-entity';
5
+ export class SqlBuilder {
8
6
  driver;
9
7
  entityStorage;
10
8
  statements = {};
@@ -14,11 +12,12 @@ class SqlBuilder {
14
12
  lastKeyNotOperator = '';
15
13
  logger;
16
14
  updatedColumns = [];
15
+ originalColumns = [];
17
16
  constructor(model) {
18
- const orm = orm_1.Orm.getInstance();
17
+ const orm = Orm.getInstance();
19
18
  this.driver = orm.driverInstance;
20
19
  this.logger = orm.logger;
21
- this.entityStorage = entities_1.EntityStorage.getInstance();
20
+ this.entityStorage = EntityStorage.getInstance();
22
21
  this.getEntity(model);
23
22
  }
24
23
  select(columns) {
@@ -26,17 +25,18 @@ class SqlBuilder {
26
25
  const schema = this.entity.schema || 'public';
27
26
  this.statements.statement = 'select';
28
27
  this.statements.columns = columns;
28
+ this.originalColumns = columns || [];
29
29
  this.statements.alias = this.getAlias(tableName);
30
30
  this.statements.table = `"${schema}"."${tableName}"`;
31
31
  return this;
32
32
  }
33
+ setStrategy(strategy = 'joined') {
34
+ this.statements.strategy = strategy;
35
+ return this;
36
+ }
33
37
  insert(values) {
34
38
  const { tableName, schema } = this.getTableName();
35
- for (let value in values) {
36
- if (this.extendsFrom(value_object_1.ValueObject, values[value].constructor.prototype)) {
37
- values[value] = values[value].getValue();
38
- }
39
- }
39
+ processValuesForInsert(values);
40
40
  this.statements.statement = 'insert';
41
41
  this.statements.alias = this.getAlias(tableName);
42
42
  this.statements.table = `"${schema}"."${tableName}"`;
@@ -45,11 +45,7 @@ class SqlBuilder {
45
45
  }
46
46
  update(values) {
47
47
  const { tableName, schema } = this.getTableName();
48
- for (let value in values) {
49
- if (this.extendsFrom(value_object_1.ValueObject, values[value].constructor.prototype)) {
50
- values[value] = values[value].getValue();
51
- }
52
- }
48
+ processValuesForUpdate(values);
53
49
  this.statements.statement = 'update';
54
50
  this.statements.alias = this.getAlias(tableName);
55
51
  this.statements.table = `${schema}.${tableName}`;
@@ -57,14 +53,14 @@ class SqlBuilder {
57
53
  return this;
58
54
  }
59
55
  where(where) {
60
- if (typeof where === 'undefined' || Object.entries(where).length === 0) {
56
+ if (!where || Object.keys(where).length === 0) {
61
57
  return this;
62
58
  }
63
- this.statements.where = this.conditionToSql(where, this.statements.alias);
59
+ this.statements.where = this.conditionToSql(where, this.statements.alias, this.model);
64
60
  return this;
65
61
  }
66
62
  orderBy(orderBy) {
67
- if (typeof orderBy === 'undefined') {
63
+ if (!orderBy) {
68
64
  return this;
69
65
  }
70
66
  this.statements.orderBy = this.objectToStringMap(orderBy);
@@ -78,13 +74,77 @@ class SqlBuilder {
78
74
  this.statements.offset = offset;
79
75
  return this;
80
76
  }
77
+ load(load) {
78
+ load?.forEach(relationshipPath => {
79
+ this.addJoinForRelationshipPath(this.entity, relationshipPath);
80
+ });
81
+ if (this.statements.join) {
82
+ this.statements.join = this.statements.join?.reverse();
83
+ }
84
+ if (this.statements.selectJoin) {
85
+ this.statements.selectJoin = this.statements.selectJoin?.reverse();
86
+ }
87
+ return this;
88
+ }
89
+ addJoinForRelationshipPath(entity, relationshipPath) {
90
+ const relationshipNames = relationshipPath.split('.');
91
+ let currentEntity = entity;
92
+ let currentAlias = this.statements.alias;
93
+ let statement = this.statements.strategy === 'joined' ? this.statements.join : this.statements.selectJoin;
94
+ let nameAliasProperty = this.statements.strategy === 'joined' ? 'joinAlias' : 'alias';
95
+ relationshipNames.forEach((relationshipName, index) => {
96
+ const relationship = currentEntity.relations.find(rel => rel.propertyKey === relationshipName);
97
+ if (!relationship) {
98
+ // @ts-ignore
99
+ throw new Error(`Relationship "${relationshipName}" not found in entity "${currentEntity.name}"`);
100
+ }
101
+ const isLastRelationship = index === relationshipNames.length - 1;
102
+ if (index === (relationshipNames.length - 2 >= 0 ? relationshipNames.length - 2 : 0)) {
103
+ const join = statement?.find(j => j.joinProperty === relationshipName);
104
+ if (join) {
105
+ // @ts-ignore
106
+ currentAlias = join[nameAliasProperty];
107
+ }
108
+ }
109
+ if (relationship.relation === 'many-to-one' && isLastRelationship) {
110
+ this.applyJoin(relationship, {}, currentAlias);
111
+ statement = this.statements.strategy === 'joined' ? this.statements.join : this.statements.selectJoin;
112
+ currentAlias = statement[statement.length - 1][nameAliasProperty];
113
+ }
114
+ currentEntity = this.entityStorage.get(relationship.entity());
115
+ });
116
+ }
117
+ getPrimaryKeyColumnName(entity) {
118
+ // Lógica para obter o nome da coluna de chave primária da entidade
119
+ // Aqui você pode substituir por sua própria lógica, dependendo da estrutura do seu projeto
120
+ // Por exemplo, se a chave primária for sempre 'id', você pode retornar 'id'.
121
+ // Se a lógica for mais complexa, você pode adicionar um método na classe Options para obter a chave primária.
122
+ return 'id';
123
+ }
124
+ async execute() {
125
+ if (!this.statements.columns) {
126
+ this.statements.columns = this.generateColumns();
127
+ }
128
+ else {
129
+ this.extractAliasForColumns();
130
+ this.filterInvalidColumns();
131
+ }
132
+ this.statements.join = this.statements.join?.reverse();
133
+ this.includeUpdatedColumns();
134
+ const result = await this.driver.executeStatement(this.statements);
135
+ this.logExecution(result);
136
+ return result;
137
+ }
81
138
  async executeAndReturnFirst() {
82
139
  this.statements.limit = 1;
83
140
  const result = await this.execute();
84
141
  if (result.query.rows.length === 0) {
85
142
  return undefined;
86
143
  }
87
- return this.transformToModel(result.query.rows[0]);
144
+ const entities = result.query.rows[0];
145
+ const model = await this.transformToModel(this.model, this.statements, entities);
146
+ await this.handleSelectJoin(entities, model);
147
+ return model;
88
148
  }
89
149
  async executeAndReturnFirstOrFail() {
90
150
  this.statements.limit = 1;
@@ -92,40 +152,126 @@ class SqlBuilder {
92
152
  if (result.query.rows.length === 0) {
93
153
  throw new Error('Result not found');
94
154
  }
95
- return this.transformToModel(result.query.rows[0]);
155
+ const entities = result.query.rows[0];
156
+ const model = await this.transformToModel(this.model, this.statements, entities);
157
+ await this.handleSelectJoin(entities, model);
158
+ return model;
96
159
  }
97
- // TODO: Corrigir tipagem do retorno de acordo com o driver
98
160
  async executeAndReturnAll() {
99
161
  const result = await this.execute();
100
162
  if (result.query.rows.length === 0) {
101
163
  return [];
102
164
  }
103
- return result.query.rows.map((row) => this.transformToModel(row));
165
+ const rows = result.query.rows;
166
+ const results = [];
167
+ for (const row of rows) {
168
+ const models = this.transformToModel(this.model, this.statements, row);
169
+ await this.handleSelectJoin(row, models);
170
+ results.push(models);
171
+ }
172
+ return results;
104
173
  }
105
- async execute() {
106
- if (!this.statements.columns) {
107
- let columns = [
108
- ...this.getColumnsEntity(this.model, this.statements.alias),
109
- ];
110
- if (this.statements.join) {
111
- columns = [
112
- ...columns,
113
- ...this.statements.join.flatMap(join => this.getColumnsEntity(join.joinEntity, join.joinAlias)),
114
- ];
174
+ async handleSelectJoin(entities, models) {
175
+ if (!this.statements.selectJoin || this.statements.selectJoin.length === 0) {
176
+ return;
177
+ }
178
+ for (const join of this.statements.selectJoin.reverse()) {
179
+ let ids = entities[`${join.originAlias}_${join.primaryKey}`];
180
+ if (typeof ids === 'undefined') {
181
+ // get of models
182
+ const selectJoined = this.statements.selectJoin.find(j => j.joinEntity === join.originEntity);
183
+ if (!selectJoined) {
184
+ continue;
185
+ }
186
+ ids = this.findIdRecursively(models, selectJoined, join);
187
+ }
188
+ if (Array.isArray(ids)) {
189
+ ids = ids.map((id) => this.t(id)).join(', ');
190
+ }
191
+ if (join.where) {
192
+ join.where = `${join.where} AND ${join.alias}."${join.fkKey}" IN (${ids})`;
193
+ }
194
+ else {
195
+ join.where = `${join.alias}."${join.fkKey}" IN (${ids})`;
115
196
  }
116
- this.statements.columns = columns;
197
+ if (join.columns && join.columns.length > 0) {
198
+ join.columns = join.columns.map(
199
+ // @ts-ignore
200
+ (column) => `${join.alias}."${column}" as "${join.alias}_${column}"`);
201
+ }
202
+ else {
203
+ join.columns = this.getColumnsEntity(join.joinEntity, join.alias);
204
+ }
205
+ const child = await this.driver.executeStatement(join);
206
+ this.logger.debug(`SQL: ${child.sql} [${Date.now() - child.startTime}ms]`);
207
+ const property = this.entityStorage.get(this.model).relations.find((rel) => rel.propertyKey === join.joinProperty);
208
+ const values = child.query.rows.map((row) => this.transformToModel(join.joinEntity, join, row));
209
+ const path = this.getPathForSelectJoin(join);
210
+ this.setValueByPath(models, path, property?.type === Array ? [...values] : values[0]);
117
211
  }
118
- else {
119
- // @ts-ignore
120
- this.statements.columns = this.statements.columns.map((column) => {
121
- return this.discoverColumnAlias(column);
122
- }).flat();
212
+ return models;
213
+ }
214
+ getPathForSelectJoin(selectJoin) {
215
+ const path = this.getPathForSelectJoinRecursive(this.statements, selectJoin);
216
+ return path.reverse();
217
+ }
218
+ setValueByPath(obj, path, value) {
219
+ let currentObj = obj;
220
+ for (let i = 0; i < path.length - 1; i++) {
221
+ const key = path[i];
222
+ currentObj[key] = currentObj[key] || {};
223
+ currentObj = currentObj[key];
224
+ }
225
+ currentObj[path[path.length - 1]] = value;
226
+ }
227
+ getPathForSelectJoinRecursive(statements, selectJoin) {
228
+ const originJoin = this.statements.selectJoin.find(j => j.joinEntity === selectJoin.originEntity);
229
+ let pathInJoin = [];
230
+ if (!originJoin) {
231
+ return [selectJoin.joinProperty];
232
+ }
233
+ if (originJoin.originEntity !== statements.originEntity) {
234
+ pathInJoin = this.getPathForSelectJoinRecursive(statements, originJoin);
235
+ }
236
+ return [selectJoin.joinProperty, ...pathInJoin];
237
+ }
238
+ findIdRecursively(models, selectJoined, join) {
239
+ let ids = models[selectJoined.originProperty][join.primaryKey];
240
+ if (typeof ids === 'undefined') {
241
+ const nextSelectJoined = this.statements.selectJoin.find(j => j.joinEntity === selectJoined.originEntity);
242
+ if (nextSelectJoined) {
243
+ // Chamada recursiva para a próxima camada
244
+ ids = this.findIdRecursively(models, nextSelectJoined, join);
245
+ }
123
246
  }
247
+ return ids;
248
+ }
249
+ generateColumns() {
250
+ let columns = [
251
+ ...this.getColumnsEntity(this.model, this.statements.alias),
252
+ ];
253
+ if (this.statements.join) {
254
+ columns = [
255
+ ...columns,
256
+ ...this.statements.join.flatMap(join => this.getColumnsEntity(join.joinEntity, join.joinAlias)),
257
+ ];
258
+ }
259
+ return columns;
260
+ }
261
+ extractAliasForColumns() {
262
+ // @ts-ignore
263
+ this.statements.columns = this.statements.columns.map((column) => {
264
+ return this.discoverColumnAlias(column);
265
+ }).flat();
266
+ }
267
+ filterInvalidColumns() {
268
+ this.statements.columns = this.statements.columns.filter(Boolean);
269
+ }
270
+ includeUpdatedColumns() {
124
271
  this.statements.columns.push(...this.updatedColumns);
125
- const result = await this.driver.executeStatement(this.statements);
126
- // console.log(result.query.rows);
272
+ }
273
+ logExecution(result) {
127
274
  this.logger.debug(`SQL: ${result.sql} [${Date.now() - result.startTime}ms]`);
128
- return result;
129
275
  }
130
276
  startTransaction() {
131
277
  return this.driver.startTransaction();
@@ -172,20 +318,29 @@ class SqlBuilder {
172
318
  }
173
319
  return `${this.statements.alias}."${column}" as ${this.statements.alias}_${column}`;
174
320
  }
175
- if (typeof this.statements.join === 'undefined') {
321
+ if (typeof this.statements.join === 'undefined' && typeof this.statements.selectJoin === 'undefined') {
176
322
  throw new Error('Join not found');
177
323
  }
178
324
  const entities = column.split('.');
179
325
  let lastEntity = this.model;
180
326
  let lastAlias = this.statements.alias;
181
327
  const relationsMap = new Map(this.entity.relations.map(rel => [rel.propertyKey, rel]));
182
- const joinMap = new Map(this.statements.join.map(join => [join.joinProperty, join]));
328
+ const joinMap = new Map();
329
+ const joinSelectMap = new Map();
330
+ this.statements.join?.forEach(join => joinMap.set(join.joinProperty, join));
331
+ this.statements.selectJoin?.forEach(join => joinSelectMap.set(join.joinProperty, join));
183
332
  for (let i = 0; i < entities.length; i++) {
184
333
  if (i === 0) {
185
334
  const relation = relationsMap.get(entities[i]);
186
335
  lastEntity = relation?.entity();
187
336
  // @ts-ignore
188
- lastAlias = joinMap.get(entities[i])?.joinAlias;
337
+ if (joinMap.has(entities[i])) {
338
+ lastAlias = joinMap.get(entities[i]).joinAlias;
339
+ }
340
+ else {
341
+ lastAlias = joinSelectMap.get(entities[i])?.alias;
342
+ return undefined;
343
+ }
189
344
  }
190
345
  else {
191
346
  if ((i + 1) === entities.length) {
@@ -219,19 +374,23 @@ class SqlBuilder {
219
374
  addLogicalOperatorToSql(conditions, operator) {
220
375
  return `(${conditions.join(` ${operator} `)})`;
221
376
  }
222
- conditionToSql(condition, alias) {
377
+ conditionToSql(condition, alias, model) {
223
378
  const sqlParts = [];
224
379
  const operators = ['$eq', '$ne', '$in', '$nin', '$like', '$gt', '$gte', '$lt', '$lte', '$and', '$or'];
225
380
  for (let [key, value] of Object.entries(condition)) {
226
- if (this.extendsFrom(value_object_1.ValueObject, value.constructor.prototype)) {
381
+ if (this.extendsFrom(ValueObject, value.constructor.prototype)) {
227
382
  value = value.getValue();
228
383
  }
229
384
  if (!operators.includes(key)) {
230
385
  this.lastKeyNotOperator = key;
231
386
  }
232
- const relationShip = this.entity.relations?.find(rel => rel.propertyKey === key);
387
+ const entity = this.entityStorage.get(model);
388
+ const relationShip = entity.relations?.find(rel => rel.propertyKey === key);
233
389
  if (relationShip) {
234
- sqlParts.push(this.applyJoin(relationShip, value, alias));
390
+ const sql = this.applyJoin(relationShip, value, alias);
391
+ if (this.statements.strategy === 'joined') {
392
+ sqlParts.push(sql);
393
+ }
235
394
  }
236
395
  else if (typeof value !== 'object' || value === null) {
237
396
  if (key === '$eq') {
@@ -245,7 +404,7 @@ class SqlBuilder {
245
404
  }
246
405
  else {
247
406
  if (['$or', '$and'].includes(key)) {
248
- sqlParts.push(this.addLogicalOperatorToSql(value.map((cond) => this.conditionToSql(cond, alias)), key.toUpperCase().replace('$', '')));
407
+ sqlParts.push(this.addLogicalOperatorToSql(value.map((cond) => this.conditionToSql(cond, alias, model)), key.toUpperCase().replace('$', '')));
249
408
  }
250
409
  for (const operator of operators) {
251
410
  if (operator in value) {
@@ -279,7 +438,7 @@ class SqlBuilder {
279
438
  break;
280
439
  case '$and':
281
440
  case '$or':
282
- const parts = value[operator].map((cond) => this.conditionToSql(cond, alias));
441
+ const parts = value[operator].map((cond) => this.conditionToSql(cond, alias, model));
283
442
  sqlParts.push(this.addLogicalOperatorToSql(parts, operator.toUpperCase().replace('$', '')));
284
443
  break;
285
444
  }
@@ -287,6 +446,9 @@ class SqlBuilder {
287
446
  }
288
447
  }
289
448
  }
449
+ if (sqlParts.length === 0) {
450
+ return '';
451
+ }
290
452
  return this.addLogicalOperatorToSql(sqlParts, 'AND');
291
453
  }
292
454
  t(value) {
@@ -306,33 +468,52 @@ class SqlBuilder {
306
468
  }
307
469
  }
308
470
  const joinAlias = `${this.getAlias(joinTableName)}`;
309
- const joinWhere = this.conditionToSql(value, joinAlias);
310
- this.statements.join = this.statements.join || [];
471
+ const joinWhere = this.conditionToSql(value, joinAlias, relationShip.entity());
311
472
  let on = '';
312
473
  switch (relationShip.relation) {
313
474
  case "one-to-many":
314
- on = `${joinAlias}.${this.getFkKey(relationShip)} = ${alias}.${originPrimaryKey}`;
475
+ on = `${joinAlias}."${this.getFkKey(relationShip)}" = ${alias}."${originPrimaryKey}"`;
315
476
  break;
316
477
  case "many-to-one":
317
- on = `${alias}.${relationShip.propertyKey} = ${joinAlias}.${this.getFkKey(relationShip)}`;
478
+ on = `${alias}."${relationShip.propertyKey}" = ${joinAlias}."${this.getFkKey(relationShip)}"`;
318
479
  break;
319
480
  }
320
- this.statements.join.push({
321
- joinAlias: joinAlias,
322
- joinTable: joinTableName,
323
- joinSchema: joinSchema || 'public',
324
- joinWhere: joinWhere,
325
- joinProperty: relationShip.propertyKey,
326
- originAlias: alias,
327
- originSchema: schema,
328
- originTable: tableName,
329
- propertyKey: relationShip.propertyKey,
330
- joinEntity: relationShip.entity(),
331
- type: 'LEFT',
332
- // @ts-ignore
333
- on,
334
- originalEntity: relationShip.originalEntity,
335
- });
481
+ if (this.statements.strategy === 'joined') {
482
+ this.statements.join = this.statements.join || [];
483
+ this.statements.join.push({
484
+ joinAlias: joinAlias,
485
+ joinTable: joinTableName,
486
+ joinSchema: joinSchema || 'public',
487
+ joinWhere: joinWhere,
488
+ joinProperty: relationShip.propertyKey,
489
+ originAlias: alias,
490
+ originSchema: schema,
491
+ originTable: tableName,
492
+ propertyKey: relationShip.propertyKey,
493
+ joinEntity: relationShip.entity(),
494
+ type: 'LEFT',
495
+ // @ts-ignore
496
+ on,
497
+ originalEntity: relationShip.originalEntity,
498
+ });
499
+ }
500
+ else {
501
+ this.statements.selectJoin = this.statements.selectJoin || [];
502
+ this.statements.selectJoin.push({
503
+ statement: 'select',
504
+ columns: this.originalColumns.filter(column => column.startsWith(`${relationShip.propertyKey}`)).map(column => column.split('.')[1]) || [],
505
+ table: `"${joinSchema || 'public'}"."${joinTableName}"`,
506
+ alias: joinAlias,
507
+ where: joinWhere,
508
+ joinProperty: relationShip.propertyKey,
509
+ fkKey: this.getFkKey(relationShip),
510
+ primaryKey: originPrimaryKey,
511
+ originAlias: alias,
512
+ originProperty: relationShip.propertyKey,
513
+ joinEntity: relationShip.entity(),
514
+ originEntity: relationShip.originalEntity,
515
+ });
516
+ }
336
517
  return joinWhere;
337
518
  }
338
519
  getFkKey(relationShip) {
@@ -360,14 +541,14 @@ class SqlBuilder {
360
541
  }
361
542
  this.entity = entity;
362
543
  }
363
- transformToModel(data) {
364
- const instance = new this.model();
544
+ transformToModel(model, statement, data) {
545
+ const instance = new model();
365
546
  instance.$_isPersisted = true;
366
547
  const entitiesByAlias = {
367
- [this.statements.alias]: instance,
548
+ [statement.alias]: instance,
368
549
  };
369
550
  const entitiesOptions = new Map();
370
- entitiesOptions.set(this.statements.alias, this.entityStorage.get(instance.constructor));
551
+ entitiesOptions.set(statement.alias, this.entityStorage.get(instance.constructor));
371
552
  if (this.statements.join) {
372
553
  this.statements.join.forEach(join => {
373
554
  const joinInstance = new join.joinEntity();
@@ -384,7 +565,7 @@ class SqlBuilder {
384
565
  }
385
566
  const entityProperty = entitiesOptions.get(alias).showProperties[prop];
386
567
  if (entityProperty) {
387
- if (this.extendsFrom(value_object_1.ValueObject, entityProperty.type.prototype)) {
568
+ if (this.extendsFrom(ValueObject, entityProperty.type.prototype)) {
388
569
  // @ts-ignore
389
570
  entity[prop] = new entityProperty.type(value);
390
571
  return;
@@ -431,7 +612,16 @@ class SqlBuilder {
431
612
  if (!e) {
432
613
  throw new Error('Entity not found');
433
614
  }
434
- return Object.keys(e.showProperties).map(key => `${alias}."${key}" as "${alias}_${key}"`);
615
+ const columns = Object.keys(e.showProperties).map(key => `${alias}."${key}" as "${alias}_${key}"`);
616
+ if (e.relations) {
617
+ for (const relation of e.relations) {
618
+ if (relation.relation === 'many-to-one') {
619
+ // @ts-ignore
620
+ columns.push(`${alias}."${relation.propertyKey}" as "${alias}_${relation.propertyKey}"`);
621
+ }
622
+ }
623
+ }
624
+ return columns;
435
625
  }
436
626
  withDefaultValues(values, entityOptions) {
437
627
  const property = Object.entries(entityOptions.showProperties).filter(([_, value]) => value.options.onInsert);
@@ -471,5 +661,33 @@ class SqlBuilder {
471
661
  return false;
472
662
  }
473
663
  }
474
- exports.SqlBuilder = SqlBuilder;
664
+ function processValuesForInsert(values) {
665
+ for (const value in values) {
666
+ if (extendsFrom(ValueObject, values[value].constructor.prototype)) {
667
+ values[value] = values[value].getValue();
668
+ continue;
669
+ }
670
+ if (values[value] instanceof BaseEntity) {
671
+ // @ts-ignore
672
+ values[value] = values[value].id; // TODO: get primary key
673
+ }
674
+ }
675
+ }
676
+ function processValuesForUpdate(values) {
677
+ for (const value in values) {
678
+ if (extendsFrom(ValueObject, values[value].constructor.prototype)) {
679
+ values[value] = values[value].getValue();
680
+ }
681
+ }
682
+ }
683
+ function extendsFrom(baseClass, instance) {
684
+ let proto = Object.getPrototypeOf(instance);
685
+ while (proto) {
686
+ if (proto === baseClass.prototype) {
687
+ return true;
688
+ }
689
+ proto = Object.getPrototypeOf(proto);
690
+ }
691
+ return false;
692
+ }
475
693
  //# sourceMappingURL=SqlBuilder.js.map