@flusys/nestjs-notification 3.0.1

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 (80) hide show
  1. package/README.md +998 -0
  2. package/adapters/index.d.ts +1 -0
  3. package/adapters/notification.adapter.d.ts +10 -0
  4. package/cjs/adapters/index.js +18 -0
  5. package/cjs/adapters/notification.adapter.js +79 -0
  6. package/cjs/config/index.js +18 -0
  7. package/cjs/config/notification.constants.js +11 -0
  8. package/cjs/controllers/index.js +18 -0
  9. package/cjs/controllers/notification.controller.js +278 -0
  10. package/cjs/docs/index.js +18 -0
  11. package/cjs/docs/notification-swagger.config.js +61 -0
  12. package/cjs/dtos/index.js +18 -0
  13. package/cjs/dtos/notification.dto.js +244 -0
  14. package/cjs/entities/index.js +48 -0
  15. package/cjs/entities/notification-with-company.entity.js +57 -0
  16. package/cjs/entities/notification.entity.js +111 -0
  17. package/cjs/gateways/index.js +18 -0
  18. package/cjs/gateways/notification.gateway.js +226 -0
  19. package/cjs/index.js +28 -0
  20. package/cjs/interfaces/index.js +19 -0
  21. package/cjs/interfaces/notification-module.interface.js +4 -0
  22. package/cjs/interfaces/notification.interface.js +4 -0
  23. package/cjs/modules/index.js +18 -0
  24. package/cjs/modules/notification.module.js +139 -0
  25. package/cjs/services/index.js +21 -0
  26. package/cjs/services/notification-config.service.js +72 -0
  27. package/cjs/services/notification-datasource.provider.js +174 -0
  28. package/cjs/services/notification-helper.service.js +186 -0
  29. package/cjs/services/notification.service.js +220 -0
  30. package/config/index.d.ts +1 -0
  31. package/config/notification.constants.d.ts +1 -0
  32. package/controllers/index.d.ts +1 -0
  33. package/controllers/notification.controller.d.ts +26 -0
  34. package/docs/index.d.ts +1 -0
  35. package/docs/notification-swagger.config.d.ts +2 -0
  36. package/dtos/index.d.ts +1 -0
  37. package/dtos/notification.dto.d.ts +47 -0
  38. package/entities/index.d.ts +8 -0
  39. package/entities/notification-with-company.entity.d.ts +4 -0
  40. package/entities/notification.entity.d.ts +10 -0
  41. package/fesm/adapters/index.js +1 -0
  42. package/fesm/adapters/notification.adapter.js +69 -0
  43. package/fesm/config/index.js +1 -0
  44. package/fesm/config/notification.constants.js +1 -0
  45. package/fesm/controllers/index.js +1 -0
  46. package/fesm/controllers/notification.controller.js +268 -0
  47. package/fesm/docs/index.js +1 -0
  48. package/fesm/docs/notification-swagger.config.js +51 -0
  49. package/fesm/dtos/index.js +1 -0
  50. package/fesm/dtos/notification.dto.js +211 -0
  51. package/fesm/entities/index.js +14 -0
  52. package/fesm/entities/notification-with-company.entity.js +47 -0
  53. package/fesm/entities/notification.entity.js +101 -0
  54. package/fesm/gateways/index.js +1 -0
  55. package/fesm/gateways/notification.gateway.js +175 -0
  56. package/fesm/index.js +20 -0
  57. package/fesm/interfaces/index.js +2 -0
  58. package/fesm/interfaces/notification-module.interface.js +1 -0
  59. package/fesm/interfaces/notification.interface.js +1 -0
  60. package/fesm/modules/index.js +1 -0
  61. package/fesm/modules/notification.module.js +129 -0
  62. package/fesm/services/index.js +4 -0
  63. package/fesm/services/notification-config.service.js +62 -0
  64. package/fesm/services/notification-datasource.provider.js +123 -0
  65. package/fesm/services/notification-helper.service.js +176 -0
  66. package/fesm/services/notification.service.js +210 -0
  67. package/gateways/index.d.ts +1 -0
  68. package/gateways/notification.gateway.d.ts +21 -0
  69. package/index.d.ts +10 -0
  70. package/interfaces/index.d.ts +2 -0
  71. package/interfaces/notification-module.interface.d.ts +20 -0
  72. package/interfaces/notification.interface.d.ts +19 -0
  73. package/modules/index.d.ts +1 -0
  74. package/modules/notification.module.d.ts +8 -0
  75. package/package.json +98 -0
  76. package/services/index.d.ts +4 -0
  77. package/services/notification-config.service.d.ts +13 -0
  78. package/services/notification-datasource.provider.d.ts +23 -0
  79. package/services/notification-helper.service.d.ts +44 -0
  80. package/services/notification.service.d.ts +35 -0
