@loomcore/api 0.0.59 → 0.1.2

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 (224) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +50 -0
  3. package/dist/__tests__/common-test.utils.d.ts +29 -60
  4. package/dist/__tests__/common-test.utils.js +88 -166
  5. package/dist/__tests__/index.d.ts +6 -0
  6. package/dist/__tests__/index.js +6 -0
  7. package/dist/__tests__/models/category.model.d.ts +8 -0
  8. package/dist/__tests__/models/category.model.js +6 -0
  9. package/dist/__tests__/models/product.model.d.ts +17 -0
  10. package/dist/__tests__/models/product.model.js +10 -0
  11. package/dist/__tests__/models/test-entity.model.d.ts +11 -0
  12. package/dist/__tests__/models/test-entity.model.js +10 -0
  13. package/dist/__tests__/models/test-item.model.d.ts +12 -0
  14. package/dist/__tests__/models/test-item.model.js +9 -0
  15. package/dist/__tests__/mongo-db.test-database.d.ts +15 -0
  16. package/dist/__tests__/mongo-db.test-database.js +74 -0
  17. package/dist/__tests__/postgres-test-migrations/001-create-test-entities-table.migration.d.ts +11 -0
  18. package/dist/__tests__/postgres-test-migrations/001-create-test-entities-table.migration.js +59 -0
  19. package/dist/__tests__/postgres-test-migrations/002-create-categories-table.migration.d.ts +11 -0
  20. package/dist/__tests__/postgres-test-migrations/002-create-categories-table.migration.js +52 -0
  21. package/dist/__tests__/postgres-test-migrations/003-create-products-table.migration.d.ts +11 -0
  22. package/dist/__tests__/postgres-test-migrations/003-create-products-table.migration.js +62 -0
  23. package/dist/__tests__/postgres-test-migrations/004-create-test-users-table.migration.d.ts +11 -0
  24. package/dist/__tests__/postgres-test-migrations/004-create-test-users-table.migration.js +66 -0
  25. package/dist/__tests__/postgres-test-migrations/005-create-test-items-table.migration.d.ts +11 -0
  26. package/dist/__tests__/postgres-test-migrations/005-create-test-items-table.migration.js +50 -0
  27. package/dist/__tests__/postgres-test-migrations/run-test-migrations.d.ts +2 -0
  28. package/dist/__tests__/postgres-test-migrations/run-test-migrations.js +22 -0
  29. package/dist/__tests__/postgres.test-database.d.ts +13 -0
  30. package/dist/__tests__/postgres.test-database.js +85 -0
  31. package/dist/__tests__/test-database.interface.d.ts +7 -0
  32. package/dist/__tests__/test-express-app.d.ts +9 -7
  33. package/dist/__tests__/test-express-app.js +38 -48
  34. package/dist/__tests__/test-objects.d.ts +23 -0
  35. package/dist/__tests__/test-objects.js +45 -0
  36. package/dist/config/base-api-config.d.ts +2 -2
  37. package/dist/config/base-api-config.js +2 -2
  38. package/dist/controllers/api.controller.d.ts +1 -5
  39. package/dist/controllers/api.controller.js +4 -11
  40. package/dist/controllers/auth.controller.d.ts +2 -2
  41. package/dist/controllers/auth.controller.js +4 -5
  42. package/dist/controllers/organizations.controller.d.ts +2 -2
  43. package/dist/controllers/organizations.controller.js +4 -4
  44. package/dist/controllers/users.controller.d.ts +2 -2
  45. package/dist/controllers/users.controller.js +2 -2
  46. package/dist/databases/index.d.ts +1 -0
  47. package/dist/databases/index.js +1 -0
  48. package/dist/databases/models/constants.d.ts +1 -0
  49. package/dist/databases/models/constants.js +1 -0
  50. package/dist/databases/models/database.d.ts +3 -0
  51. package/dist/databases/models/database.interface.d.ts +28 -0
  52. package/dist/databases/models/delete-result.d.ts +5 -0
  53. package/dist/databases/models/delete-result.js +8 -0
  54. package/dist/databases/models/index.d.ts +5 -0
  55. package/dist/databases/models/index.js +5 -0
  56. package/dist/databases/models/update-result.d.ts +5 -0
  57. package/dist/databases/models/update-result.js +8 -0
  58. package/dist/databases/mongo-db/commands/index.d.ts +8 -0
  59. package/dist/databases/mongo-db/commands/index.js +8 -0
  60. package/dist/databases/mongo-db/commands/mongo-batch-update.command.d.ts +4 -0
  61. package/dist/databases/mongo-db/commands/mongo-batch-update.command.js +41 -0
  62. package/dist/databases/mongo-db/commands/mongo-create-many.command.d.ts +5 -0
  63. package/dist/databases/mongo-db/commands/mongo-create-many.command.js +17 -0
  64. package/dist/databases/mongo-db/commands/mongo-create.command.d.ts +5 -0
  65. package/dist/databases/mongo-db/commands/mongo-create.command.js +17 -0
  66. package/dist/databases/mongo-db/commands/mongo-delete-by-id.command.d.ts +3 -0
  67. package/dist/databases/mongo-db/commands/mongo-delete-by-id.command.js +14 -0
  68. package/dist/databases/mongo-db/commands/mongo-delete-many.command.d.ts +4 -0
  69. package/dist/databases/mongo-db/commands/mongo-delete-many.command.js +9 -0
  70. package/dist/databases/mongo-db/commands/mongo-full-updateby-id.command.d.ts +3 -0
  71. package/dist/databases/mongo-db/commands/mongo-full-updateby-id.command.js +25 -0
  72. package/dist/databases/mongo-db/commands/mongo-partial-update-by-id.command.d.ts +3 -0
  73. package/dist/databases/mongo-db/commands/mongo-partial-update-by-id.command.js +25 -0
  74. package/dist/databases/mongo-db/commands/mongo-update.command.d.ts +4 -0
  75. package/dist/databases/mongo-db/commands/mongo-update.command.js +19 -0
  76. package/dist/databases/mongo-db/index.d.ts +4 -0
  77. package/dist/databases/mongo-db/index.js +4 -0
  78. package/dist/databases/mongo-db/models/no-sql-pipeline.d.ts +15 -0
  79. package/dist/databases/mongo-db/models/no-sql-pipeline.interface.d.ts +11 -0
  80. package/dist/databases/mongo-db/models/no-sql-pipeline.js +43 -0
  81. package/dist/databases/mongo-db/mongo-db.database.d.ts +32 -0
  82. package/dist/databases/mongo-db/mongo-db.database.js +65 -0
  83. package/dist/databases/mongo-db/queries/index.d.ts +6 -0
  84. package/dist/databases/mongo-db/queries/index.js +6 -0
  85. package/dist/databases/mongo-db/queries/mongo-find-one.query.d.ts +3 -0
  86. package/dist/databases/mongo-db/queries/mongo-find-one.query.js +9 -0
  87. package/dist/databases/mongo-db/queries/mongo-find.query.d.ts +3 -0
  88. package/dist/databases/mongo-db/queries/mongo-find.query.js +9 -0
  89. package/dist/databases/mongo-db/queries/mongo-get-all.query.d.ts +3 -0
  90. package/dist/databases/mongo-db/queries/mongo-get-all.query.js +17 -0
  91. package/dist/databases/mongo-db/queries/mongo-get-by-id.query.d.ts +4 -0
  92. package/dist/databases/mongo-db/queries/mongo-get-by-id.query.js +17 -0
  93. package/dist/databases/mongo-db/queries/mongo-get-count.query.d.ts +2 -0
  94. package/dist/databases/mongo-db/queries/mongo-get-count.query.js +5 -0
  95. package/dist/databases/mongo-db/queries/mongo-get.query.d.ts +4 -0
  96. package/dist/databases/mongo-db/queries/mongo-get.query.js +14 -0
  97. package/dist/databases/mongo-db/utils/build-find-options.util.d.ts +3 -0
  98. package/dist/databases/mongo-db/utils/build-find-options.util.js +15 -0
  99. package/dist/databases/mongo-db/utils/build-no-sql-match.util.d.ts +3 -0
  100. package/dist/databases/mongo-db/utils/build-no-sql-match.util.js +59 -0
  101. package/dist/databases/mongo-db/utils/convert-object-ids-to-strings.util.d.ts +1 -0
  102. package/dist/databases/mongo-db/utils/convert-object-ids-to-strings.util.js +32 -0
  103. package/dist/databases/mongo-db/utils/convert-operations-to-pipeline.util.d.ts +3 -0
  104. package/dist/databases/mongo-db/utils/convert-operations-to-pipeline.util.js +68 -0
  105. package/dist/databases/mongo-db/utils/convert-query-options-to-pipeline.util.d.ts +3 -0
  106. package/dist/databases/mongo-db/utils/convert-query-options-to-pipeline.util.js +31 -0
  107. package/dist/databases/mongo-db/utils/convert-strings-to-object-ids.util.d.ts +3 -0
  108. package/dist/databases/mongo-db/utils/convert-strings-to-object-ids.util.js +72 -0
  109. package/dist/databases/mongo-db/utils/index.d.ts +7 -0
  110. package/dist/databases/mongo-db/utils/index.js +7 -0
  111. package/dist/databases/operations/join.operation.d.ts +7 -0
  112. package/dist/databases/operations/join.operation.js +12 -0
  113. package/dist/databases/operations/operation.d.ts +2 -0
  114. package/dist/databases/postgres/commands/postgres-batch-update.command.d.ts +4 -0
  115. package/dist/databases/postgres/commands/postgres-batch-update.command.js +56 -0
  116. package/dist/databases/postgres/commands/postgres-create-many.command.d.ts +6 -0
  117. package/dist/databases/postgres/commands/postgres-create-many.command.js +63 -0
  118. package/dist/databases/postgres/commands/postgres-create.command.d.ts +6 -0
  119. package/dist/databases/postgres/commands/postgres-create.command.js +29 -0
  120. package/dist/databases/postgres/commands/postgres-delete-by-id.command.d.ts +3 -0
  121. package/dist/databases/postgres/commands/postgres-delete-by-id.command.js +6 -0
  122. package/dist/databases/postgres/commands/postgres-delete-many.command.d.ts +4 -0
  123. package/dist/databases/postgres/commands/postgres-delete-many.command.js +13 -0
  124. package/dist/databases/postgres/commands/postgres-full-update-by-id.command.d.ts +4 -0
  125. package/dist/databases/postgres/commands/postgres-full-update-by-id.command.js +72 -0
  126. package/dist/databases/postgres/commands/postgres-partial-update-by-id.command.d.ts +4 -0
  127. package/dist/databases/postgres/commands/postgres-partial-update-by-id.command.js +42 -0
  128. package/dist/databases/postgres/commands/postgres-update.command.d.ts +5 -0
  129. package/dist/databases/postgres/commands/postgres-update.command.js +48 -0
  130. package/dist/databases/postgres/migrations/001-create-migrations-table.migration.d.ts +11 -0
  131. package/dist/databases/postgres/migrations/001-create-migrations-table.migration.js +52 -0
  132. package/dist/databases/postgres/migrations/002-create-organizations-table.migration.d.ts +11 -0
  133. package/dist/databases/postgres/migrations/002-create-organizations-table.migration.js +55 -0
  134. package/dist/databases/postgres/migrations/003-create-users-table.migration.d.ts +11 -0
  135. package/dist/databases/postgres/migrations/003-create-users-table.migration.js +65 -0
  136. package/dist/databases/postgres/migrations/004-create-refresh-token-table.migration.d.ts +11 -0
  137. package/dist/databases/postgres/migrations/004-create-refresh-token-table.migration.js +57 -0
  138. package/dist/databases/postgres/migrations/index.d.ts +3 -0
  139. package/dist/databases/postgres/migrations/index.js +3 -0
  140. package/dist/databases/postgres/migrations/migration.interface.d.ts +6 -0
  141. package/dist/databases/postgres/migrations/migration.interface.js +1 -0
  142. package/dist/databases/postgres/migrations/setup-for-auth.migration.d.ts +2 -0
  143. package/dist/databases/postgres/migrations/setup-for-auth.migration.js +18 -0
  144. package/dist/databases/postgres/migrations/setup-for-multitenant.migration.d.ts +2 -0
  145. package/dist/databases/postgres/migrations/setup-for-multitenant.migration.js +16 -0
  146. package/dist/databases/postgres/postgres.database.d.ts +31 -0
  147. package/dist/databases/postgres/postgres.database.js +69 -0
  148. package/dist/databases/postgres/queries/postgres-find-one.query.d.ts +3 -0
  149. package/dist/databases/postgres/queries/postgres-find-one.query.js +13 -0
  150. package/dist/databases/postgres/queries/postgres-find.query.d.ts +3 -0
  151. package/dist/databases/postgres/queries/postgres-find.query.js +11 -0
  152. package/dist/databases/postgres/queries/postgres-get-all.query.d.ts +3 -0
  153. package/dist/databases/postgres/queries/postgres-get-all.query.js +14 -0
  154. package/dist/databases/postgres/queries/postgres-get-by-id.query.d.ts +4 -0
  155. package/dist/databases/postgres/queries/postgres-get-by-id.query.js +26 -0
  156. package/dist/databases/postgres/queries/postgres-get-count.query.d.ts +2 -0
  157. package/dist/databases/postgres/queries/postgres-get-count.query.js +4 -0
  158. package/dist/databases/postgres/queries/postgres-get.query.d.ts +4 -0
  159. package/dist/databases/postgres/queries/postgres-get.query.js +26 -0
  160. package/dist/databases/postgres/utils/build-count-query.d.ts +3 -0
  161. package/dist/databases/postgres/utils/build-count-query.js +7 -0
  162. package/dist/databases/postgres/utils/build-join-clauses.d.ts +2 -0
  163. package/dist/databases/postgres/utils/build-join-clauses.js +12 -0
  164. package/dist/databases/postgres/utils/build-order-by-clause.d.ts +2 -0
  165. package/dist/databases/postgres/utils/build-order-by-clause.js +8 -0
  166. package/dist/databases/postgres/utils/build-pagination-clause.d.ts +2 -0
  167. package/dist/databases/postgres/utils/build-pagination-clause.js +9 -0
  168. package/dist/databases/postgres/utils/build-select-clause.d.ts +3 -0
  169. package/dist/databases/postgres/utils/build-select-clause.js +28 -0
  170. package/dist/databases/postgres/utils/build-where-clause.d.ts +5 -0
  171. package/dist/databases/postgres/utils/build-where-clause.js +50 -0
  172. package/dist/databases/postgres/utils/columns-and-values-from-entity.d.ts +5 -0
  173. package/dist/databases/postgres/utils/columns-and-values-from-entity.js +9 -0
  174. package/dist/databases/postgres/utils/convert-null-to-undefined.util.d.ts +2 -0
  175. package/dist/databases/postgres/utils/convert-null-to-undefined.util.js +70 -0
  176. package/dist/databases/postgres/utils/transform-join-results.d.ts +2 -0
  177. package/dist/databases/postgres/utils/transform-join-results.js +33 -0
  178. package/dist/databases/utils/get-property-schema.util.d.ts +2 -0
  179. package/dist/databases/utils/get-property-schema.util.js +15 -0
  180. package/dist/databases/utils/index.d.ts +1 -0
  181. package/dist/databases/utils/index.js +1 -0
  182. package/dist/models/base-api-config.interface.d.ts +3 -2
  183. package/dist/models/index.d.ts +1 -1
  184. package/dist/models/index.js +1 -1
  185. package/dist/models/refresh-token.model.d.ts +18 -0
  186. package/dist/models/refresh-token.model.js +13 -0
  187. package/dist/services/auth.service.d.ts +11 -18
  188. package/dist/services/auth.service.js +29 -50
  189. package/dist/services/generic-api-service/generic-api-service.interface.d.ts +29 -0
  190. package/dist/services/generic-api-service/generic-api-service.interface.js +1 -0
  191. package/dist/services/generic-api-service/generic-api.service.d.ts +37 -0
  192. package/dist/services/generic-api-service/generic-api.service.js +178 -0
  193. package/dist/services/index.d.ts +2 -2
  194. package/dist/services/index.js +2 -2
  195. package/dist/services/multi-tenant-api.service.d.ts +9 -6
  196. package/dist/services/multi-tenant-api.service.js +10 -18
  197. package/dist/services/organization.service.d.ts +5 -5
  198. package/dist/services/organization.service.js +9 -6
  199. package/dist/services/password-reset-token.service.d.ts +3 -3
  200. package/dist/services/password-reset-token.service.js +5 -5
  201. package/dist/services/tenant-query-decorator.d.ts +1 -1
  202. package/dist/services/tenant-query-decorator.js +1 -1
  203. package/dist/services/user.service.d.ts +4 -6
  204. package/dist/services/user.service.js +4 -10
  205. package/dist/services/utils/audit-for-create.util.d.ts +2 -0
  206. package/dist/services/utils/audit-for-create.util.js +9 -0
  207. package/dist/services/utils/audit-for-update.util.d.ts +2 -0
  208. package/dist/services/utils/audit-for-update.util.js +7 -0
  209. package/dist/services/utils/strip-sender-provided-system-properties.util.d.ts +2 -0
  210. package/dist/services/utils/strip-sender-provided-system-properties.util.js +15 -0
  211. package/dist/utils/api.utils.js +2 -1
  212. package/dist/utils/index.d.ts +0 -1
  213. package/dist/utils/index.js +0 -1
  214. package/package.json +17 -6
  215. package/dist/services/generic-api-service.interface.d.ts +0 -27
  216. package/dist/services/generic-api.service.d.ts +0 -50
  217. package/dist/services/generic-api.service.js +0 -424
  218. package/dist/utils/db.utils.d.ts +0 -27
  219. package/dist/utils/db.utils.js +0 -318
  220. /package/dist/{controllers/api-controller.utils.d.ts → __tests__/test-database.interface.js} +0 -0
  221. /package/dist/{controllers/api-controller.utils.js → databases/models/database.interface.js} +0 -0
  222. /package/dist/{models/types/index.d.ts → databases/models/database.js} +0 -0
  223. /package/dist/{models/types/index.js → databases/mongo-db/models/no-sql-pipeline.interface.js} +0 -0
  224. /package/dist/{services/generic-api-service.interface.js → databases/operations/operation.js} +0 -0
