@loomcore/api 0.2.4 → 0.2.6

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 (39) hide show
  1. package/dist/__tests__/common-test.utils.d.ts +12 -12
  2. package/dist/__tests__/common-test.utils.js +94 -101
  3. package/dist/__tests__/postgres.test-database.d.ts +2 -2
  4. package/dist/__tests__/postgres.test-database.js +16 -15
  5. package/dist/__tests__/test-objects.d.ts +1 -6
  6. package/dist/__tests__/test-objects.js +34 -73
  7. package/dist/config/base-api-config.d.ts +2 -2
  8. package/dist/config/base-api-config.js +17 -10
  9. package/dist/controllers/auth.controller.d.ts +3 -5
  10. package/dist/controllers/auth.controller.js +22 -26
  11. package/dist/controllers/index.d.ts +10 -11
  12. package/dist/controllers/index.js +10 -11
  13. package/dist/databases/mongo-db/migrations/mongo-initial-schema.d.ts +2 -2
  14. package/dist/databases/mongo-db/migrations/mongo-initial-schema.js +185 -128
  15. package/dist/services/auth.service.d.ts +8 -9
  16. package/dist/services/auth.service.js +66 -82
  17. package/dist/services/email.service.js +5 -5
  18. package/dist/services/jwt.service.js +2 -2
  19. package/dist/services/multi-tenant-api.service.d.ts +4 -4
  20. package/dist/services/multi-tenant-api.service.js +8 -8
  21. package/dist/services/organization.service.d.ts +4 -4
  22. package/dist/services/organization.service.js +12 -8
  23. package/dist/services/password-reset-token.service.d.ts +4 -4
  24. package/dist/services/password-reset-token.service.js +13 -9
  25. package/dist/services/tenant-query-decorator.d.ts +1 -1
  26. package/dist/services/tenant-query-decorator.js +17 -11
  27. package/dist/services/user.service.d.ts +6 -6
  28. package/dist/services/user.service.js +7 -7
  29. package/dist/services/utils/audit-for-create.util.d.ts +1 -1
  30. package/dist/services/utils/audit-for-update.util.d.ts +1 -1
  31. package/dist/services/utils/audit-for-update.util.js +0 -1
  32. package/dist/services/utils/getUserContextAuthorizations.util.d.ts +2 -2
  33. package/dist/services/utils/strip-sender-provided-system-properties.util.d.ts +1 -1
  34. package/dist/services/utils/strip-sender-provided-system-properties.util.js +5 -3
  35. package/package.json +5 -2
  36. package/dist/controllers/persons.controller.d.ts +0 -8
  37. package/dist/controllers/persons.controller.js +0 -18
  38. package/dist/services/person.service.d.ts +0 -6
  39. package/dist/services/person.service.js +0 -7
@@ -1,19 +1,19 @@
1
- import { Request, Response, Application, NextFunction } from 'express';
2
- import { IUserContext, IQueryOptions, IUser } from '@loomcore/common/models';
3
- import { ApiController } from '../controllers/api.controller.js';
4
- import { MultiTenantApiService } from '../services/multi-tenant-api.service.js';
5
- import { Operation } from '../databases/operations/operation.js';
6
- import { GenericApiService } from '../services/index.js';
7
- import { IDatabase } from '../databases/models/index.js';
8
- import { ICategory } from './models/category.model.js';
9
- import { IProduct } from './models/product.model.js';
10
- import { IProductWithCategory } from './models/product-with-category.model.js';
11
- import { DbType } from '../databases/db-type.type.js';
1
+ import { IQueryOptions, IUser, IUserContext } from "@loomcore/common/models";
2
+ import { Application, NextFunction, Request, Response } from "express";
3
+ import { ApiController } from "../controllers/api.controller.js";
4
+ import { IDatabase } from "../databases/models/index.js";
5
+ import { Operation } from "../databases/operations/operation.js";
6
+ import { GenericApiService } from "../services/index.js";
7
+ import { MultiTenantApiService } from "../services/multi-tenant-api.service.js";
8
+ import type { DbType } from "../databases/db-type.type.js";
9
+ import { type ICategory } from "./models/category.model.js";
10
+ import { type IProduct } from "./models/product.model.js";
11
+ import { type IProductWithCategory } from "./models/product-with-category.model.js";
12
12
  declare function initialize(database: IDatabase): void;