@@ -0,0 +1,47 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ import { Column, Entity, Index } from 'typeorm';
24
+ import { Notification } from './notification.entity';
25
+ export class NotificationWithCompany extends Notification {
26
+ constructor(...args){
27
+ super(...args), _define_property(this, "companyId", void 0);
28
+ }
29
+ }
30
+ _ts_decorate([
31
+ Column({
32
+ name: 'company_id',
33
+ type: 'uuid',
34
+ nullable: true
35
+ }),
36
+ _ts_metadata("design:type", Object)
37
+ ], NotificationWithCompany.prototype, "companyId", void 0);
38
+ NotificationWithCompany = _ts_decorate([
39
+ Entity({
40
+ name: 'notification'
41
+ }),
42
+ Index([
43
+ 'companyId',
44
+ 'userId',
45
+ 'isRead'
46
+ ])
47
+ ], NotificationWithCompany);
@@ -0,0 +1,101 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ import { Identity } from '@flusys/nestjs-shared/entities';
24
+ import { Column, Entity, Index } from 'typeorm';
25
+ import { NotificationType } from '@flusys/nestjs-shared/enums';
26
+ export class Notification extends Identity {
27
+ constructor(...args){
28
+ super(...args), _define_property(this, "userId", void 0), _define_property(this, "type", void 0), _define_property(this, "title", void 0), _define_property(this, "message", void 0), _define_property(this, "data", void 0), _define_property(this, "isRead", void 0), _define_property(this, "readAt", void 0);
29
+ }
30
+ }
31
+ _ts_decorate([
32
+ Column({
33
+ name: 'user_id',
34
+ type: 'uuid',
35
+ nullable: false
36
+ }),
37
+ Index(),
38
+ _ts_metadata("design:type", String)
39
+ ], Notification.prototype, "userId", void 0);
40
+ _ts_decorate([
41
+ Column({
42
+ type: 'varchar',
43
+ length: 50,
44
+ nullable: false,
45
+ default: NotificationType.INFO
46
+ }),
47
+ _ts_metadata("design:type", String)
48
+ ], Notification.prototype, "type", void 0);
49
+ _ts_decorate([
50
+ Column({
51
+ type: 'varchar',
52
+ length: 255,
53
+ nullable: false
54
+ }),
55
+ _ts_metadata("design:type", String)
56
+ ], Notification.prototype, "title", void 0);
57
+ _ts_decorate([
58
+ Column({
59
+ type: 'text',
60
+ nullable: true
61
+ }),
62
+ _ts_metadata("design:type", Object)
63
+ ], Notification.prototype, "message", void 0);
64
+ _ts_decorate([
65
+ Column({
66
+ type: 'simple-json',
67
+ nullable: true
68
+ }),
69
+ _ts_metadata("design:type", Object)
70
+ ], Notification.prototype, "data", void 0);
71
+ _ts_decorate([
72
+ Column({
73
+ name: 'is_read',
74
+ type: 'boolean',
75
+ nullable: false,
76
+ default: false
77
+ }),
78
+ Index(),
79
+ _ts_metadata("design:type", Boolean)
80
+ ], Notification.prototype, "isRead", void 0);
81
+ _ts_decorate([
82
+ Column({
83
+ name: 'read_at',
84
+ type: 'timestamp',
85
+ nullable: true
86
+ }),
87
+ _ts_metadata("design:type", Object)
88
+ ], Notification.prototype, "readAt", void 0);
89
+ Notification = _ts_decorate([
90
+ Entity({
91
+ name: 'notification'
92
+ }),
93
+ Index([
94
+ 'userId',
95
+ 'isRead'
96
+ ]),
97
+ Index([
98
+ 'userId',
99
+ 'createdAt'
100
+ ])
101
+ ], Notification);
@@ -0,0 +1 @@
1
+ export * from './notification.gateway';
@@ -0,0 +1,175 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ function _ts_param(paramIndex, decorator) {
24
+ return function(target, key) {
25
+ decorator(target, key, paramIndex);
26
+ };
27
+ }
28
+ import { Inject, Logger } from '@nestjs/common';
29
+ import { WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
30
+ import { Server } from 'socket.io';
31
+ import * as jwt from 'jsonwebtoken';
32
+ import { NotificationConfigService } from '../services/notification-config.service';
33
+ export class NotificationGateway {
34
+ afterInit() {
35
+ this.logger.log('Notification WebSocket Gateway initialized');
36
+ }
37
+ async handleConnection(client) {
38
+ try {
39
+ const token = this.extractToken(client);
40
+ if (!token) {
41
+ this.logger.warn(`Client ${client.id} connection rejected: No token provided`);
42
+ client.disconnect();
43
+ return;
44
+ }
45
+ const payload = this.verifyToken(token);
46
+ if (!payload) {
47
+ this.logger.warn(`Client ${client.id} connection rejected: Invalid token`);
48
+ client.disconnect();
49
+ return;
50
+ }
51
+ const userId = payload.id;
52
+ client.data.userId = userId;
53
+ client.data.companyId = payload.companyId;
54
+ if (!this.connectedUsers.has(userId)) {
55
+ this.connectedUsers.set(userId, new Set());
56
+ }
57
+ this.connectedUsers.get(userId).add(client.id);
58
+ client.join(`user:${userId}`);
59
+ if (payload.companyId) {
60
+ client.join(`company:${payload.companyId}`);
61
+ }
62
+ this.logger.log(`Client ${client.id} connected for user ${userId}`);
63
+ } catch (error) {
64
+ this.logger.error(`Client ${client.id} connection error: ${error}`);
65
+ client.disconnect();
66
+ }
67
+ }
68
+ handleDisconnect(client) {
69
+ const userId = client.data.userId;
70
+ if (userId) {
71
+ const sockets = this.connectedUsers.get(userId);
72
+ sockets?.delete(client.id);
73
+ if (sockets?.size === 0) {
74
+ this.connectedUsers.delete(userId);
75
+ }
76
+ this.logger.log(`Client ${client.id} disconnected for user ${userId}`);
77
+ }
78
+ }
79
+ emitToUser(userId, event, data) {
80
+ this.server.to(`user:${userId}`).emit(event, data);
81
+ }
82
+ /**
83
+ * Emit to a specific user only on sockets connected with a specific company.
84
+ * This is crucial for multi-company scenarios where a user may be logged in
85
+ * with different companies on different devices.
86
+ *
87
+ * @param userId - The user ID
88
+ * @param companyId - The company ID (if null/undefined, emits to all user's sockets)
89
+ * @param event - The event name
90
+ * @param data - The payload
91
+ */ emitToUserInCompany(userId, companyId, event, data) {
92
+ if (!companyId) {
93
+ // No company context - emit to all user's sockets
94
+ this.emitToUser(userId, event, data);
95
+ return;
96
+ }
97
+ // Get all sockets in the user's room
98
+ const userRoom = `user:${userId}`;
99
+ const sockets = this.server.sockets.adapter.rooms.get(userRoom);
100
+ if (!sockets) {
101
+ this.logger.debug(`No sockets found for user ${userId}`);
102
+ return;
103
+ }
104
+ // Emit only to sockets that match the company context
105
+ for (const socketId of sockets){
106
+ const socket = this.server.sockets.sockets.get(socketId);
107
+ if (socket && socket.data.companyId === companyId) {
108
+ socket.emit(event, data);
109
+ }
110
+ }
111
+ }
112
+ emitToCompany(companyId, event, data) {
113
+ this.server.to(`company:${companyId}`).emit(event, data);
114
+ }
115
+ broadcast(event, data) {
116
+ this.server.emit(event, data);
117
+ }
118
+ isUserOnline(userId) {
119
+ return this.connectedUsers.has(userId);
120
+ }
121
+ getOnlineUserCount() {
122
+ return this.connectedUsers.size;
123
+ }
124
+ extractToken(client) {
125
+ const authToken = client.handshake.auth?.token;
126
+ if (authToken) return authToken;
127
+ const queryToken = client.handshake.query?.token;
128
+ if (typeof queryToken === 'string') return queryToken;
129
+ const authHeader = client.handshake.headers?.authorization;
130
+ if (authHeader?.startsWith('Bearer ')) {
131
+ return authHeader.substring(7);
132
+ }
133
+ return null;
134
+ }
135
+ verifyToken(token) {
136
+ try {
137
+ const secret = this.configService.getJwtSecret();
138
+ if (!secret) {
139
+ this.logger.error('No JWT secret configured for WebSocket authentication');
140
+ return null;
141
+ }
142
+ return jwt.verify(token, secret);
143
+ } catch (error) {
144
+ this.logger.warn(`Token verification failed: ${error}`);
145
+ return null;
146
+ }
147
+ }
148
+ constructor(configService){
149
+ _define_property(this, "configService", void 0);
150
+ _define_property(this, "logger", void 0);
151
+ _define_property(this, "connectedUsers", void 0);
152
+ _define_property(this, "server", void 0);
153
+ this.configService = configService;
154
+ this.logger = new Logger(NotificationGateway.name);
155
+ this.connectedUsers = new Map();
156
+ }
157
+ }
158
+ _ts_decorate([
159
+ WebSocketServer(),
160
+ _ts_metadata("design:type", typeof Server === "undefined" ? Object : Server)
161
+ ], NotificationGateway.prototype, "server", void 0);
162
+ NotificationGateway = _ts_decorate([
163
+ WebSocketGateway({
164
+ namespace: '/notifications',
165
+ cors: {
166
+ origin: '*',
167
+ credentials: true
168
+ }
169
+ }),
170
+ _ts_param(0, Inject(NotificationConfigService)),
171
+ _ts_metadata("design:type", Function),
172
+ _ts_metadata("design:paramtypes", [
173
+ typeof NotificationConfigService === "undefined" ? Object : NotificationConfigService
174
+ ])
175
+ ], NotificationGateway);
package/fesm/index.js ADDED
@@ -0,0 +1,20 @@
1
+ // Adapters
2
+ export * from './adapters';
3
+ // Config
4
+ export * from './config';
5
+ // Controllers
6
+ export * from './controllers';
7
+ // Docs
8
+ export * from './docs';
9
+ // DTOs
10
+ export * from './dtos';
11
+ // Entities
12
+ export * from './entities';
13
+ // Gateways
14
+ export * from './gateways';
15
+ // Interfaces
16
+ export * from './interfaces';
17
+ // Modules
18
+ export * from './modules';
19
+ // Services
20
+ export * from './services';
@@ -0,0 +1,2 @@
1
+ export * from './notification.interface';
2
+ export * from './notification-module.interface';
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1 @@
1
+ export * from './notification.module';
@@ -0,0 +1,129 @@
1
+ function _ts_decorate(decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ }
7
+ import { CacheModule, UtilsModule } from '@flusys/nestjs-shared/modules';
8
+ import { NOTIFICATION_ADAPTER } from '@flusys/nestjs-shared/interfaces';
9
+ import { Module } from '@nestjs/common';
10
+ import { NOTIFICATION_MODULE_OPTIONS } from '../config/notification.constants';
11
+ import { NotificationController } from '../controllers';
12
+ import { NotificationAdapter } from '../adapters';
13
+ import { NotificationConfigService, NotificationDataSourceProvider, NotificationService, NotificationHelperService } from '../services';
14
+ import { NotificationGateway } from '../gateways';
15
+ const CONTROLLERS = [
16
+ NotificationController
17
+ ];
18
+ const EXPORTED_SERVICES = [
19
+ NotificationConfigService,
20
+ NotificationDataSourceProvider,
21
+ NotificationService,
22
+ NotificationHelperService
23
+ ];
24
+ const ADAPTER_PROVIDER = {
25
+ provide: NOTIFICATION_ADAPTER,
26
+ useClass: NotificationAdapter
27
+ };
28
+ export class NotificationModule {
29
+ static forRoot(options) {
30
+ const enableRealtime = options.config?.enableRealtime !== false;
31
+ const gatewayProviders = enableRealtime ? [
32
+ NotificationGateway
33
+ ] : [];
34
+ return {
35
+ module: NotificationModule,
36
+ global: options.global ?? false,
37
+ imports: [
38
+ CacheModule,
39
+ UtilsModule
40
+ ],
41
+ controllers: options.includeController !== false ? CONTROLLERS : [],
42
+ providers: [
43
+ ...this.buildProviders(options),
44
+ ...gatewayProviders,
45
+ NotificationAdapter,
46
+ ADAPTER_PROVIDER
47
+ ],
48
+ exports: [
49
+ ...EXPORTED_SERVICES,
50
+ ...gatewayProviders,
51
+ NOTIFICATION_ADAPTER
52
+ ]
53
+ };
54
+ }
55
+ static forRootAsync(options) {
56
+ return {
57
+ module: NotificationModule,
58
+ global: options.global ?? false,
59
+ imports: [
60
+ ...options.imports || [],
61
+ CacheModule,
62
+ UtilsModule
63
+ ],
64
+ controllers: options.includeController !== false ? CONTROLLERS : [],
65
+ providers: [
66
+ ...this.createAsyncProviders(options),
67
+ ...this.buildProviders(),
68
+ NotificationGateway,
69
+ NotificationAdapter,
70
+ ADAPTER_PROVIDER
71
+ ],
72
+ exports: [
73
+ ...EXPORTED_SERVICES,
74
+ NotificationGateway,
75
+ NOTIFICATION_ADAPTER
76
+ ]
77
+ };
78
+ }
79
+ static buildProviders(options) {
80
+ const providers = [
81
+ ...EXPORTED_SERVICES
82
+ ];
83
+ if (options) {
84
+ providers.unshift({
85
+ provide: NOTIFICATION_MODULE_OPTIONS,
86
+ useValue: options
87
+ });
88
+ }
89
+ return providers;
90
+ }
91
+ static createAsyncProviders(options) {
92
+ if (options.useFactory) {
93
+ return [
94
+ {
95
+ provide: NOTIFICATION_MODULE_OPTIONS,
96
+ useFactory: async (...args)=>({
97
+ ...options,
98
+ config: await options.useFactory(...args)
99
+ }),
100
+ inject: options.inject || []
101
+ }
102
+ ];
103
+ }
104
+ const factoryClass = options.useClass || options.useExisting;
105
+ if (!factoryClass) return [];
106
+ const providers = [
107
+ {
108
+ provide: NOTIFICATION_MODULE_OPTIONS,
109
+ useFactory: async (factory)=>({
110
+ ...options,
111
+ config: await factory.createNotificationOptions()
112
+ }),
113
+ inject: [
114
+ factoryClass
115
+ ]
116
+ }
117
+ ];
118
+ if (options.useClass) {
119
+ providers.push({
120
+ provide: options.useClass,
121
+ useClass: options.useClass
122
+ });
123
+ }
124
+ return providers;
125
+ }
126
+ }
127
+ NotificationModule = _ts_decorate([
128
+ Module({})
129
+ ], NotificationModule);
@@ -0,0 +1,4 @@
1
+ export * from './notification-config.service';
2
+ export * from './notification-datasource.provider';
3
+ export * from './notification.service';
4
+ export * from './notification-helper.service';
@@ -0,0 +1,62 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ function _ts_param(paramIndex, decorator) {
24
+ return function(target, key) {
25
+ decorator(target, key, paramIndex);
26
+ };
27
+ }
28
+ import { Inject, Injectable } from '@nestjs/common';
29
+ import { NotificationModuleOptions } from '../interfaces';
30
+ import { NOTIFICATION_MODULE_OPTIONS } from '../config/notification.constants';
31
+ export class NotificationConfigService {
32
+ isCompanyFeatureEnabled() {
33
+ return this.options.bootstrapAppConfig?.enableCompanyFeature ?? false;
34
+ }
35
+ getDatabaseMode() {
36
+ return this.options.bootstrapAppConfig?.databaseMode ?? 'single';
37
+ }
38
+ isMultiTenant() {
39
+ return this.getDatabaseMode() === 'multi-tenant';
40
+ }
41
+ isRealtimeEnabled() {
42
+ return this.options.config?.enableRealtime !== false;
43
+ }
44
+ getJwtSecret() {
45
+ return this.options.config?.jwtSecret;
46
+ }
47
+ getOptions() {
48
+ return this.options;
49
+ }
50
+ constructor(options){
51
+ _define_property(this, "options", void 0);
52
+ this.options = options;
53
+ }
54
+ }
55
+ NotificationConfigService = _ts_decorate([
56
+ Injectable(),
57
+ _ts_param(0, Inject(NOTIFICATION_MODULE_OPTIONS)),
58
+ _ts_metadata("design:type", Function),
59
+ _ts_metadata("design:paramtypes", [
60
+ typeof NotificationModuleOptions === "undefined" ? Object : NotificationModuleOptions
61
+ ])
62
+ ], NotificationConfigService);
@@ -0,0 +1,123 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ function _ts_param(paramIndex, decorator) {
24
+ return function(target, key) {
25
+ decorator(target, key, paramIndex);
26
+ };
27
+ }
28
+ import { MultiTenantDataSourceService } from '@flusys/nestjs-shared/modules';
29
+ import { Inject, Injectable, InternalServerErrorException, Logger, Optional, Scope } from '@nestjs/common';
30
+ import { REQUEST } from '@nestjs/core';
31
+ import { Request } from 'express';
32
+ import { NotificationConfigService } from './notification-config.service';
33
+ export class NotificationDataSourceProvider extends MultiTenantDataSourceService {
34
+ static buildParentOptions(options) {
35
+ return {
36
+ bootstrapAppConfig: options.bootstrapAppConfig,
37
+ defaultDatabaseConfig: options.config?.defaultDatabaseConfig,
38
+ tenantDefaultDatabaseConfig: options.config?.tenantDefaultDatabaseConfig,
39
+ tenants: options.config?.tenants
40
+ };
41
+ }
42
+ getEnableCompanyFeatureForTenant(tenant) {
43
+ return tenant?.enableCompanyFeature ?? this.configService.isCompanyFeatureEnabled();
44
+ }
45
+ async getNotificationEntities(enableCompanyFeature) {
46
+ const enable = enableCompanyFeature ?? this.configService.isCompanyFeatureEnabled();
47
+ const entities = await import('../entities');
48
+ return enable ? [
49
+ entities.NotificationWithCompany
50
+ ] : [
51
+ entities.Notification
52
+ ];
53
+ }
54
+ async createDataSourceFromConfig(config) {
55
+ const currentTenant = this.getCurrentTenant();
56
+ const enableCompanyFeature = this.getEnableCompanyFeatureForTenant(currentTenant ?? undefined);
57
+ const entities = await this.getNotificationEntities(enableCompanyFeature);
58
+ return super.createDataSourceFromConfig(config, entities);
59
+ }
60
+ async getSingleDataSource() {
61
+ if (NotificationDataSourceProvider.singleDataSource?.isInitialized) {
62
+ return NotificationDataSourceProvider.singleDataSource;
63
+ }
64
+ if (NotificationDataSourceProvider.singleConnectionLock) {
65
+ return NotificationDataSourceProvider.singleConnectionLock;
66
+ }
67
+ const config = this.getDefaultDatabaseConfig();
68
+ if (!config) {
69
+ throw new InternalServerErrorException('No database config available. Provide defaultDatabaseConfig or tenantDefaultDatabaseConfig.');
70
+ }
71
+ const connectionPromise = this.createDataSourceFromConfig(config);
72
+ NotificationDataSourceProvider.singleConnectionLock = connectionPromise;
73
+ try {
74
+ const dataSource = await connectionPromise;
75
+ NotificationDataSourceProvider.singleDataSource = dataSource;
76
+ return dataSource;
77
+ } finally{
78
+ NotificationDataSourceProvider.singleConnectionLock = null;
79
+ }
80
+ }
81
+ async getOrCreateTenantConnection(tenant) {
82
+ const existing = NotificationDataSourceProvider.tenantConnections.get(tenant.id);
83
+ if (existing?.isInitialized) {
84
+ return existing;
85
+ }
86
+ const pendingConnection = NotificationDataSourceProvider.connectionLocks.get(tenant.id);
87
+ if (pendingConnection) {
88
+ return pendingConnection;
89
+ }
90
+ const config = this.buildTenantDatabaseConfig(tenant);
91
+ const connectionPromise = this.createDataSourceFromConfig(config);
92
+ NotificationDataSourceProvider.connectionLocks.set(tenant.id, connectionPromise);
93
+ try {
94
+ const dataSource = await connectionPromise;
95
+ NotificationDataSourceProvider.tenantConnections.set(tenant.id, dataSource);
96
+ return dataSource;
97
+ } finally{
98
+ NotificationDataSourceProvider.connectionLocks.delete(tenant.id);
99
+ }
100
+ }
101
+ constructor(configService, request){
102
+ super(NotificationDataSourceProvider.buildParentOptions(configService.getOptions()), request), _define_property(this, "configService", void 0), _define_property(this, "logger", void 0), this.configService = configService, this.logger = new Logger(NotificationDataSourceProvider.name);
103
+ }
104
+ }
105
+ _define_property(NotificationDataSourceProvider, "tenantConnections", new Map());
106
+ _define_property(NotificationDataSourceProvider, "singleDataSource", null);
107
+ _define_property(NotificationDataSourceProvider, "tenantsRegistry", new Map());
108
+ _define_property(NotificationDataSourceProvider, "initialized", false);
109
+ _define_property(NotificationDataSourceProvider, "connectionLocks", new Map());
110
+ _define_property(NotificationDataSourceProvider, "singleConnectionLock", null);
111
+ NotificationDataSourceProvider = _ts_decorate([
112
+ Injectable({
113
+ scope: Scope.REQUEST
114
+ }),
115
+ _ts_param(0, Inject(NotificationConfigService)),
116
+ _ts_param(1, Optional()),
117
+ _ts_param(1, Inject(REQUEST)),
118
+ _ts_metadata("design:type", Function),
119
+ _ts_metadata("design:paramtypes", [
120
+ typeof NotificationConfigService === "undefined" ? Object : NotificationConfigService,
121
+ typeof Request === "undefined" ? Object : Request
122
+ ])
123
+ ], NotificationDataSourceProvider);