@loomcore/api 0.1.77 → 0.1.79

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 (51) hide show
  1. package/README.md +1 -1
  2. package/dist/__tests__/common-test.utils.js +5 -3
  3. package/dist/__tests__/postgres-test-migrations/postgres-test-schema.js +25 -0
  4. package/dist/__tests__/postgres.test-database.js +2 -2
  5. package/dist/__tests__/test-objects.d.ts +6 -1
  6. package/dist/__tests__/test-objects.js +50 -4
  7. package/dist/controllers/auth.controller.d.ts +2 -0
  8. package/dist/controllers/auth.controller.js +9 -4
  9. package/dist/databases/mongo-db/migrations/mongo-initial-schema.js +23 -5
  10. package/dist/databases/operations/__tests__/models/{agent.model.d.ts → test-agent.model.d.ts} +7 -7
  11. package/dist/databases/operations/__tests__/models/test-agent.model.js +8 -0
  12. package/dist/databases/operations/__tests__/models/{client-report.model.d.ts → test-client-report.model.d.ts} +21 -16
  13. package/dist/databases/operations/__tests__/models/test-client-report.model.js +11 -0
  14. package/dist/databases/operations/__tests__/models/test-district.model.d.ts +12 -0
  15. package/dist/databases/operations/__tests__/models/{district.model.js → test-district.model.js} +2 -2
  16. package/dist/databases/operations/__tests__/models/{email-address.model.d.ts → test-email-address.model.d.ts} +3 -3
  17. package/dist/databases/operations/__tests__/models/{email-address.model.js → test-email-address.model.js} +2 -2
  18. package/dist/databases/operations/__tests__/models/test-person.model.d.ts +28 -0
  19. package/dist/databases/operations/__tests__/models/test-person.model.js +12 -0
  20. package/dist/databases/operations/__tests__/models/{phone-number.model.d.ts → test-phone-number.model.d.ts} +3 -3
  21. package/dist/databases/operations/__tests__/models/{phone-number.model.js → test-phone-number.model.js} +2 -2
  22. package/dist/databases/operations/__tests__/models/{policy.model.d.ts → test-policy.model.d.ts} +14 -7
  23. package/dist/databases/operations/__tests__/models/test-policy.model.js +12 -0
  24. package/dist/databases/operations/__tests__/models/test-premium.model.d.ts +12 -0
  25. package/dist/databases/operations/__tests__/models/test-premium.model.js +8 -0
  26. package/dist/databases/operations/__tests__/models/test-school.model.d.ts +12 -0
  27. package/dist/databases/operations/__tests__/models/{school.model.js → test-school.model.js} +2 -2
  28. package/dist/databases/operations/__tests__/models/test-state.model.d.ts +8 -0
  29. package/dist/databases/operations/__tests__/models/test-state.model.js +6 -0
  30. package/dist/databases/operations/join-many.operation.js +3 -0
  31. package/dist/databases/operations/join-through-many.operation.js +3 -0
  32. package/dist/databases/operations/join-through.operation.js +3 -0
  33. package/dist/databases/operations/join.operation.js +3 -0
  34. package/dist/databases/postgres/migrations/postgres-initial-schema.js +54 -16
  35. package/dist/databases/postgres/utils/build-join-clauses.js +282 -272
  36. package/dist/databases/postgres/utils/build-select-clause.js +19 -34
  37. package/dist/databases/postgres/utils/transform-join-results.js +198 -194
  38. package/dist/services/auth.service.d.ts +3 -2
  39. package/dist/services/auth.service.js +15 -1
  40. package/dist/services/person.service.d.ts +6 -0
  41. package/dist/services/person.service.js +7 -0
  42. package/package.json +3 -3
  43. package/dist/databases/operations/__tests__/models/agent.model.js +0 -8
  44. package/dist/databases/operations/__tests__/models/client-report.model.js +0 -11
  45. package/dist/databases/operations/__tests__/models/district.model.d.ts +0 -12
  46. package/dist/databases/operations/__tests__/models/person.model.d.ts +0 -28
  47. package/dist/databases/operations/__tests__/models/person.model.js +0 -12
  48. package/dist/databases/operations/__tests__/models/policy.model.js +0 -10
  49. package/dist/databases/operations/__tests__/models/school.model.d.ts +0 -12
  50. package/dist/databases/operations/__tests__/models/state.model.d.ts +0 -8
  51. package/dist/databases/operations/__tests__/models/state.model.js +0 -6