13
13
  declare function getRandomId(): string;
14
14
  declare function isMongoDatabase(database: IDatabase): boolean;
15
15
  declare function isPostgresDatabase(database: IDatabase): boolean;
16
- declare function getExpectedIdType(database: IDatabase): 'string' | 'number';
16
+ declare function getExpectedIdType(database: IDatabase): "string" | "number";
17
17
  declare function createMetaOrg(): Promise<void>;
18
18
  declare function deleteMetaOrg(): Promise<void>;
19
19
  declare function setupTestUsers(): Promise<{
@@ -1,39 +1,36 @@
1
- import crypto from 'crypto';
2
- import jwt from 'jsonwebtoken';
3
- import { EmptyUserContext } from '@loomcore/common/models';
4
- import { Type } from '@sinclair/typebox';
5
- import { Value } from '@sinclair/typebox/value';
6
- import { JwtService } from '../services/jwt.service.js';
7
- import { ApiController } from '../controllers/api.controller.js';
8
- import { MultiTenantApiService } from '../services/multi-tenant-api.service.js';
9
- import { LeftJoin } from '../databases/operations/left-join.operation.js';
10
- import { OrganizationService } from '../services/organization.service.js';
11
- import { AuthService, GenericApiService } from '../services/index.js';
12
- import { ObjectId } from 'mongodb';
13
- import { MongoDBDatabase } from '../databases/mongo-db/mongo-db.database.js';
14
- import { PostgresDatabase } from '../databases/postgres/postgres.database.js';
15
- import * as testObjectsModule from './test-objects.js';
16
- const { getTestMetaOrg, getTestOrg, getTestMetaOrgUser, getTestMetaOrgUserContext, getTestOrgUserContext, setTestOrgId, setTestMetaOrgId, setTestMetaOrgUserId, setTestOrgUserId } = testObjectsModule;
17
- import { CategorySpec } from './models/category.model.js';
18
- import { ProductSpec } from './models/product.model.js';
19
- import { ProductWithCategoryPublicSpec, ProductWithCategorySpec } from './models/product-with-category.model.js';
20
- import { setBaseApiConfig, config } from '../config/index.js';
21
- import { entityUtils } from '@loomcore/common/utils';
22
- import { getTestMetaOrgUserPerson, getTestOrgUser, getTestOrgUserPerson, setTestMetaOrgUserPersonId, setTestOrgUserPersonId } from './test-objects.js';
23
- import { TestEmailClient } from './test-email-client.js';
24
- import { PersonService } from '../services/person.service.js';
25
- import { apiUtils } from '../utils/index.js';
1
+ import { EmptyUserContext, } from "@loomcore/common/models";
2
+ import { Type } from "@sinclair/typebox";
3
+ import { Value } from "@sinclair/typebox/value";
4
+ import crypto from "crypto";
5
+ import jwt from "jsonwebtoken";
6
+ import { ObjectId } from "mongodb";
7
+ import { ApiController } from "../controllers/api.controller.js";
8
+ import { MongoDBDatabase } from "../databases/mongo-db/mongo-db.database.js";
9
+ import { LeftJoin } from "../databases/operations/left-join.operation.js";
10
+ import { PostgresDatabase } from "../databases/postgres/postgres.database.js";
11
+ import { AuthService, GenericApiService } from "../services/index.js";
12
+ import { JwtService } from "../services/jwt.service.js";
13
+ import { MultiTenantApiService } from "../services/multi-tenant-api.service.js";
14
+ import { OrganizationService } from "../services/organization.service.js";
15
+ import * as testObjectsModule from "./test-objects.js";
16
+ const { getTestMetaOrg, getTestOrg, getTestMetaOrgUser, getTestMetaOrgUserContext, getTestOrgUserContext, setTestOrgId, setTestMetaOrgId, setTestMetaOrgUserId, setTestOrgUserId, } = testObjectsModule;
17
+ import { entityUtils } from "@loomcore/common/utils";
18
+ import { config, setBaseApiConfig } from "../config/index.js";
19
+ import { apiUtils } from "../utils/index.js";
20
+ import { CategorySpec } from "./models/category.model.js";
21
+ import { ProductSpec } from "./models/product.model.js";
22
+ import { ProductWithCategoryPublicSpec, ProductWithCategorySpec, } from "./models/product-with-category.model.js";
23
+ import { TestEmailClient } from "./test-email-client.js";
24
+ import { getTestOrgUser } from "./test-objects.js";
26
25
  let deviceIdCookie;
27
26
  let authService;
28
27
  let organizationService;
29
- let personService;
30
- const JWT_SECRET = 'test-secret';
31
- const newUser1Email = 'one@test.com';
32
- const newUser1Password = 'testone';
33
- const constDeviceIdCookie = crypto.randomBytes(16).toString('hex');
28
+ const JWT_SECRET = "test-secret";
29
+ const newUser1Email = "one@test.com";
30
+ const newUser1Password = "testone";
31
+ const constDeviceIdCookie = crypto.randomBytes(16).toString("hex");
34
32
  function initialize(database) {
35
33
  authService = new AuthService(database);
36
- personService = new PersonService(database);
37
34
  organizationService = new OrganizationService(database);
38
35
  deviceIdCookie = constDeviceIdCookie;
39
36
  }
@@ -47,14 +44,14 @@ function isPostgresDatabase(database) {
47
44
  return database instanceof PostgresDatabase;
48
45
  }
49
46
  function getExpectedIdType(database) {
50
- return isPostgresDatabase(database) ? 'number' : 'string';
47
+ return isPostgresDatabase(database) ? "number" : "string";
51
48
  }
52
49
  async function createMetaOrg() {
53
50
  if (!config.app.isMultiTenant) {
54
51
  return;
55
52
  }
56
53
  if (!organizationService) {
57
- throw new Error('OrganizationService not initialized. Call initialize() first.');
54
+ throw new Error("OrganizationService not initialized. Call initialize() first.");
58
55
  }
59
56
  try {
60
57
  const existingMetaOrg = await organizationService.getMetaOrg(EmptyUserContext);
@@ -69,7 +66,7 @@ async function createMetaOrg() {
69
66
  }
70
67
  }
71
68
  catch (error) {
72
- console.log('Error in createMetaOrg:', error);
69
+ console.log("Error in createMetaOrg:", error);
73
70
  throw error;
74
71
  }
75
72
  }
@@ -78,10 +75,12 @@ async function deleteMetaOrg() {
78
75
  return Promise.resolve();
79
76
  }
80
77
  try {
81
- await organizationService.deleteMany(getTestMetaOrgUserContext(), { filters: { isMetaOrg: { eq: true } } });
78
+ await organizationService.deleteMany(getTestMetaOrgUserContext(), {
79
+ filters: { isMetaOrg: { eq: true } },
80
+ });
82
81
  }
83
82
  catch (error) {
84
- console.log('Error deleting meta org:', error);
83
+ console.log("Error deleting meta org:", error);
85
84
  }
86
85
  }
