@iamkirbki/database-handler-core 4.2.0 → 4.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/abstract/Model.d.ts +14 -11
  2. package/dist/abstract/Model.d.ts.map +1 -1
  3. package/dist/abstract/Model.js +48 -7
  4. package/dist/base/Query.d.ts +10 -9
  5. package/dist/base/Query.d.ts.map +1 -1
  6. package/dist/base/Query.js +31 -14
  7. package/dist/base/Record.d.ts +7 -4
  8. package/dist/base/Record.d.ts.map +1 -1
  9. package/dist/base/Record.js +36 -13
  10. package/dist/base/Table.d.ts +13 -7
  11. package/dist/base/Table.d.ts.map +1 -1
  12. package/dist/base/Table.js +81 -31
  13. package/dist/helpers/QueryStatementBuilder.d.ts +12 -10
  14. package/dist/helpers/QueryStatementBuilder.d.ts.map +1 -1
  15. package/dist/helpers/QueryStatementBuilder.js +36 -14
  16. package/dist/interfaces/IDatabaseAdapter.d.ts +1 -0
  17. package/dist/interfaces/IDatabaseAdapter.d.ts.map +1 -1
  18. package/dist/interfaces/ISchemaBuilder.d.ts +1 -1
  19. package/dist/interfaces/ISchemaBuilder.d.ts.map +1 -1
  20. package/dist/runtime/Container.d.ts +2 -0
  21. package/dist/runtime/Container.d.ts.map +1 -1
  22. package/dist/runtime/Container.js +7 -0
  23. package/dist/runtime/Repository.d.ts +18 -8
  24. package/dist/runtime/Repository.d.ts.map +1 -1
  25. package/dist/runtime/Repository.js +97 -21
  26. package/dist/types/factories.d.ts +6 -0
  27. package/dist/types/factories.d.ts.map +1 -0
  28. package/dist/types/factories.js +1 -0
  29. package/dist/types/index.d.ts +1 -0
  30. package/dist/types/index.d.ts.map +1 -1
  31. package/dist/types/index.js +1 -0
  32. package/dist/types/model.d.ts +9 -4
  33. package/dist/types/model.d.ts.map +1 -1
  34. package/dist/types/query.d.ts +14 -6
  35. package/dist/types/query.d.ts.map +1 -1
  36. package/dist/types/table.d.ts +4 -3
  37. package/dist/types/table.d.ts.map +1 -1
  38. package/package.json +1 -1
@@ -12,19 +12,30 @@ import { Record, Query } from "../index.js";
12
12
  /** Table class for interacting with a database table */