@@ -0,0 +1,16 @@
1
+ import { CreateMigrationTableMigration } from "./001-create-migrations-table.migration.js";
2
+ import { CreateOrganizationTableMigration } from "./002-create-organizations-table.migration.js";
3
+ export async function setupDatabaseForMultitenant(client, orgId) {
4
+ const migrations = [
5
+ new CreateMigrationTableMigration(client, orgId),
6
+ new CreateOrganizationTableMigration(client, orgId),
7
+ ];
8
+ let success = true;
9
+ for (const migration of migrations) {
10
+ success = await migration.execute();
11
+ if (!success) {
12
+ return false;
13
+ }
14
+ }
15
+ return success;
16
+ }
@@ -0,0 +1,31 @@
1
+ import { IQueryOptions, IModelSpec, IPagedResult, IEntity } from "@loomcore/common/models";
2
+ import { TSchema } from "@sinclair/typebox";
3
+ import { DeleteResult, IDatabase } from "../models/index.js";
4
+ import { Operation } from "../operations/operation.js";
5
+ import { Client } from 'pg';
6
+ export declare class PostgresDatabase implements IDatabase {
7
+ private client;
8
+ constructor(client: Client);
9
+ preprocessEntity<T extends IEntity>(entity: Partial<T>, modelSpec: TSchema): Partial<T>;
10
+ postprocessEntity<T extends IEntity>(entity: T, modelSpec: TSchema): T;
11
+ getAll<T extends IEntity>(operations: Operation[], pluralResourceName: string): Promise<T[]>;
12
+ get<T extends IEntity>(operations: Operation[], queryOptions: IQueryOptions, modelSpec: IModelSpec, pluralResourceName: string): Promise<IPagedResult<T>>;
13
+ getById<T extends IEntity>(operations: Operation[], queryObject: IQueryOptions, id: string, pluralResourceName: string): Promise<T | null>;
14
+ getCount(pluralResourceName: string): Promise<number>;
15
+ create<T extends IEntity>(entity: Partial<T>, pluralResourceName: string): Promise<{
16
+ insertedId: string;
17
+ entity: T;
18
+ }>;
19
+ createMany<T extends IEntity>(entities: Partial<T>[], pluralResourceName: string): Promise<{
20
+ insertedIds: string[];
21
+ entities: T[];
22
+ }>;
23
+ batchUpdate<T extends IEntity>(entities: Partial<T>[], operations: Operation[], queryObject: IQueryOptions, pluralResourceName: string): Promise<T[]>;
24
+ fullUpdateById<T extends IEntity>(operations: Operation[], id: string, entity: Partial<T>, pluralResourceName: string): Promise<T>;
25
+ partialUpdateById<T extends IEntity>(operations: Operation[], id: string, entity: Partial<T>, pluralResourceName: string): Promise<T>;
26
+ update<T extends IEntity>(queryObject: IQueryOptions, entity: Partial<T>, operations: Operation[], pluralResourceName: string): Promise<T[]>;
27
+ deleteById(id: string, pluralResourceName: string): Promise<DeleteResult>;
28
+ deleteMany(queryObject: IQueryOptions, pluralResourceName: string): Promise<DeleteResult>;
29
+ find<T extends IEntity>(queryObject: IQueryOptions, pluralResourceName: string): Promise<T[]>;
30
+ findOne<T extends IEntity>(queryObject: IQueryOptions, pluralResourceName: string): Promise<T | null>;
31
+ }
@@ -0,0 +1,69 @@
1
+ import { create as createCommand } from "./commands/postgres-create.command.js";
2
+ import { createMany as createManyCommand } from "./commands/postgres-create-many.command.js";
3
+ import { batchUpdate as batchUpdateCommand } from "./commands/postgres-batch-update.command.js";
4
+ import { fullUpdateById as fullUpdateByIdCommand } from "./commands/postgres-full-update-by-id.command.js";
5
+ import { partialUpdateById as partialUpdateByIdCommand } from "./commands/postgres-partial-update-by-id.command.js";
6
+ import { update as updateCommand } from "./commands/postgres-update.command.js";
7
+ import { deleteById as deleteByIdCommand } from "./commands/postgres-delete-by-id.command.js";
8
+ import { deleteMany as deleteManyCommand } from "./commands/postgres-delete-many.command.js";
9
+ import { findOne as findOneQuery } from "./queries/postgres-find-one.query.js";
10
+ import { find as findQuery } from "./queries/postgres-find.query.js";
11
+ import { getAll as getAllQuery } from "./queries/postgres-get-all.query.js";
12
+ import { get as getQuery } from "./queries/postgres-get.query.js";
13
+ import { getById as getByIdQuery } from "./queries/postgres-get-by-id.query.js";
14
+ import { getCount as getCountQuery } from "./queries/postgres-get-count.query.js";
15
+ import { convertNullToUndefined } from "./utils/convert-null-to-undefined.util.js";
16
+ export class PostgresDatabase {
17
+ client;
18
+ constructor(client) {
19
+ this.client = client;
20
+ }
21
+ preprocessEntity(entity, modelSpec) {
22
+ return entity;
23
+ }
24
+ postprocessEntity(entity, modelSpec) {
25
+ return convertNullToUndefined(entity, modelSpec);
26
+ }
27
+ async getAll(operations, pluralResourceName) {
28
+ return getAllQuery(this.client, operations, pluralResourceName);
29
+ }
30
+ async get(operations, queryOptions, modelSpec, pluralResourceName) {
31
+ return getQuery(this.client, operations, queryOptions, pluralResourceName);
32
+ }
33
+ async getById(operations, queryObject, id, pluralResourceName) {
34
+ return getByIdQuery(this.client, operations, queryObject, id, pluralResourceName);
35
+ }
36
+ async getCount(pluralResourceName) {
37
+ return getCountQuery(this.client, pluralResourceName);
38
+ }
39
+ async create(entity, pluralResourceName) {
40
+ return createCommand(this.client, pluralResourceName, entity);
41
+ }
42
+ async createMany(entities, pluralResourceName) {
43
+ return createManyCommand(this.client, pluralResourceName, entities);
44
+ }
45
+ async batchUpdate(entities, operations, queryObject, pluralResourceName) {
46
+ return batchUpdateCommand(this.client, entities, operations, queryObject, pluralResourceName);
47
+ }
48
+ async fullUpdateById(operations, id, entity, pluralResourceName) {
49
+ return fullUpdateByIdCommand(this.client, operations, id, entity, pluralResourceName);
50
+ }
51
+ async partialUpdateById(operations, id, entity, pluralResourceName) {
52
+ return partialUpdateByIdCommand(this.client, operations, id, entity, pluralResourceName);
53
+ }
54
+ async update(queryObject, entity, operations, pluralResourceName) {
55
+ return updateCommand(this.client, queryObject, entity, operations, pluralResourceName);
56
+ }
57
+ async deleteById(id, pluralResourceName) {
58
+ return deleteByIdCommand(this.client, id, pluralResourceName);
59
+ }
60
+ async deleteMany(queryObject, pluralResourceName) {
61
+ return deleteManyCommand(this.client, queryObject, pluralResourceName);
62
+ }
63
+ async find(queryObject, pluralResourceName) {
64
+ return findQuery(this.client, queryObject, pluralResourceName);
65
+ }
66
+ async findOne(queryObject, pluralResourceName) {
67
+ return findOneQuery(this.client, queryObject, pluralResourceName);
68
+ }
69
+ }
@@ -0,0 +1,3 @@
1
+ import { Client } from 'pg';
2
+ import { IQueryOptions } from "@loomcore/common/models";
3
+ export declare function findOne<T>(client: Client, queryObject: IQueryOptions, pluralResourceName: string): Promise<T | null>;
@@ -0,0 +1,13 @@
1
+ import { buildWhereClause } from "../utils/build-where-clause.js";
2
+ import { buildOrderByClause } from "../utils/build-order-by-clause.js";
3
+ export async function findOne(client, queryObject, pluralResourceName) {
4
+ const { whereClause, values } = buildWhereClause(queryObject);
5
+ const orderByClause = buildOrderByClause(queryObject);
6
+ const query = `SELECT * FROM "${pluralResourceName}" ${whereClause} ${orderByClause} LIMIT 1`;
7
+ const result = await client.query(query, values);
8
+ if (result.rows.length === 0) {
9
+ return null;
10
+ }
11
+ const row = result.rows[0];
12
+ return row;
13
+ }
@@ -0,0 +1,3 @@
1
+ import { Client } from 'pg';
2
+ import { IQueryOptions } from "@loomcore/common/models";
3
+ export declare function find<T>(client: Client, queryObject: IQueryOptions, pluralResourceName: string): Promise<T[]>;
@@ -0,0 +1,11 @@
1
+ import { buildWhereClause } from "../utils/build-where-clause.js";
2
+ import { buildOrderByClause } from "../utils/build-order-by-clause.js";
3
+ import { buildPaginationClause } from '../utils/build-pagination-clause.js';
4
+ export async function find(client, queryObject, pluralResourceName) {
5
+ const { whereClause, values } = buildWhereClause(queryObject);
6
+ const orderByClause = buildOrderByClause(queryObject);
7
+ const paginationClause = buildPaginationClause(queryObject);
8
+ const query = `SELECT * FROM "${pluralResourceName}" ${whereClause} ${orderByClause} ${paginationClause}`.trim();
9
+ const result = await client.query(query, values);
10
+ return result.rows;
11
+ }
@@ -0,0 +1,3 @@
1
+ import { Client } from 'pg';
2
+ import { Operation } from "../../operations/operation.js";
3
+ export declare function getAll<T>(client: Client, operations: Operation[], pluralResourceName: string): Promise<T[]>;
@@ -0,0 +1,14 @@
1
+ import { Join } from "../../operations/join.operation.js";
2
+ import { buildJoinClauses } from '../utils/build-join-clauses.js';
3
+ import { buildSelectClause } from '../utils/build-select-clause.js';
4
+ import { transformJoinResults } from '../utils/transform-join-results.js';
5
+ export async function getAll(client, operations, pluralResourceName) {
6
+ const joinClauses = buildJoinClauses(operations, pluralResourceName);
7
+ const hasJoins = operations.some(op => op instanceof Join);
8
+ const selectClause = hasJoins
9
+ ? await buildSelectClause(client, pluralResourceName, pluralResourceName, operations)
10
+ : '*';
11
+ const query = `SELECT ${selectClause} FROM "${pluralResourceName}" ${joinClauses}`;
12
+ const result = await client.query(query);
13
+ return transformJoinResults(result.rows, operations);
14
+ }
@@ -0,0 +1,4 @@
1
+ import { Client } from 'pg';
2
+ import { Operation } from "../../operations/operation.js";
3
+ import { IQueryOptions } from '@loomcore/common/models';
4
+ export declare function getById<T>(client: Client, operations: Operation[], queryObject: IQueryOptions, id: string, pluralResourceName: string): Promise<T | null>;
@@ -0,0 +1,26 @@
1
+ import { Join } from "../../operations/join.operation.js";
2
+ import { buildJoinClauses } from "../utils/build-join-clauses.js";
3
+ import { buildSelectClause } from "../utils/build-select-clause.js";
4
+ import { transformJoinResults } from "../utils/transform-join-results.js";
5
+ import { BadRequestError } from '../../../errors/index.js';
6
+ import { buildWhereClause } from '../utils/build-where-clause.js';
7
+ export async function getById(client, operations, queryObject, id, pluralResourceName) {
8
+ if (!id)
9
+ throw new BadRequestError('id is required');
10
+ const joinClauses = buildJoinClauses(operations, pluralResourceName);
11
+ const hasJoins = operations.some(op => op instanceof Join);
12
+ const selectClause = hasJoins
13
+ ? await buildSelectClause(client, pluralResourceName, pluralResourceName, operations)
14
+ : '*';
15
+ queryObject.filters || (queryObject.filters = {});
16
+ queryObject.filters._id = { eq: id };
17
+ const tablePrefix = hasJoins ? pluralResourceName : undefined;
18
+ const { whereClause, values } = buildWhereClause(queryObject, [], tablePrefix);
19
+ const query = `SELECT ${selectClause} FROM "${pluralResourceName}" ${joinClauses} ${whereClause} LIMIT 1`;
20
+ const result = await client.query(query, values);
21
+ if (result.rows.length === 0) {
22
+ return null;
23
+ }
24
+ const transformed = transformJoinResults([result.rows[0]], operations);
25
+ return transformed[0] || null;
26
+ }
@@ -0,0 +1,2 @@
1
+ import { Client } from 'pg';
2
+ export declare function getCount(client: Client, pluralResourceName: string): Promise<number>;
@@ -0,0 +1,4 @@
1
+ import { executeCountQuery } from "../utils/build-count-query.js";
2
+ export async function getCount(client, pluralResourceName) {
3
+ return executeCountQuery(client, pluralResourceName);
4
+ }
@@ -0,0 +1,4 @@
1
+ import { Client } from 'pg';
2
+ import { IQueryOptions, IPagedResult } from "@loomcore/common/models";
3
+ import { Operation } from "../../operations/operation.js";
4
+ export declare function get<T>(client: Client, operations: Operation[], queryOptions: IQueryOptions, pluralResourceName: string): Promise<IPagedResult<T>>;
@@ -0,0 +1,26 @@
1
+ import { Join } from "../../operations/join.operation.js";
2
+ import { buildWhereClause } from "../utils/build-where-clause.js";
3
+ import { buildOrderByClause } from "../utils/build-order-by-clause.js";
4
+ import { buildJoinClauses } from "../utils/build-join-clauses.js";
5
+ import { buildSelectClause } from "../utils/build-select-clause.js";
6
+ import { transformJoinResults } from "../utils/transform-join-results.js";
7
+ import { executeCountQuery } from "../utils/build-count-query.js";
8
+ import { apiUtils } from "../../../utils/api.utils.js";
9
+ import { buildPaginationClause } from '../utils/build-pagination-clause.js';
10
+ export async function get(client, operations, queryOptions, pluralResourceName) {
11
+ const joinClauses = buildJoinClauses(operations, pluralResourceName);
12
+ const orderByClause = buildOrderByClause(queryOptions);
13
+ const paginationClause = buildPaginationClause(queryOptions);
14
+ const hasJoins = operations.some(op => op instanceof Join);
15
+ const selectClause = hasJoins
16
+ ? await buildSelectClause(client, pluralResourceName, pluralResourceName, operations)
17
+ : '*';
18
+ const tablePrefix = hasJoins ? pluralResourceName : undefined;
19
+ const { whereClause, values } = buildWhereClause(queryOptions, [], tablePrefix);
20
+ const baseQuery = `SELECT ${selectClause} FROM "${pluralResourceName}" ${joinClauses} ${whereClause}`;
21
+ const total = await executeCountQuery(client, pluralResourceName, queryOptions);
22
+ const dataQuery = `${baseQuery} ${orderByClause} ${paginationClause}`.trim();
23
+ const dataResult = await client.query(dataQuery, values);
24
+ const entities = transformJoinResults(dataResult.rows, operations);
25
+ return apiUtils.getPagedResult(entities, total, queryOptions);
26
+ }
@@ -0,0 +1,3 @@
1
+ import { Client } from 'pg';
2
+ import { IQueryOptions } from "@loomcore/common/models";
3
+ export declare function executeCountQuery(client: Client, pluralResourceName: string, queryOptions?: IQueryOptions): Promise<number>;
@@ -0,0 +1,7 @@
1
+ import { buildWhereClause } from "./build-where-clause.js";
2
+ export async function executeCountQuery(client, pluralResourceName, queryOptions = {}) {
3
+ const { whereClause, values } = buildWhereClause(queryOptions);
4
+ const countQuery = `SELECT COUNT(*) as total FROM "${pluralResourceName}" ${whereClause}`;
5
+ const countResult = await client.query(countQuery, values);
6
+ return parseInt(countResult.rows[0].total, 10);
7
+ }
@@ -0,0 +1,2 @@
1
+ import { Operation } from "../../operations/operation.js";
2
+ export declare function buildJoinClauses(operations: Operation[], mainTableName?: string): string;
@@ -0,0 +1,12 @@
1
+ import { Join } from "../../operations/join.operation.js";
2
+ export function buildJoinClauses(operations, mainTableName) {
3
+ let joinClauses = '';
4
+ const joinOperations = operations.filter(op => op instanceof Join);
5
+ for (const operation of joinOperations) {
6
+ const localFieldRef = mainTableName
7
+ ? `"${mainTableName}"."${operation.localField}"`
8
+ : `"${operation.localField}"`;
9
+ joinClauses += ` LEFT JOIN "${operation.from}" AS ${operation.as} ON ${localFieldRef} = "${operation.as}"."${operation.foreignField}"`;
10
+ }
11
+ return joinClauses;
12
+ }
@@ -0,0 +1,2 @@
1
+ import { IQueryOptions } from "@loomcore/common/models";
2
+ export declare function buildOrderByClause(queryObject: IQueryOptions): string;
@@ -0,0 +1,8 @@
1
+ export function buildOrderByClause(queryObject) {
2
+ if (!queryObject.orderBy) {
3
+ return '';
4
+ }
5
+ const orderBy = queryObject.orderBy;
6
+ const sortDirection = queryObject.sortDirection || 'asc';
7
+ return `ORDER BY ${orderBy} ${sortDirection}`;
8
+ }
@@ -0,0 +1,2 @@
1
+ import { IQueryOptions } from "@loomcore/common/models";
2
+ export declare function buildPaginationClause(queryObject: IQueryOptions): string;
@@ -0,0 +1,9 @@
1
+ export function buildPaginationClause(queryObject) {
2
+ if (!queryObject.page || !queryObject.pageSize) {
3
+ return '';
4
+ }
5
+ const page = queryObject.page;
6
+ const pageSize = queryObject.pageSize;
7
+ const offset = (page - 1) * pageSize;
8
+ return `LIMIT ${pageSize} OFFSET ${offset}`;
9
+ }
@@ -0,0 +1,3 @@
1
+ import { Client } from 'pg';
2
+ import { Operation } from '../../operations/operation.js';
3
+ export declare function buildSelectClause(client: Client, mainTableName: string, mainTableAlias: string, operations: Operation[]): Promise<string>;
@@ -0,0 +1,28 @@
1
+ import { Join } from '../../operations/join.operation.js';
2
+ async function getTableColumns(client, tableName) {
3
+ const result = await client.query(`
4
+ SELECT column_name
5
+ FROM information_schema.columns
6
+ WHERE table_schema = current_schema()
7
+ AND table_name = $1
8
+ ORDER BY ordinal_position
9
+ `, [tableName]);
10
+ return result.rows.map(row => row.column_name);
11
+ }
12
+ export async function buildSelectClause(client, mainTableName, mainTableAlias, operations) {
13
+ const joinOperations = operations.filter(op => op instanceof Join);
14
+ const mainTableColumns = await getTableColumns(client, mainTableName);
15
+ const mainSelects = mainTableColumns.map(col => `"${mainTableName}"."${col}" AS "${col}"`);
16
+ const joinSelects = [];
17
+ for (const join of joinOperations) {
18
+ const joinColumns = await getTableColumns(client, join.from);
19
+ if (joinColumns.length === 0) {
20
+ continue;
21
+ }
22
+ for (const col of joinColumns) {
23
+ joinSelects.push(`${join.as}."${col}" AS "${join.as}__${col}"`);
24
+ }
25
+ }
26
+ const allSelects = [...mainSelects, ...joinSelects];
27
+ return allSelects.join(', ');
28
+ }
@@ -0,0 +1,5 @@
1
+ import { IQueryOptions } from "@loomcore/common/models";
2
+ export declare function buildWhereClause(queryObject: IQueryOptions, values?: any[], tablePrefix?: string): {
3
+ whereClause: string;
4
+ values: any[];
5
+ };
@@ -0,0 +1,50 @@
1
+ export function buildWhereClause(queryObject, values = [], tablePrefix) {
2
+ const filters = queryObject.filters || {};
3
+ const conditions = [];
4
+ let paramIndex = values.length + 1;
5
+ const qualifyColumn = (columnName) => {
6
+ return tablePrefix ? `"${tablePrefix}"."${columnName}"` : `"${columnName}"`;
7
+ };
8
+ for (const [key, value] of Object.entries(filters)) {
9
+ if (value) {
10
+ const qualifiedKey = qualifyColumn(key);
11
+ if (value.eq !== undefined) {
12
+ conditions.push(`${qualifiedKey} = $${paramIndex}`);
13
+ values.push(value.eq);
14
+ paramIndex++;
15
+ }
16
+ else if (value.in !== undefined && Array.isArray(value.in)) {
17
+ const placeholders = value.in.map(() => `$${paramIndex++}`).join(', ');
18
+ conditions.push(`${qualifiedKey} IN (${placeholders})`);
19
+ values.push(...value.in);
20
+ }
21
+ else if (value.gte !== undefined) {
22
+ conditions.push(`${qualifiedKey} >= $${paramIndex}`);
23
+ values.push(value.gte);
24
+ paramIndex++;
25
+ }
26
+ else if (value.lte !== undefined) {
27
+ conditions.push(`${qualifiedKey} <= $${paramIndex}`);
28
+ values.push(value.lte);
29
+ paramIndex++;
30
+ }
31
+ else if (value.gt !== undefined) {
32
+ conditions.push(`${qualifiedKey} > $${paramIndex}`);
33
+ values.push(value.gt);
34
+ paramIndex++;
35
+ }
36
+ else if (value.lt !== undefined) {
37
+ conditions.push(`${qualifiedKey} < $${paramIndex}`);
38
+ values.push(value.lt);
39
+ paramIndex++;
40
+ }
41
+ else if (value.contains !== undefined) {
42
+ conditions.push(`LOWER(${qualifiedKey}) LIKE LOWER($${paramIndex})`);
43
+ values.push(`%${value.contains}%`);
44
+ paramIndex++;
45
+ }
46
+ }
47
+ }
48
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
49
+ return { whereClause, values };
50
+ }
@@ -0,0 +1,5 @@
1
+ import { IEntity } from "@loomcore/common/models";
2
+ export declare function columnsAndValuesFromEntity<T extends IEntity>(entity: Partial<T>): {
3
+ columns: string[];
4
+ values: any[];
5
+ };
@@ -0,0 +1,9 @@
1
+ export function columnsAndValuesFromEntity(entity) {
2
+ const columns = [];
3
+ const values = [];
4
+ for (const [key, value] of Object.entries(entity)) {
5
+ columns.push(`"${key}"`);
6
+ values.push(value);
7
+ }
8
+ return { columns, values };
9
+ }
@@ -0,0 +1,2 @@
1
+ import { TSchema } from '@sinclair/typebox';
2
+ export declare function convertNullToUndefined<T>(data: T, schema: TSchema): T;
@@ -0,0 +1,70 @@
1
+ import _ from 'lodash';
2
+ function isPropertyOptional(key, schema) {
3
+ if (!schema || typeof schema !== 'object')
4
+ return false;
5
+ if (schema.allOf && Array.isArray(schema.allOf)) {
6
+ for (const nestedSchema of schema.allOf) {
7
+ if (!isPropertyOptional(key, nestedSchema)) {
8
+ return false;
9
+ }
10
+ }
11
+ return true;
12
+ }
13
+ if (schema.type === 'object' && schema.properties && schema.properties[key]) {
14
+ const required = schema.required || [];
15
+ return !required.includes(key);
16
+ }
17
+ return false;
18
+ }
19
+ export function convertNullToUndefined(data, schema) {
20
+ if (!data || !schema)
21
+ return data;
22
+ if (Array.isArray(data)) {
23
+ return data.map(item => convertNullToUndefined(item, schema));
24
+ }
25
+ if (typeof data !== 'object' || data === null) {
26
+ return data;
27
+ }
28
+ const clone = _.cloneDeep(data);
29
+ const processObject = (obj, subSchema) => {
30
+ if (!obj || typeof obj !== 'object' || Array.isArray(obj))
31
+ return;
32
+ if (subSchema.allOf && Array.isArray(subSchema.allOf)) {
33
+ for (const nestedSchema of subSchema.allOf) {
34
+ processObject(obj, nestedSchema);
35
+ }
36
+ return;
37
+ }
38
+ if (subSchema.type === 'object' && subSchema.properties) {
39
+ for (const [key, propSchema] of Object.entries(subSchema.properties)) {
40
+ if (!propSchema || typeof propSchema !== 'object')
41
+ continue;
42
+ const typedPropSchema = propSchema;
43
+ const value = obj[key];
44
+ if (isPropertyOptional(key, subSchema)) {
45
+ if (value === null) {
46
+ delete obj[key];
47
+ }
48
+ }
49
+ if (typedPropSchema.type === 'object' && value && typeof value === 'object' && !Array.isArray(value)) {
50
+ processObject(value, typedPropSchema);
51
+ }
52
+ if (typedPropSchema.type === 'array' && Array.isArray(value)) {
53
+ const items = typedPropSchema.items;
54
+ if (items) {
55
+ for (let i = 0; i < value.length; i++) {
56
+ if (items.type === 'object' && value[i] && typeof value[i] === 'object' && !Array.isArray(value[i])) {
57
+ processObject(value[i], items);
58
+ }
59
+ else if (items.type === 'array' && Array.isArray(value[i])) {
60
+ value[i] = convertNullToUndefined(value[i], items);
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ };
68
+ processObject(clone, schema);
69
+ return clone;
70
+ }
@@ -0,0 +1,2 @@
1
+ import { Operation } from '../../operations/operation.js';
2
+ export declare function transformJoinResults<T>(rows: any[], operations: Operation[]): T[];
@@ -0,0 +1,33 @@
1
+ import { Join } from '../../operations/join.operation.js';
2
+ export function transformJoinResults(rows, operations) {
3
+ const joinOperations = operations.filter(op => op instanceof Join);
4
+ if (joinOperations.length === 0) {
5
+ return rows;
6
+ }
7
+ return rows.map(row => {
8
+ const transformed = {};
9
+ for (const key of Object.keys(row)) {
10
+ const hasJoinPrefix = joinOperations.some(join => key.startsWith(`${join.as}__`));
11
+ if (!hasJoinPrefix) {
12
+ transformed[key] = row[key];
13
+ }
14
+ }
15
+ for (const join of joinOperations) {
16
+ const prefix = `${join.as}__`;
17
+ const joinedData = {};
18
+ let hasAnyData = false;
19
+ for (const key of Object.keys(row)) {
20
+ if (key.startsWith(prefix)) {
21
+ const columnName = key.substring(prefix.length);
22
+ const value = row[key];
23
+ joinedData[columnName] = value;
24
+ if (value !== null && value !== undefined) {
25
+ hasAnyData = true;
26
+ }
27
+ }
28
+ }
29
+ transformed[join.as] = hasAnyData ? joinedData : null;
30
+ }
31
+ return transformed;
32
+ });
33
+ }
@@ -0,0 +1,2 @@
1
+ import { TSchema } from '@sinclair/typebox';
2
+ export declare function getPropertySchema(key: string, schema: TSchema): TSchema | undefined;
@@ -0,0 +1,15 @@
1
+ export function getPropertySchema(key, schema) {
2
+ if (!schema || typeof schema !== 'object')
3
+ return undefined;
4
+ if (schema.allOf && Array.isArray(schema.allOf)) {
5
+ for (const nestedSchema of schema.allOf) {
6
+ const propSchema = getPropertySchema(key, nestedSchema);
7
+ if (propSchema)
8
+ return propSchema;
9
+ }
10
+ }
11
+ if (schema.type === 'object' && schema.properties) {
12
+ return schema.properties[key];
13
+ }
14
+ return undefined;
15
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -3,8 +3,9 @@ export interface IBaseApiConfig {
3
3
  env: string;
4
4
  hostName: string;
5
5
  clientSecret: string;
6
- mongoDbUrl?: string;
7
- databaseName?: string;
6
+ database: {
7
+ name?: string;
8
+ };
8
9
  externalPort?: number;
9
10
  internalPort?: number;
10
11
  corsAllowedOrigins: string[];
@@ -1,2 +1,2 @@
1
1
  export * from './base-api-config.interface.js';
2
- export * from './types/index.js';
2
+ export * from './refresh-token.model.js';
@@ -1,2 +1,2 @@
1
1
  export * from './base-api-config.interface.js';
2
- export * from './types/index.js';
2
+ export * from './refresh-token.model.js';
@@ -0,0 +1,18 @@
1
+ import { IEntity } from "@loomcore/common/models";
2
+ export interface IRefreshToken extends IEntity {
3
+ token: string;
4
+ deviceId: string;
5
+ userId: string;
6
+ expiresOn: number;
7
+ created: Date;
8
+ createdBy: string;
9
+ }
10
+ export declare const refreshTokenSchema: import("@sinclair/typebox").TObject<{
11
+ token: import("@sinclair/typebox").TString;
12
+ deviceId: import("@sinclair/typebox").TString;
13
+ userId: import("@sinclair/typebox").TString;
14
+ expiresOn: import("@sinclair/typebox").TNumber;
15
+ created: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TTransform<import("@sinclair/typebox").TString, Date>, import("@sinclair/typebox").TUndefined]>;
16
+ createdBy: import("@sinclair/typebox").TString;
17
+ }>;
18
+ export declare const refreshTokenModelSpec: import("@loomcore/common/models").IModelSpec<import("@sinclair/typebox").TSchema>;
@@ -0,0 +1,13 @@
1
+ import { entityUtils } from "@loomcore/common/utils";
2
+ import { TypeboxIsoDate } from "@loomcore/common/validation";
3
+ import { Type } from "@sinclair/typebox";
4
+ ;
5
+ export const refreshTokenSchema = Type.Object({
6
+ token: Type.String({ minLength: 1 }),
7
+ deviceId: Type.String({ minLength: 1 }),
8
+ userId: Type.String({ minLength: 1 }),
9
+ expiresOn: Type.Number(),
10
+ created: TypeboxIsoDate({ title: 'Created Date' }),
11
+ createdBy: Type.String({ minLength: 1 })
12
+ });
13
+ export const refreshTokenModelSpec = entityUtils.getModelSpec(refreshTokenSchema);