@tstdl/base 0.93.99 → 0.93.101

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 (85) hide show
  1. package/authentication/client/authentication.service.d.ts +1 -1
  2. package/authentication/client/authentication.service.js +23 -11
  3. package/file/mime-type.d.ts +2 -2
  4. package/file/mime-type.js +2 -3
  5. package/file/server/index.d.ts +1 -0
  6. package/file/server/index.js +1 -0
  7. package/file/server/mime-type.d.ts +2 -0
  8. package/file/server/mime-type.js +5 -0
  9. package/notification/api/index.d.ts +1 -0
  10. package/notification/api/index.js +1 -0
  11. package/notification/api/notification.api.d.ts +8 -16
  12. package/notification/api/notification.api.js +13 -26
  13. package/notification/index.d.ts +1 -1
  14. package/notification/index.js +1 -1
  15. package/notification/models/in-app-notification.model.d.ts +9 -4
  16. package/notification/models/in-app-notification.model.js +25 -10
  17. package/notification/models/index.d.ts +1 -1
  18. package/notification/models/index.js +1 -1
  19. package/notification/models/notification-log.model.d.ts +42 -5
  20. package/notification/models/notification-log.model.js +34 -20
  21. package/notification/models/notification-preference.model.d.ts +2 -2
  22. package/notification/models/notification-preference.model.js +9 -9
  23. package/notification/models/notification-type.model.d.ts +17 -0
  24. package/notification/models/{notification-category.model.js → notification-type.model.js} +12 -13
  25. package/notification/models/web-push-subscription.model.d.ts +2 -2
  26. package/notification/models/web-push-subscription.model.js +8 -7
  27. package/notification/server/api/notification.api-controller.d.ts +2 -2
  28. package/notification/server/api/notification.api-controller.js +4 -3
  29. package/notification/server/drizzle/{0000_glorious_randall.sql → 0000_shiny_the_anarchist.sql} +27 -32
  30. package/notification/server/drizzle/meta/0000_snapshot.json +179 -179
  31. package/notification/server/drizzle/meta/_journal.json +2 -2
  32. package/notification/server/module.d.ts +2 -0
  33. package/notification/server/module.js +1 -0
  34. package/notification/server/providers/channel-provider.d.ts +4 -3
  35. package/notification/server/providers/channel-provider.js +2 -1
  36. package/notification/server/providers/email-channel-provider.d.ts +3 -3
  37. package/notification/server/providers/email-channel-provider.js +7 -9
  38. package/notification/server/providers/in-app-channel-provider.d.ts +5 -5
  39. package/notification/server/providers/in-app-channel-provider.js +15 -16
  40. package/notification/server/providers/index.d.ts +1 -1
  41. package/notification/server/providers/index.js +1 -1
  42. package/notification/server/providers/web-push-channel-provider.d.ts +5 -4
  43. package/notification/server/providers/web-push-channel-provider.js +8 -7
  44. package/notification/server/schemas.d.ts +3 -3
  45. package/notification/server/schemas.js +3 -4
  46. package/notification/server/services/index.d.ts +2 -4
  47. package/notification/server/services/index.js +2 -4
  48. package/notification/server/services/notification-delivery.worker.d.ts +7 -1
  49. package/notification/server/services/notification-delivery.worker.js +49 -37
  50. package/notification/server/services/notification-sse.service.d.ts +4 -7
  51. package/notification/server/services/notification-sse.service.js +4 -11
  52. package/notification/server/services/notification-template.d.ts +2 -2
  53. package/notification/server/services/notification-template.js +3 -1
  54. package/notification/server/services/notification-template.service.d.ts +1 -1
  55. package/notification/server/services/notification-template.service.js +7 -3
  56. package/notification/server/services/notification-type.service.d.ts +11 -0
  57. package/notification/server/services/notification-type.service.js +41 -0
  58. package/notification/server/services/notification.service.d.ts +4 -5
  59. package/notification/server/services/notification.service.js +44 -27
  60. package/notification/tests/notification-api.test.js +95 -0
  61. package/notification/tests/notification-flow.test.js +174 -28
  62. package/notification/tests/notification-type.service.test.d.ts +1 -0
  63. package/notification/tests/notification-type.service.test.js +35 -0
  64. package/package.json +2 -2
  65. package/rate-limit/postgres/postgres-rate-limiter.d.ts +9 -4
  66. package/rate-limit/postgres/postgres-rate-limiter.js +17 -10
  67. package/rate-limit/rate-limiter.d.ts +6 -6
  68. package/rate-limit/tests/postgres-rate-limiter.test.js +1 -1
  69. package/task-queue/postgres/task-queue.js +1 -1
  70. package/task-queue/task-queue.d.ts +3 -3
  71. package/task-queue/tests/extensive-dependencies.test.d.ts +1 -0
  72. package/task-queue/tests/extensive-dependencies.test.js +234 -0
  73. package/notification/enums.d.ts +0 -22
  74. package/notification/enums.js +0 -19
  75. package/notification/models/notification-category.model.d.ts +0 -17
  76. package/notification/server/services/notification-category.service.d.ts +0 -11
  77. package/notification/server/services/notification-category.service.js +0 -41
  78. package/notification/server/services/notification-delivery.task.d.ts +0 -9
  79. package/notification/server/services/notification-delivery.task.js +0 -1
  80. package/notification/server/services/singleton.d.ts +0 -3
  81. package/notification/server/services/singleton.js +0 -10
  82. package/notification/tests/notification-category.service.test.js +0 -36
  83. package/notification/tests/test-notification.model.d.ts +0 -4
  84. package/notification/tests/test-notification.model.js +0 -25
  85. /package/notification/tests/{notification-category.service.test.d.ts → notification-api.test.d.ts} +0 -0