87
86
  async function setupTestUsers() {
@@ -96,47 +95,37 @@ async function setupTestUsers() {
96
95
  }
97
96
  }
98
97
  async function createTestUsers() {
99
- if (!authService || !organizationService || !personService) {
100
- throw new Error('Database not initialized. Call initialize() first.');
98
+ if (!authService || !organizationService) {
99
+ throw new Error("Database not initialized. Call initialize() first.");
101
100
  }
102
101
  try {
103
102
  const existingMetaOrg = await organizationService.getMetaOrg(EmptyUserContext);
104
103
  if (!existingMetaOrg) {
105
- throw new Error('Meta organization does not exist. Test setup is incorrect - meta org should be created by migrations or createMetaOrg().');
104
+ throw new Error("Meta organization does not exist. Test setup is incorrect - meta org should be created by migrations or createMetaOrg().");
106
105
  }
107
106
  setTestMetaOrgId(existingMetaOrg._id);
108
107
  const existingTestOrg = await organizationService.findOne(getTestMetaOrgUserContext(), { filters: { _id: { eq: getTestOrg()._id } } });
109
108
  if (!existingTestOrg) {
110
109
  const createdTestOrg = await organizationService.create(getTestMetaOrgUserContext(), getTestOrg());
111
110
  if (!createdTestOrg) {
112
- throw new Error('Failed to create test organization');
111
+ throw new Error("Failed to create test organization");
113
112
  }
114
113
  setTestOrgId(createdTestOrg._id);
115
114
  }
116
115
  else {
117
116
  setTestOrgId(existingTestOrg._id);
118
117
  }
119
- const createdTestOrgUserPerson = await personService.create(getTestOrgUserContext(), getTestOrgUserPerson());
120
- if (!createdTestOrgUserPerson) {
121
- throw new Error('Failed to create test organization user person');
122
- }
123
- setTestOrgUserPersonId(createdTestOrgUserPerson._id);
124
- const createdMetaOrgUserPerson = await personService.create(getTestMetaOrgUserContext(), getTestMetaOrgUserPerson());
125
- if (!createdMetaOrgUserPerson) {
126
- throw new Error('Failed to create meta organization user person');
127
- }
128
- setTestMetaOrgUserPersonId(createdMetaOrgUserPerson._id);
129
118
  const createdTestOrgUser = await authService.createUser(getTestOrgUserContext(), getTestOrgUser());
130
119
  const createdMetaOrgUser = await authService.createUser(getTestMetaOrgUserContext(), getTestMetaOrgUser());
131
120
  if (!createdTestOrgUser || !createdMetaOrgUser) {
132
- throw new Error('Failed to create test user');
121
+ throw new Error("Failed to create test user");
133
122
  }
134
123
  setTestMetaOrgUserId(createdMetaOrgUser._id);
135
124
  setTestOrgUserId(createdTestOrgUser._id);
136
125
  return { metaOrgUser: createdMetaOrgUser, testOrgUser: createdTestOrgUser };
137
126
  }
138
127
  catch (error) {
139
- console.log('Error in createTestUser:', error);
128
+ console.log("Error in createTestUser:", error);
140
129
  throw error;
141
130
  }
142
131
  }
@@ -144,34 +133,38 @@ async function deleteTestUser() {
144
133
  if (!authService || !organizationService) {
145
134
  return;
146
135
  }
147
- await authService.deleteById(getTestMetaOrgUserContext(), getTestMetaOrgUser()._id).catch((error) => {
136
+ await authService
137
+ .deleteById(getTestMetaOrgUserContext(), getTestMetaOrgUser()._id)
138
+ .catch((error) => {
148
139
  return null;
149
140
  });
150
- await organizationService.deleteById(getTestMetaOrgUserContext(), getTestOrg()._id).catch((error) => {
141
+ await organizationService
142
+ .deleteById(getTestMetaOrgUserContext(), getTestOrg()._id)
143
+ .catch((error) => {
151
144
  return null;
152
145
  });
153
146
  }
154
147
  async function simulateloginWithTestUser() {
155
148
  const req = {
156
- cookies: {}
149
+ cookies: {},
157
150
  };
158
151
  if (deviceIdCookie) {
159
- req.cookies['deviceId'] = deviceIdCookie;
152
+ req.cookies["deviceId"] = deviceIdCookie;
160
153
  }
161
154
  const res = {
162
155
  cookie: function (name, value) {
163
- if (name === 'deviceId') {
156
+ if (name === "deviceId") {
164
157
  deviceIdCookie = value;
165
158
  }
166
159
  return res;
167
- }
160
+ },
168
161
  };
169
162
  if (!authService) {
170
- throw new Error('AuthService not initialized. Call initialize() first.');
163
+ throw new Error("AuthService not initialized. Call initialize() first.");
171
164
  }
172
165
  const loginResponse = await authService.attemptLogin(req, res, getTestMetaOrgUser().email, testObjectsModule.TEST_META_ORG_USER_PASSWORD);
173
166
  if (!loginResponse?.tokens?.accessToken) {
174
- throw new Error('Failed to login with test user');
167
+ throw new Error("Failed to login with test user");
175
168
  }
176
169
  return `Bearer ${loginResponse.tokens.accessToken}`;
177
170
  }
@@ -185,13 +178,13 @@ function verifyToken(token) {
185
178
  }
186
179
  export class CategoryService extends GenericApiService {
187
180
  constructor(database) {
188
- super(database, 'categories', 'category', CategorySpec);
181
+ super(database, "categories", "category", CategorySpec);
189
182
  }
190
183
  }
191
184
  export class CategoryController extends ApiController {
192
185
  constructor(app, database) {
193
186
  const categoryService = new CategoryService(database);
194
- super('categories', app, categoryService, 'category', CategorySpec);
187
+ super("categories", app, categoryService, "category", CategorySpec);
195
188
  }
196
189
  }
197
190
  export function setupTestConfig(isMultiTenant = true, dbType) {
@@ -199,37 +192,37 @@ export function setupTestConfig(isMultiTenant = true, dbType) {
199
192
  app: {
200
193
  isMultiTenant: isMultiTenant,
201
194
  isAuthEnabled: true,
202
- name: 'test-app',
195
+ name: "test-app",
203
196
  dbType: dbType,
204
197
  },
205
198
  auth: {
206
- clientSecret: 'test-secret',
199
+ clientSecret: "test-secret",
207
200
  saltWorkFactor: 10,
208
201
  jwtExpirationInSeconds: 3600,
209
202
  refreshTokenExpirationInDays: 7,
210
203
  deviceIdCookieMaxAgeInDays: 730,
211
- passwordResetTokenExpirationInMinutes: 20
204
+ passwordResetTokenExpirationInMinutes: 20,
212
205
  },
213
206
  database: {
214
- name: 'test-db',
215
- host: 'localhost',
216
- password: 'test-password',
207
+ name: "test-db",
208
+ host: "localhost",
209
+ password: "test-password",
217
210
  port: 27017,
218
- username: 'test-user'
211
+ username: "test-user",
219
212
  },
220
- env: 'test',
213
+ env: "test",
221
214
  email: {
222
- fromAddress: 'test@test.com',
223
- systemEmailAddress: 'system@test.com'
215
+ fromAddress: "test@test.com",
216
+ systemEmailAddress: "system@test.com",
224
217
  },
225
218
  thirdPartyClients: {
226
- emailClient: new TestEmailClient()
219
+ emailClient: new TestEmailClient(),
227
220
  },
228
221
  network: {
229
- hostName: 'localhost',
222
+ hostName: "localhost",
230
223
  internalPort: 8083,
231
224
  externalPort: 4000,
232
- corsAllowedOrigins: ['*']
225
+ corsAllowedOrigins: ["*"],
233
226
  },
234
227
  });
235
228
  }
@@ -238,54 +231,54 @@ const prepareQueryCustom = (userContext, queryObject, operations) => {
238
231
  queryObject: queryObject,
239
232
  operations: [
240
233
  ...operations,
241
- new LeftJoin('categories', 'category_id', '_id', 'category')
242
- ]
234
+ new LeftJoin("categories", "category_id", "_id", "category"),
235
+ ],
243
236
  };
244
237
  };
245
238
  const postProcessEntityCustom = (userContext, entity) => {
246
239
  return {
247
240
  ...entity,
248
- category: entity._joinData?.category
241
+ category: entity._joinData?.category,
249
242
  };
250
243
  };
251
244
  export class ProductService extends GenericApiService {
252
245
  constructor(database) {
253
- super(database, 'products', 'product', ProductSpec);
246
+ super(database, "products", "product", ProductSpec);
254
247
  }
255
248
  }
256
249
  export class ProductsController extends ApiController {
257
250
  constructor(app, database) {
258
251
  const productService = new ProductService(database);
259
- super('products', app, productService, 'product', ProductSpec);
252
+ super("products", app, productService, "product", ProductSpec);
260
253
  }
261
254
  async get(req, res, next) {
262
- res.set('Content-Type', 'application/json');
255
+ res.set("Content-Type", "application/json");
263
256
  const userContext = req.userContext;
264
257
  if (!userContext) {
265
- throw new Error('User context not found');
258
+ throw new Error("User context not found");
266
259
  }
267
260
  const queryOptions = apiUtils.getQueryOptionsFromRequest(req);
268
261
  const pagedResult = await this.service.get(userContext, queryOptions, prepareQueryCustom, postProcessEntityCustom);
269
262
  apiUtils.apiResponse(res, 200, { data: pagedResult }, ProductWithCategorySpec, ProductWithCategoryPublicSpec);
270
263
  }
271
264
  async getAll(req, res, next) {
272
- res.set('Content-Type', 'application/json');
265
+ res.set("Content-Type", "application/json");
273
266
  const userContext = req.userContext;
274
267
  if (!userContext) {
275
- throw new Error('User context not found');
268
+ throw new Error("User context not found");
276
269
  }
277
270
  const entities = await this.service.getAll(userContext, prepareQueryCustom, postProcessEntityCustom);
278
271
  apiUtils.apiResponse(res, 200, { data: entities }, ProductWithCategorySpec, ProductWithCategoryPublicSpec);
279
272
  }
280
273
  async getById(req, res, next) {
281
- res.set('Content-Type', 'application/json');
274
+ res.set("Content-Type", "application/json");
282
275
  const userContext = req.userContext;
283
276
  if (!userContext) {
284
- throw new Error('User context not found');
277
+ throw new Error("User context not found");
285
278
  }
286
279
  const idParam = req.params?.id;
287
280
  if (!idParam) {
288
- throw new Error('ID parameter is required');
281
+ throw new Error("ID parameter is required");
289
282
  }
290
283
  try {
291
284
  const id = Value.Convert(this.idSchema, idParam);
@@ -300,13 +293,13 @@ export class ProductsController extends ApiController {
300
293
  export class MultiTenantProductService extends MultiTenantApiService {
301
294
  db;
302
295
  constructor(database) {
303
- super(database, 'products', 'product', ProductSpec);
296
+ super(database, "products", "product", ProductSpec);
304
297
  this.db = database;
305
298
  }
306
299
  prepareQuery(userContext, queryObject, operations) {
307
300
  const newOperations = [
308
301
  ...operations,
309
- new LeftJoin('categories', 'categoryId', '_id', 'category')
302
+ new LeftJoin("categories", "categoryId", "_id", "category"),
310
303
  ];
311
304
  return super.prepareQuery(userContext, queryObject, newOperations);
312
305
  }
@@ -324,12 +317,14 @@ export class MultiTenantProductsController extends ApiController {
324
317
  const AggregatedProductSchema = Type.Intersect([
325
318
  ProductSpec.fullSchema,
326
319
  Type.Partial(Type.Object({
327
- category: CategorySpec.fullSchema
328
- }))
320
+ category: CategorySpec.fullSchema,
321
+ })),
322
+ ]);
323
+ const PublicAggregatedProductSchema = Type.Omit(AggregatedProductSchema, [
324
+ "internalNumber",
329
325
  ]);
330
- const PublicAggregatedProductSchema = Type.Omit(AggregatedProductSchema, ['internalNumber']);
331
326
  const PublicAggregatedProductSpec = entityUtils.getModelSpec(PublicAggregatedProductSchema);
332
- super('multi-tenant-products', app, productService, 'product', ProductSpec, PublicAggregatedProductSpec);
327
+ super("multi-tenant-products", app, productService, "product", ProductSpec, PublicAggregatedProductSpec);
333
328
  }
334
329
  }
335
330
  function configureJwtSecret() {
@@ -339,17 +334,15 @@ function configureJwtSecret() {
339
334
  };
340
335
  }
341
336
  async function loginWithTestUser(agent) {
342
- agent.set('Cookie', [`deviceId=${deviceIdCookie}`]);
337
+ agent.set("Cookie", [`deviceId=${deviceIdCookie}`]);
343
338
  const testUser = getTestMetaOrgUser();
344
- const response = await agent
345
- .post('/api/auth/login')
346
- .send({
339
+ const response = await agent.post("/api/auth/login").send({
347
340
  email: testUser.email,
348
341
  password: testUser.password,
349
342
  });
350
343
  if (!response.body?.data?.tokens?.accessToken) {
351
- console.error('Login failed:', response.body);
352
- throw new Error('Failed to login with test user');
344
+ console.error("Login failed:", response.body);
345
+ throw new Error("Failed to login with test user");
353
346
  }
354
347
  const authorizationHeaderValue = `Bearer ${response.body?.data?.tokens?.accessToken}`;
355
348
  return authorizationHeaderValue;
@@ -360,7 +353,7 @@ async function cleanup() {
360
353
  await deleteMetaOrg();
361
354
  }
362
355
  catch (error) {
363
- console.log('Error during cleanup:', error);
356
+ console.log("Error during cleanup:", error);
364
357
  }
365
358
  }
366
359
  const testUtils = {
@@ -382,6 +375,6 @@ const testUtils = {
382
375
  verifyToken,
383
376
  isMongoDatabase,
384
377
  isPostgresDatabase,
385
- getExpectedIdType
378
+ getExpectedIdType,
386
379
  };
387
380
  export default testUtils;
@@ -1,5 +1,5 @@
1
- import { ITestDatabase } from './test-database.interface.js';
2
- import { IDatabase } from '../databases/models/index.js';
1
+ import type { IDatabase } from "../databases/models/index.js";
2
+ import type { ITestDatabase } from "./test-database.interface.js";
3
3
  export declare class TestPostgresDatabase implements ITestDatabase {
4
4
  private database;
5
5
  private postgresClient;
@@ -1,10 +1,10 @@
1
- import testUtils from './common-test.utils.js';
1
+ import { Pool } from "pg";
2
2
  import { newDb } from "pg-mem";
3
- import { Pool } from 'pg';
4
- import { PostgresDatabase } from '../databases/postgres/postgres.database.js';
5
- import { config } from '../config/base-api-config.js';
6
- import { runInitialSchemaMigrations, runTestSchemaMigrations } from '../databases/postgres/migrations/__tests__/test-migration-helper.js';
7
- const USE_REAL_POSTGRES = process.env.USE_REAL_POSTGRES === 'true';
3
+ import { config } from "../config/base-api-config.js";
4
+ import { runInitialSchemaMigrations, runTestSchemaMigrations, } from "../databases/postgres/migrations/__tests__/test-migration-helper.js";
5
+ import { PostgresDatabase } from "../databases/postgres/postgres.database.js";
6
+ import testUtils from "./common-test.utils.js";
7
+ const USE_REAL_POSTGRES = process.env.USE_REAL_POSTGRES === "true";
8
8
  export class TestPostgresDatabase {
9
9
  database = null;
10
10
  postgresClient = null;
@@ -18,7 +18,7 @@ export class TestPostgresDatabase {
18
18
  return this.initPromise;
19
19
  }
20
20
  getRandomId() {
21
- throw new Error('getRandomId() should not be used for PostgreSQL _id fields. PostgreSQL uses auto-generated integer IDs. Remove _id from entities and let the database generate it.');
21
+ throw new Error("getRandomId() should not be used for PostgreSQL _id fields. PostgreSQL uses auto-generated integer IDs. Remove _id from entities and let the database generate it.");
22
22
  }
23
23
  async _performInit() {
24
24
  if (!this.database) {
@@ -32,13 +32,14 @@ export class TestPostgresDatabase {
32
32
  });
33
33
  this.migrationPool = pool;
34
34
  try {
35
- await pool.query('SELECT now(), current_database()');
35
+ await pool.query("SELECT now(), current_database()");
36
36
  }
37
37
  catch (error) {
38
38
  await pool.end();
39
39
  this.migrationPool = null;
40
40
  const errorMessage = error.message || String(error);
41
- const isPermissionError = errorMessage.includes('permission denied') || errorMessage.includes('operation not permitted');
41
+ const isPermissionError = errorMessage.includes("permission denied") ||
42
+ errorMessage.includes("operation not permitted");
42
43
  if (isPermissionError) {
43
44
  throw new Error(`Docker permission error. Please ensure:\n` +
44
45
  `1. Docker Desktop is running\n` +
@@ -64,9 +65,9 @@ export class TestPostgresDatabase {
64
65
  }
65
66
  this.database = new PostgresDatabase(connection);
66
67
  this.postgresClient = connection;
67
- const { initializeSystemUserContext, isSystemUserContextInitialized } = await import('@loomcore/common/models');
68
+ const { initializeSystemUserContext, isSystemUserContextInitialized } = await import("@loomcore/common/models");
68
69
  if (!isSystemUserContextInitialized()) {
69
- initializeSystemUserContext(config.email?.systemEmailAddress || 'system@test.com', undefined);
70
+ initializeSystemUserContext(config.email?.systemEmailAddress || "system@test.com", undefined);
70
71
  }
71
72
  await runInitialSchemaMigrations(pool, config);
72
73
  await runTestSchemaMigrations(pool, config);
@@ -84,12 +85,12 @@ export class TestPostgresDatabase {
84
85
  `);
85
86
  }
86
87
  catch (error) {
87
- console.log('Note: Indexes may be created later when tables are initialized:', error.message);
88
+ console.log("Note: Indexes may be created later when tables are initialized:", error.message);
88
89
  }
89
90
  }
90
91
  async clearCollections() {
91
92
  if (!this.postgresClient) {
92
- throw new Error('Database not initialized');
93
+ throw new Error("Database not initialized");
93
94
  }
94
95
  const result = await this.postgresClient.query(`
95
96
  SELECT "table_name"
@@ -98,7 +99,7 @@ export class TestPostgresDatabase {
98
99
  AND "table_type" = 'BASE TABLE'
99
100
  `);
100
101
  if (USE_REAL_POSTGRES) {
101
- await this.postgresClient.query(`TRUNCATE TABLE ${result.rows.map(row => `"${row.table_name}"`).join(', ')} RESTART IDENTITY CASCADE`);
102
+ await this.postgresClient.query(`TRUNCATE TABLE ${result.rows.map((row) => `"${row.table_name}"`).join(", ")} RESTART IDENTITY CASCADE`);
102
103
  }
103
104
  else {
104
105
  result.rows.forEach(async (row) => {
@@ -120,7 +121,7 @@ export class TestPostgresDatabase {
120
121
  }
121
122
  }
122
123
  catch (error) {
123
- console.warn('Error closing PostgreSQL connection:', error);
124
+ console.warn("Error closing PostgreSQL connection:", error);
124
125
  }
125
126
  }
126
127
  this.migrationPool = null;
@@ -1,20 +1,15 @@
1
- import { IOrganization, IUserContext, IUser, IPersonModel } from "@loomcore/common/models";
1
+ import type { IOrganization, IUser, IUserContext } from "@loomcore/common/models";
2
2
  export declare let TEST_META_ORG_ID: string | number;
3
3
  export declare let TEST_META_ORG_USER_ID: string | number;
4
- export declare let TEST_META_ORG_USER_PERSON_ID: string | number;
5
4
  export declare function setTestMetaOrgId(metaOrgId: string | number): void;
6
5
  export declare function setTestMetaOrgUserId(userId: string | number): void;
7
- export declare function setTestMetaOrgUserPersonId(personId: string | number): void;
8
6
  export declare const TEST_META_ORG_USER_PASSWORD = "test-meta-org-user-password";
9
7
  export declare function getTestMetaOrg(): IOrganization;
10
8
  export declare function getTestMetaOrgUser(): IUser;
11
- export declare function getTestMetaOrgUserPerson(): IPersonModel;
12
9
  export declare function getTestMetaOrgUserContext(): IUserContext;
13
10
  export declare function setTestOrgId(orgId: string | number): void;
14
11
  export declare function setTestOrgUserId(userId: string | number): void;
15
- export declare function setTestOrgUserPersonId(personId: string | number): void;
16
12
  export declare function getTestOrg(): IOrganization;
17
13
  export declare const TEST_ORG_USER_PASSWORD = "test-org-user-password";
18
14
  export declare function getTestOrgUser(): IUser;
19
- export declare function getTestOrgUserPerson(): IPersonModel;
20
15
  export declare function getTestOrgUserContext(): IUserContext;