@loomcore/api 0.1.92 → 0.1.94

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/LICENSE +201 -201
  2. package/README.md +77 -77
  3. package/dist/__tests__/common-test.utils.js +0 -4
  4. package/dist/__tests__/postgres-test-migrations/postgres-test-schema.js +266 -266
  5. package/dist/__tests__/postgres.test-database.js +8 -8
  6. package/dist/config/base-api-config.d.ts +1 -1
  7. package/dist/config/base-api-config.js +12 -7
  8. package/dist/databases/migrations/migration-runner.d.ts +3 -5
  9. package/dist/databases/migrations/migration-runner.js +40 -44
  10. package/dist/databases/mongo-db/migrations/mongo-initial-schema.d.ts +2 -3
  11. package/dist/databases/mongo-db/migrations/mongo-initial-schema.js +102 -81
  12. package/dist/databases/mongo-db/utils/build-mongo-url.util.d.ts +4 -2
  13. package/dist/databases/postgres/commands/postgres-batch-update.command.js +7 -7
  14. package/dist/databases/postgres/commands/postgres-create-many.command.js +4 -4
  15. package/dist/databases/postgres/commands/postgres-create.command.js +4 -4
  16. package/dist/databases/postgres/commands/postgres-full-update-by-id.command.js +13 -13
  17. package/dist/databases/postgres/commands/postgres-partial-update-by-id.command.js +7 -7
  18. package/dist/databases/postgres/commands/postgres-update.command.js +7 -7
  19. package/dist/databases/postgres/migrations/__tests__/test-migration-helper.js +8 -1
  20. package/dist/databases/postgres/migrations/postgres-initial-schema.d.ts +2 -3
  21. package/dist/databases/postgres/migrations/postgres-initial-schema.js +263 -266
  22. package/dist/databases/postgres/postgres.database.js +17 -17
  23. package/dist/databases/postgres/utils/build-join-clauses.js +151 -151
  24. package/dist/databases/postgres/utils/build-postgres-url.util.d.ts +4 -2
  25. package/dist/databases/postgres/utils/build-select-clause.js +6 -6
  26. package/dist/databases/postgres/utils/does-table-exist.util.js +4 -4
  27. package/dist/models/app-config.interface.d.ts +8 -0
  28. package/dist/models/base-api-config.interface.d.ts +4 -17
  29. package/dist/models/database-config.interface.d.ts +7 -0
  30. package/dist/models/index.d.ts +3 -1
  31. package/dist/models/index.js +3 -1
  32. package/dist/models/initial-database-config.interface.d.ts +16 -0
  33. package/dist/models/initial-database-config.interface.js +1 -0
  34. package/package.json +92 -92
  35. package/dist/models/multi-tenant-config.interface.d.ts +0 -4
  36. package/dist/models/reset-api-config.interface.d.ts +0 -6
  37. /package/dist/models/{multi-tenant-config.interface.js → app-config.interface.js} +0 -0
  38. /package/dist/models/{reset-api-config.interface.js → database-config.interface.js} +0 -0
@@ -70,23 +70,23 @@ export class PostgresDatabase {
70
70
  }
