@loomcore/api 0.0.59 → 0.1.0
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.
- package/LICENSE +201 -0
- package/README.md +50 -0
- package/dist/__tests__/common-test.utils.d.ts +29 -60
- package/dist/__tests__/common-test.utils.js +88 -166
- package/dist/__tests__/index.d.ts +6 -0
- package/dist/__tests__/index.js +6 -0
- package/dist/__tests__/models/category.model.d.ts +8 -0
- package/dist/__tests__/models/category.model.js +6 -0
- package/dist/__tests__/models/mongo-test-entity.model.d.ts +11 -0
- package/dist/__tests__/models/mongo-test-entity.model.js +13 -0
- package/dist/__tests__/models/product.model.d.ts +17 -0
- package/dist/__tests__/models/product.model.js +10 -0
- package/dist/__tests__/models/test-entity.model.d.ts +11 -0
- package/dist/__tests__/models/test-entity.model.js +10 -0
- package/dist/__tests__/models/test-item.model.d.ts +12 -0
- package/dist/__tests__/models/test-item.model.js +9 -0
- package/dist/__tests__/mongo-db.test-database.d.ts +15 -0
- package/dist/__tests__/mongo-db.test-database.js +74 -0
- package/dist/__tests__/postgres-test-migrations/001-create-test-entities-table.migration.d.ts +11 -0
- package/dist/__tests__/postgres-test-migrations/001-create-test-entities-table.migration.js +59 -0
- package/dist/__tests__/postgres-test-migrations/002-create-categories-table.migration.d.ts +11 -0
- package/dist/__tests__/postgres-test-migrations/002-create-categories-table.migration.js +52 -0
- package/dist/__tests__/postgres-test-migrations/003-create-products-table.migration.d.ts +11 -0
- package/dist/__tests__/postgres-test-migrations/003-create-products-table.migration.js +62 -0
- package/dist/__tests__/postgres-test-migrations/004-create-test-users-table.migration.d.ts +11 -0
- package/dist/__tests__/postgres-test-migrations/004-create-test-users-table.migration.js +66 -0
- package/dist/__tests__/postgres-test-migrations/005-create-test-items-table.migration.d.ts +11 -0
- package/dist/__tests__/postgres-test-migrations/005-create-test-items-table.migration.js +50 -0
- package/dist/__tests__/postgres-test-migrations/run-test-migrations.d.ts +2 -0
- package/dist/__tests__/postgres-test-migrations/run-test-migrations.js +22 -0
- package/dist/__tests__/postgres.test-database.d.ts +13 -0
- package/dist/__tests__/postgres.test-database.js +85 -0
- package/dist/__tests__/test-database.interface.d.ts +7 -0
- package/dist/__tests__/test-express-app.d.ts +9 -7
- package/dist/__tests__/test-express-app.js +38 -48
- package/dist/__tests__/test-mongo-db.d.ts +14 -0
- package/dist/__tests__/test-mongo-db.js +81 -0
- package/dist/__tests__/test-objects.d.ts +23 -0
- package/dist/__tests__/test-objects.js +45 -0
- package/dist/__tests__/test-user.d.ts +3 -0
- package/dist/__tests__/test-user.js +16 -0
- package/dist/config/base-api-config.d.ts +2 -2
- package/dist/config/base-api-config.js +2 -2
- package/dist/controllers/api.controller.d.ts +1 -5
- package/dist/controllers/api.controller.js +4 -11
- package/dist/controllers/auth.controller.d.ts +2 -2
- package/dist/controllers/auth.controller.js +4 -5
- package/dist/controllers/organizations.controller.d.ts +2 -2
- package/dist/controllers/organizations.controller.js +4 -4
- package/dist/controllers/users.controller.d.ts +2 -2
- package/dist/controllers/users.controller.js +2 -2
- package/dist/databases/index.d.ts +1 -0
- package/dist/databases/index.js +1 -0
- package/dist/databases/models/constants.d.ts +1 -0
- package/dist/databases/models/constants.js +1 -0
- package/dist/databases/models/database.d.ts +3 -0
- package/dist/databases/models/database.interface.d.ts +28 -0
- package/dist/databases/models/delete-result.d.ts +5 -0
- package/dist/databases/models/delete-result.js +8 -0
- package/dist/databases/models/index.d.ts +5 -0
- package/dist/databases/models/index.js +5 -0
- package/dist/databases/models/update-result.d.ts +5 -0
- package/dist/databases/models/update-result.js +8 -0
- package/dist/databases/mongo-db/commands/batch-update.command.d.ts +3 -0
- package/dist/databases/mongo-db/commands/batch-update.command.js +41 -0
- package/dist/databases/mongo-db/commands/create-many.command.d.ts +5 -0
- package/dist/databases/mongo-db/commands/create-many.command.js +17 -0
- package/dist/databases/mongo-db/commands/create.command.d.ts +5 -0
- package/dist/databases/mongo-db/commands/create.command.js +17 -0
- package/dist/databases/mongo-db/commands/delete-by-id.command.d.ts +3 -0
- package/dist/databases/mongo-db/commands/delete-by-id.command.js +9 -0
- package/dist/databases/mongo-db/commands/delete-many.command.d.ts +4 -0
- package/dist/databases/mongo-db/commands/delete-many.command.js +9 -0
- package/dist/databases/mongo-db/commands/full-updateby-id.command.d.ts +3 -0
- package/dist/databases/mongo-db/commands/full-updateby-id.command.js +21 -0
- package/dist/databases/mongo-db/commands/index.d.ts +8 -0
- package/dist/databases/mongo-db/commands/index.js +8 -0
- package/dist/databases/mongo-db/commands/mongo-batch-update.command.d.ts +4 -0
- package/dist/databases/mongo-db/commands/mongo-batch-update.command.js +41 -0
- package/dist/databases/mongo-db/commands/mongo-create-many.command.d.ts +5 -0
- package/dist/databases/mongo-db/commands/mongo-create-many.command.js +17 -0
- package/dist/databases/mongo-db/commands/mongo-create.command.d.ts +5 -0
- package/dist/databases/mongo-db/commands/mongo-create.command.js +17 -0
- package/dist/databases/mongo-db/commands/mongo-delete-by-id.command.d.ts +3 -0
- package/dist/databases/mongo-db/commands/mongo-delete-by-id.command.js +14 -0
- package/dist/databases/mongo-db/commands/mongo-delete-many.command.d.ts +4 -0
- package/dist/databases/mongo-db/commands/mongo-delete-many.command.js +9 -0
- package/dist/databases/mongo-db/commands/mongo-full-updateby-id.command.d.ts +3 -0
- package/dist/databases/mongo-db/commands/mongo-full-updateby-id.command.js +25 -0
- package/dist/databases/mongo-db/commands/mongo-partial-update-by-id.command.d.ts +3 -0
- package/dist/databases/mongo-db/commands/mongo-partial-update-by-id.command.js +25 -0
- package/dist/databases/mongo-db/commands/mongo-update.command.d.ts +4 -0
- package/dist/databases/mongo-db/commands/mongo-update.command.js +19 -0
- package/dist/databases/mongo-db/commands/partial-update-by-id.command.d.ts +3 -0
- package/dist/databases/mongo-db/commands/partial-update-by-id.command.js +21 -0
- package/dist/databases/mongo-db/commands/update.command.d.ts +4 -0
- package/dist/databases/mongo-db/commands/update.command.js +19 -0
- package/dist/databases/mongo-db/index.d.ts +4 -0
- package/dist/databases/mongo-db/index.js +4 -0
- package/dist/databases/mongo-db/models/no-sql-pipeline.d.ts +15 -0
- package/dist/databases/mongo-db/models/no-sql-pipeline.interface.d.ts +11 -0
- package/dist/databases/mongo-db/models/no-sql-pipeline.js +43 -0
- package/dist/databases/mongo-db/mongo-db.database.d.ts +32 -0
- package/dist/databases/mongo-db/mongo-db.database.js +65 -0
- package/dist/databases/mongo-db/queries/find-one.query.d.ts +3 -0
- package/dist/databases/mongo-db/queries/find-one.query.js +9 -0
- package/dist/databases/mongo-db/queries/find.query.d.ts +3 -0
- package/dist/databases/mongo-db/queries/find.query.js +9 -0
- package/dist/databases/mongo-db/queries/get-all.query.d.ts +3 -0
- package/dist/databases/mongo-db/queries/get-all.query.js +17 -0
- package/dist/databases/mongo-db/queries/get-by-id.query.d.ts +3 -0
- package/dist/databases/mongo-db/queries/get-by-id.query.js +20 -0
- package/dist/databases/mongo-db/queries/get-count.query.d.ts +2 -0
- package/dist/databases/mongo-db/queries/get-count.query.js +5 -0
- package/dist/databases/mongo-db/queries/get.query.d.ts +4 -0
- package/dist/databases/mongo-db/queries/get.query.js +14 -0
- package/dist/databases/mongo-db/queries/index.d.ts +6 -0
- package/dist/databases/mongo-db/queries/index.js +6 -0
- package/dist/databases/mongo-db/queries/mongo-find-one.query.d.ts +3 -0
- package/dist/databases/mongo-db/queries/mongo-find-one.query.js +9 -0
- package/dist/databases/mongo-db/queries/mongo-find.query.d.ts +3 -0
- package/dist/databases/mongo-db/queries/mongo-find.query.js +9 -0
- package/dist/databases/mongo-db/queries/mongo-get-all.query.d.ts +3 -0
- package/dist/databases/mongo-db/queries/mongo-get-all.query.js +17 -0
- package/dist/databases/mongo-db/queries/mongo-get-by-id.query.d.ts +4 -0
- package/dist/databases/mongo-db/queries/mongo-get-by-id.query.js +17 -0
- package/dist/databases/mongo-db/queries/mongo-get-count.query.d.ts +2 -0
- package/dist/databases/mongo-db/queries/mongo-get-count.query.js +5 -0
- package/dist/databases/mongo-db/queries/mongo-get.query.d.ts +4 -0
- package/dist/databases/mongo-db/queries/mongo-get.query.js +14 -0
- package/dist/databases/mongo-db/utils/build-find-options.util.d.ts +3 -0
- package/dist/databases/mongo-db/utils/build-find-options.util.js +15 -0
- package/dist/databases/mongo-db/utils/build-no-sql-match.util.d.ts +3 -0
- package/dist/databases/mongo-db/utils/build-no-sql-match.util.js +59 -0
- package/dist/databases/mongo-db/utils/convert-object-ids-to-strings.util.d.ts +1 -0
- package/dist/databases/mongo-db/utils/convert-object-ids-to-strings.util.js +32 -0
- package/dist/databases/mongo-db/utils/convert-operations-to-pipeline.util.d.ts +3 -0
- package/dist/databases/mongo-db/utils/convert-operations-to-pipeline.util.js +68 -0
- package/dist/databases/mongo-db/utils/convert-query-options-to-pipeline.util.d.ts +3 -0
- package/dist/databases/mongo-db/utils/convert-query-options-to-pipeline.util.js +31 -0
- package/dist/databases/mongo-db/utils/convert-strings-to-object-ids.util.d.ts +3 -0
- package/dist/databases/mongo-db/utils/convert-strings-to-object-ids.util.js +72 -0
- package/dist/databases/mongo-db/utils/index.d.ts +7 -0
- package/dist/databases/mongo-db/utils/index.js +7 -0
- package/dist/databases/operations/join.operation.d.ts +7 -0
- package/dist/databases/operations/join.operation.js +12 -0
- package/dist/databases/operations/operation.d.ts +2 -0
- package/dist/databases/postgres/commands/postgres-batch-update.command.d.ts +4 -0
- package/dist/databases/postgres/commands/postgres-batch-update.command.js +56 -0
- package/dist/databases/postgres/commands/postgres-create-many.command.d.ts +6 -0
- package/dist/databases/postgres/commands/postgres-create-many.command.js +63 -0
- package/dist/databases/postgres/commands/postgres-create.command.d.ts +6 -0
- package/dist/databases/postgres/commands/postgres-create.command.js +29 -0
- package/dist/databases/postgres/commands/postgres-delete-by-id.command.d.ts +3 -0
- package/dist/databases/postgres/commands/postgres-delete-by-id.command.js +6 -0
- package/dist/databases/postgres/commands/postgres-delete-many.command.d.ts +4 -0
- package/dist/databases/postgres/commands/postgres-delete-many.command.js +13 -0
- package/dist/databases/postgres/commands/postgres-full-update-by-id.command.d.ts +4 -0
- package/dist/databases/postgres/commands/postgres-full-update-by-id.command.js +72 -0
- package/dist/databases/postgres/commands/postgres-partial-update-by-id.command.d.ts +4 -0
- package/dist/databases/postgres/commands/postgres-partial-update-by-id.command.js +42 -0
- package/dist/databases/postgres/commands/postgres-update.command.d.ts +5 -0
- package/dist/databases/postgres/commands/postgres-update.command.js +48 -0
- package/dist/databases/postgres/migrations/001-create-migrations-table.migration.d.ts +11 -0
- package/dist/databases/postgres/migrations/001-create-migrations-table.migration.js +52 -0
- package/dist/databases/postgres/migrations/002-create-organizations-table.migration.d.ts +11 -0
- package/dist/databases/postgres/migrations/002-create-organizations-table.migration.js +55 -0
- package/dist/databases/postgres/migrations/003-create-users-table.migration.d.ts +11 -0
- package/dist/databases/postgres/migrations/003-create-users-table.migration.js +65 -0
- package/dist/databases/postgres/migrations/004-create-refresh-token-table.migration.d.ts +11 -0
- package/dist/databases/postgres/migrations/004-create-refresh-token-table.migration.js +57 -0
- package/dist/databases/postgres/migrations/index.d.ts +3 -0
- package/dist/databases/postgres/migrations/index.js +3 -0
- package/dist/databases/postgres/migrations/migration.d.ts +6 -0
- package/dist/databases/postgres/migrations/migration.interface.d.ts +6 -0
- package/dist/databases/postgres/migrations/migration.interface.js +1 -0
- package/dist/databases/postgres/migrations/migration.js +14 -0
- package/dist/databases/postgres/migrations/runMigrations.d.ts +2 -0
- package/dist/databases/postgres/migrations/runMigrations.js +20 -0
- package/dist/databases/postgres/migrations/setup-for-auth.migration.d.ts +2 -0
- package/dist/databases/postgres/migrations/setup-for-auth.migration.js +18 -0
- package/dist/databases/postgres/migrations/setup-for-multitenant.migration.d.ts +2 -0
- package/dist/databases/postgres/migrations/setup-for-multitenant.migration.js +16 -0
- package/dist/databases/postgres/postgres.database.d.ts +31 -0
- package/dist/databases/postgres/postgres.database.js +69 -0
- package/dist/databases/postgres/queries/postgres-find-one.query.d.ts +3 -0
- package/dist/databases/postgres/queries/postgres-find-one.query.js +13 -0
- package/dist/databases/postgres/queries/postgres-find.query.d.ts +3 -0
- package/dist/databases/postgres/queries/postgres-find.query.js +11 -0
- package/dist/databases/postgres/queries/postgres-get-all.query.d.ts +3 -0
- package/dist/databases/postgres/queries/postgres-get-all.query.js +14 -0
- package/dist/databases/postgres/queries/postgres-get-by-id.query.d.ts +4 -0
- package/dist/databases/postgres/queries/postgres-get-by-id.query.js +26 -0
- package/dist/databases/postgres/queries/postgres-get-count.query.d.ts +2 -0
- package/dist/databases/postgres/queries/postgres-get-count.query.js +4 -0
- package/dist/databases/postgres/queries/postgres-get.query.d.ts +4 -0
- package/dist/databases/postgres/queries/postgres-get.query.js +26 -0
- package/dist/databases/postgres/utils/build-count-query.d.ts +3 -0
- package/dist/databases/postgres/utils/build-count-query.js +7 -0
- package/dist/databases/postgres/utils/build-join-clauses.d.ts +2 -0
- package/dist/databases/postgres/utils/build-join-clauses.js +12 -0
- package/dist/databases/postgres/utils/build-order-by-clause.d.ts +2 -0
- package/dist/databases/postgres/utils/build-order-by-clause.js +8 -0
- package/dist/databases/postgres/utils/build-pagination-clause.d.ts +2 -0
- package/dist/databases/postgres/utils/build-pagination-clause.js +9 -0
- package/dist/databases/postgres/utils/build-select-clause.d.ts +3 -0
- package/dist/databases/postgres/utils/build-select-clause.js +28 -0
- package/dist/databases/postgres/utils/build-where-clause.d.ts +5 -0
- package/dist/databases/postgres/utils/build-where-clause.js +50 -0
- package/dist/databases/postgres/utils/columns-and-values-from-entity.d.ts +5 -0
- package/dist/databases/postgres/utils/columns-and-values-from-entity.js +9 -0
- package/dist/databases/postgres/utils/convert-null-to-undefined.util.d.ts +2 -0
- package/dist/databases/postgres/utils/convert-null-to-undefined.util.js +70 -0
- package/dist/databases/postgres/utils/transform-join-results.d.ts +2 -0
- package/dist/databases/postgres/utils/transform-join-results.js +33 -0
- package/dist/databases/utils/database-to-idatabase.util.d.ts +3 -0
- package/dist/databases/utils/database-to-idatabase.util.js +14 -0
- package/dist/databases/utils/get-property-schema.util.d.ts +2 -0
- package/dist/databases/utils/get-property-schema.util.js +15 -0
- package/dist/databases/utils/index.d.ts +1 -0
- package/dist/databases/utils/index.js +1 -0
- package/dist/models/base-api-config.interface.d.ts +3 -2
- package/dist/models/index.d.ts +1 -1
- package/dist/models/index.js +1 -1
- package/dist/models/refresh-token.d.ts +9 -0
- package/dist/models/refresh-token.js +2 -0
- package/dist/models/refresh-token.model.d.ts +18 -0
- package/dist/models/refresh-token.model.js +13 -0
- package/dist/models/refresh-token.spec.d.ts +1 -0
- package/dist/models/refresh-token.spec.js +12 -0
- package/dist/services/auth.service.d.ts +11 -18
- package/dist/services/auth.service.js +29 -50
- package/dist/services/generic-api-service/generic-api-service.interface.d.ts +29 -0
- package/dist/services/generic-api-service/generic-api-service.interface.js +1 -0
- package/dist/services/generic-api-service/generic-api.service.d.ts +37 -0
- package/dist/services/generic-api-service/generic-api.service.js +178 -0
- package/dist/services/index.d.ts +2 -2
- package/dist/services/index.js +2 -2
- package/dist/services/multi-tenant-api.service.d.ts +9 -6
- package/dist/services/multi-tenant-api.service.js +10 -18
- package/dist/services/organization.service.d.ts +5 -5
- package/dist/services/organization.service.js +9 -6
- package/dist/services/password-reset-token.service.d.ts +3 -3
- package/dist/services/password-reset-token.service.js +5 -5
- package/dist/services/tenant-query-decorator.d.ts +1 -1
- package/dist/services/tenant-query-decorator.js +1 -1
- package/dist/services/user.service.d.ts +4 -6
- package/dist/services/user.service.js +4 -10
- package/dist/services/utils/audit-for-create.util.d.ts +2 -0
- package/dist/services/utils/audit-for-create.util.js +9 -0
- package/dist/services/utils/audit-for-update.util.d.ts +2 -0
- package/dist/services/utils/audit-for-update.util.js +7 -0
- package/dist/services/utils/strip-sender-provided-system-properties.util.d.ts +2 -0
- package/dist/services/utils/strip-sender-provided-system-properties.util.js +15 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/utils/api.utils.js +2 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -1
- package/dist/utils/sql.db.utils.d.ts +14 -0
- package/dist/utils/sql.db.utils.js +94 -0
- package/package.json +4 -2
- package/dist/services/generic-api-service.interface.d.ts +0 -27
- package/dist/services/generic-api.service.d.ts +0 -50
- package/dist/services/generic-api.service.js +0 -424
- package/dist/utils/db.utils.d.ts +0 -27
- package/dist/utils/db.utils.js +0 -318
- /package/dist/{controllers/api-controller.utils.d.ts → __tests__/test-database.interface.js} +0 -0
- /package/dist/{controllers/api-controller.utils.js → databases/models/database.interface.js} +0 -0
- /package/dist/{models/types/index.d.ts → databases/models/database.js} +0 -0
- /package/dist/{models/types/index.js → databases/mongo-db/models/no-sql-pipeline.interface.js} +0 -0
- /package/dist/{services/generic-api-service.interface.js → databases/operations/operation.js} +0 -0
|
@@ -1,70 +1,41 @@
|
|
|
1
|
-
import { ObjectId } from 'mongodb';
|
|
2
1
|
import crypto from 'crypto';
|
|
3
2
|
import jwt from 'jsonwebtoken';
|
|
3
|
+
import { getSystemUserContext } from '@loomcore/common/models';
|
|
4
4
|
import { Type } from '@sinclair/typebox';
|
|
5
|
-
import { TypeboxObjectId } from '@loomcore/common/validation';
|
|
6
5
|
import { JwtService } from '../services/jwt.service.js';
|
|
7
|
-
import { passwordUtils } from '../utils/password.utils.js';
|
|
8
|
-
import { AuthService } from '../services/auth.service.js';
|
|
9
|
-
import { GenericApiService } from '../services/generic-api.service.js';
|
|
10
6
|
import { ApiController } from '../controllers/api.controller.js';
|
|
11
|
-
import { entityUtils } from '@loomcore/common/utils';
|
|
12
7
|
import { MultiTenantApiService } from '../services/multi-tenant-api.service.js';
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
import { Join } from '../databases/operations/join.operation.js';
|
|
9
|
+
import { OrganizationService } from '../services/organization.service.js';
|
|
10
|
+
import { IdNotFoundError } from '../errors/index.js';
|
|
11
|
+
import { AuthService, GenericApiService } from '../services/index.js';
|
|
12
|
+
import { ObjectId } from 'mongodb';
|
|
13
|
+
import { testMetaOrg, testOrg, getTestUser, testUserContext } from './test-objects.js';
|
|
14
|
+
import { CategorySpec } from './models/category.model.js';
|
|
15
|
+
import { ProductSpec } from './models/product.model.js';
|
|
15
16
|
let deviceIdCookie;
|
|
16
17
|
let authService;
|
|
17
|
-
let
|
|
18
|
+
let organizationService;
|
|
18
19
|
const JWT_SECRET = 'test-secret';
|
|
19
20
|
const newUser1Email = 'one@test.com';
|
|
20
21
|
const newUser1Password = 'testone';
|
|
21
|
-
const testUserId = '67f33ed5b75090e0dda18a3c';
|
|
22
|
-
const testOrgId = '67e8e19b149f740323af93d7';
|
|
23
|
-
const testOrgName = 'Test Organization';
|
|
24
|
-
const testUserEmail = 'test@example.com';
|
|
25
|
-
const testUserEmailCaseInsensitive = 'tesT@example.com';
|
|
26
|
-
const testUserPassword = 'testPassword';
|
|
27
22
|
const constDeviceIdCookie = crypto.randomBytes(16).toString('hex');
|
|
28
|
-
const testUserContext = {
|
|
29
|
-
user: {
|
|
30
|
-
_id: testUserId,
|
|
31
|
-
email: testUserEmail,
|
|
32
|
-
_created: new Date(),
|
|
33
|
-
_createdBy: 'system',
|
|
34
|
-
_updated: new Date(),
|
|
35
|
-
_updatedBy: 'system'
|
|
36
|
-
},
|
|
37
|
-
_orgId: testOrgId
|
|
38
|
-
};
|
|
39
23
|
function initialize(database) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
organizations: db.collection('organizations'),
|
|
44
|
-
};
|
|
45
|
-
authService = new AuthService(db);
|
|
24
|
+
authService = new AuthService(database);
|
|
25
|
+
organizationService = new OrganizationService(database);
|
|
26
|
+
deviceIdCookie = constDeviceIdCookie;
|
|
46
27
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
createIndexes: "users", indexes: [{ key: { email: 1 }, name: 'email_index', unique: true, collation: { locale: 'en', strength: 1 } }]
|
|
50
|
-
});
|
|
28
|
+
function getRandomId() {
|
|
29
|
+
return new ObjectId().toString();
|
|
51
30
|
}
|
|
52
31
|
async function createMetaOrg() {
|
|
53
|
-
if (!
|
|
54
|
-
throw new Error('
|
|
32
|
+
if (!organizationService) {
|
|
33
|
+
throw new Error('OrganizationService not initialized. Call initialize() first.');
|
|
55
34
|
}
|
|
56
35
|
try {
|
|
57
|
-
const existingMetaOrg = await
|
|
36
|
+
const existingMetaOrg = await organizationService.findOne(testUserContext, { filters: { isMetaOrg: { eq: true } } });
|
|
58
37
|
if (!existingMetaOrg) {
|
|
59
|
-
const metaOrgInsertResult = await
|
|
60
|
-
_id: new ObjectId(),
|
|
61
|
-
name: 'Meta Organization',
|
|
62
|
-
isMetaOrg: true,
|
|
63
|
-
_created: new Date(),
|
|
64
|
-
_createdBy: 'system',
|
|
65
|
-
_updated: new Date(),
|
|
66
|
-
_updatedBy: 'system'
|
|
67
|
-
});
|
|
38
|
+
const metaOrgInsertResult = await organizationService.create(testUserContext, testMetaOrg);
|
|
68
39
|
}
|
|
69
40
|
}
|
|
70
41
|
catch (error) {
|
|
@@ -73,11 +44,11 @@ async function createMetaOrg() {
|
|
|
73
44
|
}
|
|
74
45
|
}
|
|
75
46
|
async function deleteMetaOrg() {
|
|
76
|
-
if (!
|
|
47
|
+
if (!organizationService) {
|
|
77
48
|
return Promise.resolve();
|
|
78
49
|
}
|
|
79
50
|
try {
|
|
80
|
-
await
|
|
51
|
+
await organizationService.deleteMany(testUserContext, { filters: { isMetaOrg: { eq: true } } });
|
|
81
52
|
}
|
|
82
53
|
catch (error) {
|
|
83
54
|
console.log('Error deleting meta org:', error);
|
|
@@ -94,51 +65,44 @@ async function setupTestUser() {
|
|
|
94
65
|
}
|
|
95
66
|
}
|
|
96
67
|
async function createTestUser() {
|
|
97
|
-
if (!
|
|
68
|
+
if (!authService || !organizationService) {
|
|
98
69
|
throw new Error('Database not initialized. Call initialize() first.');
|
|
99
70
|
}
|
|
100
71
|
try {
|
|
101
|
-
|
|
102
|
-
|
|
72
|
+
let existingOrg;
|
|
73
|
+
try {
|
|
74
|
+
existingOrg = await organizationService.getById(testUserContext, testOrg._id);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (error instanceof IdNotFoundError) {
|
|
78
|
+
existingOrg = null;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
103
84
|
if (!existingOrg) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
_updatedBy: 'system'
|
|
111
|
-
});
|
|
85
|
+
await organizationService.create(testUserContext, testOrg);
|
|
86
|
+
}
|
|
87
|
+
const systemUserContext = getSystemUserContext();
|
|
88
|
+
const createdUser = await authService.createUser(systemUserContext, getTestUser());
|
|
89
|
+
if (!createdUser) {
|
|
90
|
+
throw new Error('Failed to create test user');
|
|
112
91
|
}
|
|
113
|
-
|
|
114
|
-
_id: new ObjectId(testUserId),
|
|
115
|
-
email: testUserEmail,
|
|
116
|
-
password: hashedAndSaltedTestUserPassword,
|
|
117
|
-
_orgId: testOrgId,
|
|
118
|
-
_created: new Date(),
|
|
119
|
-
_createdBy: 'system',
|
|
120
|
-
_updated: new Date(),
|
|
121
|
-
_updatedBy: 'system'
|
|
122
|
-
};
|
|
123
|
-
const insertResult = await collections.users.insertOne(localTestUser);
|
|
124
|
-
delete localTestUser['password'];
|
|
125
|
-
testUser = { ...localTestUser, _id: localTestUser._id.toString() };
|
|
126
|
-
return localTestUser;
|
|
92
|
+
return createdUser;
|
|
127
93
|
}
|
|
128
94
|
catch (error) {
|
|
129
95
|
console.log('Error in createTestUser:', error);
|
|
130
96
|
throw error;
|
|
131
97
|
}
|
|
132
98
|
}
|
|
133
|
-
function deleteTestUser() {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
return Promise.all(promises);
|
|
99
|
+
async function deleteTestUser() {
|
|
100
|
+
await authService.deleteById(testUserContext, getTestUser()._id).catch((error) => {
|
|
101
|
+
return null;
|
|
102
|
+
});
|
|
103
|
+
await organizationService.deleteById(testUserContext, testOrg._id).catch((error) => {
|
|
104
|
+
return null;
|
|
105
|
+
});
|
|
142
106
|
}
|
|
143
107
|
async function simulateloginWithTestUser() {
|
|
144
108
|
const req = {
|
|
@@ -155,7 +119,7 @@ async function simulateloginWithTestUser() {
|
|
|
155
119
|
return res;
|
|
156
120
|
}
|
|
157
121
|
};
|
|
158
|
-
const loginResponse = await authService.attemptLogin(req, res,
|
|
122
|
+
const loginResponse = await authService.attemptLogin(req, res, getTestUser().email, getTestUser().password);
|
|
159
123
|
if (!loginResponse?.tokens?.accessToken) {
|
|
160
124
|
throw new Error('Failed to login with test user');
|
|
161
125
|
}
|
|
@@ -164,10 +128,10 @@ async function simulateloginWithTestUser() {
|
|
|
164
128
|
function getAuthToken() {
|
|
165
129
|
const payload = {
|
|
166
130
|
user: {
|
|
167
|
-
_id:
|
|
168
|
-
email:
|
|
131
|
+
_id: getTestUser()._id,
|
|
132
|
+
email: getTestUser().email
|
|
169
133
|
},
|
|
170
|
-
_orgId:
|
|
134
|
+
_orgId: testOrg._id
|
|
171
135
|
};
|
|
172
136
|
const token = JwtService.sign(payload, JWT_SECRET, { expiresIn: 3600 });
|
|
173
137
|
return `Bearer ${token}`;
|
|
@@ -175,64 +139,41 @@ function getAuthToken() {
|
|
|
175
139
|
function verifyToken(token) {
|
|
176
140
|
return JwtService.verify(token, JWT_SECRET);
|
|
177
141
|
}
|
|
178
|
-
export const CategorySchema = Type.Object({
|
|
179
|
-
_id: Type.Optional(TypeboxObjectId()),
|
|
180
|
-
name: Type.String(),
|
|
181
|
-
});
|
|
182
|
-
export const CategorySpec = entityUtils.getModelSpec(CategorySchema);
|
|
183
|
-
export const ProductSchema = Type.Object({
|
|
184
|
-
_id: Type.Optional(TypeboxObjectId()),
|
|
185
|
-
name: Type.String(),
|
|
186
|
-
description: Type.Optional(Type.String()),
|
|
187
|
-
internalNumber: Type.Optional(Type.String()),
|
|
188
|
-
categoryId: TypeboxObjectId({ title: 'Category ID' }),
|
|
189
|
-
});
|
|
190
|
-
export const ProductSpec = entityUtils.getModelSpec(ProductSchema, { isAuditable: true });
|
|
191
|
-
export const PublicProductSchema = Type.Omit(ProductSpec.fullSchema, ['internalNumber']);
|
|
192
142
|
export class CategoryService extends GenericApiService {
|
|
193
|
-
constructor(
|
|
194
|
-
super(
|
|
143
|
+
constructor(database) {
|
|
144
|
+
super(database, 'categories', 'category', CategorySpec);
|
|
195
145
|
}
|
|
196
146
|
}
|
|
197
147
|
export class CategoryController extends ApiController {
|
|
198
|
-
constructor(app,
|
|
199
|
-
const categoryService = new CategoryService(
|
|
148
|
+
constructor(app, database) {
|
|
149
|
+
const categoryService = new CategoryService(database);
|
|
200
150
|
super('categories', app, categoryService, 'category', CategorySpec);
|
|
201
151
|
}
|
|
202
152
|
}
|
|
203
153
|
export class ProductService extends GenericApiService {
|
|
204
|
-
|
|
205
|
-
|
|
154
|
+
db;
|
|
155
|
+
constructor(database) {
|
|
156
|
+
super(database, 'products', 'product', ProductSpec);
|
|
157
|
+
this.db = database;
|
|
206
158
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
from: 'categories',
|
|
212
|
-
localField: 'categoryId',
|
|
213
|
-
foreignField: '_id',
|
|
214
|
-
as: 'category'
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
$unwind: {
|
|
219
|
-
path: '$category',
|
|
220
|
-
preserveNullAndEmptyArrays: true
|
|
221
|
-
}
|
|
222
|
-
}
|
|
159
|
+
prepareQuery(userContext, queryObject, operations) {
|
|
160
|
+
const newOperations = [
|
|
161
|
+
...operations,
|
|
162
|
+
new Join('categories', 'categoryId', '_id', 'category')
|
|
223
163
|
];
|
|
164
|
+
return super.prepareQuery(userContext, queryObject, newOperations);
|
|
224
165
|
}
|
|
225
|
-
|
|
166
|
+
postprocessEntity(userContext, single) {
|
|
226
167
|
if (single && single.category) {
|
|
227
168
|
const categoryService = new CategoryService(this.db);
|
|
228
|
-
single.category = categoryService.
|
|
169
|
+
single.category = categoryService.postprocessEntity(userContext, single.category);
|
|
229
170
|
}
|
|
230
|
-
return super.
|
|
171
|
+
return super.postprocessEntity(userContext, single);
|
|
231
172
|
}
|
|
232
173
|
}
|
|
233
174
|
export class ProductsController extends ApiController {
|
|
234
|
-
constructor(app,
|
|
235
|
-
const productService = new ProductService(
|
|
175
|
+
constructor(app, database) {
|
|
176
|
+
const productService = new ProductService(database);
|
|
236
177
|
const AggregatedProductSchema = Type.Intersect([
|
|
237
178
|
ProductSpec.fullSchema,
|
|
238
179
|
Type.Partial(Type.Object({
|
|
@@ -244,38 +185,29 @@ export class ProductsController extends ApiController {
|
|
|
244
185
|
}
|
|
245
186
|
}
|
|
246
187
|
export class MultiTenantProductService extends MultiTenantApiService {
|
|
247
|
-
|
|
248
|
-
|
|
188
|
+
db;
|
|
189
|
+
constructor(database) {
|
|
190
|
+
super(database, 'products', 'product', ProductSpec);
|
|
191
|
+
this.db = database;
|
|
249
192
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
from: 'categories',
|
|
255
|
-
localField: 'categoryId',
|
|
256
|
-
foreignField: '_id',
|
|
257
|
-
as: 'category'
|
|
258
|
-
}
|
|
259
|
-
},
|
|
260
|
-
{
|
|
261
|
-
$unwind: {
|
|
262
|
-
path: '$category',
|
|
263
|
-
preserveNullAndEmptyArrays: true
|
|
264
|
-
}
|
|
265
|
-
}
|
|
193
|
+
prepareQuery(userContext, queryObject, operations) {
|
|
194
|
+
const newOperations = [
|
|
195
|
+
...operations,
|
|
196
|
+
new Join('categories', 'categoryId', '_id', 'category')
|
|
266
197
|
];
|
|
198
|
+
return super.prepareQuery(userContext, queryObject, newOperations);
|
|
267
199
|
}
|
|
268
|
-
|
|
200
|
+
postprocessEntity(userContext, single) {
|
|
269
201
|
if (single && single.category) {
|
|
270
202
|
const categoryService = new CategoryService(this.db);
|
|
271
|
-
single.category = categoryService.
|
|
203
|
+
single.category = categoryService.postprocessEntity(userContext, single.category);
|
|
272
204
|
}
|
|
273
|
-
return super.
|
|
205
|
+
return super.postprocessEntity(userContext, single);
|
|
274
206
|
}
|
|
275
207
|
}
|
|
276
208
|
export class MultiTenantProductsController extends ApiController {
|
|
277
|
-
constructor(app,
|
|
278
|
-
const productService = new MultiTenantProductService(
|
|
209
|
+
constructor(app, database) {
|
|
210
|
+
const productService = new MultiTenantProductService(database);
|
|
279
211
|
const AggregatedProductSchema = Type.Intersect([
|
|
280
212
|
ProductSpec.fullSchema,
|
|
281
213
|
Type.Partial(Type.Object({
|
|
@@ -286,9 +218,6 @@ export class MultiTenantProductsController extends ApiController {
|
|
|
286
218
|
super('multi-tenant-products', app, productService, 'product', ProductSpec, PublicAggregatedProductSchema);
|
|
287
219
|
}
|
|
288
220
|
}
|
|
289
|
-
function getTestUser() {
|
|
290
|
-
return testUser;
|
|
291
|
-
}
|
|
292
221
|
function configureJwtSecret() {
|
|
293
222
|
const originalJwtVerify = jwt.verify;
|
|
294
223
|
jwt.verify = function (token, secret, options) {
|
|
@@ -297,11 +226,12 @@ function configureJwtSecret() {
|
|
|
297
226
|
}
|
|
298
227
|
async function loginWithTestUser(agent) {
|
|
299
228
|
agent.set('Cookie', [`deviceId=${deviceIdCookie}`]);
|
|
229
|
+
const testUser = getTestUser();
|
|
300
230
|
const response = await agent
|
|
301
231
|
.post('/api/auth/login')
|
|
302
232
|
.send({
|
|
303
|
-
email:
|
|
304
|
-
password:
|
|
233
|
+
email: testUser.email,
|
|
234
|
+
password: testUser.password,
|
|
305
235
|
});
|
|
306
236
|
if (!response.body?.data?.tokens?.accessToken) {
|
|
307
237
|
console.error('Login failed:', response.body);
|
|
@@ -320,28 +250,20 @@ async function cleanup() {
|
|
|
320
250
|
}
|
|
321
251
|
}
|
|
322
252
|
const testUtils = {
|
|
253
|
+
getRandomId,
|
|
323
254
|
cleanup,
|
|
324
255
|
configureJwtSecret,
|
|
325
256
|
constDeviceIdCookie,
|
|
326
|
-
createIndexes,
|
|
327
257
|
createMetaOrg,
|
|
328
258
|
deleteMetaOrg,
|
|
329
259
|
deleteTestUser,
|
|
330
260
|
getAuthToken,
|
|
331
|
-
getTestUser,
|
|
332
261
|
initialize,
|
|
333
262
|
loginWithTestUser,
|
|
334
263
|
newUser1Email,
|
|
335
264
|
newUser1Password,
|
|
336
265
|
setupTestUser,
|
|
337
266
|
simulateloginWithTestUser,
|
|
338
|
-
testUserContext,
|
|
339
|
-
testUserId,
|
|
340
|
-
testUserEmail,
|
|
341
|
-
testUserEmailCaseInsensitive,
|
|
342
|
-
testUserPassword,
|
|
343
|
-
testOrgId,
|
|
344
|
-
testOrgName,
|
|
345
267
|
verifyToken
|
|
346
268
|
};
|
|
347
269
|
export default testUtils;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './postgres-test-migrations/001-create-test-entities-table.migration.js';
|
|
2
|
+
export * from './models/test-entity.model.js';
|
|
3
|
+
export * from './postgres.test-database.js';
|
|
4
|
+
export * from './mongo-db.test-database.js';
|
|
5
|
+
export * from './test-express-app.js';
|
|
6
|
+
export * from './test-database.interface.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './postgres-test-migrations/001-create-test-entities-table.migration.js';
|
|
2
|
+
export * from './models/test-entity.model.js';
|
|
3
|
+
export * from './postgres.test-database.js';
|
|
4
|
+
export * from './mongo-db.test-database.js';
|
|
5
|
+
export * from './test-express-app.js';
|
|
6
|
+
export * from './test-database.interface.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IEntity } from "@loomcore/common/models";
|
|
2
|
+
export interface ICategory extends IEntity {
|
|
3
|
+
name: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const CategorySchema: import("@sinclair/typebox").TObject<{
|
|
6
|
+
name: import("@sinclair/typebox").TString;
|
|
7
|
+
}>;
|
|
8
|
+
export declare const CategorySpec: import("@loomcore/common/models").IModelSpec<import("@sinclair/typebox").TSchema>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IAuditable, IEntity, IModelSpec } from "@loomcore/common/models";
|
|
2
|
+
import { TSchema } from "@sinclair/typebox";
|
|
3
|
+
export declare const MongoTestEntitySchema: TSchema;
|
|
4
|
+
export interface MongoTestEntity extends IEntity, IAuditable {
|
|
5
|
+
name: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
isActive?: boolean;
|
|
8
|
+
tags?: string[];
|
|
9
|
+
count?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare const mongoTestEntityModelSpec: IModelSpec;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { entityUtils } from "@loomcore/common/utils";
|
|
2
|
+
import { TypeboxObjectId } from "@loomcore/common/validation";
|
|
3
|
+
import { Type } from "@sinclair/typebox";
|
|
4
|
+
export const MongoTestEntitySchema = Type.Object({
|
|
5
|
+
_id: TypeboxObjectId(),
|
|
6
|
+
_orgId: Type.Optional(TypeboxObjectId()),
|
|
7
|
+
name: Type.String({ minLength: 1 }),
|
|
8
|
+
description: Type.Optional(Type.String()),
|
|
9
|
+
isActive: Type.Optional(Type.Boolean()),
|
|
10
|
+
tags: Type.Optional(Type.Array(Type.String())),
|
|
11
|
+
count: Type.Optional(Type.Number())
|
|
12
|
+
});
|
|
13
|
+
export const mongoTestEntityModelSpec = entityUtils.getModelSpec(MongoTestEntitySchema, { isAuditable: true });
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { IAuditable, IEntity } from "@loomcore/common/models";
|
|
2
|
+
import { ICategory } from "./category.model.js";
|
|
3
|
+
export interface IProduct extends IEntity, IAuditable {
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
internalNumber?: string;
|
|
7
|
+
categoryId: string;
|
|
8
|
+
category?: ICategory;
|
|
9
|
+
}
|
|
10
|
+
export declare const ProductSchema: import("@sinclair/typebox").TObject<{
|
|
11
|
+
name: import("@sinclair/typebox").TString;
|
|
12
|
+
description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
13
|
+
internalNumber: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
14
|
+
categoryId: import("@sinclair/typebox").TString;
|
|
15
|
+
}>;
|
|
16
|
+
export declare const ProductSpec: import("@loomcore/common/models").IModelSpec<import("@sinclair/typebox").TSchema>;
|
|
17
|
+
export declare const PublicProductSchema: import("@sinclair/typebox").TObject<{}>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { entityUtils } from "@loomcore/common/utils";
|
|
2
|
+
import { Type } from "@sinclair/typebox";
|
|
3
|
+
export const ProductSchema = Type.Object({
|
|
4
|
+
name: Type.String(),
|
|
5
|
+
description: Type.Optional(Type.String()),
|
|
6
|
+
internalNumber: Type.Optional(Type.String()),
|
|
7
|
+
categoryId: Type.String({ title: 'Category ID' }),
|
|
8
|
+
});
|
|
9
|
+
export const ProductSpec = entityUtils.getModelSpec(ProductSchema, { isAuditable: true });
|
|
10
|
+
export const PublicProductSchema = Type.Omit(ProductSpec.fullSchema, ['internalNumber']);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IAuditable, IEntity, IModelSpec } from "@loomcore/common/models";
|
|
2
|
+
import { TSchema } from "@sinclair/typebox";
|
|
3
|
+
export declare const TestEntitySchema: TSchema;
|
|
4
|
+
export interface TestEntity extends IEntity, IAuditable {
|
|
5
|
+
name: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
isActive?: boolean;
|
|
8
|
+
tags?: string[];
|
|
9
|
+
count?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare const testModelSpec: IModelSpec;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { entityUtils } from "@loomcore/common/utils";
|
|
2
|
+
import { Type } from "@sinclair/typebox";
|
|
3
|
+
export const TestEntitySchema = Type.Object({
|
|
4
|
+
name: Type.String({ minLength: 1 }),
|
|
5
|
+
description: Type.Optional(Type.String()),
|
|
6
|
+
isActive: Type.Optional(Type.Boolean()),
|
|
7
|
+
tags: Type.Optional(Type.Array(Type.String())),
|
|
8
|
+
count: Type.Optional(Type.Number())
|
|
9
|
+
});
|
|
10
|
+
export const testModelSpec = entityUtils.getModelSpec(TestEntitySchema, { isAuditable: true });
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IAuditable, IEntity } from "@loomcore/common/models";
|
|
2
|
+
export interface ITestItem extends IEntity, IAuditable {
|
|
3
|
+
name: string;
|
|
4
|
+
value?: number;
|
|
5
|
+
eventDate?: Date;
|
|
6
|
+
}
|
|
7
|
+
export declare const TestItemSchema: import("@sinclair/typebox").TObject<{
|
|
8
|
+
name: import("@sinclair/typebox").TString;
|
|
9
|
+
value: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
10
|
+
eventDate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TTransform<import("@sinclair/typebox").TString, Date>, import("@sinclair/typebox").TUndefined]>>;
|
|
11
|
+
}>;
|
|
12
|
+
export declare const TestItemSpec: import("@loomcore/common/models").IModelSpec<import("@sinclair/typebox").TSchema>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { entityUtils } from "@loomcore/common/utils";
|
|
2
|
+
import { TypeboxIsoDate } from "@loomcore/common/validation";
|
|
3
|
+
import { Type } from "@sinclair/typebox";
|
|
4
|
+
export const TestItemSchema = Type.Object({
|
|
5
|
+
name: Type.String(),
|
|
6
|
+
value: Type.Optional(Type.Number()),
|
|
7
|
+
eventDate: Type.Optional(TypeboxIsoDate())
|
|
8
|
+
});
|
|
9
|
+
export const TestItemSpec = entityUtils.getModelSpec(TestItemSchema, { isAuditable: true });
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ITestDatabase } from './test-database.interface.js';
|
|
2
|
+
import { IDatabase } from '../databases/models/index.js';
|
|
3
|
+
export declare class TestMongoDatabase implements ITestDatabase {
|
|
4
|
+
private mongoServer;
|
|
5
|
+
private mongoClient;
|
|
6
|
+
private mongoDb;
|
|
7
|
+
private database;
|
|
8
|
+
private initPromise;
|
|
9
|
+
init(databaseName: string): Promise<IDatabase>;
|
|
10
|
+
getRandomId(): string;
|
|
11
|
+
private _performInit;
|
|
12
|
+
private createIndexes;
|
|
13
|
+
clearCollections(): Promise<void>;
|
|
14
|
+
cleanup(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { MongoMemoryServer } from 'mongodb-memory-server';
|
|
2
|
+
import { MongoClient, ObjectId } from 'mongodb';
|
|
3
|
+
import testUtils from './common-test.utils.js';
|
|
4
|
+
import { initSystemUserContext } from '../config/base-api-config.js';
|
|
5
|
+
import { MongoDBDatabase } from '../databases/index.js';
|
|
6
|
+
export class TestMongoDatabase {
|
|
7
|
+
mongoServer = null;
|
|
8
|
+
mongoClient = null;
|
|
9
|
+
mongoDb = null;
|
|
10
|
+
database = null;
|
|
11
|
+
initPromise = null;
|
|
12
|
+
async init(databaseName) {
|
|
13
|
+
if (this.initPromise) {
|
|
14
|
+
return this.initPromise;
|
|
15
|
+
}
|
|
16
|
+
this.initPromise = this._performInit(databaseName);
|
|
17
|
+
return this.initPromise;
|
|
18
|
+
}
|
|
19
|
+
getRandomId() {
|
|
20
|
+
return new ObjectId().toString();
|
|
21
|
+
}
|
|
22
|
+
async _performInit(databaseName) {
|
|
23
|
+
if (!this.database) {
|
|
24
|
+
this.mongoServer = await MongoMemoryServer.create({
|
|
25
|
+
instance: {
|
|
26
|
+
ip: '127.0.0.1',
|
|
27
|
+
port: 0,
|
|
28
|
+
},
|
|
29
|
+
binary: {
|
|
30
|
+
downloadDir: process.env.HOME ? `${process.env.HOME}/.cache/mongodb-binaries` : undefined,
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
const uri = this.mongoServer.getUri();
|
|
34
|
+
this.mongoClient = await MongoClient.connect(uri);
|
|
35
|
+
this.mongoDb = this.mongoClient.db();
|
|
36
|
+
const testDatabase = new MongoDBDatabase(this.mongoDb);
|
|
37
|
+
this.database = testDatabase;
|
|
38
|
+
testUtils.initialize(testDatabase);
|
|
39
|
+
await this.createIndexes(this.mongoDb);
|
|
40
|
+
await testUtils.createMetaOrg();
|
|
41
|
+
}
|
|
42
|
+
await initSystemUserContext(this.database);
|
|
43
|
+
return this.database;
|
|
44
|
+
}
|
|
45
|
+
async createIndexes(db) {
|
|
46
|
+
await db.command({
|
|
47
|
+
createIndexes: "users", indexes: [{ key: { email: 1 }, name: 'email_index', unique: true, collation: { locale: 'en', strength: 1 } }]
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async clearCollections() {
|
|
51
|
+
if (!this.mongoDb) {
|
|
52
|
+
throw new Error('Database not initialized');
|
|
53
|
+
}
|
|
54
|
+
const collections = await this.mongoDb.collections();
|
|
55
|
+
for (const collection of collections) {
|
|
56
|
+
await collection.deleteMany({});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async cleanup() {
|
|
60
|
+
await testUtils.cleanup();
|
|
61
|
+
await this.clearCollections();
|
|
62
|
+
if (this.mongoClient) {
|
|
63
|
+
await this.mongoClient.close();
|
|
64
|
+
}
|
|
65
|
+
if (this.mongoServer) {
|
|
66
|
+
await this.mongoServer.stop();
|
|
67
|
+
}
|
|
68
|
+
this.initPromise = null;
|
|
69
|
+
this.mongoDb = null;
|
|
70
|
+
this.database = null;
|
|
71
|
+
this.mongoClient = null;
|
|
72
|
+
this.mongoServer = null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Client } from "pg";
|
|
2
|
+
import { IMigration } from "../../databases/postgres/migrations/migration.interface.js";
|
|
3
|
+
export declare class CreateTestEntitiesTableMigration 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
|
+
}
|