@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,11 @@
1
+ import { IMigration } from "../../databases/postgres/migrations/index.js";
2
+ import { Client } from "pg";
3
+ export declare class CreateCategoriesTableMigration implements IMigration {
4
+ private readonly client;
5
+ private readonly orgId?;
6
+ constructor(client: Client, orgId?: string | undefined);
7
+ index: number;
8
+ _id: string;
9
+ execute(): Promise<boolean>;
10
+ revert(): Promise<boolean>;
11
+ }
@@ -0,0 +1,52 @@
1
+ import { randomUUID } from "crypto";
2
+ export class CreateCategoriesTableMigration {
3
+ client;
4
+ orgId;
5
+ constructor(client, orgId) {
6
+ this.client = client;
7
+ this.orgId = orgId;
8
+ }
9
+ index = 2;
10
+ _id = randomUUID().toString();
11
+ async execute() {
12
+ try {
13
+ await this.client.query(`
14
+ CREATE TABLE "categories" (
15
+ "_id" VARCHAR(255) PRIMARY KEY,
16
+ "_orgId" VARCHAR(255),
17
+ "name" VARCHAR(255) NOT NULL
18
+ )
19
+ `);
20
+ if (this.orgId) {
21
+ await this.client.query(`
22
+ Insert into "migrations" ("_id", "_orgId", "index", "hasRun", "reverted") values ('${this._id}', '${this.orgId}', ${this.index}, TRUE, FALSE);
23
+ `);
24
+ }
25
+ else {
26
+ await this.client.query(`
27
+ Insert into "migrations" ("_id", "index", "hasRun", "reverted") values ('${this._id}', ${this.index}, TRUE, FALSE);
28
+ `);
29
+ }
30
+ return true;
31
+ }
32
+ catch (error) {
33
+ console.error('Error creating categories table:', error);
34
+ return false;
35
+ }
36
+ }
37
+ async revert() {
38
+ try {
39
+ await this.client.query(`
40
+ DROP TABLE "categories";
41
+ `);
42
+ await this.client.query(`
43
+ Update "migrations" SET "reverted" = TRUE WHERE "_id" = '${this._id}';
44
+ `);
45
+ }
46
+ catch (error) {
47
+ console.error('Error reverting categories table:', error);
48
+ return false;
49
+ }
50
+ return true;
51
+ }
52
+ }
@@ -0,0 +1,11 @@
1
+ import { Client } from "pg";
2
+ import { IMigration } from "../../databases/postgres/migrations/index.js";
3
+ export declare class CreateProductsTableMigration implements IMigration {
4
+ private readonly client;
5
+ private readonly orgId?;
6
+ constructor(client: Client, orgId?: string | undefined);
7
+ index: number;
8
+ _id: string;
9
+ execute(): Promise<boolean>;
10
+ revert(): Promise<boolean>;
11
+ }
@@ -0,0 +1,62 @@
1
+ import { randomUUID } from "crypto";
2
+ export class CreateProductsTableMigration {
3
+ client;
4
+ orgId;
5
+ constructor(client, orgId) {
6
+ this.client = client;
7
+ this.orgId = orgId;
8
+ }
9
+ index = 3;
10
+ _id = randomUUID().toString();
11
+ async execute() {
12
+ try {
13
+ await this.client.query(`
14
+ CREATE TABLE "products" (
15
+ "_id" VARCHAR(255) PRIMARY KEY,
16
+ "_orgId" VARCHAR(255),
17
+ "name" VARCHAR(255) NOT NULL,
18
+ "description" TEXT,
19
+ "internalNumber" VARCHAR(255),
20
+ "categoryId" VARCHAR(255) NOT NULL REFERENCES "categories"("_id"),
21
+ "_created" TIMESTAMP NOT NULL,
22
+ "_createdBy" VARCHAR(255) NOT NULL,
23
+ "_updated" TIMESTAMP NOT NULL,
24
+ "_updatedBy" VARCHAR(255) NOT NULL,
25
+ "_deleted" TIMESTAMP,
26
+ "_deletedBy" VARCHAR(255)
27
+ )
28
+ `);
29
+ if (this.orgId) {
30
+ await this.client.query(`
31
+ Insert into "migrations" ("_id", "_orgId", "index", "hasRun", "reverted") values ('${this._id}', '${this.orgId}', ${this.index}, TRUE, FALSE);
32
+ `);
33
+ }
34
+ else {
35
+ await this.client.query(`
36
+ Insert into "migrations" ("_id", "index", "hasRun", "reverted") values ('${this._id}', ${this.index}, TRUE, FALSE);
37
+ `);
38
+ }
39
+ return true;
40
+ }
41
+ catch (error) {
42
+ console.error('Error creating products table:', error);
43
+ return false;
44
+ }
45
+ return true;
46
+ }
47
+ async revert() {
48
+ try {
49
+ await this.client.query(`
50
+ DROP TABLE "products";
51
+ `);
52
+ await this.client.query(`
53
+ Update "migrations" SET "reverted" = TRUE WHERE "_id" = '${this._id}';
54
+ `);
55
+ }
56
+ catch (error) {
57
+ console.error('Error reverting products table:', error);
58
+ return false;
59
+ }
60
+ return true;
61
+ }
62
+ }
@@ -0,0 +1,11 @@
1
+ import { Client } from "pg";
2
+ import { IMigration } from "../../databases/postgres/migrations/index.js";
3
+ export declare class CreateTestUsersTableMigration implements IMigration {
4
+ private readonly client;
5
+ private readonly orgId?;
6
+ constructor(client: Client, orgId?: string | undefined);
7
+ index: number;
8
+ _id: string;
9
+ execute(): Promise<boolean>;
10
+ revert(): Promise<boolean>;
11
+ }
@@ -0,0 +1,66 @@
1
+ import { randomUUID } from "crypto";
2
+ export class CreateTestUsersTableMigration {
3
+ client;
4
+ orgId;
5
+ constructor(client, orgId) {
6
+ this.client = client;
7
+ this.orgId = orgId;
8
+ }
9
+ index = 4;
10
+ _id = randomUUID().toString();
11
+ async execute() {
12
+ try {
13
+ await this.client.query(`
14
+ CREATE TABLE "testUsers" (
15
+ "_id" VARCHAR(255) PRIMARY KEY,
16
+ "_orgId" VARCHAR(255),
17
+ "email" VARCHAR(255) NOT NULL,
18
+ "password" VARCHAR(255) NOT NULL,
19
+ "firstName" VARCHAR(255),
20
+ "lastName" VARCHAR(255),
21
+ "displayName" VARCHAR(255),
22
+ "roles" TEXT[],
23
+ "_lastLoggedIn" TIMESTAMP,
24
+ "_lastPasswordChange" TIMESTAMP,
25
+ "_created" TIMESTAMP NOT NULL,
26
+ "_createdBy" VARCHAR(255) NOT NULL,
27
+ "_updated" TIMESTAMP NOT NULL,
28
+ "_updatedBy" VARCHAR(255) NOT NULL,
29
+ "_deleted" TIMESTAMP,
30
+ "_deletedBy" VARCHAR(255)
31
+ )
32
+ `);
33
+ if (this.orgId) {
34
+ await this.client.query(`
35
+ Insert into "migrations" ("_id", "_orgId", "index", "hasRun", "reverted") values ('${this._id}', '${this.orgId}', ${this.index}, TRUE, FALSE);
36
+ `);
37
+ }
38
+ else {
39
+ await this.client.query(`
40
+ Insert into "migrations" ("_id", "index", "hasRun", "reverted") values ('${this._id}', ${this.index}, TRUE, FALSE);
41
+ `);
42
+ }
43
+ return true;
44
+ }
45
+ catch (error) {
46
+ console.error('Error creating test users table:', error);
47
+ return false;
48
+ }
49
+ return true;
50
+ }
51
+ async revert() {
52
+ try {
53
+ await this.client.query(`
54
+ DROP TABLE "testUsers";
55
+ `);
56
+ }
57
+ catch (error) {
58
+ await this.client.query(`
59
+ Update "migrations" SET "reverted" = TRUE WHERE "_id" = '${this._id}';
60
+ `);
61
+ console.error('Error reverting test users table:', error);
62
+ return false;
63
+ }
64
+ return true;
65
+ }
66
+ }
@@ -0,0 +1,11 @@
1
+ import { Client } from "pg";
2
+ import { IMigration } from "../../databases/postgres/migrations/index.js";
3
+ export declare class CreateTestItemsTableMigration implements IMigration {
4
+ private readonly client;
5
+ private readonly orgId?;
6
+ constructor(client: Client, orgId?: string | undefined);
7
+ index: number;
8
+ _id: string;
9
+ execute(): Promise<boolean>;
10
+ revert(): Promise<boolean>;
11
+ }
@@ -0,0 +1,50 @@
1
+ import { randomUUID } from "crypto";
2
+ export class CreateTestItemsTableMigration {
3
+ client;
4
+ orgId;
5
+ constructor(client, orgId) {
6
+ this.client = client;
7
+ this.orgId = orgId;
8
+ }
9
+ index = 5;
10
+ _id = randomUUID().toString();
11
+ async execute() {
12
+ try {
13
+ await this.client.query(`
14
+ CREATE TABLE "testItems" (
15
+ "_id" VARCHAR(255) PRIMARY KEY,
16
+ "_orgId" VARCHAR(255),
17
+ "name" VARCHAR(255) NOT NULL,
18
+ "value" INTEGER,
19
+ "eventDate" TIMESTAMP,
20
+ "_created" TIMESTAMP NOT NULL,
21
+ "_createdBy" VARCHAR(255) NOT NULL,
22
+ "_updated" TIMESTAMP NOT NULL,
23
+ "_updatedBy" VARCHAR(255) NOT NULL,
24
+ "_deleted" TIMESTAMP,
25
+ "_deletedBy" VARCHAR(255)
26
+ )
27
+ `);
28
+ }
29
+ catch (error) {
30
+ console.error('Error creating test items table:', error);
31
+ return false;
32
+ }
33
+ return true;
34
+ }
35
+ async revert() {
36
+ try {
37
+ await this.client.query(`
38
+ DROP TABLE "testItems";
39
+ `);
40
+ }
41
+ catch (error) {
42
+ await this.client.query(`
43
+ Update "migrations" SET "reverted" = TRUE WHERE "_id" = '${this._id}';
44
+ `);
45
+ console.error('Error reverting test items table:', error);
46
+ return false;
47
+ }
48
+ return true;
49
+ }
50
+ }
@@ -0,0 +1,2 @@
1
+ import { Client } from "pg";
2
+ export declare function runTestMigrations(client: Client, orgId?: string): Promise<boolean>;
@@ -0,0 +1,22 @@
1
+ import { CreateTestEntitiesTableMigration } from "./001-create-test-entities-table.migration.js";
2
+ import { CreateCategoriesTableMigration } from "./002-create-categories-table.migration.js";
3
+ import { CreateProductsTableMigration } from "./003-create-products-table.migration.js";
4
+ import { CreateTestUsersTableMigration } from "./004-create-test-users-table.migration.js";
5
+ import { CreateTestItemsTableMigration } from "./005-create-test-items-table.migration.js";
6
+ export async function runTestMigrations(client, orgId) {
7
+ const migrations = [
8
+ new CreateTestEntitiesTableMigration(client, orgId),
9
+ new CreateCategoriesTableMigration(client, orgId),
10
+ new CreateProductsTableMigration(client, orgId),
11
+ new CreateTestUsersTableMigration(client, orgId),
12
+ new CreateTestItemsTableMigration(client, orgId),
13
+ ];
14
+ let success = true;
15
+ for (const migration of migrations) {
16
+ success = await migration.execute();
17
+ if (!success) {
18
+ return false;
19
+ }
20
+ }
21
+ return success;
22
+ }
@@ -0,0 +1,13 @@
1
+ import { ITestDatabase } from './test-database.interface.js';
2
+ import { IDatabase } from '../databases/models/index.js';
3
+ export declare class TestPostgresDatabase implements ITestDatabase {
4
+ private database;
5
+ private postgresClient;
6
+ private initPromise;
7
+ init(databaseName: string): Promise<IDatabase>;
8
+ getRandomId(): string;
9
+ private _performInit;
10
+ private createIndexes;
11
+ clearCollections(): Promise<void>;
12
+ cleanup(): Promise<void>;
13
+ }
@@ -0,0 +1,85 @@
1
+ import { randomUUID } from 'crypto';
2
+ import testUtils from './common-test.utils.js';
3
+ import { initSystemUserContext } from '../config/base-api-config.js';
4
+ import { newDb } from "pg-mem";
5
+ import { setupDatabaseForMultitenant } from '../databases/postgres/migrations/setup-for-multitenant.migration.js';
6
+ import { setupDatabaseForAuth } from '../databases/postgres/migrations/setup-for-auth.migration.js';
7
+ import { runTestMigrations } from './postgres-test-migrations/run-test-migrations.js';
8
+ import { PostgresDatabase } from '../databases/postgres/postgres.database.js';
9
+ import { testOrg } from './test-objects.js';
10
+ export class TestPostgresDatabase {
11
+ database = null;
12
+ postgresClient = null;
13
+ initPromise = null;
14
+ async init(databaseName) {
15
+ if (this.initPromise) {
16
+ return this.initPromise;
17
+ }
18
+ this.initPromise = this._performInit(databaseName);
19
+ return this.initPromise;
20
+ }
21
+ getRandomId() {
22
+ return randomUUID();
23
+ }
24
+ async _performInit(databaseName) {
25
+ if (!this.database) {
26
+ const { Client } = newDb().adapters.createPg();
27
+ const postgresClient = new Client();
28
+ await postgresClient.connect();
29
+ const testDatabase = new PostgresDatabase(postgresClient);
30
+ this.database = testDatabase;
31
+ this.postgresClient = postgresClient;
32
+ let success = await setupDatabaseForMultitenant(postgresClient, testOrg._id);
33
+ if (!success) {
34
+ throw new Error('Failed to setup for multitenant');
35
+ }
36
+ success = await setupDatabaseForAuth(postgresClient, testOrg._id);
37
+ if (!success) {
38
+ throw new Error('Failed to setup for auth');
39
+ }
40
+ success = await runTestMigrations(postgresClient, testOrg._id);
41
+ if (!success) {
42
+ throw new Error('Failed to run test migrations');
43
+ }
44
+ testUtils.initialize(testDatabase);
45
+ await this.createIndexes(postgresClient);
46
+ await testUtils.createMetaOrg();
47
+ }
48
+ await initSystemUserContext(this.database);
49
+ return this.database;
50
+ }
51
+ async createIndexes(client) {
52
+ try {
53
+ await client.query(`
54
+ CREATE INDEX IF NOT EXISTS email_index ON users (LOWER(email));
55
+ CREATE UNIQUE INDEX IF NOT EXISTS email_unique_index ON users (LOWER(email));
56
+ `);
57
+ }
58
+ catch (error) {
59
+ console.log('Note: Indexes may be created later when tables are initialized:', error.message);
60
+ }
61
+ }
62
+ async clearCollections() {
63
+ if (!this.postgresClient) {
64
+ throw new Error('Database not initialized');
65
+ }
66
+ const result = await this.postgresClient.query(`
67
+ SELECT "table_name"
68
+ FROM information_schema.tables
69
+ WHERE "table_schema" = 'public'
70
+ AND "table_type" = 'BASE TABLE'
71
+ `);
72
+ result.rows.forEach(async (row) => {
73
+ await this.postgresClient?.query(`TRUNCATE TABLE "${row.table_name}" RESTART IDENTITY CASCADE`);
74
+ });
75
+ }
76
+ async cleanup() {
77
+ await testUtils.cleanup();
78
+ if (!this.postgresClient) {
79
+ throw new Error('Database not initialized');
80
+ }
81
+ await this.postgresClient.end();
82
+ this.initPromise = null;
83
+ this.database = null;
84
+ }
85
+ }
@@ -0,0 +1,7 @@
1
+ import { IDatabase } from "../databases/models/index.js";
2
+ export type ITestDatabase = {
3
+ init(databaseName: string): Promise<IDatabase>;
4
+ getRandomId(): string;
5
+ clearCollections(): Promise<void>;
6
+ cleanup(): Promise<void>;
7
+ };
@@ -1,18 +1,20 @@
1
1
  import { Application } from 'express';