@@ -0,0 +1,12 @@
1
+ import { entityUtils } from "@loomcore/common/utils";
2
+ import { Type } from "@sinclair/typebox";
3
+ import { testAgentSchema } from "./test-agent.model.js";
4
+ import { testPremiumSchema } from "./test-premium.model.js";
5
+ export const testPolicySchema = Type.Object({
6
+ client_id: Type.Number(),
7
+ amount: Type.Number(),
8
+ frequency: Type.String(),
9
+ agents: Type.Optional(Type.Array(testAgentSchema)),
10
+ policy_premiums: Type.Optional(Type.Array(testPremiumSchema))
11
+ });
12
+ export const testPolicyModelSpec = entityUtils.getModelSpec(testPolicySchema, { isAuditable: true });
@@ -0,0 +1,12 @@
1
+ import type { IAuditable, IEntity } from "@loomcore/common/models";
2
+ export interface ITestPremiumModel extends IEntity, IAuditable {
3
+ policy_id: number;
4
+ amount: number;
5
+ date: Date | string;
6
+ }
7
+ export declare const testPremiumSchema: import("@sinclair/typebox").TObject<{
8
+ policy_id: import("@sinclair/typebox").TNumber;
9
+ amount: import("@sinclair/typebox").TNumber;
10
+ date: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TDate, import("@sinclair/typebox").TString]>;
11
+ }>;
12
+ export declare const testPremiumModelSpec: import("@loomcore/common/models").IModelSpec<import("@sinclair/typebox").TSchema>;
@@ -0,0 +1,8 @@
1
+ import { entityUtils } from "@loomcore/common/utils";
2
+ import { Type } from "@sinclair/typebox";
3
+ export const testPremiumSchema = Type.Object({
4
+ policy_id: Type.Number(),
5
+ amount: Type.Number(),
6
+ date: Type.Union([Type.Date(), Type.String()])
7
+ });
8
+ export const testPremiumModelSpec = entityUtils.getModelSpec(testPremiumSchema, { isAuditable: true });
@@ -0,0 +1,12 @@
1
+ import type { IAuditable, IEntity } from "@loomcore/common/models";
2
+ import { ITestDistrictModel } from "./test-district.model.js";
3
+ export interface ITestSchoolModel extends IEntity, IAuditable {
4
+ name: string;
5
+ district_id: number;
6
+ district?: ITestDistrictModel;
7
+ }
8
+ export declare const testSchoolSchema: import("@sinclair/typebox").TObject<{
9
+ name: import("@sinclair/typebox").TString;
10
+ district_id: import("@sinclair/typebox").TNumber;
11
+ }>;
12
+ export declare const testSchoolModelSpec: import("@loomcore/common/models").IModelSpec<import("@sinclair/typebox").TSchema>;
@@ -1,7 +1,7 @@
1
1
  import { entityUtils } from "@loomcore/common/utils";
2
2
  import { Type } from "@sinclair/typebox";