@@ -25,7 +25,7 @@ export declare class AuthenticationClientService<AdditionalTokenPayload extends
25
25
  private readonly forceRefreshToken;
26
26
  private readonly lock;
27
27
  private readonly logger;
28
- private readonly disposeToken;
28
+ private readonly disposeSignal;
29
29
  private clockOffset;
30
30
  private refreshLoopPromise;
31
31
  /**
@@ -7,23 +7,24 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
- import { Subject, filter, firstValueFrom, race, timer } from 'rxjs';
10
+ import { Subject, filter, firstValueFrom, map, race, timer } from 'rxjs';
11
11
  import { CancellationSignal, CancellationToken } from '../../cancellation/token.js';
12
12
  import { BadRequestError } from '../../errors/bad-request.error.js';
13
13
  import { ForbiddenError } from '../../errors/forbidden.error.js';
14
+ import { formatError } from '../../errors/index.js';
14
15
  import { InvalidTokenError } from '../../errors/invalid-token.error.js';
15
16
  import { NotFoundError } from '../../errors/not-found.error.js';
16
17
  import { NotSupportedError } from '../../errors/not-supported.error.js';
17
18
  import { UnauthorizedError } from '../../errors/unauthorized.error.js';
19
+ import { HttpError } from '../../http/index.js';
18
20
  import { Singleton, afterResolve, inject } from '../../injector/index.js';
19
21
  import { Lock } from '../../lock/index.js';
20
22
  import { Logger } from '../../logger/index.js';
21
23
  import { MessageBus } from '../../message-bus/index.js';
22
24
  import { computed, signal, toObservable } from '../../signals/api.js';
23
25
  import { currentTimestampSeconds } from '../../utils/date-time.js';
24
- import { formatError } from '../../errors/index.js';
25
26
  import { timeout } from '../../utils/timing.js';
26
- import { assertDefinedPass, isDefined, isNotFunction, isNullOrUndefined, isUndefined } from '../../utils/type-guards.js';
27
+ import { assertDefinedPass, isDefined, isInstanceOf, isNotFunction, isNullOrUndefined, isUndefined } from '../../utils/type-guards.js';
27
28
  import { millisecondsPerMinute, millisecondsPerSecond } from '../../utils/units.js';
28
29
  import { AUTHENTICATION_API_CLIENT, INITIAL_AUTHENTICATION_DATA } from './tokens.js';
29
30
  const tokenStorageKey = 'AuthenticationService:token';
@@ -69,7 +70,7 @@ let AuthenticationClientService = class AuthenticationClientService {
69
70
  forceRefreshToken = new CancellationToken();
70
71
  lock = inject(Lock, refreshLockResource);
71
72
  logger = inject(Logger, 'AuthenticationService');
72
- disposeToken = inject(CancellationSignal).createChild();
73
+ disposeSignal = inject(CancellationSignal).createChild();
73
74
  clockOffset = 0;
74
75
  refreshLoopPromise;
75
76
  /**
@@ -188,7 +189,7 @@ let AuthenticationClientService = class AuthenticationClientService {
188
189
  * Stops refresh loop and completes subjects.
189
190
  */