2
- import { Db } from 'mongodb';
2
+ import { ITestDatabase } from './test-database.interface.js';
3
+ import { IDatabase } from '../databases/models/database.interface.js';
3
4
  export declare class TestExpressApp {
4
5
  private static app;
5
- private static mongoServer;
6
- private static client;
7
- private static db;
6
+ private static database;
7
+ private static testDatabase;
8
8
  private static initPromise;
9
- static init(): Promise<{
9
+ private static databaseName;
10
+ static init(useMongoDb?: boolean): Promise<{
10
11
  app: Application;
11
- db: Db;
12
+ database: IDatabase;
13
+ testDatabase: ITestDatabase;
12
14
  agent: any;
13
15
  }>;
14
16
  private static _performInit;
15
17
  static setupErrorHandling(): Promise<void>;
16
- static cleanup(): Promise<void>;
17
18
  static clearCollections(): Promise<void>;
19
+ static cleanup(): Promise<void>;
18
20
  }
@@ -2,34 +2,38 @@ import express from 'express';
2
2
  import bodyParser from 'body-parser';
3
3
  import cookieParser from 'cookie-parser';
4
4
  import supertest from 'supertest';
5
- import { MongoMemoryServer } from 'mongodb-memory-server';
6
- import { MongoClient } from 'mongodb';
7
5
  import { initializeTypeBox } from '@loomcore/common/validation';
8
- import testUtils from './common-test.utils.js';
9
- import { setBaseApiConfig, initSystemUserContext } from '../config/base-api-config.js';
6
+ import { setBaseApiConfig } from '../config/base-api-config.js';
10
7
  import { errorHandler } from '../middleware/error-handler.js';
11
8
  import { ensureUserContext } from '../middleware/ensure-user-context.js';
9
+ import { TestMongoDatabase } from './mongo-db.test-database.js';
10
+ import { TestPostgresDatabase } from './postgres.test-database.js';
12
11
  export class TestExpressApp {
13
12
  static app;
14
- static mongoServer;
15
- static client;
16
- static db;
13
+ static database;
14
+ static testDatabase;
17
15
  static initPromise = null;
18
- static async init() {
16
+ static databaseName = 'test-db';
17
+ static async init(useMongoDb) {
18
+ if (useMongoDb === undefined) {
19
+ const testDb = process.env.TEST_DATABASE;
20
+ useMongoDb = testDb === 'mongodb';
21
+ }
19
22
  if (this.initPromise) {
20
23
  return this.initPromise;
21
24
  }
22
- this.initPromise = this._performInit();
25
+ this.initPromise = this._performInit(useMongoDb);
23
26
  return this.initPromise;
24
27
  }
25
- static async _performInit() {
28
+ static async _performInit(useMongoDb) {
26
29
  setBaseApiConfig({
27
30
  env: 'test',
28
31
  hostName: 'localhost',
29
32
  appName: 'test-app',
30
33
  clientSecret: 'test-secret',
31
- mongoDbUrl: '',
32
- databaseName: '',
34
+ database: {
35
+ name: this.databaseName,
36
+ },
33
37
  externalPort: 4000,
34
38
  internalPort: 8083,
35
39
  corsAllowedOrigins: ['*'],
@@ -53,24 +57,18 @@ export class TestExpressApp {
53
57
  }
54
58
  });
55
59
  initializeTypeBox();
56
- if (!this.db) {
57
- this.mongoServer = await MongoMemoryServer.create({
58
- instance: {
59
- ip: '127.0.0.1',
60
- port: 0,
61
- },
62
- binary: {
63
- downloadDir: process.env.HOME ? `${process.env.HOME}/.cache/mongodb-binaries` : undefined,
64
- }
65
- });
66
- const uri = this.mongoServer.getUri();
67
- this.client = await MongoClient.connect(uri);
68
- this.db = this.client.db();
69
- testUtils.initialize(this.db);
70
- await testUtils.createIndexes(this.db);
71
- await testUtils.createMetaOrg();
60
+ if (!this.database) {
61
+ if (useMongoDb) {
62
+ const testMongoDb = new TestMongoDatabase();
63
+ this.testDatabase = testMongoDb;
64
+ this.database = await testMongoDb.init(this.databaseName);
65
+ }
66
+ else {
67
+ const testPostgresDb = new TestPostgresDatabase();
68
+ this.testDatabase = testPostgresDb;
69
+ this.database = await testPostgresDb.init(this.databaseName);
70
+ }
72
71
  }
73
- await initSystemUserContext(this.db);
74
72
  if (!this.app) {
75
73
  this.app = express();
76
74
  this.app.use(bodyParser.json());
@@ -83,34 +81,26 @@ export class TestExpressApp {
83
81
  const agent = supertest.agent(this.app);
84
82
  return {
85
83
  app: this.app,
86
- db: this.db,
84
+ database: this.database,
85
+ testDatabase: this.testDatabase,
87
86
  agent
88
87
  };
89
88
  }
90
89
  static async setupErrorHandling() {
91
90
  this.app.use(errorHandler);
92
91
  }
93
- static async cleanup() {
94
- await testUtils.cleanup();
95
- if (this.client) {
96
- await this.client.close();
92
+ static async clearCollections() {
93
+ if (this.testDatabase) {
94
+ await this.testDatabase.clearCollections();
97
95
  }
98
- if (this.mongoServer) {
99
- await this.mongoServer.stop();
96
+ }
97
+ static async cleanup() {
98
+ if (this.testDatabase) {
99
+ await this.testDatabase.cleanup();
100
100
  }
101
101
  this.initPromise = null;
102
102
  this.app = undefined;
103
- this.db = undefined;
104
- this.client = undefined;
105
- this.mongoServer = undefined;
106
- }
107
- static async clearCollections() {
108
- if (!this.db) {
109
- throw new Error('Database not initialized');
110
- }
111
- const collections = await this.db.collections();
112
- for (const collection of collections) {
113
- await collection.deleteMany({});
114
- }
103
+ this.database = undefined;
104
+ this.testDatabase = undefined;
115
105
  }
116
106
  }
@@ -0,0 +1,23 @@
1
+ import { IOrganization, IUser, IUserContext } from "@loomcore/common/models";
2
+ export declare const testUser: IUser;
3
+ export declare function getTestUser(): {
4
+ email: string;
5
+ firstName?: string;
6
+ lastName?: string;
7
+ displayName?: string;
8
+ password: string;
9
+ roles?: string[];
10
+ _lastLoggedIn?: Date;
11
+ _lastPasswordChange?: Date;
12
+ _created: Date;
13
+ _createdBy: string;
14
+ _updated: Date;
15
+ _updatedBy: string;
16
+ _deleted?: Date;
17
+ _deletedBy?: string;
18
+ _id: string;
19
+ _orgId?: string;
20
+ };
21
+ export declare const testUserContext: IUserContext;
22
+ export declare const testMetaOrg: IOrganization;
23
+ export declare const testOrg: IOrganization;
@@ -0,0 +1,45 @@
1
+ export const testUser = {
2
+ _id: '69261672f48fb7bf76e54dfb',
3
+ email: 'test@example.com',
4
+ password: 'testpassword',
5
+ firstName: 'Test',
6
+ lastName: 'User',
7
+ displayName: 'Test User',
8
+ roles: ['user'],
9
+ _orgId: '6926167d06c0073a778a124f',
10
+ _created: new Date(),
11
+ _createdBy: 'system',
12
+ _lastLoggedIn: new Date(),
13
+ _lastPasswordChange: new Date(),
14
+ _updated: new Date(),
15
+ _updatedBy: 'system',
16
+ };
17
+ export function getTestUser() {
18
+ return { ...testUser };
19
+ }
20
+ export const testUserContext = {
21
+ user: getTestUser(),
22
+ _orgId: '6926167d06c0073a778a124f'
23
+ };
24
+ export const testMetaOrg = {
25
+ _id: '69261691f936c45f85da24d0',
26
+ name: 'Test Meta Organization',
27
+ code: 'test-meta-org',
28
+ status: 1,
29
+ isMetaOrg: true,
30
+ _created: new Date(),
31
+ _createdBy: 'system',
32
+ _updated: new Date(),
33
+ _updatedBy: 'system',
34
+ };
35
+ export const testOrg = {
36
+ _id: '6926167d06c0073a778a124f',
37
+ name: 'Test Organization',
38
+ code: 'test-org',
39
+ status: 1,
40
+ isMetaOrg: false,
41
+ _created: new Date(),
42
+ _createdBy: 'system',
43
+ _updated: new Date(),
44
+ _updatedBy: 'system',
45
+ };
@@ -1,5 +1,5 @@
1
- import { Db } from 'mongodb';
2
1
  import { IBaseApiConfig } from '../models/index.js';
2
+ import { IDatabase } from '../databases/models/index.js';
3
3
  export declare let config: IBaseApiConfig;
4
4
  export declare function setBaseApiConfig(apiConfig: IBaseApiConfig): void;
5
- export declare function initSystemUserContext(db: Db): Promise<void>;
5
+ export declare function initSystemUserContext(database: IDatabase): Promise<void>;