71
71
  async getUserAuthorizations(userId, orgId) {
72
72
  const now = new Date();
73
- let query = `
74
- SELECT DISTINCT
75
- ur."user_id" as "userId",
76
- r."name" as "role",
77
- f."name" as "feature",
78
- a."config",
79
- a."_id",
80
- a."_orgId"
81
- FROM "user_roles" ur
82
- INNER JOIN "roles" r ON ur."role_id" = r."_id"
83
- INNER JOIN "authorizations" a ON r."_id" = a."role_id"
84
- INNER JOIN "features" f ON a."feature_id" = f."_id"
85
- WHERE ur."user_id" = $1
86
- AND ur."_deleted" IS NULL
87
- AND a."_deleted" IS NULL
88
- AND (a."start_date" IS NULL OR a."start_date" <= $2)
89
- AND (a."end_date" IS NULL OR a."end_date" >= $2)
73
+ let query = `
74
+ SELECT DISTINCT
75
+ ur."user_id" as "userId",
76
+ r."name" as "role",
77
+ f."name" as "feature",
78
+ a."config",
79
+ a."_id",
80
+ a."_orgId"
81
+ FROM "user_roles" ur
82
+ INNER JOIN "roles" r ON ur."role_id" = r."_id"
83
+ INNER JOIN "authorizations" a ON r."_id" = a."role_id"
84
+ INNER JOIN "features" f ON a."feature_id" = f."_id"
85
+ WHERE ur."user_id" = $1
86
+ AND ur."_deleted" IS NULL
87
+ AND a."_deleted" IS NULL
88
+ AND (a."start_date" IS NULL OR a."start_date" <= $2)
89
+ AND (a."end_date" IS NULL OR a."end_date" >= $2)
90
90
  `;
91
91
  const values = [userId, now];
92
92
  if (orgId) {
@@ -116,53 +116,53 @@ export function buildJoinClauses(operations, mainTableName) {
116
116
  });
117
117
  if (nestedJoin) {
118
118
  const nestedField = nestedJoin.localField.split('.')[1];
119
- enrichmentJoins += ` LEFT JOIN LATERAL (
120
- SELECT COALESCE(
121
- JSON_AGG(
122
- enrich_elem.value || jsonb_build_object('${nestedJoin.as}', nested_join_data.${nestedJoin.as})
123
- ),
124
- '[]'::json
125
- ) AS enriched
126
- FROM (
127
- SELECT COALESCE(JSON_AGG(row_to_json(enrich_table)), '[]'::json) AS enriched
128
- FROM "${enrichOp.from}" AS enrich_table
129
- WHERE enrich_table."${enrichOp.foreignField}" = (elem.value->>'${enrichField}')::integer
130
- AND enrich_table."_deleted" IS NULL
131
- ) AS enrich_data
132
- CROSS JOIN LATERAL jsonb_array_elements(enrich_data.enriched::jsonb) AS enrich_elem
133
- LEFT JOIN LATERAL (
134
- SELECT row_to_json(nested_table) AS ${nestedJoin.as}
135
- FROM "${nestedJoin.from}" AS nested_table
136
- WHERE nested_table."${nestedJoin.foreignField}" = (enrich_elem.value->>'${nestedField}')::integer
137
- AND nested_table."_deleted" IS NULL
138
- LIMIT 1
139
- ) AS nested_join_data ON true
119
+ enrichmentJoins += ` LEFT JOIN LATERAL (
120
+ SELECT COALESCE(
121
+ JSON_AGG(
122
+ enrich_elem.value || jsonb_build_object('${nestedJoin.as}', nested_join_data.${nestedJoin.as})
123
+ ),
124
+ '[]'::json
125
+ ) AS enriched
126
+ FROM (
127
+ SELECT COALESCE(JSON_AGG(row_to_json(enrich_table)), '[]'::json) AS enriched
128
+ FROM "${enrichOp.from}" AS enrich_table
129
+ WHERE enrich_table."${enrichOp.foreignField}" = (elem.value->>'${enrichField}')::integer
130
+ AND enrich_table."_deleted" IS NULL
131
+ ) AS enrich_data
132
+ CROSS JOIN LATERAL jsonb_array_elements(enrich_data.enriched::jsonb) AS enrich_elem
133
+ LEFT JOIN LATERAL (
134
+ SELECT row_to_json(nested_table) AS ${nestedJoin.as}
135
+ FROM "${nestedJoin.from}" AS nested_table
136
+ WHERE nested_table."${nestedJoin.foreignField}" = (enrich_elem.value->>'${nestedField}')::integer
137
+ AND nested_table."_deleted" IS NULL
138
+ LIMIT 1
139
+ ) AS nested_join_data ON true
140
140
  ) AS ${enrichAlias} ON true`;
141
141
  }
142
142
  else {
143
- enrichmentJoins += ` LEFT JOIN LATERAL (
144
- SELECT COALESCE(JSON_AGG(row_to_json(enrich_table)), '[]'::json) AS enriched
145
- FROM "${enrichOp.from}" AS enrich_table
146
- WHERE enrich_table."${enrichOp.foreignField}" = (elem.value->>'${enrichField}')::integer
147
- AND enrich_table."_deleted" IS NULL
143
+ enrichmentJoins += ` LEFT JOIN LATERAL (
144
+ SELECT COALESCE(JSON_AGG(row_to_json(enrich_table)), '[]'::json) AS enriched
145
+ FROM "${enrichOp.from}" AS enrich_table
146
+ WHERE enrich_table."${enrichOp.foreignField}" = (elem.value->>'${enrichField}')::integer
147
+ AND enrich_table."_deleted" IS NULL
148
148
  ) AS ${enrichAlias} ON true`;
149
149
  }
150
150
  jsonBuildObjects += ` || jsonb_build_object('${enrichOp.as}', COALESCE(${enrichAlias}.enriched, '[]'::json))`;
151
151
  }
152
- joinClauses += ` LEFT JOIN LATERAL (
153
- SELECT COALESCE(
154
- JSON_AGG(
155
- elem.value${jsonBuildObjects}
156
- ),
157
- '[]'::json
158
- ) AS aggregated
159
- FROM (
160
- SELECT COALESCE(JSON_AGG(row_to_json(target_table)), '[]'::json) AS aggregated
161
- FROM "${target.from}" AS target_table
162
- WHERE target_table."${target.foreignField}" = ${targetLocalFieldRef}
163
- AND target_table."_deleted" IS NULL
164
- ) AS original_data
165
- CROSS JOIN LATERAL jsonb_array_elements(original_data.aggregated::jsonb) AS elem${enrichmentJoins}
152
+ joinClauses += ` LEFT JOIN LATERAL (
153
+ SELECT COALESCE(
154
+ JSON_AGG(
155
+ elem.value${jsonBuildObjects}
156
+ ),
157
+ '[]'::json
158
+ ) AS aggregated
159
+ FROM (
160
+ SELECT COALESCE(JSON_AGG(row_to_json(target_table)), '[]'::json) AS aggregated
161
+ FROM "${target.from}" AS target_table
162
+ WHERE target_table."${target.foreignField}" = ${targetLocalFieldRef}
163
+ AND target_table."_deleted" IS NULL
164
+ ) AS original_data
165
+ CROSS JOIN LATERAL jsonb_array_elements(original_data.aggregated::jsonb) AS elem${enrichmentJoins}
166
166
  ) AS ${target.as} ON true`;
167
167
  enrichedAliases.add(target.as);
168
168
  processedAliases.add(target.as);
@@ -173,26 +173,26 @@ export function buildJoinClauses(operations, mainTableName) {
173
173
  }
174
174
  else {
175
175
  const localFieldRef = resolveLocalField(operation.localField, mainTableName, operations);
176
- joinClauses += ` LEFT JOIN LATERAL (
177
- SELECT COALESCE(JSON_AGG(row_to_json("${operation.from}")), '[]'::json) AS aggregated
178
- FROM "${operation.from}"
179
- WHERE "${operation.from}"."${operation.foreignField}" = ${localFieldRef}
180
- AND "${operation.from}"."_deleted" IS NULL
176
+ joinClauses += ` LEFT JOIN LATERAL (
177
+ SELECT COALESCE(JSON_AGG(row_to_json("${operation.from}")), '[]'::json) AS aggregated
178
+ FROM "${operation.from}"
179
+ WHERE "${operation.from}"."${operation.foreignField}" = ${localFieldRef}
180
+ AND "${operation.from}"."_deleted" IS NULL
181
181
  ) AS ${operation.as} ON true`;
182
182
  processedAliases.add(operation.as);
183
183
  }
184
184
  }
185
185
  else if (operation instanceof JoinThrough) {
186
186
  const localFieldRef = resolveLocalField(operation.localField, mainTableName, operations);
187
- joinClauses += ` LEFT JOIN LATERAL (
188
- SELECT row_to_json(${operation.as}) AS aggregated
189
- FROM "${operation.through}"
190
- INNER JOIN "${operation.from}" AS ${operation.as}
191
- ON ${operation.as}."${operation.foreignField}" = "${operation.through}"."${operation.throughForeignField}"
192
- WHERE "${operation.through}"."${operation.throughLocalField}" = ${localFieldRef}
193
- AND "${operation.through}"."_deleted" IS NULL
194
- AND ${operation.as}."_deleted" IS NULL
195
- LIMIT 1
187
+ joinClauses += ` LEFT JOIN LATERAL (
188
+ SELECT row_to_json(${operation.as}) AS aggregated
189
+ FROM "${operation.through}"
190
+ INNER JOIN "${operation.from}" AS ${operation.as}
191
+ ON ${operation.as}."${operation.foreignField}" = "${operation.through}"."${operation.throughForeignField}"
192
+ WHERE "${operation.through}"."${operation.throughLocalField}" = ${localFieldRef}
193
+ AND "${operation.through}"."_deleted" IS NULL
194
+ AND ${operation.as}."_deleted" IS NULL
195
+ LIMIT 1
196
196
  ) AS ${operation.as} ON true`;
197
197
  processedAliases.add(operation.as);
198
198
  }
@@ -221,35 +221,35 @@ export function buildJoinClauses(operations, mainTableName) {
221
221
  j.localField.startsWith(`${enrichOp.as}.`));
222
222
  if (nestedJoin) {
223
223
  const nestedField = nestedJoin.localField.split('.')[1];
224
- enrichmentJoins += ` LEFT JOIN LATERAL (
225
- SELECT COALESCE(
226
- JSON_AGG(
227
- enrich_elem.value || jsonb_build_object('${nestedJoin.as}', nested_join_data.${nestedJoin.as})
228
- ),
229
- '[]'::json
230
- ) AS enriched
231
- FROM (
232
- SELECT COALESCE(JSON_AGG(row_to_json(enrich_table)), '[]'::json) AS enriched
233
- FROM "${enrichOp.from}" AS enrich_table
234
- WHERE enrich_table."${enrichOp.foreignField}" = (elem.value->>'${enrichField}')::integer
235
- AND enrich_table."_deleted" IS NULL
236
- ) AS enrich_data
237
- CROSS JOIN LATERAL jsonb_array_elements(enrich_data.enriched::jsonb) AS enrich_elem
238
- LEFT JOIN LATERAL (
239
- SELECT row_to_json(nested_table) AS ${nestedJoin.as}
240
- FROM "${nestedJoin.from}" AS nested_table
241
- WHERE nested_table."${nestedJoin.foreignField}" = (enrich_elem.value->>'${nestedField}')::integer
242
- AND nested_table."_deleted" IS NULL
243
- LIMIT 1
244
- ) AS nested_join_data ON true
224
+ enrichmentJoins += ` LEFT JOIN LATERAL (
225
+ SELECT COALESCE(
226
+ JSON_AGG(
227
+ enrich_elem.value || jsonb_build_object('${nestedJoin.as}', nested_join_data.${nestedJoin.as})
228
+ ),
229
+ '[]'::json
230
+ ) AS enriched
231
+ FROM (
232
+ SELECT COALESCE(JSON_AGG(row_to_json(enrich_table)), '[]'::json) AS enriched
233
+ FROM "${enrichOp.from}" AS enrich_table
234
+ WHERE enrich_table."${enrichOp.foreignField}" = (elem.value->>'${enrichField}')::integer
235
+ AND enrich_table."_deleted" IS NULL
236
+ ) AS enrich_data
237
+ CROSS JOIN LATERAL jsonb_array_elements(enrich_data.enriched::jsonb) AS enrich_elem
238
+ LEFT JOIN LATERAL (
239
+ SELECT row_to_json(nested_table) AS ${nestedJoin.as}
240
+ FROM "${nestedJoin.from}" AS nested_table
241
+ WHERE nested_table."${nestedJoin.foreignField}" = (enrich_elem.value->>'${nestedField}')::integer
242
+ AND nested_table."_deleted" IS NULL
243
+ LIMIT 1
244
+ ) AS nested_join_data ON true
245
245
  ) AS ${enrichAlias} ON true`;
246
246
  }
247
247
  else {
248
- enrichmentJoins += ` LEFT JOIN LATERAL (
249
- SELECT COALESCE(JSON_AGG(row_to_json(enrich_table)), '[]'::json) AS enriched
250
- FROM "${enrichOp.from}" AS enrich_table
251
- WHERE enrich_table."${enrichOp.foreignField}" = (elem.value->>'${enrichField}')::integer
252
- AND enrich_table."_deleted" IS NULL
248
+ enrichmentJoins += ` LEFT JOIN LATERAL (
249
+ SELECT COALESCE(JSON_AGG(row_to_json(enrich_table)), '[]'::json) AS enriched
250
+ FROM "${enrichOp.from}" AS enrich_table
251
+ WHERE enrich_table."${enrichOp.foreignField}" = (elem.value->>'${enrichField}')::integer
252
+ AND enrich_table."_deleted" IS NULL
253
253
  ) AS ${enrichAlias} ON true`;
254
254
  }
255
255
  }
@@ -270,82 +270,82 @@ export function buildJoinClauses(operations, mainTableName) {
270
270
  });
271
271
  if (nestedJoin) {
272
272
  const nestedField = nestedJoin.localField.split('.')[1];
273
- enrichmentJoins += ` LEFT JOIN LATERAL (
274
- SELECT COALESCE(
275
- JSON_AGG(
276
- enrich_elem.value || jsonb_build_object('${nestedJoin.as}', nested_join_data.${nestedJoin.as})
277
- ),
278
- '[]'::json
279
- ) AS enriched
280
- FROM (
281
- SELECT COALESCE(JSON_AGG(row_to_json(${enrichAlias}_table)), '[]'::json) AS enriched
282
- FROM "${enrichOp.through}"
283
- INNER JOIN "${enrichOp.from}" AS ${enrichAlias}_table
284
- ON ${enrichAlias}_table."${enrichOp.foreignField}" = "${enrichOp.through}"."${enrichOp.throughForeignField}"
285
- WHERE "${enrichOp.through}"."${enrichOp.throughLocalField}" = (elem.value->>'${enrichField}')::integer
286
- AND "${enrichOp.through}"."_deleted" IS NULL
287
- AND ${enrichAlias}_table."_deleted" IS NULL
288
- ) AS enrich_data
289
- CROSS JOIN LATERAL jsonb_array_elements(enrich_data.enriched::jsonb) AS enrich_elem
290
- LEFT JOIN LATERAL (
291
- SELECT row_to_json(nested_table) AS ${nestedJoin.as}
292
- FROM "${nestedJoin.from}" AS nested_table
293
- WHERE nested_table."${nestedJoin.foreignField}" = (enrich_elem.value->>'${nestedField}')::integer
294
- AND nested_table."_deleted" IS NULL
295
- LIMIT 1
296
- ) AS nested_join_data ON true
273
+ enrichmentJoins += ` LEFT JOIN LATERAL (
274
+ SELECT COALESCE(
275
+ JSON_AGG(
276
+ enrich_elem.value || jsonb_build_object('${nestedJoin.as}', nested_join_data.${nestedJoin.as})
277
+ ),
278
+ '[]'::json
279
+ ) AS enriched
280
+ FROM (
281
+ SELECT COALESCE(JSON_AGG(row_to_json(${enrichAlias}_table)), '[]'::json) AS enriched
282
+ FROM "${enrichOp.through}"
283
+ INNER JOIN "${enrichOp.from}" AS ${enrichAlias}_table
284
+ ON ${enrichAlias}_table."${enrichOp.foreignField}" = "${enrichOp.through}"."${enrichOp.throughForeignField}"
285
+ WHERE "${enrichOp.through}"."${enrichOp.throughLocalField}" = (elem.value->>'${enrichField}')::integer
286
+ AND "${enrichOp.through}"."_deleted" IS NULL
287
+ AND ${enrichAlias}_table."_deleted" IS NULL
288
+ ) AS enrich_data
289
+ CROSS JOIN LATERAL jsonb_array_elements(enrich_data.enriched::jsonb) AS enrich_elem
290
+ LEFT JOIN LATERAL (
291
+ SELECT row_to_json(nested_table) AS ${nestedJoin.as}
292
+ FROM "${nestedJoin.from}" AS nested_table
293
+ WHERE nested_table."${nestedJoin.foreignField}" = (enrich_elem.value->>'${nestedField}')::integer
294
+ AND nested_table."_deleted" IS NULL
295
+ LIMIT 1
296
+ ) AS nested_join_data ON true
297
297
  ) AS ${enrichAlias} ON true`;
298
298
  }
299
299
  else {
300
- enrichmentJoins += ` LEFT JOIN LATERAL (
301
- SELECT COALESCE(JSON_AGG(row_to_json(${enrichAlias}_table)), '[]'::json) AS enriched
302
- FROM "${enrichOp.through}"
303
- INNER JOIN "${enrichOp.from}" AS ${enrichAlias}_table
304
- ON ${enrichAlias}_table."${enrichOp.foreignField}" = "${enrichOp.through}"."${enrichOp.throughForeignField}"
305
- WHERE "${enrichOp.through}"."${enrichOp.throughLocalField}" = (elem.value->>'${enrichField}')::integer
306
- AND "${enrichOp.through}"."_deleted" IS NULL
307
- AND ${enrichAlias}_table."_deleted" IS NULL
300
+ enrichmentJoins += ` LEFT JOIN LATERAL (
301
+ SELECT COALESCE(JSON_AGG(row_to_json(${enrichAlias}_table)), '[]'::json) AS enriched
302
+ FROM "${enrichOp.through}"
303
+ INNER JOIN "${enrichOp.from}" AS ${enrichAlias}_table
304
+ ON ${enrichAlias}_table."${enrichOp.foreignField}" = "${enrichOp.through}"."${enrichOp.throughForeignField}"
305
+ WHERE "${enrichOp.through}"."${enrichOp.throughLocalField}" = (elem.value->>'${enrichField}')::integer
306
+ AND "${enrichOp.through}"."_deleted" IS NULL
307
+ AND ${enrichAlias}_table."_deleted" IS NULL
308
308
  ) AS ${enrichAlias} ON true`;
309
309
  }
310
310
  }
311
311
  jsonBuildObjects += ` || jsonb_build_object('${enrichOp.as}', COALESCE(${enrichAlias}.enriched, '[]'::json))`;
312
312
  }
313
313
  if (isTargetJoinMany) {
314
- joinClauses += ` LEFT JOIN LATERAL (
315
- SELECT COALESCE(
316
- JSON_AGG(
317
- elem.value${jsonBuildObjects}
318
- ),
319
- '[]'::json
320
- ) AS aggregated
321
- FROM (
322
- SELECT COALESCE(JSON_AGG(row_to_json(target_table)), '[]'::json) AS aggregated
323
- FROM "${target.from}" AS target_table
324
- WHERE target_table."${target.foreignField}" = ${targetLocalFieldRef}
325
- AND target_table."_deleted" IS NULL
326
- ) AS original_data
327
- CROSS JOIN LATERAL jsonb_array_elements(original_data.aggregated::jsonb) AS elem${enrichmentJoins}
314
+ joinClauses += ` LEFT JOIN LATERAL (
315
+ SELECT COALESCE(
316
+ JSON_AGG(
317
+ elem.value${jsonBuildObjects}
318
+ ),
319
+ '[]'::json
320
+ ) AS aggregated
321
+ FROM (
322
+ SELECT COALESCE(JSON_AGG(row_to_json(target_table)), '[]'::json) AS aggregated
323
+ FROM "${target.from}" AS target_table
324
+ WHERE target_table."${target.foreignField}" = ${targetLocalFieldRef}
325
+ AND target_table."_deleted" IS NULL
326
+ ) AS original_data
327
+ CROSS JOIN LATERAL jsonb_array_elements(original_data.aggregated::jsonb) AS elem${enrichmentJoins}
328
328
  ) AS ${target.as} ON true`;
329
329
  }
330
330
  else {
331
331
  const targetThrough = target;
332
- joinClauses += ` LEFT JOIN LATERAL (
333
- SELECT COALESCE(
334
- JSON_AGG(
335
- elem.value${jsonBuildObjects}
336
- ),
337
- '[]'::json
338
- ) AS aggregated
339
- FROM (
340
- SELECT COALESCE(JSON_AGG(row_to_json(target_table)), '[]'::json) AS aggregated
341
- FROM "${targetThrough.through}"
342
- INNER JOIN "${targetThrough.from}" AS target_table
343
- ON target_table."${targetThrough.foreignField}" = "${targetThrough.through}"."${targetThrough.throughForeignField}"
344
- WHERE "${targetThrough.through}"."${targetThrough.throughLocalField}" = ${targetLocalFieldRef}
345
- AND "${targetThrough.through}"."_deleted" IS NULL
346
- AND target_table."_deleted" IS NULL
347
- ) AS original_data
348
- CROSS JOIN LATERAL jsonb_array_elements(original_data.aggregated::jsonb) AS elem${enrichmentJoins}
332
+ joinClauses += ` LEFT JOIN LATERAL (
333
+ SELECT COALESCE(
334
+ JSON_AGG(
335
+ elem.value${jsonBuildObjects}
336
+ ),
337
+ '[]'::json
338
+ ) AS aggregated
339
+ FROM (
340
+ SELECT COALESCE(JSON_AGG(row_to_json(target_table)), '[]'::json) AS aggregated
341
+ FROM "${targetThrough.through}"
342
+ INNER JOIN "${targetThrough.from}" AS target_table
343
+ ON target_table."${targetThrough.foreignField}" = "${targetThrough.through}"."${targetThrough.throughForeignField}"
344
+ WHERE "${targetThrough.through}"."${targetThrough.throughLocalField}" = ${targetLocalFieldRef}
345
+ AND "${targetThrough.through}"."_deleted" IS NULL
346
+ AND target_table."_deleted" IS NULL
347
+ ) AS original_data
348
+ CROSS JOIN LATERAL jsonb_array_elements(original_data.aggregated::jsonb) AS elem${enrichmentJoins}
349
349
  ) AS ${target.as} ON true`;
350
350
  }
351
351
  enrichedAliases.add(target.as);
@@ -357,14 +357,14 @@ export function buildJoinClauses(operations, mainTableName) {
357
357
  }
358
358
  else {
359
359
  const localFieldRef = resolveLocalField(operation.localField, mainTableName, operations);
360
- joinClauses += ` LEFT JOIN LATERAL (
361
- SELECT COALESCE(JSON_AGG(row_to_json(${operation.as})), '[]'::json) AS aggregated
362
- FROM "${operation.through}"
363
- INNER JOIN "${operation.from}" AS ${operation.as}
364
- ON ${operation.as}."${operation.foreignField}" = "${operation.through}"."${operation.throughForeignField}"
365
- WHERE "${operation.through}"."${operation.throughLocalField}" = ${localFieldRef}
366
- AND "${operation.through}"."_deleted" IS NULL
367
- AND ${operation.as}."_deleted" IS NULL
360
+ joinClauses += ` LEFT JOIN LATERAL (
361
+ SELECT COALESCE(JSON_AGG(row_to_json(${operation.as})), '[]'::json) AS aggregated
362
+ FROM "${operation.through}"
363
+ INNER JOIN "${operation.from}" AS ${operation.as}
364
+ ON ${operation.as}."${operation.foreignField}" = "${operation.through}"."${operation.throughForeignField}"
365
+ WHERE "${operation.through}"."${operation.throughLocalField}" = ${localFieldRef}
366
+ AND "${operation.through}"."_deleted" IS NULL
367
+ AND ${operation.as}."_deleted" IS NULL
368
368
  ) AS ${operation.as} ON true`;
369
369
  processedAliases.add(operation.as);
370
370
  }
@@ -1,2 +1,4 @@
1
- import { IBaseApiConfig } from "../../../models/base-api-config.interface.js";
2
- export declare function buildPostgresUrl(config: IBaseApiConfig): string;
1
+ import { IDatabaseConfig } from "../../../models/database-config.interface.js";
2
+ export declare function buildPostgresUrl(config: {
3
+ database: IDatabaseConfig;
4
+ }): string;
@@ -3,12 +3,12 @@ import { JoinMany } from '../../operations/join-many.operation.js';
3
3
  import { JoinThrough } from '../../operations/join-through.operation.js';
4
4
  import { JoinThroughMany } from '../../operations/join-through-many.operation.js';
5
5
  async function getTableColumns(client, tableName) {
6
- const result = await client.query(`
7
- SELECT column_name
8
- FROM information_schema.columns
9
- WHERE table_schema = current_schema()
10
- AND table_name = $1
11
- ORDER BY ordinal_position
6
+ const result = await client.query(`
7
+ SELECT column_name
8
+ FROM information_schema.columns
9
+ WHERE table_schema = current_schema()
10
+ AND table_name = $1
11
+ ORDER BY ordinal_position
12
12
  `, [tableName]);
13
13
  return result.rows.map(row => row.column_name);
14
14
  }
@@ -1,8 +1,8 @@
1
1
  export async function doesTableExist(client, tableName) {
2
- const result = await client.query(`
3
- SELECT EXISTS (
4
- SELECT 1 FROM information_schema.tables WHERE table_schema = current_schema() AND table_name = $1
5
- )
2
+ const result = await client.query(`
3
+ SELECT EXISTS (
4
+ SELECT 1 FROM information_schema.tables WHERE table_schema = current_schema() AND table_name = $1
5
+ )
6
6
  `, [tableName]);
7
7
  return result.rows[0].exists;
8
8
  }
@@ -0,0 +1,8 @@
1
+ import { DbType } from "../databases/db-type.type.js";
2
+ export interface IAppConfig {
3
+ dbType: DbType;
4
+ isMultiTenant: boolean;
5
+ isAuthEnabled: boolean;
6
+ name: string;
7
+ primaryTimezone?: string;
8
+ }
@@ -1,30 +1,17 @@
1
- import { DbType } from "../databases/db-type.type.js";
1
+ import { IAppConfig } from "./app-config.interface.js";
2
2
  import { IAuthConfig } from "./auth-config.interface.js";
3
+ import { IDatabaseConfig } from "./database-config.interface.js";
3
4
  import { IEmailConfig } from "./email-config.interface.js";
4
5
  import { IEmailClient } from "./email-client.interface.js";
5
- import { IMultiTenantConfig } from "./multi-tenant-config.interface.js";
6
6
  export interface IBaseApiConfig {
7
- app: {
8
- dbType: DbType;
9
- isMultiTenant: boolean;
10
- isAuthEnabled: boolean;
11
- name: string;
12
- primaryTimezone?: string;
13
- };
7
+ app: IAppConfig;
14
8
  auth?: IAuthConfig;
15
- database: {
16
- host: string;
17
- name: string;
18
- password: string;
19
- port: number;
20
- username: string;
21
- };
9
+ database: IDatabaseConfig;
22
10
  debug?: {
23
11
  showErrors?: boolean;
24
12
  };
25
13
  email?: IEmailConfig;
26
14
  env: string;
27
- multiTenant?: IMultiTenantConfig;
28
15
  network: {
29
16
  corsAllowedOrigins: string[];
30
17
  externalPort?: number;
@@ -0,0 +1,7 @@
1
+ export interface IDatabaseConfig {
2
+ host: string;
3
+ name: string;
4
+ password: string;
5
+ port: number;
6
+ username: string;
7
+ }
@@ -1,4 +1,6 @@
1
+ export * from './app-config.interface.js';
1
2
  export * from './base-api-config.interface.js';
2
- export * from './reset-api-config.interface.js';
3
+ export * from './database-config.interface.js';
4
+ export * from './initial-database-config.interface.js';
3
5
  export * from './refresh-token.model.js';
4
6
  export * from './email-client.interface.js';
@@ -1,4 +1,6 @@
1
+ export * from './app-config.interface.js';
1
2
  export * from './base-api-config.interface.js';
2
- export * from './reset-api-config.interface.js';
3
+ export * from './database-config.interface.js';
4
+ export * from './initial-database-config.interface.js';
3
5
  export * from './refresh-token.model.js';
4
6
  export * from './email-client.interface.js';
@@ -0,0 +1,16 @@
1
+ import { IAppConfig } from "./app-config.interface.js";
2
+ import { IDatabaseConfig } from "./database-config.interface.js";
3
+ import { IEmailConfig } from "./email-config.interface.js";
4
+ export interface IInitialDbMigrationConfig {
5
+ app: IAppConfig;
6
+ database: IDatabaseConfig;
7
+ adminUser: {
8
+ email: string;
9
+ password: string;
10
+ };
11
+ multiTenant: {
12
+ metaOrgName: string;
13
+ metaOrgCode: string;
14
+ };
15
+ email?: IEmailConfig;
16
+ }
@@ -0,0 +1 @@
1
+ export {};