3
- export const schoolSchema = Type.Object({
3
+ export const testSchoolSchema = Type.Object({
4
4
  name: Type.String(),
5
5
  district_id: Type.Number(),
6
6
  });
7
- export const schoolModelSpec = entityUtils.getModelSpec(schoolSchema, { isAuditable: true });
7
+ export const testSchoolModelSpec = entityUtils.getModelSpec(testSchoolSchema, { isAuditable: true });
@@ -0,0 +1,8 @@
1
+ import type { IAuditable, IEntity } from "@loomcore/common/models";
2
+ export interface ITestStateModel extends IEntity, IAuditable {
3
+ name: string;
4
+ }
5
+ export declare const testStateSchema: import("@sinclair/typebox").TObject<{
6
+ name: import("@sinclair/typebox").TString;
7
+ }>;
8
+ export declare const testStateModelSpec: import("@loomcore/common/models").IModelSpec<import("@sinclair/typebox").TSchema>;
@@ -0,0 +1,6 @@
1
+ import { entityUtils } from "@loomcore/common/utils";
2
+ import { Type } from "@sinclair/typebox";
3
+ export const testStateSchema = Type.Object({
4
+ name: Type.String(),
5
+ });
6
+ export const testStateModelSpec = entityUtils.getModelSpec(testStateSchema, { isAuditable: true });
@@ -4,6 +4,9 @@ export class JoinMany {
4
4
  foreignField;
5
5
  as;
6
6
  constructor(from, localField, foreignField, as) {
7
+ if (from === as) {
8
+ throw new Error(`JoinMany alias "${as}" must be different from table name "${from}". The alias is used to identify the join result and must be unique.`);
9
+ }
7
10
  this.from = from;
8
11
  this.localField = localField;
9
12
  this.foreignField = foreignField;
@@ -7,6 +7,9 @@ export class JoinThroughMany {
7
7
  foreignField;
8
8
  as;
9
9
  constructor(from, through, localField, throughLocalField, throughForeignField, foreignField, as) {
10
+ if (from === as) {
11
+ throw new Error(`JoinThroughMany alias "${as}" must be different from table name "${from}". The alias is used to identify the join result and must be unique.`);
12
+ }
10
13
  this.from = from;
11
14
  this.through = through;
12
15
  this.localField = localField;
@@ -7,6 +7,9 @@ export class JoinThrough {
7
7
  foreignField;
8
8
  as;
9
9
  constructor(from, through, localField, throughLocalField, throughForeignField, foreignField, as) {
10
+ if (from === as) {
11
+ throw new Error(`JoinThrough alias "${as}" must be different from table name "${from}". The alias is used to identify the join result and must be unique.`);
12
+ }
10
13
  this.from = from;
11
14
  this.through = through;
12
15
  this.localField = localField;
@@ -4,6 +4,9 @@ export class Join {
4
4
  foreignField;
5
5
  as;
6
6
  constructor(from, localField, foreignField, as) {
7
+ if (from === as) {
8
+ throw new Error(`Join alias "${as}" must be different from table name "${from}". The alias is used to identify the join result and must be unique.`);
9
+ }
7
10
  this.from = from;
8
11
  this.localField = localField;
9
12
  this.foreignField = foreignField;
@@ -43,21 +43,54 @@ export const getPostgresInitialSchema = (config) => {
43
43
  }
44
44
  if (isAuthEnabled)
45
45
  migrations.push({
46
- name: '00000000000002_schema-users',
46
+ name: '00000000000002_schema-persons',
47
47
  up: async ({ context: pool }) => {
48
48
  const orgColumnDef = isMultiTenant ? '"_orgId" INTEGER,' : '';
49
- const uniqueConstraint = isMultiTenant
49
+ await pool.query(`
50
+ CREATE TABLE IF NOT EXISTS "persons" (
51
+ "_id" INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
52
+ ${orgColumnDef}
53
+ "externalId" VARCHAR(255) UNIQUE,
54
+ "firstName" VARCHAR(255) NOT NULL,
55
+ "middleName" VARCHAR(255),
56
+ "lastName" VARCHAR(255) NOT NULL,
57
+ "dateOfBirth" DATE,
58
+ "isAgent" BOOLEAN NOT NULL DEFAULT FALSE,
59
+ "isClient" BOOLEAN NOT NULL DEFAULT FALSE,
60
+ "isEmployee" BOOLEAN NOT NULL DEFAULT FALSE,
61
+ "extendedTypes" INTEGER NOT NULL DEFAULT 0,
62
+ "_created" TIMESTAMPTZ NOT NULL,
63
+ "_createdBy" INTEGER NOT NULL,
64
+ "_updated" TIMESTAMPTZ NOT NULL,
65
+ "_updatedBy" INTEGER NOT NULL,
66
+ "_deleted" TIMESTAMPTZ,
67
+ "_deletedBy" INTEGER
68
+ )
69
+ `);
70
+ },
71
+ down: async ({ context: pool }) => {
72
+ await pool.query('DROP TABLE IF EXISTS "persons"');
73
+ }
74
+ });
75
+ if (isAuthEnabled)
76
+ migrations.push({
77
+ name: '00000000000003_schema-users',
78
+ up: async ({ context: pool }) => {
79
+ const orgColumnDef = isMultiTenant ? '"_orgId" INTEGER,' : '';
80
+ let uniqueConstraint = isMultiTenant
50
81
  ? 'CONSTRAINT "uk_users_email" UNIQUE ("_orgId", "email")'
51
82
  : 'CONSTRAINT "uk_users_email" UNIQUE ("email")';
83
+ uniqueConstraint += `,
84
+ CONSTRAINT "fk_users_personId" FOREIGN KEY("personId") REFERENCES "persons"("_id") ON DELETE CASCADE`;
52
85
  await pool.query(`
53
86
  CREATE TABLE IF NOT EXISTS "users" (
54
87
  "_id" INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
55
88
  ${orgColumnDef}
89
+ "externalId" VARCHAR(255) UNIQUE,
56
90
  "email" VARCHAR(255) NOT NULL,
57
- "firstName" VARCHAR(255),
58
- "lastName" VARCHAR(255),
59
91
  "displayName" VARCHAR(255),
60
92
  "password" VARCHAR(255) NOT NULL,
93
+ "personId" INTEGER UNIQUE,
61
94
  "_lastLoggedIn" TIMESTAMPTZ,
62
95
  "_lastPasswordChange" TIMESTAMPTZ,
63
96
  "_created" TIMESTAMPTZ NOT NULL,
@@ -76,7 +109,7 @@ export const getPostgresInitialSchema = (config) => {
76
109
  });
77
110
  if (isAuthEnabled)
78
111
  migrations.push({
79
- name: '00000000000003_schema-refresh-tokens',
112
+ name: '00000000000004_schema-refresh-tokens',
80
113
  up: async ({ context: pool }) => {
81
114
  const orgColumnDef = isMultiTenant ? '"_orgId" INTEGER,' : '';
82
115
  await pool.query(`
@@ -99,7 +132,7 @@ export const getPostgresInitialSchema = (config) => {
99
132
  });
100
133
  if (isAuthEnabled)
101
134
  migrations.push({
102
- name: '00000000000004_schema-password-reset-tokens',
135
+ name: '00000000000005_schema-password-reset-tokens',
103
136
  up: async ({ context: pool }) => {
104
137
  const orgColumnDef = isMultiTenant ? '"_orgId" INTEGER,' : '';
105
138
  const uniqueConstraint = isMultiTenant
@@ -128,7 +161,7 @@ export const getPostgresInitialSchema = (config) => {
128
161
  });
129
162
  if (isAuthEnabled)
130
163
  migrations.push({
131
- name: '00000000000005_schema-roles',
164
+ name: '00000000000006_schema-roles',
132
165
  up: async ({ context: pool }) => {
133
166
  const orgColumnDef = isMultiTenant ? '"_orgId" INTEGER,' : '';
134
167
  const uniqueConstraint = isMultiTenant
@@ -150,7 +183,7 @@ export const getPostgresInitialSchema = (config) => {
150
183
  });
151
184
  if (isAuthEnabled)
152
185
  migrations.push({
153
- name: '00000000000006_schema-user-roles',
186
+ name: '00000000000007_schema-user-roles',
154
187
  up: async ({ context: pool }) => {
155
188
  const orgColumnDef = isMultiTenant ? '"_orgId" INTEGER,' : '';
156
189
  const uniqueConstraint = isMultiTenant
@@ -180,7 +213,7 @@ export const getPostgresInitialSchema = (config) => {
180
213
  });
181
214
  if (isAuthEnabled)
182
215
  migrations.push({
183
- name: '00000000000007_schema-features',
216
+ name: '00000000000008_schema-features',
184
217
  up: async ({ context: pool }) => {
185
218
  const orgColumnDef = isMultiTenant ? '"_orgId" INTEGER,' : '';
186
219
  const uniqueConstraint = isMultiTenant
@@ -202,7 +235,7 @@ export const getPostgresInitialSchema = (config) => {
202
235
  });
203
236
  if (isAuthEnabled)
204
237
  migrations.push({
205
- name: '00000000000008_schema-authorizations',
238
+ name: '00000000000009_schema-authorizations',
206
239
  up: async ({ context: pool }) => {
207
240
  const orgColumnDef = isMultiTenant ? '"_orgId" INTEGER,' : '';
208
241
  const uniqueConstraint = isMultiTenant
@@ -235,7 +268,7 @@ export const getPostgresInitialSchema = (config) => {
235
268
  });
236
269
  if (isMultiTenant) {
237
270
  migrations.push({
238
- name: '00000000000009_data-meta-org',
271
+ name: '00000000000010_data-meta-org',
239
272
  up: async ({ context: pool }) => {
240
273
  const result = await pool.query(`
241
274
  INSERT INTO "organizations" ("name", "code", "status", "isMetaOrg", "_created", "_createdBy", "_updated", "_updatedBy")
@@ -254,7 +287,7 @@ export const getPostgresInitialSchema = (config) => {
254
287
  }
255
288
  if (isAuthEnabled) {
256
289
  migrations.push({
257
- name: '00000000000010_data-admin-user',
290
+ name: '00000000000011_data-admin-user',
258
291
  up: async ({ context: pool }) => {
259
292
  const client = await pool.connect();
260
293
  try {
@@ -273,14 +306,19 @@ export const getPostgresInitialSchema = (config) => {
273
306
  const userData = {
274
307
  email: config.auth?.adminUser?.email,
275
308
  password: config.auth?.adminUser?.password,
276
- firstName: 'Admin',
277
- lastName: 'User',
278
309
  displayName: 'Admin User',
279
310
  };
280
311
  if (isMultiTenant && systemUserContext.organization?._id) {
281
312
  userData._orgId = systemUserContext.organization._id;
282
313
  }
283
- await authService.createUser(systemUserContext, userData);
314
+ const personData = {
315
+ firstName: 'Admin',
316
+ lastName: 'User',
317
+ };
318
+ if (isMultiTenant && systemUserContext.organization?._id) {
319
+ personData._orgId = systemUserContext.organization._id;
320
+ }
321
+ await authService.createUser(systemUserContext, userData, personData);
284
322
  }
285
323
  finally {
286
324
  client.release();
@@ -295,7 +333,7 @@ export const getPostgresInitialSchema = (config) => {
295
333
  }
296
334
  if (config.auth) {
297
335
  migrations.push({
298
- name: '00000000000011_data-admin-authorizations',
336
+ name: '00000000000012_data-admin-authorizations',
299
337
  up: async ({ context: pool }) => {
300
338
  const client = await pool.connect();
301
339
  try {