@futdevpro/nts-dynamo 1.9.15 → 1.9.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.copilot/patterns.json +7 -7
- package/.github/workflows/main.yml +206 -0
- package/HOWTO.md +15 -15
- package/README.md +140 -140
- package/build/_models/control-models/endpoint-params.control-model.d.ts.map +1 -1
- package/build/_models/control-models/endpoint-params.control-model.js +2 -0
- package/build/_models/control-models/endpoint-params.control-model.js.map +1 -1
- package/build/_models/control-models/socket-event.control-model.js +1 -1
- package/build/_services/core/global.service.d.ts.map +1 -1
- package/build/_services/core/global.service.js +1 -0
- package/build/_services/core/global.service.js.map +1 -1
- package/build/_services/route/routing-module.service.d.ts +1 -0
- package/build/_services/route/routing-module.service.d.ts.map +1 -1
- package/build/_services/route/routing-module.service.js +17 -23
- package/build/_services/route/routing-module.service.js.map +1 -1
- package/build/_services/server/app.server.d.ts.map +1 -1
- package/build/_services/server/app.server.js +4 -1
- package/build/_services/server/app.server.js.map +1 -1
- package/build/_services/socket/socket-client.service.d.ts.map +1 -1
- package/build/_services/socket/socket-client.service.js +1 -0
- package/build/_services/socket/socket-client.service.js.map +1 -1
- package/nodemon.json +17 -15
- package/package.json +5 -5
- package/src/_constants/global-settings.const.ts +27 -27
- package/src/_constants/index.ts +2 -2
- package/src/_constants/mocks/app-extended-server.mock.ts +198 -198
- package/src/_constants/mocks/app-params.mock.ts +9 -9
- package/src/_constants/mocks/app-server.mock.ts +185 -185
- package/src/_constants/mocks/auth-service.mock.ts +28 -28
- package/src/_constants/mocks/controller.mock.ts +16 -16
- package/src/_constants/mocks/data-model.mock.ts +83 -83
- package/src/_constants/mocks/email-service-collection.mock.ts +13 -13
- package/src/_constants/mocks/email-service.mock.ts +19 -19
- package/src/_constants/mocks/email-template.mock.html +14 -14
- package/src/_constants/mocks/endpoint.mock.ts +90 -90
- package/src/_constants/mocks/socket-client.mock.ts +43 -43
- package/src/_constants/mocks/socket-server.mock.ts +43 -43
- package/src/_enums/data-model-type.enum.ts +14 -14
- package/src/_enums/data-service-function.enum.ts +15 -15
- package/src/_enums/http/http-call-type.enum.ts +12 -12
- package/src/_enums/http/http-response-type.enum.ts +7 -7
- package/src/_enums/http/socket-event-type.enum.ts +18 -18
- package/src/_enums/index.ts +13 -13
- package/src/_enums/predefined-data-types.enum.ts +27 -27
- package/src/_enums/route-security.enum.ts +12 -12
- package/src/_enums/socket-security.enum.ts +11 -11
- package/src/_models/control-models/api-call-params.control-model.ts +126 -126
- package/src/_models/control-models/app-ext-system-controls.control-model.ts +9 -9
- package/src/_models/control-models/app-params.control-model.ts +45 -45
- package/src/_models/control-models/app-system-controls.control-model.ts +9 -9
- package/src/_models/control-models/endpoint-params.control-model.ts +309 -307
- package/src/_models/control-models/http-settings.control-model.ts +29 -29
- package/src/_models/control-models/index.ts +13 -13
- package/src/_models/control-models/socket-client-service-params.control-model.ts +28 -28
- package/src/_models/control-models/socket-event.control-model.ts +150 -150
- package/src/_models/control-models/socket-presence.control-model.ts +207 -207
- package/src/_models/control-models/socket-server-service-params.control-model.ts +20 -20
- package/src/_models/control-models/system-control.control-model.ts +12 -12
- package/src/_models/index.ts +9 -9
- package/src/_models/interfaces/certification-settings.interface.ts +7 -7
- package/src/_models/interfaces/global-service-settings.interface.ts +45 -45
- package/src/_models/interfaces/global-settings.interface.ts +83 -83
- package/src/_models/interfaces/index.ts +7 -7
- package/src/_models/interfaces/routing-module-settings.interface.ts +20 -20
- package/src/_models/types/db-filter.type.ts +108 -108
- package/src/_models/types/db-update.type.ts +100 -100
- package/src/_models/types/index.ts +5 -5
- package/src/_modules/api-service.index.ts +12 -12
- package/src/_modules/app-extended.index.ts +28 -28
- package/src/_modules/app.index.ts +24 -24
- package/src/_modules/auth.index.ts +7 -7
- package/src/_modules/constants.index.ts +2 -2
- package/src/_modules/controller.index.ts +10 -10
- package/src/_modules/custom-data/custom-data.controller.ts +69 -69
- package/src/_modules/custom-data/custom-data.data-service.ts +20 -20
- package/src/_modules/custom-data/get-custom-data-routing-module.util.ts +23 -23
- package/src/_modules/custom-data/index.ts +6 -6
- package/src/_modules/custom-data-module.index.ts +2 -2
- package/src/_modules/data-service.index.ts +9 -9
- package/src/_modules/email.index.ts +8 -8
- package/src/_modules/enums.index.ts +2 -2
- package/src/_modules/extended.index.ts +8 -8
- package/src/_modules/models.index.ts +2 -2
- package/src/_modules/services.index.ts +2 -2
- package/src/_modules/test/get-test-routing-module.util.ts +23 -23
- package/src/_modules/test/index.ts +5 -5
- package/src/_modules/test/test.controller.ts +115 -115
- package/src/_modules/test-module.index.ts +2 -2
- package/src/_modules/usage/get-usage-routing-module.util.ts +22 -22
- package/src/_modules/usage/index.ts +7 -7
- package/src/_modules/usage/usage.controller.ts +120 -120
- package/src/_modules/usage/usage.data-service.ts +172 -172
- package/src/_modules/usage-module.index.ts +2 -2
- package/src/_services/base/data.service.ts +921 -921
- package/src/_services/base/db.service.spec.ts +32 -32
- package/src/_services/base/db.service.ts +1063 -1063
- package/src/_services/base/singleton.service.ts +21 -21
- package/src/_services/core/api.service.ts +453 -453
- package/src/_services/core/auth.service.ts +172 -172
- package/src/_services/core/email.service.ts +678 -678
- package/src/_services/core/global.service.ts +270 -269
- package/src/_services/core/service-collection.service.ts +5 -5
- package/src/_services/index.ts +23 -23
- package/src/_services/route/controller.service.ts +129 -129
- package/src/_services/route/routing-module.service.ts +293 -273
- package/src/_services/server/app-extended.server.spec.ts +76 -76
- package/src/_services/server/app-extended.server.ts +520 -520
- package/src/_services/server/app.server.spec.ts +67 -67
- package/src/_services/server/app.server.ts +1181 -1179
- package/src/_services/shared.service.spec.ts +19 -19
- package/src/_services/shared.static-service.ts +73 -73
- package/src/_services/socket/socket-client.service.ts +236 -235
- package/src/_services/socket/socket-server.service.spec.ts +11 -11
- package/src/_services/socket/socket-server.service.ts +761 -761
- package/src/index.ts +18 -18
- package/tsconfig.json +41 -41
- package/build/tsconfig.tsbuildinfo +0 -1
|
@@ -1,761 +1,761 @@
|
|
|
1
|
-
|
|
2
|
-
import * as SocketIO from 'socket.io';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
DynamoFM_AnyError, DynamoFM_Array, DynamoFM_Error, DynamoFM_Error_Settings, DynamoFM_Log
|
|
6
|
-
} from '@futdevpro/fsm-dynamo';
|
|
7
|
-
|
|
8
|
-
import { DynamoNTS_SingletonService } from '../base/singleton.service';
|
|
9
|
-
import { DynamoNTS_globalSettings } from '../../_constants/global-settings.const';
|
|
10
|
-
import { DynamoNTS_SocketEventKey } from '../../_enums/http/socket-event-type.enum';
|
|
11
|
-
import { DynamoNTS_SocketSecurity } from '../../_enums/socket-security.enum';
|
|
12
|
-
import {
|
|
13
|
-
DynamoNTS_SocketServerService_Params
|
|
14
|
-
} from '../../_models/control-models/socket-server-service-params.control-model';
|
|
15
|
-
import {
|
|
16
|
-
DynamoNTS_SocketPresence
|
|
17
|
-
} from '../../_models/control-models/socket-presence.control-model';
|
|
18
|
-
import {
|
|
19
|
-
DynamoNTS_SocketEvent, DynamoNTS_SocketEventPreprocessTask, DynamoNTS_SocketEventTask
|
|
20
|
-
} from '../../_models/control-models/socket-event.control-model';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* You need to define the following functions:
|
|
24
|
-
* ```ts
|
|
25
|
-
* getServiceParams(): DynamoNTS_SocketServerServiceParams;
|
|
26
|
-
*
|
|
27
|
-
* getIncomingEvents(): DynamoNTS_SocketEvent<any>[];
|
|
28
|
-
*
|
|
29
|
-
* getPresenceFromSubscrioptionEventContent(
|
|
30
|
-
* socketSubscription: T_SubscriptionContent,
|
|
31
|
-
* socket: SocketIO.Socket
|
|
32
|
-
* ): Promise<T_Presence>;
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
export abstract class DynamoNTS_SocketServerService<
|
|
36
|
-
T_Presence extends DynamoNTS_SocketPresence = DynamoNTS_SocketPresence,
|
|
37
|
-
T_SubscriptionContent = any,
|
|
38
|
-
T_ErrorContent = any
|
|
39
|
-
> extends DynamoNTS_SingletonService {
|
|
40
|
-
|
|
41
|
-
protected params: DynamoNTS_SocketServerService_Params;
|
|
42
|
-
get name(): string { return this.params.name; }
|
|
43
|
-
get port(): number { return this.params.port; }
|
|
44
|
-
get security(): DynamoNTS_SocketSecurity { return this.params.security; }
|
|
45
|
-
get activeSubscriptionsCount(): number { return this.presences.length; }
|
|
46
|
-
|
|
47
|
-
protected openSocketServer: SocketIO.Server;
|
|
48
|
-
protected secureSocketServer: SocketIO.Server;
|
|
49
|
-
|
|
50
|
-
private connectEvent: DynamoNTS_SocketEvent<SocketIO.Socket>;
|
|
51
|
-
protected incomingEvents: DynamoNTS_SocketEvent<any>[];
|
|
52
|
-
|
|
53
|
-
private subscriptionEvent: DynamoNTS_SocketEvent<any>;
|
|
54
|
-
private unsubscribeEvent: DynamoNTS_SocketEvent<any>;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* You need to setup a function that converts subscription event content to presence.
|
|
58
|
-
* You should do authentication and authorization here.
|
|
59
|
-
*/
|
|
60
|
-
protected abstract getPresenceFromSubscrioptionEventContent(
|
|
61
|
-
socketSubscription: T_SubscriptionContent, socket: SocketIO.Socket
|
|
62
|
-
): Promise<T_Presence>;
|
|
63
|
-
protected presences: T_Presence[] = [];
|
|
64
|
-
|
|
65
|
-
protected logSetup: boolean;
|
|
66
|
-
protected logFn: boolean;
|
|
67
|
-
|
|
68
|
-
defaultErrorUserMsg =
|
|
69
|
-
`We encountered an unhandled Socket Server Error, ` +
|
|
70
|
-
`\nplease contact the responsible development team.`;
|
|
71
|
-
|
|
72
|
-
constructor(){
|
|
73
|
-
super();
|
|
74
|
-
|
|
75
|
-
this.asyncConstructor().catch((error: any) => {
|
|
76
|
-
DynamoFM_Log.error(
|
|
77
|
-
`Socket Server Service setup failed: ${this.params?.name} (${this.params?.port})`,
|
|
78
|
-
error
|
|
79
|
-
);
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
private async asyncConstructor(): Promise<void> {
|
|
84
|
-
try {
|
|
85
|
-
this.logSetup = DynamoNTS_globalSettings.logSetup;
|
|
86
|
-
this.params = this.getServiceParams();
|
|
87
|
-
this.incomingEvents = this.getIncomingEvents() ?? [];
|
|
88
|
-
|
|
89
|
-
await this.prepareEvents();
|
|
90
|
-
|
|
91
|
-
if (this.logSetup) console.log(
|
|
92
|
-
`Socket Server Service setup done: ${this.params.name} (${this.params.port}) ` +
|
|
93
|
-
`serurity: ${this.params.security}\n`
|
|
94
|
-
);
|
|
95
|
-
} catch (error) {
|
|
96
|
-
DynamoFM_Log.error(
|
|
97
|
-
`Socket Server Service setup failed: ${this.params?.name} (${this.params?.port})`,
|
|
98
|
-
error
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
throw new DynamoFM_Error({
|
|
102
|
-
errorCode: 'NTS-SSS-001',
|
|
103
|
-
error: error,
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* You must setup events and required services for this function
|
|
110
|
-
*/
|
|
111
|
-
private async prepareEvents(): Promise<void> {
|
|
112
|
-
try {
|
|
113
|
-
/** Setup connect event */
|
|
114
|
-
const connectEventIndex = this.incomingEvents.findIndex(
|
|
115
|
-
(event: DynamoNTS_SocketEvent<any>) =>
|
|
116
|
-
event.eventKey === DynamoNTS_SocketEventKey.connection
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
if (0 <= connectEventIndex) {
|
|
120
|
-
this.connectEvent = this.incomingEvents.splice(connectEventIndex)[0];
|
|
121
|
-
} else {
|
|
122
|
-
this.connectEvent = new DynamoNTS_SocketEvent({
|
|
123
|
-
eventKey: DynamoNTS_SocketEventKey.connection,
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
this.connectEvent.serviceName = this.params.name;
|
|
127
|
-
|
|
128
|
-
/** Setup subscriptions events */
|
|
129
|
-
if (this.getPresenceFromSubscrioptionEventContent) {
|
|
130
|
-
/** Setup subscription event */
|
|
131
|
-
const subscriptionEventIndex = this.incomingEvents.findIndex(
|
|
132
|
-
(event: DynamoNTS_SocketEvent<any>) =>
|
|
133
|
-
event.eventKey === DynamoNTS_SocketEventKey.subscribe
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
if (0 <= subscriptionEventIndex) {
|
|
137
|
-
this.subscriptionEvent = this.incomingEvents.splice(subscriptionEventIndex)[0];
|
|
138
|
-
DynamoFM_Log.error(
|
|
139
|
-
`You should not set the subscription event, but the subscriptions tasks, ` +
|
|
140
|
-
`in case you need additional steps for your subscriptions.`,
|
|
141
|
-
`${this.params.name} (${this.params.port})`
|
|
142
|
-
);
|
|
143
|
-
} else {
|
|
144
|
-
this.subscriptionEvent = new DynamoNTS_SocketEvent<T_SubscriptionContent>({
|
|
145
|
-
eventKey: DynamoNTS_SocketEventKey.subscribe,
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (this.getSubscriptionPreProcessess) {
|
|
150
|
-
this.subscriptionEvent.preProcessess.push(...this.getSubscriptionPreProcessess());
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (this.getSubscriptionTasks) {
|
|
154
|
-
this.subscriptionEvent.tasks.push(...this.getSubscriptionTasks());
|
|
155
|
-
}
|
|
156
|
-
this.subscriptionEvent.serviceName = this.params.name;
|
|
157
|
-
|
|
158
|
-
/** Setup subscription event */
|
|
159
|
-
const unsubscribeEventIndex = this.incomingEvents.findIndex(
|
|
160
|
-
(event: DynamoNTS_SocketEvent<any>) =>
|
|
161
|
-
event.eventKey === DynamoNTS_SocketEventKey.unsubscribe
|
|
162
|
-
);
|
|
163
|
-
|
|
164
|
-
if (0 <= unsubscribeEventIndex) {
|
|
165
|
-
this.unsubscribeEvent = this.incomingEvents.splice(unsubscribeEventIndex)[0];
|
|
166
|
-
DynamoFM_Log.error(
|
|
167
|
-
`You should not set the unsubscribe event, but the unsubscribe tasks, ` +
|
|
168
|
-
`in case you need additional steps for your unsubscribe.`,
|
|
169
|
-
`${this.params.name} (${this.params.port})`
|
|
170
|
-
);
|
|
171
|
-
} else {
|
|
172
|
-
this.unsubscribeEvent = new DynamoNTS_SocketEvent<T_SubscriptionContent>({
|
|
173
|
-
eventKey: DynamoNTS_SocketEventKey.unsubscribe,
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (this.getUnsubscribePreProcessess) {
|
|
178
|
-
this.unsubscribeEvent.preProcessess.push(...this.getUnsubscribePreProcessess());
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (this.getUnsubscribeTasks) {
|
|
182
|
-
this.unsubscribeEvent.tasks.push(...this.getUnsubscribeTasks());
|
|
183
|
-
}
|
|
184
|
-
this.unsubscribeEvent.serviceName = this.params.name;
|
|
185
|
-
|
|
186
|
-
/** Setup disconnect event */
|
|
187
|
-
const disconnectEventIndex = this.incomingEvents.findIndex(
|
|
188
|
-
(event: DynamoNTS_SocketEvent<any>) =>
|
|
189
|
-
event.eventKey === DynamoNTS_SocketEventKey.disconnect
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
if (0 <= disconnectEventIndex) {
|
|
193
|
-
this.incomingEvents[disconnectEventIndex].serviceName = this.params.name;
|
|
194
|
-
this.incomingEvents[disconnectEventIndex].tasks.push(this.disconnectBaseTask);
|
|
195
|
-
} else {
|
|
196
|
-
this.incomingEvents.push(
|
|
197
|
-
new DynamoNTS_SocketEvent({
|
|
198
|
-
serviceName: this.params.name,
|
|
199
|
-
eventKey: DynamoNTS_SocketEventKey.disconnect,
|
|
200
|
-
tasks: [
|
|
201
|
-
this.disconnectBaseTask,
|
|
202
|
-
],
|
|
203
|
-
})
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/** Setup error event */
|
|
208
|
-
const errorEventIndex = this.incomingEvents.findIndex(
|
|
209
|
-
(event: DynamoNTS_SocketEvent<any>) => event.eventKey === DynamoNTS_SocketEventKey.error
|
|
210
|
-
);
|
|
211
|
-
|
|
212
|
-
if (errorEventIndex == -1 && this.errorHandling) {
|
|
213
|
-
this.incomingEvents.push(new DynamoNTS_SocketEvent<T_ErrorContent>({
|
|
214
|
-
serviceName: this.params.name,
|
|
215
|
-
eventKey: DynamoNTS_SocketEventKey.error,
|
|
216
|
-
tasks: [
|
|
217
|
-
this.errorHandling,
|
|
218
|
-
],
|
|
219
|
-
}));
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
this.subscriptionEvent.socketName = this.params.name;
|
|
223
|
-
} else {
|
|
224
|
-
DynamoFM_Log.error(
|
|
225
|
-
'getPresenceFromSubscrioptionEventContent is not set',
|
|
226
|
-
`${this.params.name} (${this.params.port})`
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/** Set incoming events serviceName */
|
|
231
|
-
this.incomingEvents.forEach((event: DynamoNTS_SocketEvent<any>) => {
|
|
232
|
-
event.serviceName = this.params.name;
|
|
233
|
-
});
|
|
234
|
-
} catch (error) {
|
|
235
|
-
DynamoFM_Log.error(
|
|
236
|
-
`Socket Server Service - Event Preparation setup failed: ` +
|
|
237
|
-
`${this.params?.name} (${this.params?.port})`,
|
|
238
|
-
error
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
throw error;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// eslint-disable-next-line max-lines-per-function
|
|
246
|
-
async setupSocketServer(
|
|
247
|
-
newSocketServer: SocketIO.Server,
|
|
248
|
-
security: DynamoNTS_SocketSecurity.open | DynamoNTS_SocketSecurity.secure,
|
|
249
|
-
successCallback: () => void
|
|
250
|
-
): Promise<SocketIO.Server> {
|
|
251
|
-
try {
|
|
252
|
-
if (this.logFn) console.log('\nfn:. setupSocketServer');
|
|
253
|
-
|
|
254
|
-
newSocketServer.on(DynamoNTS_SocketEventKey.connection, async (socket: SocketIO.Socket) => {
|
|
255
|
-
try {
|
|
256
|
-
let issuer: string;
|
|
257
|
-
|
|
258
|
-
await this.connectEvent.executeEventTasks(socket);
|
|
259
|
-
|
|
260
|
-
if (this.getPresenceFromSubscrioptionEventContent) {
|
|
261
|
-
socket.on(
|
|
262
|
-
DynamoNTS_SocketEventKey.subscribe,
|
|
263
|
-
async (content: any) => {
|
|
264
|
-
try {
|
|
265
|
-
/**
|
|
266
|
-
* usually socket logs are in event.executeEventTasks(),
|
|
267
|
-
* but subscribe event is an exception from this,
|
|
268
|
-
* to be able to check content before getPresenceFromSubscrioptionEventContent
|
|
269
|
-
*/
|
|
270
|
-
if (DynamoNTS_globalSettings.logSocketEventContent) {
|
|
271
|
-
DynamoFM_Log.log(
|
|
272
|
-
`--=> incoming socket(${this.params.name}) ` +
|
|
273
|
-
`event: ${DynamoNTS_SocketEventKey.subscribe};` +
|
|
274
|
-
`\ncontent:`, content
|
|
275
|
-
);
|
|
276
|
-
} else {
|
|
277
|
-
DynamoFM_Log.log(
|
|
278
|
-
`--=> incoming socket(${this.params.name}) ` +
|
|
279
|
-
`event: ${DynamoNTS_SocketEventKey.subscribe}`
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const presence: T_Presence = await this.getPresenceFromSubscrioptionEventContent(
|
|
284
|
-
content, socket
|
|
285
|
-
);
|
|
286
|
-
|
|
287
|
-
presence.serviceName = this.params.name;
|
|
288
|
-
issuer = presence.issuerId;
|
|
289
|
-
|
|
290
|
-
this.addSocketToPresence(presence);
|
|
291
|
-
await this.subscriptionEvent.executeEventTasks(content, issuer);
|
|
292
|
-
|
|
293
|
-
socket.emit(
|
|
294
|
-
DynamoNTS_SocketEventKey.subscriptionSuccessful,
|
|
295
|
-
'subscribe was successful',
|
|
296
|
-
error => {
|
|
297
|
-
DynamoFM_Log.error(
|
|
298
|
-
`Emitting subscriptionSuccessful event failed!` +
|
|
299
|
-
`\nerror:`, error
|
|
300
|
-
);
|
|
301
|
-
}
|
|
302
|
-
);
|
|
303
|
-
|
|
304
|
-
DynamoFM_Log.success(
|
|
305
|
-
`<-==> socket(${this.params.name}) subscription successfull (${issuer})`
|
|
306
|
-
);
|
|
307
|
-
} catch (error) {
|
|
308
|
-
DynamoFM_Log.error(
|
|
309
|
-
`Socket Subscription failed: ${this.params.name} ` ,
|
|
310
|
-
`(${this.params.port}) will disconnect now...`,
|
|
311
|
-
error
|
|
312
|
-
);
|
|
313
|
-
socket.emit(DynamoNTS_SocketEventKey.error, error);
|
|
314
|
-
socket.disconnect();
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
);
|
|
318
|
-
|
|
319
|
-
socket.on(
|
|
320
|
-
DynamoNTS_SocketEventKey.unsubscribe,
|
|
321
|
-
async (issuer: string) => {
|
|
322
|
-
try {
|
|
323
|
-
/**
|
|
324
|
-
* usually socket logs are in event.executeEventTasks(),
|
|
325
|
-
* but unsubscribe event is an exception from this,
|
|
326
|
-
* to be able to check content before getPresenceFromSubscrioptionEventContent
|
|
327
|
-
*/
|
|
328
|
-
if (DynamoNTS_globalSettings.logSocketEventContent) {
|
|
329
|
-
DynamoFM_Log.log(
|
|
330
|
-
`--=> incoming socket(${this.params.name}) ` +
|
|
331
|
-
`event: ${DynamoNTS_SocketEventKey.unsubscribe};` +
|
|
332
|
-
`\ncontent:`, issuer
|
|
333
|
-
);
|
|
334
|
-
} else {
|
|
335
|
-
DynamoFM_Log.log(
|
|
336
|
-
`--=> incoming socket(${this.params.name}) ` +
|
|
337
|
-
`event: ${DynamoNTS_SocketEventKey.unsubscribe}`
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
this.removeSubscription(socket, issuer);
|
|
342
|
-
|
|
343
|
-
await this.subscriptionEvent.executeEventTasks(issuer, issuer);
|
|
344
|
-
|
|
345
|
-
socket.emit(
|
|
346
|
-
DynamoNTS_SocketEventKey.unsubscribeSuccessful,
|
|
347
|
-
'unsubscribe was successful',
|
|
348
|
-
error => {
|
|
349
|
-
DynamoFM_Log.error(
|
|
350
|
-
`Emitting unsubscribeSuccessful event failed!` +
|
|
351
|
-
`\nerror:`, error
|
|
352
|
-
);
|
|
353
|
-
}
|
|
354
|
-
);
|
|
355
|
-
|
|
356
|
-
DynamoFM_Log.success(
|
|
357
|
-
`< x > socket(${this.params.name}) unsubscribe successfull (${issuer})`
|
|
358
|
-
);
|
|
359
|
-
} catch (error) {
|
|
360
|
-
DynamoFM_Log.error(
|
|
361
|
-
`Socket unsubscribe failed: ${this.params.name} ` ,
|
|
362
|
-
`(${this.params.port}) will disconnect now...`,
|
|
363
|
-
error
|
|
364
|
-
);
|
|
365
|
-
socket.emit(DynamoNTS_SocketEventKey.error, error);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
this.incomingEvents.forEach((event: DynamoNTS_SocketEvent<any>) => {
|
|
372
|
-
socket.on(
|
|
373
|
-
event.eventKey,
|
|
374
|
-
async (content: any) => {
|
|
375
|
-
try {
|
|
376
|
-
await event.executeEventTasks(content, issuer);
|
|
377
|
-
} catch (error) {
|
|
378
|
-
DynamoFM_Log.error(
|
|
379
|
-
`Socket Event failed: ${this.params.name} (${this.params.port})`,
|
|
380
|
-
error
|
|
381
|
-
);
|
|
382
|
-
socket.emit(DynamoNTS_SocketEventKey.error, error);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
);
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
if (DynamoNTS_globalSettings.logMainSocketEvents) {
|
|
389
|
-
DynamoFM_Log.success(`< > socket(${this.params.name}): new CONNECTION established`);
|
|
390
|
-
}
|
|
391
|
-
} catch (error) {
|
|
392
|
-
DynamoFM_Log.error(
|
|
393
|
-
`Socket Connection failed: ${this.params.name} ` +
|
|
394
|
-
`(${this.params.port}) will disconnect now...`,
|
|
395
|
-
error
|
|
396
|
-
);
|
|
397
|
-
socket.emit(DynamoNTS_SocketEventKey.error, error);
|
|
398
|
-
socket.disconnect();
|
|
399
|
-
}
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
newSocketServer.listen(this.params.port);
|
|
403
|
-
|
|
404
|
-
DynamoFM_Log.success(
|
|
405
|
-
`\nsocket server setup finished: ${this.params.name}` +
|
|
406
|
-
`\nsocket server listening on port: ${this.params.port}`
|
|
407
|
-
);
|
|
408
|
-
|
|
409
|
-
successCallback();
|
|
410
|
-
|
|
411
|
-
if (security === DynamoNTS_SocketSecurity.open) {
|
|
412
|
-
this.openSocketServer = newSocketServer;
|
|
413
|
-
|
|
414
|
-
return this.openSocketServer;
|
|
415
|
-
} else {
|
|
416
|
-
this.secureSocketServer = newSocketServer;
|
|
417
|
-
|
|
418
|
-
return this.secureSocketServer;
|
|
419
|
-
}
|
|
420
|
-
} catch (error) {
|
|
421
|
-
DynamoFM_Log.error(
|
|
422
|
-
`Socket Server Service - Deep Setup failed: ${this.params?.name} ` +
|
|
423
|
-
`(${this.params?.port})`,
|
|
424
|
-
error
|
|
425
|
-
);
|
|
426
|
-
|
|
427
|
-
throw error;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
protected async addSocketToPresence(newPresence: T_Presence): Promise<void> {
|
|
432
|
-
try {
|
|
433
|
-
const activePresence: T_Presence = this.presences.find(
|
|
434
|
-
(pres: T_Presence) => pres.issuerId === newPresence.issuerId
|
|
435
|
-
);
|
|
436
|
-
|
|
437
|
-
if (activePresence) {
|
|
438
|
-
activePresence.sockets.push(...newPresence.sockets);
|
|
439
|
-
} else {
|
|
440
|
-
this.presences.push(newPresence);
|
|
441
|
-
}
|
|
442
|
-
} catch (error) {
|
|
443
|
-
DynamoFM_Log.error(
|
|
444
|
-
`Socket Subscription failed: ${this.params?.name} (${this.params?.port})`,
|
|
445
|
-
error
|
|
446
|
-
);
|
|
447
|
-
|
|
448
|
-
throw error;
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
private async disconnectBaseTask(socket: SocketIO.Socket, issuer: string): Promise<void> {
|
|
453
|
-
try {
|
|
454
|
-
await this.removeSubscription(socket, issuer);
|
|
455
|
-
|
|
456
|
-
DynamoFM_Log.info(`< x > socket(${this.params.name}) disconnected (${issuer})`);
|
|
457
|
-
} catch (error) {
|
|
458
|
-
throw new DynamoFM_Error({
|
|
459
|
-
...this._getDefaultErrorSettings(
|
|
460
|
-
'disconnectBaseTask',
|
|
461
|
-
error,
|
|
462
|
-
issuer
|
|
463
|
-
),
|
|
464
|
-
|
|
465
|
-
errorCode: 'NTS-SSS-109',
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
private async removeSubscription(socket: SocketIO.Socket, issuer?: string): Promise<void> {
|
|
471
|
-
try {
|
|
472
|
-
const activePresenceIndex: number = this.presences.findIndex(
|
|
473
|
-
(pres: DynamoNTS_SocketPresence) => pres.sockets.includes(socket)
|
|
474
|
-
);
|
|
475
|
-
|
|
476
|
-
if (activePresenceIndex === -1) {
|
|
477
|
-
throw new DynamoFM_Error({
|
|
478
|
-
...this._getDefaultErrorSettings(
|
|
479
|
-
'sendEventForId',
|
|
480
|
-
new Error(
|
|
481
|
-
`closing socket(${this.params.name}) does not match any in the activePresences`
|
|
482
|
-
),
|
|
483
|
-
issuer
|
|
484
|
-
),
|
|
485
|
-
|
|
486
|
-
errorCode: 'NTS-SSS-203',
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
const activePresence: DynamoNTS_SocketPresence = this.presences[activePresenceIndex];
|
|
491
|
-
|
|
492
|
-
if (activePresence.issuerId !== issuer) {
|
|
493
|
-
throw new DynamoFM_Error({
|
|
494
|
-
...this._getDefaultErrorSettings(
|
|
495
|
-
'sendEventForId',
|
|
496
|
-
new Error(
|
|
497
|
-
`socket subscription for ${issuer} and ${activePresence.issuerId} does not match.`
|
|
498
|
-
),
|
|
499
|
-
issuer
|
|
500
|
-
),
|
|
501
|
-
|
|
502
|
-
errorCode: 'NTS-SSS-201',
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
const socketIndex = activePresence.sockets.findIndex((s: SocketIO.Socket) => s === socket);
|
|
507
|
-
|
|
508
|
-
if (socketIndex === -1) {
|
|
509
|
-
throw new DynamoFM_Error({
|
|
510
|
-
...this._getDefaultErrorSettings(
|
|
511
|
-
'sendEventForId',
|
|
512
|
-
new Error(
|
|
513
|
-
`closing socket(${this.params.name}) does not match any in the activePresences`
|
|
514
|
-
),
|
|
515
|
-
issuer
|
|
516
|
-
),
|
|
517
|
-
|
|
518
|
-
errorCode: 'NTS-SSS-202',
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
activePresence.sockets.splice(socketIndex);
|
|
523
|
-
|
|
524
|
-
if (this.getSubscriptionCloseTasks) {
|
|
525
|
-
await DynamoFM_Array.asyncForEach(
|
|
526
|
-
this.getSubscriptionCloseTasks(),
|
|
527
|
-
async (task: DynamoNTS_SocketEventTask<null>) => {
|
|
528
|
-
await task(null, issuer);
|
|
529
|
-
}
|
|
530
|
-
);
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
if (activePresence.sockets.length === 0) {
|
|
534
|
-
this.presences.splice(activePresenceIndex);
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
socket.disconnect();
|
|
538
|
-
DynamoFM_Log.info(`<x==> socket(${this.params.name}) unsubscription successfull (${issuer})`);
|
|
539
|
-
} catch (error) {
|
|
540
|
-
throw new DynamoFM_Error({
|
|
541
|
-
...this._getDefaultErrorSettings(
|
|
542
|
-
'sendEventForId',
|
|
543
|
-
error,
|
|
544
|
-
issuer
|
|
545
|
-
),
|
|
546
|
-
|
|
547
|
-
errorCode: 'NTS-SSS-200',
|
|
548
|
-
message: `socket(${this.params.name}) Subscription Removal failed: ${this.params?.name}`,
|
|
549
|
-
});
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
/* emitServerEvent(event: string, content: any): void {
|
|
554
|
-
try {
|
|
555
|
-
DynamoFM_Log.log(` <=-- emitting server socket(${this.params.name}) event: ${event}`);
|
|
556
|
-
|
|
557
|
-
this.openSocketServer.emit(event, content, error => {
|
|
558
|
-
DynamoFM_Log.error(`Emitting server event '${event}' failed!\nerror:`, error);
|
|
559
|
-
});
|
|
560
|
-
} catch (error) {
|
|
561
|
-
throw new DynamoFM_Error({
|
|
562
|
-
...this._getDefaultErrorSettings(
|
|
563
|
-
'emitEvent',
|
|
564
|
-
error
|
|
565
|
-
),
|
|
566
|
-
|
|
567
|
-
errorCode: 'NTS-SSS-500',
|
|
568
|
-
message: `socket(${this.params.name}) Event Emit (${event}) failed: ${this.params?.name}`,
|
|
569
|
-
});
|
|
570
|
-
}
|
|
571
|
-
} */
|
|
572
|
-
|
|
573
|
-
idIsSubscribed(id: string): boolean {
|
|
574
|
-
try {
|
|
575
|
-
return !!this.presences.find(
|
|
576
|
-
(presence: DynamoNTS_SocketPresence) => presence.issuerId === id
|
|
577
|
-
);
|
|
578
|
-
} catch (error) {
|
|
579
|
-
throw new DynamoFM_Error({
|
|
580
|
-
...this._getDefaultErrorSettings(
|
|
581
|
-
'idIsSubscribed',
|
|
582
|
-
error
|
|
583
|
-
),
|
|
584
|
-
|
|
585
|
-
errorCode: 'NTS-SSS-600',
|
|
586
|
-
message: `socket(${this.params.name}) ID Subscription Check (${id}) failed`,
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
async emitError(presenceIssuerId: string, error: any, issuer: string): Promise<void> {
|
|
592
|
-
try {
|
|
593
|
-
await this.sendEventForId(presenceIssuerId, DynamoNTS_SocketEventKey.error, error, issuer);
|
|
594
|
-
} catch (error) {
|
|
595
|
-
throw new DynamoFM_Error({
|
|
596
|
-
...this._getDefaultErrorSettings(
|
|
597
|
-
'emitError',
|
|
598
|
-
error,
|
|
599
|
-
presenceIssuerId
|
|
600
|
-
),
|
|
601
|
-
|
|
602
|
-
errorCode: 'NTS-SSS-700',
|
|
603
|
-
message: `socket(${this.params.name}) Error Emit (id: ${presenceIssuerId}) failed`,
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
async sendEventForId(id: string, event: string, content: any, issuer: string): Promise<void> {
|
|
609
|
-
try {
|
|
610
|
-
const presence: DynamoNTS_SocketPresence = this.presences.find(
|
|
611
|
-
(pres: DynamoNTS_SocketPresence) => pres.issuerId === id
|
|
612
|
-
);
|
|
613
|
-
|
|
614
|
-
if (!presence) {
|
|
615
|
-
throw new DynamoFM_Error({
|
|
616
|
-
...this._getDefaultErrorSettings(
|
|
617
|
-
'sendEventForId',
|
|
618
|
-
new Error(`No active socket with this specific ID: ${id}`),
|
|
619
|
-
content?.source
|
|
620
|
-
),
|
|
621
|
-
|
|
622
|
-
status: 404,
|
|
623
|
-
errorCode: 'NTS-SSS-301',
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
presence.emitEvent(event, content, issuer);
|
|
628
|
-
|
|
629
|
-
if (DynamoNTS_globalSettings.logSocketEventContent) {
|
|
630
|
-
DynamoFM_Log.success(
|
|
631
|
-
` <--= emitted socket(${this.params.name}) event for presence: ${event}, ` +
|
|
632
|
-
`\n presenceId: ${id}, sockets: ${presence.sockets.length}` +
|
|
633
|
-
`\n content:`, content
|
|
634
|
-
);
|
|
635
|
-
} else {
|
|
636
|
-
DynamoFM_Log.success(
|
|
637
|
-
` <--= emitted socket(${this.params.name}) event for presence: ${event}, ` +
|
|
638
|
-
`\n presenceId: ${id}, sockets: ${presence.sockets.length}`
|
|
639
|
-
);
|
|
640
|
-
}
|
|
641
|
-
} catch (error) {
|
|
642
|
-
try {
|
|
643
|
-
if (error.flag.includes('DYNAMO') && error?.accitionalInfo?.inactiveSockets) {
|
|
644
|
-
const sockets: SocketIO.Socket[] = error.accitionalInfo.inactiveSockets;
|
|
645
|
-
|
|
646
|
-
await DynamoFM_Array.asyncForEach(sockets, async (socket: SocketIO.Socket) => {
|
|
647
|
-
await this.removeSubscription(socket);
|
|
648
|
-
});
|
|
649
|
-
|
|
650
|
-
const presence: DynamoNTS_SocketPresence = this.presences.find(
|
|
651
|
-
(pres: DynamoNTS_SocketPresence) => pres.issuerId === id
|
|
652
|
-
);
|
|
653
|
-
|
|
654
|
-
if (!presence) {
|
|
655
|
-
throw new DynamoFM_Error({
|
|
656
|
-
...this._getDefaultErrorSettings(
|
|
657
|
-
'sendEventForId',
|
|
658
|
-
new Error(`No active socket(${this.params.name}) with this specific ID: ${id}`),
|
|
659
|
-
content?.source
|
|
660
|
-
),
|
|
661
|
-
|
|
662
|
-
status: 404,
|
|
663
|
-
errorCode: 'NTS-SSS-302',
|
|
664
|
-
});
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
} catch (error) {
|
|
668
|
-
throw new DynamoFM_Error({
|
|
669
|
-
...this._getDefaultErrorSettings('sendEventForId', error, content?.source),
|
|
670
|
-
|
|
671
|
-
errorCode: 'NTS-SSS-310',
|
|
672
|
-
message:
|
|
673
|
-
`Error handling of inactive sockets(${this.params.name}) failed!` +
|
|
674
|
-
`\n(Socket Event Emit for id (${id}, ${event}) failed)`,
|
|
675
|
-
});
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
throw new DynamoFM_Error({
|
|
679
|
-
...this._getDefaultErrorSettings('sendEventForId', error, content?.source),
|
|
680
|
-
|
|
681
|
-
errorCode: 'NTS-SSS-310',
|
|
682
|
-
message: `socket(${this.params.name}) Event Emit for id (${id}, ${event}) failed`,
|
|
683
|
-
});
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
broadcastEvent(event: string, content: any, issuer: string): void {
|
|
688
|
-
try {
|
|
689
|
-
DynamoFM_Log.log(` <=-== broadcasting socket(${this.params.name}) event: ${event}`);
|
|
690
|
-
|
|
691
|
-
this.presences.forEach((presence: DynamoNTS_SocketPresence) => {
|
|
692
|
-
presence.emitEvent(event, content, issuer);
|
|
693
|
-
});
|
|
694
|
-
} catch (error) {
|
|
695
|
-
DynamoFM_Log.error(`socket(${this.params.name}) Event Broadcast (${event}) failed`, error);
|
|
696
|
-
|
|
697
|
-
throw new DynamoFM_Error({
|
|
698
|
-
...this._getDefaultErrorSettings('broadcastEvent', error),
|
|
699
|
-
|
|
700
|
-
errorCode: 'NTS-SSS-400',
|
|
701
|
-
message: `socket(${this.params.name}) Event Broadcast (${event}) failed`,
|
|
702
|
-
});
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
private _getDefaultErrorSettings(
|
|
707
|
-
fnName: string,
|
|
708
|
-
error: DynamoFM_AnyError,
|
|
709
|
-
issuer?: string
|
|
710
|
-
): DynamoFM_Error_Settings {
|
|
711
|
-
return {
|
|
712
|
-
status: (error as DynamoFM_Error)?.___status ?? 500,
|
|
713
|
-
message: (error as Error)?.message ?? `${fnName} was UNSUCCESFUL (NTS)`,
|
|
714
|
-
addECToUserMsg: !(error as DynamoFM_Error)?.__userMessage,
|
|
715
|
-
userMessage: (error as DynamoFM_Error)?.__userMessage ?? this.defaultErrorUserMsg,
|
|
716
|
-
issuer: issuer,
|
|
717
|
-
issuerService: this.constructor?.name,
|
|
718
|
-
error: error,
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
/**
|
|
723
|
-
* You must setup params for the service in this function
|
|
724
|
-
*/
|
|
725
|
-
protected abstract getServiceParams(): DynamoNTS_SocketServerService_Params;
|
|
726
|
-
|
|
727
|
-
/**
|
|
728
|
-
* You must setup events and required services in this function
|
|
729
|
-
*/
|
|
730
|
-
protected abstract getIncomingEvents(): DynamoNTS_SocketEvent<any>[];
|
|
731
|
-
|
|
732
|
-
/**
|
|
733
|
-
* You can setup tasks for the subscription event in this function
|
|
734
|
-
*/
|
|
735
|
-
protected getSubscriptionTasks?(): DynamoNTS_SocketEventTask<T_SubscriptionContent>[];
|
|
736
|
-
|
|
737
|
-
/**
|
|
738
|
-
* You can setup tasks for the subscription event in this function
|
|
739
|
-
*/
|
|
740
|
-
protected getSubscriptionCloseTasks?(): DynamoNTS_SocketEventTask<null>[];
|
|
741
|
-
|
|
742
|
-
/**
|
|
743
|
-
* You can setup preprocessess for the subscription event in this function
|
|
744
|
-
*/
|
|
745
|
-
protected getSubscriptionPreProcessess?(): DynamoNTS_SocketEventPreprocessTask[];
|
|
746
|
-
|
|
747
|
-
/**
|
|
748
|
-
* You can setup tasks for the unsubscribe event in this function
|
|
749
|
-
*/
|
|
750
|
-
protected getUnsubscribeTasks?(): DynamoNTS_SocketEventTask<T_SubscriptionContent>[];
|
|
751
|
-
|
|
752
|
-
/**
|
|
753
|
-
* You can setup preprocessess for the unsubscribe event in this function
|
|
754
|
-
*/
|
|
755
|
-
protected getUnsubscribePreProcessess?(): DynamoNTS_SocketEventPreprocessTask[];
|
|
756
|
-
|
|
757
|
-
/**
|
|
758
|
-
* You can setup tasks for the error event in this function
|
|
759
|
-
*/
|
|
760
|
-
protected errorHandling?: DynamoNTS_SocketEventTask<T_ErrorContent>;
|
|
761
|
-
}
|
|
1
|
+
|
|
2
|
+
import * as SocketIO from 'socket.io';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
DynamoFM_AnyError, DynamoFM_Array, DynamoFM_Error, DynamoFM_Error_Settings, DynamoFM_Log
|
|
6
|
+
} from '@futdevpro/fsm-dynamo';
|
|
7
|
+
|
|
8
|
+
import { DynamoNTS_SingletonService } from '../base/singleton.service';
|
|
9
|
+
import { DynamoNTS_globalSettings } from '../../_constants/global-settings.const';
|
|
10
|
+
import { DynamoNTS_SocketEventKey } from '../../_enums/http/socket-event-type.enum';
|
|
11
|
+
import { DynamoNTS_SocketSecurity } from '../../_enums/socket-security.enum';
|
|
12
|
+
import {
|
|
13
|
+
DynamoNTS_SocketServerService_Params
|
|
14
|
+
} from '../../_models/control-models/socket-server-service-params.control-model';
|
|
15
|
+
import {
|
|
16
|
+
DynamoNTS_SocketPresence
|
|
17
|
+
} from '../../_models/control-models/socket-presence.control-model';
|
|
18
|
+
import {
|
|
19
|
+
DynamoNTS_SocketEvent, DynamoNTS_SocketEventPreprocessTask, DynamoNTS_SocketEventTask
|
|
20
|
+
} from '../../_models/control-models/socket-event.control-model';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* You need to define the following functions:
|
|
24
|
+
* ```ts
|
|
25
|
+
* getServiceParams(): DynamoNTS_SocketServerServiceParams;
|
|
26
|
+
*
|
|
27
|
+
* getIncomingEvents(): DynamoNTS_SocketEvent<any>[];
|
|
28
|
+
*
|
|
29
|
+
* getPresenceFromSubscrioptionEventContent(
|
|
30
|
+
* socketSubscription: T_SubscriptionContent,
|
|
31
|
+
* socket: SocketIO.Socket
|
|
32
|
+
* ): Promise<T_Presence>;
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export abstract class DynamoNTS_SocketServerService<
|
|
36
|
+
T_Presence extends DynamoNTS_SocketPresence = DynamoNTS_SocketPresence,
|
|
37
|
+
T_SubscriptionContent = any,
|
|
38
|
+
T_ErrorContent = any
|
|
39
|
+
> extends DynamoNTS_SingletonService {
|
|
40
|
+
|
|
41
|
+
protected params: DynamoNTS_SocketServerService_Params;
|
|
42
|
+
get name(): string { return this.params.name; }
|
|
43
|
+
get port(): number { return this.params.port; }
|
|
44
|
+
get security(): DynamoNTS_SocketSecurity { return this.params.security; }
|
|
45
|
+
get activeSubscriptionsCount(): number { return this.presences.length; }
|
|
46
|
+
|
|
47
|
+
protected openSocketServer: SocketIO.Server;
|
|
48
|
+
protected secureSocketServer: SocketIO.Server;
|
|
49
|
+
|
|
50
|
+
private connectEvent: DynamoNTS_SocketEvent<SocketIO.Socket>;
|
|
51
|
+
protected incomingEvents: DynamoNTS_SocketEvent<any>[];
|
|
52
|
+
|
|
53
|
+
private subscriptionEvent: DynamoNTS_SocketEvent<any>;
|
|
54
|
+
private unsubscribeEvent: DynamoNTS_SocketEvent<any>;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* You need to setup a function that converts subscription event content to presence.
|
|
58
|
+
* You should do authentication and authorization here.
|
|
59
|
+
*/
|
|
60
|
+
protected abstract getPresenceFromSubscrioptionEventContent(
|
|
61
|
+
socketSubscription: T_SubscriptionContent, socket: SocketIO.Socket
|
|
62
|
+
): Promise<T_Presence>;
|
|
63
|
+
protected presences: T_Presence[] = [];
|
|
64
|
+
|
|
65
|
+
protected logSetup: boolean;
|
|
66
|
+
protected logFn: boolean;
|
|
67
|
+
|
|
68
|
+
defaultErrorUserMsg =
|
|
69
|
+
`We encountered an unhandled Socket Server Error, ` +
|
|
70
|
+
`\nplease contact the responsible development team.`;
|
|
71
|
+
|
|
72
|
+
constructor(){
|
|
73
|
+
super();
|
|
74
|
+
|
|
75
|
+
this.asyncConstructor().catch((error: any) => {
|
|
76
|
+
DynamoFM_Log.error(
|
|
77
|
+
`Socket Server Service setup failed: ${this.params?.name} (${this.params?.port})`,
|
|
78
|
+
error
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private async asyncConstructor(): Promise<void> {
|
|
84
|
+
try {
|
|
85
|
+
this.logSetup = DynamoNTS_globalSettings.logSetup;
|
|
86
|
+
this.params = this.getServiceParams();
|
|
87
|
+
this.incomingEvents = this.getIncomingEvents() ?? [];
|
|
88
|
+
|
|
89
|
+
await this.prepareEvents();
|
|
90
|
+
|
|
91
|
+
if (this.logSetup) console.log(
|
|
92
|
+
`Socket Server Service setup done: ${this.params.name} (${this.params.port}) ` +
|
|
93
|
+
`serurity: ${this.params.security}\n`
|
|
94
|
+
);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
DynamoFM_Log.error(
|
|
97
|
+
`Socket Server Service setup failed: ${this.params?.name} (${this.params?.port})`,
|
|
98
|
+
error
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
throw new DynamoFM_Error({
|
|
102
|
+
errorCode: 'NTS-SSS-001',
|
|
103
|
+
error: error,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* You must setup events and required services for this function
|
|
110
|
+
*/
|
|
111
|
+
private async prepareEvents(): Promise<void> {
|
|
112
|
+
try {
|
|
113
|
+
/** Setup connect event */
|
|
114
|
+
const connectEventIndex = this.incomingEvents.findIndex(
|
|
115
|
+
(event: DynamoNTS_SocketEvent<any>) =>
|
|
116
|
+
event.eventKey === DynamoNTS_SocketEventKey.connection
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
if (0 <= connectEventIndex) {
|
|
120
|
+
this.connectEvent = this.incomingEvents.splice(connectEventIndex)[0];
|
|
121
|
+
} else {
|
|
122
|
+
this.connectEvent = new DynamoNTS_SocketEvent({
|
|
123
|
+
eventKey: DynamoNTS_SocketEventKey.connection,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
this.connectEvent.serviceName = this.params.name;
|
|
127
|
+
|
|
128
|
+
/** Setup subscriptions events */
|
|
129
|
+
if (this.getPresenceFromSubscrioptionEventContent) {
|
|
130
|
+
/** Setup subscription event */
|
|
131
|
+
const subscriptionEventIndex = this.incomingEvents.findIndex(
|
|
132
|
+
(event: DynamoNTS_SocketEvent<any>) =>
|
|
133
|
+
event.eventKey === DynamoNTS_SocketEventKey.subscribe
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
if (0 <= subscriptionEventIndex) {
|
|
137
|
+
this.subscriptionEvent = this.incomingEvents.splice(subscriptionEventIndex)[0];
|
|
138
|
+
DynamoFM_Log.error(
|
|
139
|
+
`You should not set the subscription event, but the subscriptions tasks, ` +
|
|
140
|
+
`in case you need additional steps for your subscriptions.`,
|
|
141
|
+
`${this.params.name} (${this.params.port})`
|
|
142
|
+
);
|
|
143
|
+
} else {
|
|
144
|
+
this.subscriptionEvent = new DynamoNTS_SocketEvent<T_SubscriptionContent>({
|
|
145
|
+
eventKey: DynamoNTS_SocketEventKey.subscribe,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (this.getSubscriptionPreProcessess) {
|
|
150
|
+
this.subscriptionEvent.preProcessess.push(...this.getSubscriptionPreProcessess());
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (this.getSubscriptionTasks) {
|
|
154
|
+
this.subscriptionEvent.tasks.push(...this.getSubscriptionTasks());
|
|
155
|
+
}
|
|
156
|
+
this.subscriptionEvent.serviceName = this.params.name;
|
|
157
|
+
|
|
158
|
+
/** Setup subscription event */
|
|
159
|
+
const unsubscribeEventIndex = this.incomingEvents.findIndex(
|
|
160
|
+
(event: DynamoNTS_SocketEvent<any>) =>
|
|
161
|
+
event.eventKey === DynamoNTS_SocketEventKey.unsubscribe
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
if (0 <= unsubscribeEventIndex) {
|
|
165
|
+
this.unsubscribeEvent = this.incomingEvents.splice(unsubscribeEventIndex)[0];
|
|
166
|
+
DynamoFM_Log.error(
|
|
167
|
+
`You should not set the unsubscribe event, but the unsubscribe tasks, ` +
|
|
168
|
+
`in case you need additional steps for your unsubscribe.`,
|
|
169
|
+
`${this.params.name} (${this.params.port})`
|
|
170
|
+
);
|
|
171
|
+
} else {
|
|
172
|
+
this.unsubscribeEvent = new DynamoNTS_SocketEvent<T_SubscriptionContent>({
|
|
173
|
+
eventKey: DynamoNTS_SocketEventKey.unsubscribe,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (this.getUnsubscribePreProcessess) {
|
|
178
|
+
this.unsubscribeEvent.preProcessess.push(...this.getUnsubscribePreProcessess());
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (this.getUnsubscribeTasks) {
|
|
182
|
+
this.unsubscribeEvent.tasks.push(...this.getUnsubscribeTasks());
|
|
183
|
+
}
|
|
184
|
+
this.unsubscribeEvent.serviceName = this.params.name;
|
|
185
|
+
|
|
186
|
+
/** Setup disconnect event */
|
|
187
|
+
const disconnectEventIndex = this.incomingEvents.findIndex(
|
|
188
|
+
(event: DynamoNTS_SocketEvent<any>) =>
|
|
189
|
+
event.eventKey === DynamoNTS_SocketEventKey.disconnect
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
if (0 <= disconnectEventIndex) {
|
|
193
|
+
this.incomingEvents[disconnectEventIndex].serviceName = this.params.name;
|
|
194
|
+
this.incomingEvents[disconnectEventIndex].tasks.push(this.disconnectBaseTask);
|
|
195
|
+
} else {
|
|
196
|
+
this.incomingEvents.push(
|
|
197
|
+
new DynamoNTS_SocketEvent({
|
|
198
|
+
serviceName: this.params.name,
|
|
199
|
+
eventKey: DynamoNTS_SocketEventKey.disconnect,
|
|
200
|
+
tasks: [
|
|
201
|
+
this.disconnectBaseTask,
|
|
202
|
+
],
|
|
203
|
+
})
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** Setup error event */
|
|
208
|
+
const errorEventIndex = this.incomingEvents.findIndex(
|
|
209
|
+
(event: DynamoNTS_SocketEvent<any>) => event.eventKey === DynamoNTS_SocketEventKey.error
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
if (errorEventIndex == -1 && this.errorHandling) {
|
|
213
|
+
this.incomingEvents.push(new DynamoNTS_SocketEvent<T_ErrorContent>({
|
|
214
|
+
serviceName: this.params.name,
|
|
215
|
+
eventKey: DynamoNTS_SocketEventKey.error,
|
|
216
|
+
tasks: [
|
|
217
|
+
this.errorHandling,
|
|
218
|
+
],
|
|
219
|
+
}));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
this.subscriptionEvent.socketName = this.params.name;
|
|
223
|
+
} else {
|
|
224
|
+
DynamoFM_Log.error(
|
|
225
|
+
'getPresenceFromSubscrioptionEventContent is not set',
|
|
226
|
+
`${this.params.name} (${this.params.port})`
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** Set incoming events serviceName */
|
|
231
|
+
this.incomingEvents.forEach((event: DynamoNTS_SocketEvent<any>) => {
|
|
232
|
+
event.serviceName = this.params.name;
|
|
233
|
+
});
|
|
234
|
+
} catch (error) {
|
|
235
|
+
DynamoFM_Log.error(
|
|
236
|
+
`Socket Server Service - Event Preparation setup failed: ` +
|
|
237
|
+
`${this.params?.name} (${this.params?.port})`,
|
|
238
|
+
error
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
throw error;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// eslint-disable-next-line max-lines-per-function
|
|
246
|
+
async setupSocketServer(
|
|
247
|
+
newSocketServer: SocketIO.Server,
|
|
248
|
+
security: DynamoNTS_SocketSecurity.open | DynamoNTS_SocketSecurity.secure,
|
|
249
|
+
successCallback: () => void
|
|
250
|
+
): Promise<SocketIO.Server> {
|
|
251
|
+
try {
|
|
252
|
+
if (this.logFn) console.log('\nfn:. setupSocketServer');
|
|
253
|
+
|
|
254
|
+
newSocketServer.on(DynamoNTS_SocketEventKey.connection, async (socket: SocketIO.Socket) => {
|
|
255
|
+
try {
|
|
256
|
+
let issuer: string;
|
|
257
|
+
|
|
258
|
+
await this.connectEvent.executeEventTasks(socket);
|
|
259
|
+
|
|
260
|
+
if (this.getPresenceFromSubscrioptionEventContent) {
|
|
261
|
+
socket.on(
|
|
262
|
+
DynamoNTS_SocketEventKey.subscribe,
|
|
263
|
+
async (content: any) => {
|
|
264
|
+
try {
|
|
265
|
+
/**
|
|
266
|
+
* usually socket logs are in event.executeEventTasks(),
|
|
267
|
+
* but subscribe event is an exception from this,
|
|
268
|
+
* to be able to check content before getPresenceFromSubscrioptionEventContent
|
|
269
|
+
*/
|
|
270
|
+
if (DynamoNTS_globalSettings.logSocketEventContent) {
|
|
271
|
+
DynamoFM_Log.log(
|
|
272
|
+
`--=> incoming socket(${this.params.name}) ` +
|
|
273
|
+
`event: ${DynamoNTS_SocketEventKey.subscribe};` +
|
|
274
|
+
`\ncontent:`, content
|
|
275
|
+
);
|
|
276
|
+
} else {
|
|
277
|
+
DynamoFM_Log.log(
|
|
278
|
+
`--=> incoming socket(${this.params.name}) ` +
|
|
279
|
+
`event: ${DynamoNTS_SocketEventKey.subscribe}`
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const presence: T_Presence = await this.getPresenceFromSubscrioptionEventContent(
|
|
284
|
+
content, socket
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
presence.serviceName = this.params.name;
|
|
288
|
+
issuer = presence.issuerId;
|
|
289
|
+
|
|
290
|
+
this.addSocketToPresence(presence);
|
|
291
|
+
await this.subscriptionEvent.executeEventTasks(content, issuer);
|
|
292
|
+
|
|
293
|
+
socket.emit(
|
|
294
|
+
DynamoNTS_SocketEventKey.subscriptionSuccessful,
|
|
295
|
+
'subscribe was successful',
|
|
296
|
+
error => {
|
|
297
|
+
DynamoFM_Log.error(
|
|
298
|
+
`Emitting subscriptionSuccessful event failed!` +
|
|
299
|
+
`\nerror:`, error
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
DynamoFM_Log.success(
|
|
305
|
+
`<-==> socket(${this.params.name}) subscription successfull (${issuer})`
|
|
306
|
+
);
|
|
307
|
+
} catch (error) {
|
|
308
|
+
DynamoFM_Log.error(
|
|
309
|
+
`Socket Subscription failed: ${this.params.name} ` ,
|
|
310
|
+
`(${this.params.port}) will disconnect now...`,
|
|
311
|
+
error
|
|
312
|
+
);
|
|
313
|
+
socket.emit(DynamoNTS_SocketEventKey.error, error);
|
|
314
|
+
socket.disconnect();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
socket.on(
|
|
320
|
+
DynamoNTS_SocketEventKey.unsubscribe,
|
|
321
|
+
async (issuer: string) => {
|
|
322
|
+
try {
|
|
323
|
+
/**
|
|
324
|
+
* usually socket logs are in event.executeEventTasks(),
|
|
325
|
+
* but unsubscribe event is an exception from this,
|
|
326
|
+
* to be able to check content before getPresenceFromSubscrioptionEventContent
|
|
327
|
+
*/
|
|
328
|
+
if (DynamoNTS_globalSettings.logSocketEventContent) {
|
|
329
|
+
DynamoFM_Log.log(
|
|
330
|
+
`--=> incoming socket(${this.params.name}) ` +
|
|
331
|
+
`event: ${DynamoNTS_SocketEventKey.unsubscribe};` +
|
|
332
|
+
`\ncontent:`, issuer
|
|
333
|
+
);
|
|
334
|
+
} else {
|
|
335
|
+
DynamoFM_Log.log(
|
|
336
|
+
`--=> incoming socket(${this.params.name}) ` +
|
|
337
|
+
`event: ${DynamoNTS_SocketEventKey.unsubscribe}`
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
this.removeSubscription(socket, issuer);
|
|
342
|
+
|
|
343
|
+
await this.subscriptionEvent.executeEventTasks(issuer, issuer);
|
|
344
|
+
|
|
345
|
+
socket.emit(
|
|
346
|
+
DynamoNTS_SocketEventKey.unsubscribeSuccessful,
|
|
347
|
+
'unsubscribe was successful',
|
|
348
|
+
error => {
|
|
349
|
+
DynamoFM_Log.error(
|
|
350
|
+
`Emitting unsubscribeSuccessful event failed!` +
|
|
351
|
+
`\nerror:`, error
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
DynamoFM_Log.success(
|
|
357
|
+
`< x > socket(${this.params.name}) unsubscribe successfull (${issuer})`
|
|
358
|
+
);
|
|
359
|
+
} catch (error) {
|
|
360
|
+
DynamoFM_Log.error(
|
|
361
|
+
`Socket unsubscribe failed: ${this.params.name} ` ,
|
|
362
|
+
`(${this.params.port}) will disconnect now...`,
|
|
363
|
+
error
|
|
364
|
+
);
|
|
365
|
+
socket.emit(DynamoNTS_SocketEventKey.error, error);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
this.incomingEvents.forEach((event: DynamoNTS_SocketEvent<any>) => {
|
|
372
|
+
socket.on(
|
|
373
|
+
event.eventKey,
|
|
374
|
+
async (content: any) => {
|
|
375
|
+
try {
|
|
376
|
+
await event.executeEventTasks(content, issuer);
|
|
377
|
+
} catch (error) {
|
|
378
|
+
DynamoFM_Log.error(
|
|
379
|
+
`Socket Event failed: ${this.params.name} (${this.params.port})`,
|
|
380
|
+
error
|
|
381
|
+
);
|
|
382
|
+
socket.emit(DynamoNTS_SocketEventKey.error, error);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
if (DynamoNTS_globalSettings.logMainSocketEvents) {
|
|
389
|
+
DynamoFM_Log.success(`< > socket(${this.params.name}): new CONNECTION established`);
|
|
390
|
+
}
|
|
391
|
+
} catch (error) {
|
|
392
|
+
DynamoFM_Log.error(
|
|
393
|
+
`Socket Connection failed: ${this.params.name} ` +
|
|
394
|
+
`(${this.params.port}) will disconnect now...`,
|
|
395
|
+
error
|
|
396
|
+
);
|
|
397
|
+
socket.emit(DynamoNTS_SocketEventKey.error, error);
|
|
398
|
+
socket.disconnect();
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
newSocketServer.listen(this.params.port);
|
|
403
|
+
|
|
404
|
+
DynamoFM_Log.success(
|
|
405
|
+
`\nsocket server setup finished: ${this.params.name}` +
|
|
406
|
+
`\nsocket server listening on port: ${this.params.port}`
|
|
407
|
+
);
|
|
408
|
+
|
|
409
|
+
successCallback();
|
|
410
|
+
|
|
411
|
+
if (security === DynamoNTS_SocketSecurity.open) {
|
|
412
|
+
this.openSocketServer = newSocketServer;
|
|
413
|
+
|
|
414
|
+
return this.openSocketServer;
|
|
415
|
+
} else {
|
|
416
|
+
this.secureSocketServer = newSocketServer;
|
|
417
|
+
|
|
418
|
+
return this.secureSocketServer;
|
|
419
|
+
}
|
|
420
|
+
} catch (error) {
|
|
421
|
+
DynamoFM_Log.error(
|
|
422
|
+
`Socket Server Service - Deep Setup failed: ${this.params?.name} ` +
|
|
423
|
+
`(${this.params?.port})`,
|
|
424
|
+
error
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
throw error;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
protected async addSocketToPresence(newPresence: T_Presence): Promise<void> {
|
|
432
|
+
try {
|
|
433
|
+
const activePresence: T_Presence = this.presences.find(
|
|
434
|
+
(pres: T_Presence) => pres.issuerId === newPresence.issuerId
|
|
435
|
+
);
|
|
436
|
+
|
|
437
|
+
if (activePresence) {
|
|
438
|
+
activePresence.sockets.push(...newPresence.sockets);
|
|
439
|
+
} else {
|
|
440
|
+
this.presences.push(newPresence);
|
|
441
|
+
}
|
|
442
|
+
} catch (error) {
|
|
443
|
+
DynamoFM_Log.error(
|
|
444
|
+
`Socket Subscription failed: ${this.params?.name} (${this.params?.port})`,
|
|
445
|
+
error
|
|
446
|
+
);
|
|
447
|
+
|
|
448
|
+
throw error;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
private async disconnectBaseTask(socket: SocketIO.Socket, issuer: string): Promise<void> {
|
|
453
|
+
try {
|
|
454
|
+
await this.removeSubscription(socket, issuer);
|
|
455
|
+
|
|
456
|
+
DynamoFM_Log.info(`< x > socket(${this.params.name}) disconnected (${issuer})`);
|
|
457
|
+
} catch (error) {
|
|
458
|
+
throw new DynamoFM_Error({
|
|
459
|
+
...this._getDefaultErrorSettings(
|
|
460
|
+
'disconnectBaseTask',
|
|
461
|
+
error,
|
|
462
|
+
issuer
|
|
463
|
+
),
|
|
464
|
+
|
|
465
|
+
errorCode: 'NTS-SSS-109',
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
private async removeSubscription(socket: SocketIO.Socket, issuer?: string): Promise<void> {
|
|
471
|
+
try {
|
|
472
|
+
const activePresenceIndex: number = this.presences.findIndex(
|
|
473
|
+
(pres: DynamoNTS_SocketPresence) => pres.sockets.includes(socket)
|
|
474
|
+
);
|
|
475
|
+
|
|
476
|
+
if (activePresenceIndex === -1) {
|
|
477
|
+
throw new DynamoFM_Error({
|
|
478
|
+
...this._getDefaultErrorSettings(
|
|
479
|
+
'sendEventForId',
|
|
480
|
+
new Error(
|
|
481
|
+
`closing socket(${this.params.name}) does not match any in the activePresences`
|
|
482
|
+
),
|
|
483
|
+
issuer
|
|
484
|
+
),
|
|
485
|
+
|
|
486
|
+
errorCode: 'NTS-SSS-203',
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const activePresence: DynamoNTS_SocketPresence = this.presences[activePresenceIndex];
|
|
491
|
+
|
|
492
|
+
if (activePresence.issuerId !== issuer) {
|
|
493
|
+
throw new DynamoFM_Error({
|
|
494
|
+
...this._getDefaultErrorSettings(
|
|
495
|
+
'sendEventForId',
|
|
496
|
+
new Error(
|
|
497
|
+
`socket subscription for ${issuer} and ${activePresence.issuerId} does not match.`
|
|
498
|
+
),
|
|
499
|
+
issuer
|
|
500
|
+
),
|
|
501
|
+
|
|
502
|
+
errorCode: 'NTS-SSS-201',
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const socketIndex = activePresence.sockets.findIndex((s: SocketIO.Socket) => s === socket);
|
|
507
|
+
|
|
508
|
+
if (socketIndex === -1) {
|
|
509
|
+
throw new DynamoFM_Error({
|
|
510
|
+
...this._getDefaultErrorSettings(
|
|
511
|
+
'sendEventForId',
|
|
512
|
+
new Error(
|
|
513
|
+
`closing socket(${this.params.name}) does not match any in the activePresences`
|
|
514
|
+
),
|
|
515
|
+
issuer
|
|
516
|
+
),
|
|
517
|
+
|
|
518
|
+
errorCode: 'NTS-SSS-202',
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
activePresence.sockets.splice(socketIndex);
|
|
523
|
+
|
|
524
|
+
if (this.getSubscriptionCloseTasks) {
|
|
525
|
+
await DynamoFM_Array.asyncForEach(
|
|
526
|
+
this.getSubscriptionCloseTasks(),
|
|
527
|
+
async (task: DynamoNTS_SocketEventTask<null>) => {
|
|
528
|
+
await task(null, issuer);
|
|
529
|
+
}
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
if (activePresence.sockets.length === 0) {
|
|
534
|
+
this.presences.splice(activePresenceIndex);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
socket.disconnect();
|
|
538
|
+
DynamoFM_Log.info(`<x==> socket(${this.params.name}) unsubscription successfull (${issuer})`);
|
|
539
|
+
} catch (error) {
|
|
540
|
+
throw new DynamoFM_Error({
|
|
541
|
+
...this._getDefaultErrorSettings(
|
|
542
|
+
'sendEventForId',
|
|
543
|
+
error,
|
|
544
|
+
issuer
|
|
545
|
+
),
|
|
546
|
+
|
|
547
|
+
errorCode: 'NTS-SSS-200',
|
|
548
|
+
message: `socket(${this.params.name}) Subscription Removal failed: ${this.params?.name}`,
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/* emitServerEvent(event: string, content: any): void {
|
|
554
|
+
try {
|
|
555
|
+
DynamoFM_Log.log(` <=-- emitting server socket(${this.params.name}) event: ${event}`);
|
|
556
|
+
|
|
557
|
+
this.openSocketServer.emit(event, content, error => {
|
|
558
|
+
DynamoFM_Log.error(`Emitting server event '${event}' failed!\nerror:`, error);
|
|
559
|
+
});
|
|
560
|
+
} catch (error) {
|
|
561
|
+
throw new DynamoFM_Error({
|
|
562
|
+
...this._getDefaultErrorSettings(
|
|
563
|
+
'emitEvent',
|
|
564
|
+
error
|
|
565
|
+
),
|
|
566
|
+
|
|
567
|
+
errorCode: 'NTS-SSS-500',
|
|
568
|
+
message: `socket(${this.params.name}) Event Emit (${event}) failed: ${this.params?.name}`,
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
} */
|
|
572
|
+
|
|
573
|
+
idIsSubscribed(id: string): boolean {
|
|
574
|
+
try {
|
|
575
|
+
return !!this.presences.find(
|
|
576
|
+
(presence: DynamoNTS_SocketPresence) => presence.issuerId === id
|
|
577
|
+
);
|
|
578
|
+
} catch (error) {
|
|
579
|
+
throw new DynamoFM_Error({
|
|
580
|
+
...this._getDefaultErrorSettings(
|
|
581
|
+
'idIsSubscribed',
|
|
582
|
+
error
|
|
583
|
+
),
|
|
584
|
+
|
|
585
|
+
errorCode: 'NTS-SSS-600',
|
|
586
|
+
message: `socket(${this.params.name}) ID Subscription Check (${id}) failed`,
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
async emitError(presenceIssuerId: string, error: any, issuer: string): Promise<void> {
|
|
592
|
+
try {
|
|
593
|
+
await this.sendEventForId(presenceIssuerId, DynamoNTS_SocketEventKey.error, error, issuer);
|
|
594
|
+
} catch (error) {
|
|
595
|
+
throw new DynamoFM_Error({
|
|
596
|
+
...this._getDefaultErrorSettings(
|
|
597
|
+
'emitError',
|
|
598
|
+
error,
|
|
599
|
+
presenceIssuerId
|
|
600
|
+
),
|
|
601
|
+
|
|
602
|
+
errorCode: 'NTS-SSS-700',
|
|
603
|
+
message: `socket(${this.params.name}) Error Emit (id: ${presenceIssuerId}) failed`,
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
async sendEventForId(id: string, event: string, content: any, issuer: string): Promise<void> {
|
|
609
|
+
try {
|
|
610
|
+
const presence: DynamoNTS_SocketPresence = this.presences.find(
|
|
611
|
+
(pres: DynamoNTS_SocketPresence) => pres.issuerId === id
|
|
612
|
+
);
|
|
613
|
+
|
|
614
|
+
if (!presence) {
|
|
615
|
+
throw new DynamoFM_Error({
|
|
616
|
+
...this._getDefaultErrorSettings(
|
|
617
|
+
'sendEventForId',
|
|
618
|
+
new Error(`No active socket with this specific ID: ${id}`),
|
|
619
|
+
content?.source
|
|
620
|
+
),
|
|
621
|
+
|
|
622
|
+
status: 404,
|
|
623
|
+
errorCode: 'NTS-SSS-301',
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
presence.emitEvent(event, content, issuer);
|
|
628
|
+
|
|
629
|
+
if (DynamoNTS_globalSettings.logSocketEventContent) {
|
|
630
|
+
DynamoFM_Log.success(
|
|
631
|
+
` <--= emitted socket(${this.params.name}) event for presence: ${event}, ` +
|
|
632
|
+
`\n presenceId: ${id}, sockets: ${presence.sockets.length}` +
|
|
633
|
+
`\n content:`, content
|
|
634
|
+
);
|
|
635
|
+
} else {
|
|
636
|
+
DynamoFM_Log.success(
|
|
637
|
+
` <--= emitted socket(${this.params.name}) event for presence: ${event}, ` +
|
|
638
|
+
`\n presenceId: ${id}, sockets: ${presence.sockets.length}`
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
} catch (error) {
|
|
642
|
+
try {
|
|
643
|
+
if (error.flag.includes('DYNAMO') && error?.accitionalInfo?.inactiveSockets) {
|
|
644
|
+
const sockets: SocketIO.Socket[] = error.accitionalInfo.inactiveSockets;
|
|
645
|
+
|
|
646
|
+
await DynamoFM_Array.asyncForEach(sockets, async (socket: SocketIO.Socket) => {
|
|
647
|
+
await this.removeSubscription(socket);
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
const presence: DynamoNTS_SocketPresence = this.presences.find(
|
|
651
|
+
(pres: DynamoNTS_SocketPresence) => pres.issuerId === id
|
|
652
|
+
);
|
|
653
|
+
|
|
654
|
+
if (!presence) {
|
|
655
|
+
throw new DynamoFM_Error({
|
|
656
|
+
...this._getDefaultErrorSettings(
|
|
657
|
+
'sendEventForId',
|
|
658
|
+
new Error(`No active socket(${this.params.name}) with this specific ID: ${id}`),
|
|
659
|
+
content?.source
|
|
660
|
+
),
|
|
661
|
+
|
|
662
|
+
status: 404,
|
|
663
|
+
errorCode: 'NTS-SSS-302',
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
} catch (error) {
|
|
668
|
+
throw new DynamoFM_Error({
|
|
669
|
+
...this._getDefaultErrorSettings('sendEventForId', error, content?.source),
|
|
670
|
+
|
|
671
|
+
errorCode: 'NTS-SSS-310',
|
|
672
|
+
message:
|
|
673
|
+
`Error handling of inactive sockets(${this.params.name}) failed!` +
|
|
674
|
+
`\n(Socket Event Emit for id (${id}, ${event}) failed)`,
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
throw new DynamoFM_Error({
|
|
679
|
+
...this._getDefaultErrorSettings('sendEventForId', error, content?.source),
|
|
680
|
+
|
|
681
|
+
errorCode: 'NTS-SSS-310',
|
|
682
|
+
message: `socket(${this.params.name}) Event Emit for id (${id}, ${event}) failed`,
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
broadcastEvent(event: string, content: any, issuer: string): void {
|
|
688
|
+
try {
|
|
689
|
+
DynamoFM_Log.log(` <=-== broadcasting socket(${this.params.name}) event: ${event}`);
|
|
690
|
+
|
|
691
|
+
this.presences.forEach((presence: DynamoNTS_SocketPresence) => {
|
|
692
|
+
presence.emitEvent(event, content, issuer);
|
|
693
|
+
});
|
|
694
|
+
} catch (error) {
|
|
695
|
+
DynamoFM_Log.error(`socket(${this.params.name}) Event Broadcast (${event}) failed`, error);
|
|
696
|
+
|
|
697
|
+
throw new DynamoFM_Error({
|
|
698
|
+
...this._getDefaultErrorSettings('broadcastEvent', error),
|
|
699
|
+
|
|
700
|
+
errorCode: 'NTS-SSS-400',
|
|
701
|
+
message: `socket(${this.params.name}) Event Broadcast (${event}) failed`,
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
private _getDefaultErrorSettings(
|
|
707
|
+
fnName: string,
|
|
708
|
+
error: DynamoFM_AnyError,
|
|
709
|
+
issuer?: string
|
|
710
|
+
): DynamoFM_Error_Settings {
|
|
711
|
+
return {
|
|
712
|
+
status: (error as DynamoFM_Error)?.___status ?? 500,
|
|
713
|
+
message: (error as Error)?.message ?? `${fnName} was UNSUCCESFUL (NTS)`,
|
|
714
|
+
addECToUserMsg: !(error as DynamoFM_Error)?.__userMessage,
|
|
715
|
+
userMessage: (error as DynamoFM_Error)?.__userMessage ?? this.defaultErrorUserMsg,
|
|
716
|
+
issuer: issuer,
|
|
717
|
+
issuerService: this.constructor?.name,
|
|
718
|
+
error: error,
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* You must setup params for the service in this function
|
|
724
|
+
*/
|
|
725
|
+
protected abstract getServiceParams(): DynamoNTS_SocketServerService_Params;
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* You must setup events and required services in this function
|
|
729
|
+
*/
|
|
730
|
+
protected abstract getIncomingEvents(): DynamoNTS_SocketEvent<any>[];
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* You can setup tasks for the subscription event in this function
|
|
734
|
+
*/
|
|
735
|
+
protected getSubscriptionTasks?(): DynamoNTS_SocketEventTask<T_SubscriptionContent>[];
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* You can setup tasks for the subscription event in this function
|
|
739
|
+
*/
|
|
740
|
+
protected getSubscriptionCloseTasks?(): DynamoNTS_SocketEventTask<null>[];
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* You can setup preprocessess for the subscription event in this function
|
|
744
|
+
*/
|
|
745
|
+
protected getSubscriptionPreProcessess?(): DynamoNTS_SocketEventPreprocessTask[];
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* You can setup tasks for the unsubscribe event in this function
|
|
749
|
+
*/
|
|
750
|
+
protected getUnsubscribeTasks?(): DynamoNTS_SocketEventTask<T_SubscriptionContent>[];
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* You can setup preprocessess for the unsubscribe event in this function
|
|
754
|
+
*/
|
|
755
|
+
protected getUnsubscribePreProcessess?(): DynamoNTS_SocketEventPreprocessTask[];
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* You can setup tasks for the error event in this function
|
|
759
|
+
*/
|
|
760
|
+
protected errorHandling?: DynamoNTS_SocketEventTask<T_ErrorContent>;
|
|
761
|
+
}
|