13
13
  export default class Table {
14
14
  /** Private constructor - use Table.create() */
15
- constructor(name) {
15
+ constructor(name, customAdapter, queryFactory = (config) => new Query(config), recordFactory = (table, values, adapter) => new Record(table, values, adapter)) {
16
16
  this._name = name;
17
+ this._customAdapter = customAdapter;
18
+ this._queryFactory = queryFactory;
19
+ this._recordFactory = recordFactory;
20
+ this._query = this._queryFactory({
21
+ tableName: this._name,
22
+ adapterName: this._customAdapter,
23
+ recordFactory: this._recordFactory
24
+ });
25
+ }
26
+ get QueryHelperObject() {
27
+ return this._query;
17
28
  }
18
29
  /** Get raw column information */
19
- TableColumnInformation() {
30
+ TableColumnInformation(tableName) {
20
31
  return __awaiter(this, void 0, void 0, function* () {
21
- return Query.tableColumnInformation(this._name);
32
+ return this._query.TableColumnInformation(tableName || this._name);
22
33
  });
23
34
  }
24
35
  /** Get readable, formatted column information */
25
36
  ReadableTableColumnInformation() {
26
37
  return __awaiter(this, void 0, void 0, function* () {
27
- const columns = yield this.TableColumnInformation();
38
+ const columns = yield this.TableColumnInformation(this._name);
28
39
  return columns.map((col) => ({
29
40
  name: col.name,
30
41
  type: col.type,
@@ -37,7 +48,12 @@ export default class Table {
37
48
  Drop() {
38
49
  return __awaiter(this, void 0, void 0, function* () {
39
50
  const queryStr = `DROP TABLE IF EXISTS "${this._name}";`;
40
- const query = new Query(this._name, queryStr);
51
+ const query = this._queryFactory({
52
+ tableName: this._name,
53
+ query: queryStr,
54
+ adapterName: this._customAdapter,
55
+ recordFactory: this._recordFactory
56
+ });
41
57
  yield query.Run();
42
58
  });
43
59
  }
@@ -51,9 +67,15 @@ export default class Table {
51
67
  limit: options === null || options === void 0 ? void 0 : options.limit,
52
68
  offset: options === null || options === void 0 ? void 0 : options.offset,
53
69
  });
54
- const query = new Query(this._name, queryStr);
70
+ let params = {};
55
71
  if ((options === null || options === void 0 ? void 0 : options.where) && Object.keys(options.where).length > 0)
56
- query.Parameters = options.where;
72
+ params = options.where;
73
+ const query = this._queryFactory({
74
+ tableName: this._name,
75
+ query: queryStr,
76
+ parameters: params,
77
+ recordFactory: this._recordFactory
78
+ });
57
79
  const results = yield query.All();
58
80
  return results;
59
81
  });
@@ -73,15 +95,29 @@ export default class Table {
73
95
  /** Get the total count of records */
74
96
  RecordsCount() {
75
97
  return __awaiter(this, void 0, void 0, function* () {
76
- const query = new Query(this._name, `SELECT COUNT(*) as count FROM "${this._name}";`);
98
+ const query = this._queryFactory({
99
+ tableName: this._name,
100
+ query: `SELECT COUNT(*) as count FROM "${this._name}"`,
101
+ recordFactory: this._recordFactory
102
+ });
77
103
  const count = yield query.Count();
78
104
  return count || 0;
79
105
  });
80
106
  }
107
+ exists() {
108
+ return __awaiter(this, void 0, void 0, function* () {
109
+ const query = this._queryFactory({
110
+ tableName: this._name,
111
+ adapterName: this._customAdapter,
112
+ recordFactory: this._recordFactory
113
+ });
114
+ return yield query.DoesTableExist();
115
+ });
116
+ }
81
117
  /** Insert a record into the table */
82
118
  Insert(values) {
83
119
  return __awaiter(this, void 0, void 0, function* () {
84
- const record = new Record(values, this._name);
120
+ const record = this._recordFactory(this._name, values, this._customAdapter);
85
121
  yield record.Insert();
86
122
  return record;
87
123
  });
@@ -89,38 +125,52 @@ export default class Table {
89
125
  /** Perform JOIN operations with other tables */
90
126
  Join(Joins, options) {
91
127
  return __awaiter(this, void 0, void 0, function* () {
92
- const queryString = QueryStatementBuilder.BuildJoin(this._name, Joins, options);
93
- const query = new Query(this._name, queryString);
94
- // Set parameters if WHERE clause is present
95
- if (options === null || options === void 0 ? void 0 : options.where) {
96
- query.Parameters = options.where;
97
- }
128
+ const queryString = yield QueryStatementBuilder.BuildJoin(this._name, Joins, this.QueryHelperObject, options);
129
+ let params = {};
130
+ if (options === null || options === void 0 ? void 0 : options.where)
131
+ params = options.where;
132
+ const query = this._queryFactory({
133
+ tableName: this._name,
134
+ query: queryString,
135
+ parameters: params,
136
+ recordFactory: this._recordFactory
137
+ });
98
138
  const joinedTables = Array.isArray(Joins) ? Joins.map(j => j.fromTable) : [Joins.fromTable];
139
+ if (options) {
140
+ options.select = joinedTables.map(table => `${table}.*`).join(', ');
141
+ }
99
142
  const records = yield query.All();
100
- return yield this.splitJoinValues(records, joinedTables);
143
+ const splitTables = yield this.splitJoinValues(records, joinedTables);
144
+ return splitTables;
101
145
  });
102
146
  }
103
147
  splitJoinValues(records, joinedTables) {
104
148
  return __awaiter(this, void 0, void 0, function* () {
105
- const thisRecordColumns = (yield this.TableColumnInformation()).map(col => col.name);
106
- const tableColumnsMap = new Map();
107
- for (const tableName of joinedTables) {
108
- const columns = (yield Query.tableColumnInformation(tableName)).map(col => col.name);
109
- tableColumnsMap.set(tableName, columns);
110
- }
111
149
  return records.map(record => {
112
150
  if (!record.values)
113
151
  return record;
114
- const thisRecordEntries = thisRecordColumns
115
- .map(colName => [colName, record.values[colName]])
116
- .filter(([, value]) => value !== undefined);
117
- const joinedRecords = {};
118
- for (const [tableName, tableColumns] of tableColumnsMap) {
119
- const joinedRecordEntries = Object.entries(record.values)
120
- .filter(([key]) => tableColumns.includes(key));
121
- joinedRecords[tableName] = Object.fromEntries(joinedRecordEntries);
152
+ const mainTableData = {};
153
+ const joinedTableData = {};
154
+ for (const tableName of joinedTables) {
155
+ joinedTableData[tableName] = {};
156
+ }
157
+ for (const [aliasedKey, value] of Object.entries(record.values)) {
158
+ if (aliasedKey.includes('__')) {
159
+ const [tableName, columnName] = aliasedKey.split('__');
160
+ if (tableName === this._name) {
161
+ mainTableData[columnName] = value;
162
+ }
163
+ else if (joinedTables.includes(tableName)) {
164
+ joinedTableData[tableName][columnName] = value;
165
+ }
166
+ }
167
+ else {
168
+ mainTableData[aliasedKey] = value;
169
+ }
122
170
  }
123
- return new Record(Object.assign(Object.assign({}, Object.fromEntries(thisRecordEntries)), joinedRecords), this._name);
171
+ // Combine main table data with nested joined table data
172
+ const combinedData = Object.assign(Object.assign({}, mainTableData), joinedTableData);
173
+ return this._recordFactory(this._name, combinedData, this._customAdapter);
124
174
  });
125
175
  });
126
176
  }
@@ -1,4 +1,5 @@
1
- import { DefaultQueryOptions, QueryOptions, QueryCondition, Join, QueryWhereParameters } from "../types/index.js";
1
+ import { Query } from "../index.js";
2
+ import { DefaultQueryParameters, ExtraQueryParameters, QueryWhereCondition, Join, QueryIsEqualParameter } from "../types/index.js";
2
3
  /** Utility class for building SQL query strings */
3
4
  export default class QueryStatementBuilder {
4
5
  /**
@@ -25,7 +26,7 @@ export default class QueryStatementBuilder {
25
26
  * // "SELECT id, name, email FROM users WHERE status = @status AND age = @age ORDER BY created_at DESC LIMIT 10 OFFSET 20"
26
27
  * ```
27
28
  */
28
- static BuildSelect(tableName: string, options?: DefaultQueryOptions & QueryOptions): string;
29
+ static BuildSelect(tableName: string, options?: DefaultQueryParameters & ExtraQueryParameters): string;
29
30
  /**
30
31
  * Build an INSERT SQL statement with named parameter placeholders
31
32
  *
@@ -45,7 +46,7 @@ export default class QueryStatementBuilder {
45
46
  * // Note: The actual values will be bound separately using the Parameters object
46
47
  * ```
47
48
  */
48
- static BuildInsert(tableName: string, record: QueryWhereParameters): string;
49
+ static BuildInsert(tableName: string, record: QueryIsEqualParameter): string;
49
50
  /**
50
51
  * Build an UPDATE SQL statement with SET clause and WHERE conditions
51
52
  *
@@ -72,7 +73,7 @@ export default class QueryStatementBuilder {
72
73
  * // "UPDATE users SET status = @status WHERE status = @status AND last_login = @last_login"
73
74
  * ```
74
75
  */
75
- static BuildUpdate(tableName: string, record: QueryCondition, where: QueryCondition): string;
76
+ static BuildUpdate(tableName: string, record: QueryWhereCondition, where: QueryWhereCondition): string;
76
77
  /**
77
78
  * Build a DELETE SQL statement with WHERE conditions
78
79
  *
@@ -93,7 +94,7 @@ export default class QueryStatementBuilder {
93
94
  * // "DELETE FROM users WHERE status = @status AND last_login = @last_login"
94
95
  * ```
95
96
  */
96
- static BuildDelete(tableName: string, where: QueryCondition): string;
97
+ static BuildDelete(tableName: string, where: QueryWhereCondition): string;
97
98
  /**
98
99
  * Build a COUNT SQL statement to count rows, optionally with WHERE conditions
99
100
  *
@@ -115,7 +116,7 @@ export default class QueryStatementBuilder {
115
116
  * // "SELECT COUNT(*) as count FROM users WHERE status = @status AND age = @age"
116
117
  * ```
117
118
  */
118
- static BuildCount(tableName: string, where?: QueryCondition): string;
119
+ static BuildCount(tableName: string, where?: QueryWhereCondition): string;
119
120
  /**
120
121
  * Build a WHERE clause from parameter conditions (helper method)
121
122
  *
@@ -144,7 +145,7 @@ export default class QueryStatementBuilder {
144
145
  * // ""
145
146
  * ```
146
147
  */
147
- static BuildWhere(where?: QueryCondition): string;
148
+ static BuildWhere(where?: QueryWhereCondition): string;
148
149
  private static buildWhereWithOperators;
149
150
  private static buildWhereSimple;
150
151
  /**
@@ -191,7 +192,8 @@ export default class QueryStatementBuilder {
191
192
  * );
192
193
  * ```
193
194
  */
194
- static BuildJoin(fromTableName: string, joins: Join | Join[], options?: DefaultQueryOptions & QueryOptions): string;
195
+ static BuildJoin(fromTableName: string, joins: Join | Join[], query: Query, options?: DefaultQueryParameters & ExtraQueryParameters): Promise<string>;
196
+ static BuildJoinSelect(fromTableName: string, joins: Join | Join[], query: Query): Promise<string>;
195
197
  /**
196
198
  * Build JOIN clause(s) recursively (helper method)
197
199
  *
@@ -264,7 +266,7 @@ export default class QueryStatementBuilder {
264
266
  * // "ON users.id = orders.user_id AND users.company_id = orders.company_id"
265
267
  * ```
266
268
  */
267
- static BuildJoinOnPart(tableName: string, joinTableName: string, on: QueryWhereParameters | QueryWhereParameters[]): string;
269
+ static BuildJoinOnPart(tableName: string, joinTableName: string, on: QueryIsEqualParameter | QueryIsEqualParameter[]): string;
268
270
  /**
269
271
  * Build query options clause (ORDER BY, LIMIT, OFFSET) (helper method)
270
272
  *
@@ -298,6 +300,6 @@ export default class QueryStatementBuilder {
298
300
  * // "LIMIT 25 OFFSET 50"
299
301
  * ```
300
302
  */
301
- static BuildQueryOptions(options: QueryOptions): string;
303
+ static BuildQueryOptions(options: ExtraQueryParameters): string;
302
304
  }
303
305
  //# sourceMappingURL=QueryStatementBuilder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"QueryStatementBuilder.d.ts","sourceRoot":"","sources":["../../src/helpers/QueryStatementBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,cAAc,EAAE,IAAI,EAAmB,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEtI,mDAAmD;AACnD,MAAM,CAAC,OAAO,OAAO,qBAAqB;IACtC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;WACW,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,YAAY,GAAG,MAAM;IAWlG;;;;;;;;;;;;;;;;;;OAkBG;WACW,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,MAAM;IAYlF;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;WACW,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM;IAWnG;;;;;;;;;;;;;;;;;;;OAmBG;WACW,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM;IAS3E;;;;;;;;;;;;;;;;;;;;OAoBG;WACW,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,cAAc,GAAG,MAAM;IAQ3E;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;WACW,UAAU,CAAC,KAAK,CAAC,EAAE,cAAc,GAAG,MAAM;IAgBxD,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAStC,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAK/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2CG;WACW,SAAS,CACnB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,EACpB,OAAO,CAAC,EAAE,mBAAmB,GAAG,YAAY,GAC7C,MAAM;IAWT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCG;WACW,aAAa,CACvB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,GACrB,MAAM;IAcT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;WACW,eAAe,CACzB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,EAAE,EAAE,oBAAoB,GAAG,oBAAoB,EAAE,GAClD,MAAM;IAWT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;WACW,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM;CAiBjE"}
1
+ {"version":3,"file":"QueryStatementBuilder.d.ts","sourceRoot":"","sources":["../../src/helpers/QueryStatementBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,IAAI,EAA6B,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAEjK,mDAAmD;AACnD,MAAM,CAAC,OAAO,OAAO,qBAAqB;IACtC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;WACW,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,oBAAoB,GAAG,MAAM;IAW7G;;;;;;;;;;;;;;;;;;OAkBG;WACW,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,GAAG,MAAM;IAYnF;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;WACW,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,EAAE,KAAK,EAAE,mBAAmB,GAAG,MAAM;IAW7G;;;;;;;;;;;;;;;;;;;OAmBG;WACW,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,MAAM;IAShF;;;;;;;;;;;;;;;;;;;;OAoBG;WACW,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,mBAAmB,GAAG,MAAM;IAQhF;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;WACW,UAAU,CAAC,KAAK,CAAC,EAAE,mBAAmB,GAAG,MAAM;IAgB7D,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAStC,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAK/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2CG;WACiB,SAAS,CACzB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,EACpB,KAAK,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,sBAAsB,GAAG,oBAAoB,GACxD,OAAO,CAAC,MAAM,CAAC;WAaE,eAAe,CAC/B,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,EACpB,KAAK,EAAE,KAAK,GACb,OAAO,CAAC,MAAM,CAAC;IAmBlB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCG;WACW,aAAa,CACvB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,GACrB,MAAM;IAaT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;WACW,eAAe,CACzB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,EAAE,EAAE,qBAAqB,GAAG,qBAAqB,EAAE,GACpD,MAAM;IAWT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;WACW,iBAAiB,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM;CAiBzE"}
@@ -1,3 +1,12 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  /** Utility class for building SQL query strings */
2
11
  export default class QueryStatementBuilder {
3
12
  /**
@@ -245,15 +254,29 @@ export default class QueryStatementBuilder {
245
254
  * );
246
255
  * ```
247
256
  */
248
- static BuildJoin(fromTableName, joins, options) {
249
- var _a;
250
- const queryParts = [];
251
- queryParts.push(`SELECT ${(_a = options === null || options === void 0 ? void 0 : options.select) !== null && _a !== void 0 ? _a : "*"}`);
252
- queryParts.push(`FROM "${fromTableName}"`);
253
- queryParts.push(this.BuildJoinPart(fromTableName, joins));
254
- queryParts.push(this.BuildWhere(options === null || options === void 0 ? void 0 : options.where));
255
- queryParts.push(this.BuildQueryOptions(options !== null && options !== void 0 ? options : {}));
256
- return queryParts.join(" ");
257
+ static BuildJoin(fromTableName, joins, query, options) {
258
+ return __awaiter(this, void 0, void 0, function* () {
259
+ const queryParts = [];
260
+ const selectClause = yield QueryStatementBuilder.BuildJoinSelect(fromTableName, joins, query);
261
+ queryParts.push(`SELECT ${selectClause}`);
262
+ queryParts.push(`FROM "${fromTableName}"`);
263
+ queryParts.push(this.BuildJoinPart(fromTableName, joins));
264
+ queryParts.push(this.BuildWhere(options === null || options === void 0 ? void 0 : options.where));
265
+ queryParts.push(this.BuildQueryOptions(options !== null && options !== void 0 ? options : {}));
266
+ return queryParts.join(" ");
267
+ });
268
+ }
269
+ static BuildJoinSelect(fromTableName, joins, query) {
270
+ return __awaiter(this, void 0, void 0, function* () {
271
+ const mainTableCols = yield query.TableColumnInformation(fromTableName);
272
+ const mainTableSelect = mainTableCols.map(col => `"${fromTableName}"."${col.name}" AS "${fromTableName}__${col.name}"`).join(', ');
273
+ const joinArray = Array.isArray(joins) ? joins : [joins];
274
+ const joinedSelects = yield Promise.all(joinArray.map((join) => __awaiter(this, void 0, void 0, function* () {
275
+ const cols = yield query.TableColumnInformation(join.fromTable);
276
+ return cols.map(col => `"${join.fromTable}"."${col.name}" AS "${join.fromTable}__${col.name}"`).join(', ');
277
+ })));
278
+ return [mainTableSelect, ...joinedSelects].join(', ');
279
+ });
257
280
  }
258
281
  /**
259
282
  * Build JOIN clause(s) recursively (helper method)
@@ -296,12 +319,11 @@ export default class QueryStatementBuilder {
296
319
  */
297
320
  static BuildJoinPart(fromTableName, joins) {
298
321
  const queryParts = [];
299
- const joinsArray = Array.isArray(joins) ? joins : [joins];
300
- let currentTableName = fromTableName;
301
- for (const join of joinsArray) {
322
+ joins = Array.isArray(joins) ? joins : [joins];
323
+ for (const join of joins) {
324
+ const baseTable = join.baseTable || fromTableName; // Use explicit base or default
302
325
  queryParts.push(`${join.joinType} JOIN "${join.fromTable}"`);
303
- queryParts.push(this.BuildJoinOnPart(currentTableName, join.fromTable, join.on));
304
- currentTableName = join.fromTable;
326
+ queryParts.push(this.BuildJoinOnPart(baseTable, join.fromTable, join.on));
305
327
  }
306
328
  return queryParts.join(" ");
307
329
  }
@@ -6,6 +6,7 @@ export default interface IDatabaseAdapter {
6
6
  exec(query: string): Promise<void>;
7
7
  transaction(fn: (items: any[]) => void): Promise<Function>;
8
8
  tableColumnInformation(tableName: string): Promise<TableColumnInfo[]>;
9
+ tableExists(tableName: string): Promise<boolean>;
9
10
  close(): Promise<void>;
10
11
  }
11
12
  //# sourceMappingURL=IDatabaseAdapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"IDatabaseAdapter.d.ts","sourceRoot":"","sources":["../../src/interfaces/IDatabaseAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,iBAAiB,MAAM,wBAAwB,CAAC;AAEvD,MAAM,CAAC,OAAO,WAAW,gBAAgB;IACrC,OAAO,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3D,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACtE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B"}
1
+ {"version":3,"file":"IDatabaseAdapter.d.ts","sourceRoot":"","sources":["../../src/interfaces/IDatabaseAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,iBAAiB,MAAM,wBAAwB,CAAC;AAEvD,MAAM,CAAC,OAAO,WAAW,gBAAgB;IACrC,OAAO,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3D,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACtE,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B"}
@@ -1,7 +1,7 @@
1
1
  import SchemaTableBuilder from "../abstract/SchemaTableBuilder.js";
2
2
  export default interface AbstractSchemaBuilder {
3
3
  createTable(name: string, callback: (table: SchemaTableBuilder) => void): Promise<void>;
4
- dropTable(name: string): Promise<void>;
4
+ dropTable(name: string, cascade?: boolean): Promise<void>;
5
5
  alterTable(oldName: string, callback: (table: SchemaTableBuilder) => void): Promise<void>;
6
6
  }
7
7
  //# sourceMappingURL=ISchemaBuilder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ISchemaBuilder.d.ts","sourceRoot":"","sources":["../../src/interfaces/ISchemaBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,MAAM,sCAAsC,CAAC;AAEtE,MAAM,CAAC,OAAO,WAAW,qBAAqB;IAC1C,WAAW,CACP,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAC9C,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB,SAAS,CACL,IAAI,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB,UAAU,CACN,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAC9C,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB"}
1
+ {"version":3,"file":"ISchemaBuilder.d.ts","sourceRoot":"","sources":["../../src/interfaces/ISchemaBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,MAAM,sCAAsC,CAAC;AAEtE,MAAM,CAAC,OAAO,WAAW,qBAAqB;IAC1C,WAAW,CACP,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAC9C,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB,SAAS,CACL,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,OAAO,GAClB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB,UAAU,CACN,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAC9C,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB"}
@@ -7,6 +7,8 @@ declare class Container {
7
7
  static getInstance(): Container;
8
8
  registerAdapter(name: string, adapter: IDatabaseAdapter, isDefault?: boolean): void;
9
9
  getAdapter(name?: string): IDatabaseAdapter;
10
+ clear(): void;
11
+ static resetInstance(): void;
10
12
  }
11
13
  export default Container;
12
14
  //# sourceMappingURL=Container.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Container.d.ts","sourceRoot":"","sources":["../../src/runtime/Container.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,sCAAsC,CAAC;AAEpE,cAAM,SAAS;IACX,OAAO,CAAC,MAAM,CAAC,SAAS,CAAY;IACpC,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,eAAe,CAAC,CAAmB;IAE3C,OAAO;WAEO,WAAW,IAAI,SAAS;IAO/B,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,SAAS,UAAQ,GAAG,IAAI;IAYjF,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,gBAAgB;CASrD;AAED,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"Container.d.ts","sourceRoot":"","sources":["../../src/runtime/Container.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,sCAAsC,CAAC;AAEpE,cAAM,SAAS;IACX,OAAO,CAAC,MAAM,CAAC,SAAS,CAAY;IACpC,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,eAAe,CAAC,CAAmB;IAE3C,OAAO;WAEO,WAAW,IAAI,SAAS;IAO/B,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,SAAS,UAAQ,GAAG,IAAI;IAYjF,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,gBAAgB;IAU3C,KAAK,IAAI,IAAI;WAKN,aAAa,IAAI,IAAI;CAGtC;AAED,eAAe,SAAS,CAAC"}
@@ -29,5 +29,12 @@ class Container {
29
29
  throw new Error("No default adapter set");
30
30
  return this._defaultAdapter;
31
31
  }
32
+ clear() {
33
+ this._adapters.clear();
34
+ this._defaultAdapter = undefined;
35
+ }
36
+ static resetInstance() {
37
+ Container._instance = new Container();
38
+ }
32
39
  }
33
40
  export default Container;
@@ -1,20 +1,30 @@
1
1
  import type Model from "../abstract/Model.js";
2
2
  import Record from "../base/Record.js";
3
- import { columnType, QueryCondition, QueryOptions, QueryWhereParameters } from "../types/index.js";
3
+ import { columnType, QueryWhereCondition, ExtraQueryParameters, relation, QueryComparisonParameters, QueryIsEqualParameter, TableFactory } from "../types/index.js";
4
4
  export default class Repository<Type extends columnType, ModelType extends Model<Type>> {
5
5
  private static _instances;
6
6
  private models;
7
+ private manyToManyRelations;
7
8
  private Table;
8
- constructor(tableName: string, ModelClass: ModelType);
9
- static getInstance<ModelType extends columnType>(ModelClass: new () => Model<ModelType>, tableName: string): Repository<ModelType, Model<ModelType>>;
9
+ private customDatabaseAdapter?;
10
+ private tableFactory;
11
+ constructor(tableName: string, ModelClass: ModelType, customDatabaseAdapter?: string, tableFactory?: TableFactory);
12
+ static getInstance<ModelType extends columnType>(ModelClass: new () => Model<ModelType>, tableName: string, customDatabaseAdapter?: string, tableFactory?: TableFactory): Repository<ModelType, Model<ModelType>>;
13
+ static clearInstances(): void;
14
+ private generatePivotTableKeys;
15
+ insertRecordIntoPivotTable(foreignKey: string, modelOfOrigin: ModelType, relation: relation): Promise<void>;
16
+ deleteRecordFromPivotTable(foreignKey: string, modelOfOrigin: ModelType, relation: relation): Promise<void>;
17
+ getManyToManyRelation(relation: relation): Promise<relation | undefined>;
18
+ doesTableExist(name: string): Promise<boolean>;
10
19
  syncModel(model: ModelType): void;
11
20
  getModel(name: string): ModelType;
12
21
  save(attributes: Type): Promise<void>;
13
- first(conditions: QueryCondition, Model: Model<Type>): Promise<Type | null>;
14
- get(conditions: QueryCondition, queryOptions: QueryOptions, Model: Model<Type>): Promise<Type[]>;
15
- all(Model: Model<Type>, queryscopes?: QueryCondition, queryOptions?: QueryOptions): Promise<Type[]>;
16
- update(primaryKey: QueryWhereParameters, newAttributes: Partial<Type>): Promise<Record<Type> | undefined>;
22
+ first(conditions: QueryWhereCondition, Model: Model<Type>): Promise<Type | null>;
23
+ get(conditions: QueryWhereCondition, queryOptions: ExtraQueryParameters, Model: Model<Type>): Promise<Type[]>;
24
+ all(Model: Model<Type>, queryscopes?: QueryWhereCondition, queryOptions?: ExtraQueryParameters): Promise<Type[]>;
25
+ update(primaryKey: QueryIsEqualParameter, newAttributes: Partial<Type>): Promise<Record<Type> | undefined>;
17
26
  private join;
18
- private mergeQueryConditions;
27
+ mergeQueryWhereConditions(base: QueryWhereCondition, additional: QueryWhereCondition): QueryComparisonParameters[];
28
+ ConvertParamsToArray(params: QueryWhereCondition): QueryComparisonParameters[];
19
29
  }
20
30
  //# sourceMappingURL=Repository.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Repository.d.ts","sourceRoot":"","sources":["../../src/runtime/Repository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,yBAAyB,CAAC;AACjD,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAG1C,OAAO,EAAE,UAAU,EAAQ,cAAc,EAAE,YAAY,EAA6B,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEvI,MAAM,CAAC,OAAO,OAAO,UAAU,CAAC,IAAI,SAAS,UAAU,EAAE,SAAS,SAAS,KAAK,CAAC,IAAI,CAAC;IAClF,OAAO,CAAC,MAAM,CAAC,UAAU,CAAqE;IAC9F,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,KAAK,CAAO;gBAER,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS;WAMtC,WAAW,CAAC,SAAS,SAAS,UAAU,EAClD,UAAU,EAAE,UAAU,KAAK,CAAC,SAAS,CAAC,EACtC,SAAS,EAAE,MAAM,GAClB,UAAU,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAWnC,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAKjC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;IAI3B,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC,KAAK,CAAC,UAAU,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAW3E,GAAG,CAAC,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAQhG,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,EAAE,cAAc,EAAE,YAAY,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAQnG,MAAM,CAAC,UAAU,EAAE,oBAAoB,EAAE,aAAa,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;YAOxG,IAAI;IAyBlB,OAAO,CAAC,oBAAoB;CAG/B"}
1
+ {"version":3,"file":"Repository.d.ts","sourceRoot":"","sources":["../../src/runtime/Repository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,yBAAyB,CAAC;AACjD,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAQ,mBAAmB,EAAE,oBAAoB,EAAE,QAAQ,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAE7K,MAAM,CAAC,OAAO,OAAO,UAAU,CAAC,IAAI,SAAS,UAAU,EAAE,SAAS,SAAS,KAAK,CAAC,IAAI,CAAC;IAClF,OAAO,CAAC,MAAM,CAAC,UAAU,CAAqE;IAC9F,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,mBAAmB,CAAoC;IAC/D,OAAO,CAAC,KAAK,CAAO;IACpB,OAAO,CAAC,qBAAqB,CAAC,CAAS;IACvC,OAAO,CAAC,YAAY,CAAe;gBAG/B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,SAAS,EACrB,qBAAqB,CAAC,EAAE,MAAM,EAC9B,YAAY,GAAE,YAA0D;WAS9D,WAAW,CAAC,SAAS,SAAS,UAAU,EAClD,UAAU,EAAE,UAAU,KAAK,CAAC,SAAS,CAAC,EACtC,SAAS,EAAE,MAAM,EACjB,qBAAqB,CAAC,EAAE,MAAM,EAC9B,YAAY,CAAC,EAAE,YAAY,GAC5B,UAAU,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;WAgB5B,cAAc,IAAI,IAAI;IAIpC,OAAO,CAAC,sBAAsB;IAajB,0BAA0B,CACnC,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,SAAS,EACxB,QAAQ,EAAE,QAAQ,GACnB,OAAO,CAAC,IAAI,CAAC;IAKH,0BAA0B,CACnC,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,SAAS,EACxB,QAAQ,EAAE,QAAQ,GACnB,OAAO,CAAC,IAAI,CAAC;IAMH,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAaxE,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpD,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAKjC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;IAI3B,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC,KAAK,CAAC,UAAU,EAAE,mBAAmB,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAYhF,GAAG,CAAC,UAAU,EAAE,mBAAmB,EAAE,YAAY,EAAE,oBAAoB,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAS7G,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,EAAE,mBAAmB,EAAE,YAAY,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAShH,MAAM,CAAC,UAAU,EAAE,qBAAqB,EAAE,aAAa,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;YAOzG,IAAI;IAgDX,yBAAyB,CAAC,IAAI,EAAE,mBAAmB,EAAE,UAAU,EAAE,mBAAmB,GAAG,yBAAyB,EAAE;IAKlH,oBAAoB,CAAC,MAAM,EAAE,mBAAmB,GAAG,yBAAyB,EAAE;CAIxF"}
@@ -7,25 +7,71 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import Query from "../base/Query.js";
11
10
  import Table from "../base/Table.js";
12
11
  class Repository {
13
- constructor(tableName, ModelClass) {
12
+ constructor(tableName, ModelClass, customDatabaseAdapter, tableFactory = (name, adapter) => new Table(name, adapter)) {
14
13
  var _a;
15
14
  this.models = new Map();
15
+ this.manyToManyRelations = new Map();
16
16
  const modelPk = ((_a = ModelClass.primaryKey) === null || _a === void 0 ? void 0 : _a.toString()) || ModelClass.constructor.name;
17
17
  this.models.set(modelPk, ModelClass);
18
- this.Table = new Table(tableName);
18
+ this.tableFactory = tableFactory;
19
+ this.Table = this.tableFactory(tableName, customDatabaseAdapter);
20
+ this.customDatabaseAdapter = customDatabaseAdapter;
19
21
  }
20
- static getInstance(ModelClass, tableName) {
22
+ static getInstance(ModelClass, tableName, customDatabaseAdapter, tableFactory) {
21
23
  const className = ModelClass.name;
22
24
  if (!this._instances.has(className)) {
23
- const instance = new Repository(tableName, new ModelClass());
25
+ const instance = new Repository(tableName, new ModelClass(), customDatabaseAdapter, tableFactory);
24
26
  this._instances.set(className, instance);
25
27
  return instance;
26
28
  }
27
29
  return this._instances.get(className);
28
30
  }
31
+ static clearInstances() {
32
+ this._instances.clear();
33
+ }
34
+ generatePivotTableKeys(foreignKey, modelOfOrigin, relation) {
35
+ var _a;
36
+ const isLocal = !((_a = relation.pivotLocalKey) === null || _a === void 0 ? void 0 : _a.includes(modelOfOrigin.Configuration.table));
37
+ return {
38
+ [relation.pivotLocalKey]: isLocal ? foreignKey : modelOfOrigin.values[relation.foreignKey],
39
+ [relation.pivotForeignKey]: isLocal ? modelOfOrigin.values[relation.foreignKey] : foreignKey
40
+ };
41
+ }
42
+ insertRecordIntoPivotTable(foreignKey, modelOfOrigin, relation) {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ const table = this.tableFactory(relation.pivotTable, this.customDatabaseAdapter);
45
+ yield table.Insert(this.generatePivotTableKeys(foreignKey, modelOfOrigin, relation));
46
+ });
47
+ }
48
+ deleteRecordFromPivotTable(foreignKey, modelOfOrigin, relation) {
49
+ return __awaiter(this, void 0, void 0, function* () {
50
+ const table = this.tableFactory(relation.pivotTable, this.customDatabaseAdapter);
51
+ const record = yield table.Record(this.generatePivotTableKeys(foreignKey, modelOfOrigin, relation));
52
+ yield (record === null || record === void 0 ? void 0 : record.Delete());
53
+ });
54
+ }
55
+ getManyToManyRelation(relation) {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ if (relation.pivotTable && this.manyToManyRelations.has(relation.pivotTable)) {
58
+ return this.manyToManyRelations.get(relation.pivotTable);
59
+ }
60
+ if (yield this.doesTableExist(relation.pivotTable)) {
61
+ this.manyToManyRelations.set(relation.pivotTable, relation);
62
+ return relation;
63
+ }
64
+ else {
65
+ throw new Error(`Pivot table ${relation.pivotTable} does not exist. Create it in alphabetical order before using many-to-many relationships.`);
66
+ }
67
+ });
68
+ }
69
+ doesTableExist(name) {
70
+ return __awaiter(this, void 0, void 0, function* () {
71
+ const table = this.tableFactory(name, this.customDatabaseAdapter);
72
+ return yield table.exists();
73
+ });
74
+ }
29
75
  syncModel(model) {
30
76
  var _a;
31
77
  const modelPk = ((_a = model.primaryKey) === null || _a === void 0 ? void 0 : _a.toString()) || model.constructor.name;
@@ -43,7 +89,8 @@ class Repository {
43
89
  return __awaiter(this, void 0, void 0, function* () {
44
90
  let record;
45
91
  if (Model.JoinedEntities.length > 0) {
46
- record = yield this.join(Model, conditions, { limit: 1 }).then(results => results[0]);
92
+ const results = yield this.join(Model, conditions, { limit: 1 });
93
+ record = results[0] ? { values: results[0] } : undefined;
47
94
  }
48
95
  else {
49
96
  record = yield this.Table.Record({ where: conditions });
@@ -57,7 +104,8 @@ class Repository {
57
104
  return yield this.join(Model, conditions, queryOptions);
58
105
  }
59
106
  else {
60
- return yield this.Table.Records(Object.assign({ where: conditions }, queryOptions)).then(records => records.map(record => record.values));
107
+ const records = yield this.Table.Records(Object.assign({ where: conditions }, queryOptions));
108
+ return records.map(record => record.values);
61
109
  }
62
110
  });
63
111
  }
@@ -67,7 +115,8 @@ class Repository {
67
115
  return yield this.join(Model);
68
116
  }
69
117
  else {
70
- return yield this.Table.Records(Object.assign({ where: queryscopes }, queryOptions)).then(records => records.map(record => record.values));
118
+ const records = yield this.Table.Records(Object.assign({ where: queryscopes }, queryOptions));
119
+ return records.map(record => record.values);
71
120
  }
72
121
  });
73
122
  }
@@ -81,28 +130,55 @@ class Repository {
81
130
  }
82
131
  join(Model, conditions, queryOptions) {
83
132
  return __awaiter(this, void 0, void 0, function* () {
84
- const Join = Model.JoinedEntities.map(join => {
85
- const relation = Model.Relations.find(rel => rel.model.Configuration.table.toLowerCase() === join.relation.toLowerCase());
133
+ const Join = Model.JoinedEntities.flatMap(join => {
134
+ const relation = Model.Relations.find(rel => rel.model.Configuration.table.replace("_", "").toLowerCase() === join.relation.toLowerCase());
86
135
  if (join.queryScopes) {
87
- conditions = this.mergeQueryConditions(conditions || {}, join.queryScopes);
136
+ conditions = this.mergeQueryWhereConditions(conditions || {}, join.queryScopes);
88
137
  }
89
138
  if (!relation) {
90
139
  throw new Error(`Relation for joined entity ${join} not found.`);
91
140
  }
141
+ if (relation.type === 'manyToMany') {
142
+ return [
143
+ {
144
+ fromTable: relation.pivotTable,
145
+ baseTable: Model.Configuration.table,
146
+ joinType: 'INNER',
147
+ on: [
148
+ { [relation.pivotForeignKey]: relation.localKey }
149
+ ]
150
+ },
151
+ {
152
+ fromTable: relation.model.Configuration.table,
153
+ baseTable: relation.pivotTable,
154
+ joinType: 'INNER',
155
+ on: [
156
+ { [relation.foreignKey]: relation.pivotLocalKey }
157
+ ]
158
+ }
159
+ ];
160
+ }
92
161
  const JoinType = relation.type === 'hasOne' || relation.type === 'belongsTo' ? 'INNER' : 'LEFT';
93
- return {
94
- fromTable: relation.model.Configuration.table,
95
- joinType: JoinType,
96
- on: [
97
- { [relation.foreignKey]: relation.localKey }
98
- ]
99
- };
162
+ return [{
163
+ fromTable: relation.model.Configuration.table,
164
+ baseTable: Model.Configuration.table,
165
+ joinType: JoinType,
166
+ on: [
167
+ { [relation.foreignKey]: relation.localKey }
168
+ ]
169
+ }];
100
170
  });
101
- return (yield this.Table.Join(Join, Object.assign({ where: conditions }, queryOptions))).map(record => record.values);
171
+ const records = yield this.Table.Join(Join, Object.assign({ where: conditions }, queryOptions));
172
+ return records.map(record => record.values);
102
173
  });
103
174
  }
104
- mergeQueryConditions(base, additional) {
105
- return [...Query.ConvertParamsToArray(base), ...Query.ConvertParamsToArray(additional)];
175
+ mergeQueryWhereConditions(base, additional) {
176
+ const query = this.Table.QueryHelperObject;
177
+ return [...query.ConvertParamsToArray(base), ...query.ConvertParamsToArray(additional)];
178
+ }
179
+ ConvertParamsToArray(params) {
180
+ const query = this.Table.QueryHelperObject;
181
+ return query.ConvertParamsToArray(params);
106
182
  }
107
183
  }
108
184
  Repository._instances = new Map();
@@ -0,0 +1,6 @@
1
+ import type Table from "../base/Table";
2
+ import type { columnType, Query, QueryConstructorType, Record } from "../index.js";
3
+ export type TableFactory = (name: string, adapter?: string) => Table;
4
+ export type QueryFactory = (config: QueryConstructorType) => Query;
5
+ export type RecordFactory = <T extends columnType>(table: string, values: T, adapter?: string, queryFactory?: QueryFactory, recordFactory?: RecordFactory) => Record<T>;
6
+ //# sourceMappingURL=factories.d.ts.map