190
191
  async dispose() {
191
- this.disposeToken.set();
192
+ this.disposeSignal.set();
192
193
  await this.refreshLoopPromise;
193
194
  this.errorSubject.complete();
194
195
  await this.loggedOutBus.dispose();
@@ -375,13 +376,13 @@ let AuthenticationClientService = class AuthenticationClientService {
375
376
  if (this.isLoggedIn()) {
376
377
  await this.syncClock();
377
378
  }
378
- while (this.disposeToken.isUnset) {
379
+ while (this.disposeSignal.isUnset) {
379
380
  try {
380
381
  const token = this.token();
381
382
  if (isUndefined(token)) {
382
383
  // Wait for login or dispose.
383
384
  // We ignore forceRefreshToken here because we can't refresh without a token.
384
- await firstValueFrom(race([this.definedToken$, this.disposeToken]), { defaultValue: undefined });
385
+ await firstValueFrom(race([this.definedToken$, this.disposeSignal]), { defaultValue: undefined });
385
386
  continue;
386
387
  }
387
388
  const now = this.estimatedServerTimestampSeconds();
@@ -402,13 +403,20 @@ let AuthenticationClientService = class AuthenticationClientService {
402
403
  if (!lockAcquired) {
403
404
  // Lock held by another instance, wait 5 seconds or until state/token changes.
404
405
  // We ignore forceRefreshToken here to avoid a busy loop if it is already set.
405
- await firstValueFrom(race([timer(5000), this.disposeToken, this.token$.pipe(filter((t) => t !== token))]), { defaultValue: undefined });
406
+ const changeReason = await firstValueFrom(race([
407
+ timer(5000).pipe(map(() => 'timer')),
408
+ this.token$.pipe(filter((t) => t !== token), map(() => 'token')),
409
+ this.disposeSignal,
410
+ ]), { defaultValue: undefined });
411
+ if (changeReason == 'token') {
412
+ this.forceRefreshToken.unset();
413
+ }
406
414
  continue;
407
415
  }
408
416
  }
409
417
  const delay = Math.min(maxRefreshDelay, ((this.token()?.exp ?? 0) - this.estimatedServerTimestampSeconds() - refreshBufferSeconds) * millisecondsPerSecond);
410
418
  const wakeUpSignals = [
411
- this.disposeToken,
419
+ this.disposeSignal,
412
420
  this.token$.pipe(filter((t) => t != token)),
413
421
  ];
414
422
  if (!forceRefresh) {
@@ -423,14 +431,18 @@ let AuthenticationClientService = class AuthenticationClientService {
423
431
  }
424
432
  catch (error) {
425
433
  this.logger.error(error);
426
- await firstValueFrom(race([timer(5000), this.disposeToken, this.token$.pipe(filter((t) => t !== this.token()))]), { defaultValue: undefined });
434
+ const initialToken = this.token();
435
+ await firstValueFrom(race([timer(5000), this.disposeSignal, this.token$.pipe(filter((t) => t != initialToken))]), { defaultValue: undefined });
436
+ await timeout(2500);
427
437
  }
428
438
  }
429
439
  }
430
440
  async handleRefreshError(error) {
431
441
  this.logger.error(error);
432
442
  this.errorSubject.next(error);
433
- if (unrecoverableErrors.some((errorType) => error instanceof errorType)) {
443
+ const isUnrecoverable = unrecoverableErrors.some((errorType) => isInstanceOf(error, errorType))
444
+ || (error instanceof HttpError && ((error.response?.statusCode == 401) || (error.response?.statusCode == 404)));
445
+ if (isUnrecoverable) {
434
446
  await this.logout();
435
447
  }
436
448
  }
@@ -1,3 +1,3 @@
1
- export declare function getMimeType(file: string | Uint8Array | ReadableStream<Uint8Array>): Promise<string | undefined>;
2
- export declare function getMimeType<F>(file: string | Uint8Array | ReadableStream<Uint8Array>, fallback: F): Promise<string | F>;
1
+ export declare function getMimeType(file: Uint8Array | ReadableStream<Uint8Array>): Promise<string | undefined>;
2
+ export declare function getMimeType<F>(file: Uint8Array | ReadableStream<Uint8Array>, fallback: F): Promise<string | F>;
3
3
  export declare function getMimeTypeExtensions(mimeType: string): string[];
package/file/mime-type.js CHANGED
@@ -1,10 +1,9 @@
1
- import { fileTypeFromBuffer, fileTypeFromFile, fileTypeFromStream } from 'file-type/node';
2
- import { isReadableStream, isString, isUint8Array } from '../utils/type-guards.js';
1
+ import { fileTypeFromBuffer, fileTypeFromStream } from 'file-type';
3
2
  import { match } from 'ts-pattern';
3
+ import { isReadableStream, isUint8Array } from '../utils/type-guards.js';
4
4
  import { mimeTypesMap } from './mime-types.js';
5
5
  export async function getMimeType(file, fallback) {
6
6
  const result = await match(file)
7
- .when(isString, async (f) => await fileTypeFromFile(f))
8
7
  .when(isUint8Array, async (f) => await fileTypeFromBuffer(f))
9
8
  .when((isReadableStream), async (f) => await fileTypeFromStream(f))
10
9
  .exhaustive();
@@ -1 +1,2 @@
1
+ export * from './mime-type.js';
1
2
  export * from './temporary-file.js';
@@ -1 +1,2 @@
1
+ export * from './mime-type.js';
1
2
  export * from './temporary-file.js';
@@ -0,0 +1,2 @@
1
+ export declare function getMimeTypeFromFile(path: string): Promise<string | undefined>;
2
+ export declare function getMimeTypeFromFile<F>(path: string, fallback: F): Promise<string | F>;
@@ -0,0 +1,5 @@
1
+ import { fileTypeFromFile } from 'file-type/node';
2
+ export async function getMimeTypeFromFile(path, fallback) {
3
+ const result = await fileTypeFromFile(path);
4
+ return result?.mime ?? fallback;
5
+ }
@@ -0,0 +1 @@
1
+ export * from './notification.api.js';
@@ -0,0 +1 @@
1
+ export * from './notification.api.js';
@@ -1,4 +1,5 @@
1
1
  import { ServerSentEvents } from '../../sse/server-sent-events.js';
2
+ import { InAppNotificationView } from '../models/in-app-notification.model.js';
2
3
  export declare const notificationApiDefinition: {
3
4
  resource: string;
4
5
  endpoints: {
@@ -15,16 +16,7 @@ export declare const notificationApiDefinition: {
15
16
  limit?: number | undefined;
16
17
  includeArchived?: boolean | undefined;
17
18
  }>;
18
- result: import("../../schema/index.js").ArraySchema<{
19
- type: string;
20
- id: string;
21
- createdAt: number;
22
- priority: string;
23
- logId: string;
24
- payload?: {} | undefined;
25
- readAt?: number | undefined;
26
- archivedAt?: number | undefined;
27
- }>;
19
+ result: import("../../schema/index.js").ArraySchema<InAppNotificationView>;
28
20
  };
29
21
  markRead: {
30
22
  resource: string;
@@ -46,17 +38,17 @@ export declare const notificationApiDefinition: {
46
38
  resource: string;
47
39
  method: "GET";
48
40
  result: import("../../schema/index.js").ArraySchema<{
41
+ type: string;
49
42
  enabled: boolean;
50
- channel: string;
51
- categoryId: string;
43
+ channel: "email" | "in-app" | "web-push";
52
44
  }>;
53
45
  };
54
46
  updatePreference: {
55
47
  resource: string;
56
48
  method: "POST";
57
49
  parameters: import("../../schema/index.js").ObjectSchema<{
58
- readonly categoryId: string;
59
- readonly channel: string;
50
+ readonly type: string;
51
+ readonly channel: "email" | "in-app" | "web-push";
60
52
  readonly enabled: boolean;
61
53
  }>;
62
54
  result: import("../../schema/index.js").LiteralSchema<"ok">;
@@ -67,8 +59,8 @@ export declare const notificationApiDefinition: {
67
59
  parameters: import("../../schema/index.js").ObjectSchema<{
68
60
  readonly endpoint: string;
69
61
  readonly keys: {
70
- auth: string;
71
- p256dh: string;
62
+ p256dhBase64: string;
63
+ authBase64: string;
72
64
  };
73
65
  }>;
74
66
  result: import("../../schema/index.js").LiteralSchema<"ok">;
@@ -1,9 +1,10 @@
1
1
  import { defineApi } from '../../api/types.js';
2
- import { boolean, explicitObject, literal, number, object, optional, string, array, unknown } from '../../schema/index.js';
3
- import { NotificationChannel } from '../enums.js';
2
+ import { array, boolean, enumeration, explicitObject, literal, number, object, optional, string } from '../../schema/index.js';
4
3
  import { ServerSentEvents } from '../../sse/server-sent-events.js';
4
+ import { InAppNotificationView } from '../models/in-app-notification.model.js';
5
+ import { NotificationChannel } from '../models/index.js';
5
6
  export const notificationApiDefinition = defineApi({
6
- resource: 'notification',
7
+ resource: 'notifications',
7
8
  endpoints: {
8
9
  stream: {
9
10
  resource: 'stream',
@@ -18,40 +19,26 @@ export const notificationApiDefinition = defineApi({
18
19
  offset: optional(number()),
19
20
  includeArchived: optional(boolean()),
20
21
  }),
21
- result: array(object({
22
- id: string(),
23
- logId: string(),
24
- readAt: optional(number()),
25
- archivedAt: optional(number()),
26
- // Add more joined fields from Log if needed, or return polymorphic payload
27
- type: string(),
28
- priority: string(),
29
- createdAt: number(),
30
- payload: optional(object({})),
31
- })),
22
+ result: array(InAppNotificationView),
32
23
  },
33
24
  markRead: {
34
25
  resource: 'in-app/:id/read',
35
26
  method: 'POST',
36
- parameters: object({
37
- id: string(),
38
- }),
27
+ parameters: object({ id: string() }),
39
28
  result: literal('ok'),
40
29
  },
41
30
  archive: {
42
31
  resource: 'in-app/:id/archive',
43
32
  method: 'POST',
44
- parameters: object({
45
- id: string(),
46
- }),
33
+ parameters: object({ id: string() }),
47
34
  result: literal('ok'),
48
35
  },
49
36
  getPreferences: {
50
37
  resource: 'preferences',
51
38
  method: 'GET',
52
39
  result: array(object({
53
- categoryId: string(),
54
- channel: string(),
40
+ type: string(),
41
+ channel: enumeration(NotificationChannel),
55
42
  enabled: boolean(),
56
43
  })),
57
44
  },
@@ -59,8 +46,8 @@ export const notificationApiDefinition = defineApi({
59
46
  resource: 'preferences',
60
47
  method: 'POST',
61
48
  parameters: explicitObject({
62
- categoryId: string(),
63
- channel: string(),
49
+ type: string(),
50
+ channel: enumeration(NotificationChannel),
64
51
  enabled: boolean(),
65
52
  }),
66
53
  result: literal('ok'),
@@ -71,8 +58,8 @@ export const notificationApiDefinition = defineApi({
71
58
  parameters: explicitObject({
72
59
  endpoint: string(),
73
60
  keys: object({
74
- p256dh: string(),
75
- auth: string(),
61
+ p256dhBase64: string(),
62
+ authBase64: string(),
76
63
  }),
77
64
  }),
78
65
  result: literal('ok'),
@@ -1,2 +1,2 @@
1
- export * from './enums.js';
1
+ export * from './api/index.js';
2
2
  export * from './models/index.js';
@@ -1,2 +1,2 @@
1
- export * from './enums.js';
1
+ export * from './api/index.js';
2
2
  export * from './models/index.js';
@@ -1,9 +1,14 @@
1
- import { TenantEntity, type Uuid } from '../../orm/index.js';
1
+ import { TenantBaseEntity, type Uuid } from '../../orm/index.js';
2
2
  import type { Timestamp } from '../../orm/types.js';
3
- export declare class InAppNotification extends TenantEntity {
3
+ import { type NotificationLog } from './notification-log.model.js';
4
+ export declare class InAppNotification extends TenantBaseEntity {
4
5
  static readonly entityName = "InAppNotification";
5
6
  userId: Uuid;
6
7
  logId: Uuid;
7
- readAt: Timestamp | null;
8
- archivedAt: Timestamp | null;
8
+ readTimestamp: Timestamp | null;
9
+ archiveTimestamp: Timestamp | null;
9
10
  }
11
+ export declare class InAppNotificationView extends InAppNotification {
12
+ notification: NotificationLog;
13
+ }
14
+ export declare function toInAppNotificationView(inAppNotification: InAppNotification, notification: NotificationLog): InAppNotificationView;
@@ -7,16 +7,17 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
- import { User } from '../../authentication/models/user.model.js';
11
- import { TenantEntity, TenantReference, TimestampProperty, UuidProperty } from '../../orm/index.js';
12
- import { NotificationLog } from './notification-log.model.js';
10
+ import { User } from '../../authentication/index.js';
11
+ import { ForeignKey, Index, TenantBaseEntity, TenantReference, TimestampProperty, UuidProperty } from '../../orm/index.js';
12
+ import { Property } from '../../schema/index.js';
13
+ import { NotificationLogEntity } from './notification-log.model.js';
13
14
  import { NotificationTable } from './notification-table.js';
14
- let InAppNotification = class InAppNotification extends TenantEntity {
15
+ let InAppNotification = class InAppNotification extends TenantBaseEntity {
15
16
  static entityName = 'InAppNotification';
16
17
  userId;
17
18
  logId;
18
- readAt;
19
- archivedAt;
19
+ readTimestamp;
20
+ archiveTimestamp;
20
21
  };
21
22
  __decorate([
22
23
  UuidProperty(),
@@ -25,18 +26,32 @@ __decorate([
25
26
  ], InAppNotification.prototype, "userId", void 0);
26
27
  __decorate([
27
28
  UuidProperty(),
28
- TenantReference(() => NotificationLog),
29
29
  __metadata("design:type", String)
30
30
  ], InAppNotification.prototype, "logId", void 0);
31
31
  __decorate([
32
32
  TimestampProperty({ nullable: true }),
33
33
  __metadata("design:type", Object)
34
- ], InAppNotification.prototype, "readAt", void 0);
34
+ ], InAppNotification.prototype, "readTimestamp", void 0);
35
35
  __decorate([
36
36
  TimestampProperty({ nullable: true }),
37
37
  __metadata("design:type", Object)
38
- ], InAppNotification.prototype, "archivedAt", void 0);
38
+ ], InAppNotification.prototype, "archiveTimestamp", void 0);
39
39
  InAppNotification = __decorate([
40
- NotificationTable({ name: 'in_app' })
40
+ NotificationTable({ name: 'in_app' }),
41
+ ForeignKey(() => NotificationLogEntity, ['tenantId', 'logId', 'userId'], ['tenantId', 'id', 'userId']),
42
+ Index(['tenantId', 'userId', 'readTimestamp', 'archiveTimestamp'])
41
43
  ], InAppNotification);
42
44
  export { InAppNotification };
45
+ export class InAppNotificationView extends InAppNotification {
46
+ notification;
47
+ }
48
+ __decorate([
49
+ Property(NotificationLogEntity),
50
+ __metadata("design:type", Object)
51
+ ], InAppNotificationView.prototype, "notification", void 0);
52
+ export function toInAppNotificationView(inAppNotification, notification) {
53
+ return {
54
+ ...inAppNotification,
55
+ notification,
56
+ };
57
+ }
@@ -1,6 +1,6 @@
1
1
  export * from './in-app-notification.model.js';
2
- export * from './notification-category.model.js';
3
2
  export * from './notification-log.model.js';
4
3
  export * from './notification-preference.model.js';
5
4
  export * from './notification-table.js';
5
+ export * from './notification-type.model.js';
6
6
  export * from './web-push-subscription.model.js';
@@ -1,6 +1,6 @@
1
1
  export * from './in-app-notification.model.js';
2
- export * from './notification-category.model.js';
3
2
  export * from './notification-log.model.js';
4
3
  export * from './notification-preference.model.js';
5
4
  export * from './notification-table.js';
5
+ export * from './notification-type.model.js';
6
6
  export * from './web-push-subscription.model.js';
@@ -1,13 +1,50 @@
1
+ import { type EnumType } from '../../enumeration/index.js';
1
2
  import { type Json, TenantEntity, type Uuid } from '../../orm/index.js';
2
3
  import type { ObjectLiteral } from '../../types/types.js';
3
- import { NotificationPriority, NotificationStatus } from '../enums.js';
4
- export declare class NotificationLog extends TenantEntity {
4
+ export declare const NotificationChannel: {
5
+ readonly InApp: "in-app";
6
+ readonly Email: "email";
7
+ readonly WebPush: "web-push";
8
+ };
9
+ export type NotificationChannel = EnumType<typeof NotificationChannel>;
10
+ export declare const NotificationPriority: {
11
+ readonly Low: "low";
12
+ readonly Medium: "medium";
13
+ readonly High: "high";
14
+ readonly Urgent: "urgent";
15
+ };
16
+ export type NotificationPriority = EnumType<typeof NotificationPriority>;
17
+ export declare const NotificationStatus: {
18
+ readonly Pending: "pending";
19
+ readonly Sent: "sent";
20
+ readonly Delivered: "delivered";
21
+ readonly Read: "read";
22
+ readonly Failed: "failed";
23
+ };
24
+ export type NotificationStatus = EnumType<typeof NotificationStatus>;
25
+ export type NotificationDefinition<Payload extends ObjectLiteral = ObjectLiteral> = {
26
+ payload: Payload;
27
+ };
28
+ export type NotificationDefinitionMap<Definition extends Record<string, NotificationDefinition> = Record<string, NotificationDefinition>> = Definition;
29
+ export type NotificationTypes<Definitions extends NotificationDefinitionMap> = Extract<keyof Definitions, string>;
30
+ export type NotificationPayload<Definitions extends NotificationDefinitionMap, Type extends NotificationTypes<Definitions>> = Definitions[Type]['payload'];
31
+ export type NotificationOfType<Definitions extends NotificationDefinitionMap, Type extends NotificationTypes<Definitions>> = string extends NotificationTypes<Definitions> ? NotificationLog<Definitions> & {
32
+ type: Type;
33
+ } : Extract<NotificationLog<Definitions>, {
34
+ type: Type;
35
+ }>;
36
+ export type NotificationLog<Definitions extends NotificationDefinitionMap = NotificationDefinitionMap> = {
37
+ [Type in NotificationTypes<Definitions>]: Omit<NotificationLogEntity<Definitions, Type>, 'type' | 'payload'> & {
38
+ type: Type;
39
+ payload: Json<NotificationPayload<Definitions, Type>> | null;
40
+ };
41
+ }[NotificationTypes<Definitions>];
42
+ export declare class NotificationLogEntity<Definitions extends NotificationDefinitionMap = NotificationDefinitionMap, Type extends NotificationTypes<Definitions> = NotificationTypes<Definitions>> extends TenantEntity {
5
43
  static readonly entityName = "NotificationLog";
6
44
  userId: Uuid;
7
- categoryId: Uuid;
8
- type: string;
45
+ type: Type;
9
46
  priority: NotificationPriority;
10
47
  status: NotificationStatus;
11
48
  currentStep: number;
12
- payload: Json<ObjectLiteral> | null;
49
+ payload: Json<NotificationPayload<Definitions, Type>> | null;
13
50
  }
@@ -8,15 +8,32 @@ var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
10
  import { User } from '../../authentication/models/user.model.js';
11
- import { JsonProperty, TenantEntity, TenantReference, UuidProperty } from '../../orm/index.js';
11
+ import { defineEnum } from '../../enumeration/index.js';
12
+ import { JsonProperty, Reference, TenantEntity, TenantReference, Unique, UuidProperty } from '../../orm/index.js';
12
13
  import { Enumeration, Integer, StringProperty } from '../../schema/index.js';
13
- import { NotificationPriority, NotificationStatus } from '../enums.js';
14
- import { NotificationCategory } from './notification-category.model.js';
15
14
  import { NotificationTable } from './notification-table.js';
16
- let NotificationLog = class NotificationLog extends TenantEntity {
15
+ import { NotificationType } from './notification-type.model.js';
16
+ export const NotificationChannel = defineEnum('NotificationChannel', {
17
+ InApp: 'in-app',
18
+ Email: 'email',
19
+ WebPush: 'web-push',
20
+ });
21
+ export const NotificationPriority = defineEnum('NotificationPriority', {
22
+ Low: 'low',
23
+ Medium: 'medium',
24
+ High: 'high',
25
+ Urgent: 'urgent',
26
+ });
27
+ export const NotificationStatus = defineEnum('NotificationStatus', {
28
+ Pending: 'pending',
29
+ Sent: 'sent',
30
+ Delivered: 'delivered',
31
+ Read: 'read',
32
+ Failed: 'failed',
33
+ });
34
+ let NotificationLogEntity = class NotificationLogEntity extends TenantEntity {
17
35
  static entityName = 'NotificationLog';
18
36
  userId;
19
- categoryId;
20
37
  type;
21
38
  priority;
22
39
  status;
@@ -27,33 +44,30 @@ __decorate([
27
44
  UuidProperty(),
28
45
  TenantReference(() => User),
29
46
  __metadata("design:type", String)
30
- ], NotificationLog.prototype, "userId", void 0);
31
- __decorate([
32
- UuidProperty(),
33
- TenantReference(() => NotificationCategory),
34
- __metadata("design:type", String)
35
- ], NotificationLog.prototype, "categoryId", void 0);
47
+ ], NotificationLogEntity.prototype, "userId", void 0);
36
48
  __decorate([
49
+ Reference(() => NotificationType, 'key'),
37
50
  StringProperty(),
38
51
  __metadata("design:type", String)
39
- ], NotificationLog.prototype, "type", void 0);
52
+ ], NotificationLogEntity.prototype, "type", void 0);
40
53
  __decorate([
41
54
  Enumeration(NotificationPriority),
42
55
  __metadata("design:type", String)
43
- ], NotificationLog.prototype, "priority", void 0);
56
+ ], NotificationLogEntity.prototype, "priority", void 0);
44
57
  __decorate([
45
58
  Enumeration(NotificationStatus),
46
59
  __metadata("design:type", String)
47
- ], NotificationLog.prototype, "status", void 0);
60
+ ], NotificationLogEntity.prototype, "status", void 0);
48
61
  __decorate([
49
62
  Integer(),
50
63
  __metadata("design:type", Number)
51
- ], NotificationLog.prototype, "currentStep", void 0);
64
+ ], NotificationLogEntity.prototype, "currentStep", void 0);
52
65
  __decorate([
53
66
  JsonProperty({ nullable: true }),
54
67
  __metadata("design:type", Object)
55
- ], NotificationLog.prototype, "payload", void 0);
56
- NotificationLog = __decorate([
57
- NotificationTable({ name: 'log' })
58
- ], NotificationLog);
59
- export { NotificationLog };
68
+ ], NotificationLogEntity.prototype, "payload", void 0);
69
+ NotificationLogEntity = __decorate([
70
+ NotificationTable({ name: 'log' }),
71
+ Unique(['tenantId', 'id', 'userId'])
72
+ ], NotificationLogEntity);
73
+ export { NotificationLogEntity };
@@ -1,9 +1,9 @@
1
1
  import { TenantEntity, type Uuid } from '../../orm/index.js';
2
- import { NotificationChannel } from '../enums.js';
2
+ import { NotificationChannel } from './notification-log.model.js';
3
3
  export declare class NotificationPreference extends TenantEntity {
4
4
  static readonly entityName = "NotificationPreference";
5
5
  userId: Uuid;
6
- categoryId: Uuid;
6
+ type: string;
7
7
  channel: NotificationChannel;
8
8
  enabled: boolean;
9
9
  }
@@ -8,15 +8,15 @@ var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
10
  import { User } from '../../authentication/models/user.model.js';
11
- import { TenantEntity, TenantReference, Unique, UuidProperty } from '../../orm/index.js';
12
- import { BooleanProperty, Enumeration } from '../../schema/index.js';
13
- import { NotificationChannel } from '../enums.js';
14
- import { NotificationCategory } from './notification-category.model.js';
11
+ import { Reference, TenantEntity, TenantReference, Unique, UuidProperty } from '../../orm/index.js';
12
+ import { BooleanProperty, Enumeration, StringProperty } from '../../schema/index.js';
13
+ import { NotificationChannel } from './notification-log.model.js';
15
14
  import { NotificationTable } from './notification-table.js';
15
+ import { NotificationType } from './notification-type.model.js';
16
16
  let NotificationPreference = class NotificationPreference extends TenantEntity {
17
17
  static entityName = 'NotificationPreference';
18
18
  userId;
19
- categoryId;
19
+ type;
20
20
  channel;
21
21
  enabled;
22
22
  };
@@ -26,10 +26,10 @@ __decorate([
26
26
  __metadata("design:type", String)
27
27
  ], NotificationPreference.prototype, "userId", void 0);
28
28
  __decorate([
29
- UuidProperty(),
30
- TenantReference(() => NotificationCategory),
29
+ Reference(() => NotificationType, 'key'),
30
+ StringProperty(),
31
31
  __metadata("design:type", String)
32
- ], NotificationPreference.prototype, "categoryId", void 0);
32
+ ], NotificationPreference.prototype, "type", void 0);
33
33
  __decorate([
34
34
  Enumeration(NotificationChannel),
35
35
  __metadata("design:type", String)
@@ -40,6 +40,6 @@ __decorate([
40
40
  ], NotificationPreference.prototype, "enabled", void 0);
41
41
  NotificationPreference = __decorate([
42
42
  NotificationTable({ name: 'preference' }),
43
- Unique(['tenantId', 'userId', 'categoryId', 'channel'])
43
+ Unique(['tenantId', 'userId', 'type', 'channel'])
44
44
  ], NotificationPreference);
45
45
  export { NotificationPreference };
@@ -0,0 +1,17 @@
1
+ import { Entity } from '../../orm/index.js';
2
+ import type { NotificationChannel } from './notification-log.model.js';
3
+ export type ThrottlingConfig = {
4
+ limit: number;
5
+ interval: number;
6
+ };
7
+ export type EscalationRule = {
8
+ delay: number;
9
+ channel: NotificationChannel;
10
+ };
11
+ export declare class NotificationType extends Entity {
12
+ static readonly entityName = "NotificationType";
13
+ label: string;
14
+ key: string;
15
+ throttling: ThrottlingConfig | null;
16
+ escalations: EscalationRule[] | null;
17
+ }