@midwayjs/socketio 4.0.0-beta.8 → 4.0.0

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.
@@ -3,9 +3,11 @@ import { Application, IMidwaySocketIOOptions, Context, NextFunction } from './in
3
3
  export declare class MidwaySocketIOFramework extends BaseFramework<Application, Context, IMidwaySocketIOOptions> {
4
4
  private namespaceList;
5
5
  protected connectionMiddlewareManager: ContextMiddlewareManager<Context, unknown, unknown>;
6
+ protected socketServerPort: number;
6
7
  configure(): IMidwaySocketIOOptions;
7
8
  applicationInitialize(): Promise<void>;
8
9
  run(): Promise<void>;
10
+ getSocketServerPort(): number;
9
11
  protected beforeStop(): Promise<void>;
10
12
  private loadMidwayController;
11
13
  private addNamespace;
package/dist/framework.js CHANGED
@@ -12,9 +12,11 @@ const util_1 = require("util");
12
12
  const debug = (0, util_1.debuglog)('midway:socket.io');
13
13
  const socket_io_1 = require("socket.io");
14
14
  const core_2 = require("@midwayjs/core");
15
+ const utils_1 = require("./utils");
15
16
  let MidwaySocketIOFramework = class MidwaySocketIOFramework extends core_1.BaseFramework {
16
17
  namespaceList = [];
17
18
  connectionMiddlewareManager = this.createMiddlewareManager();
19
+ socketServerPort;
18
20
  configure() {
19
21
  return this.configService.getConfiguration('socketIO');
20
22
  }
@@ -36,15 +38,24 @@ let MidwaySocketIOFramework = class MidwaySocketIOFramework extends core_1.BaseF
36
38
  this.logger.debug('[midway:socketio] init socket.io-redis ready!');
37
39
  }
38
40
  // listen port when http server not exist
39
- if (this.configurationOptions.port) {
40
- this.app.listen(this.configurationOptions.port, this.configurationOptions);
41
- this.logger.info(`[midway:socketio] Socket.io server port = ${this.configurationOptions.port} start success`);
41
+ if (typeof this.configurationOptions.port === 'number') {
42
+ let customPort = this.configurationOptions.port;
43
+ if (customPort === 0) {
44
+ customPort = await (0, utils_1.getFreePort)();
45
+ this.logger.info(`[midway:socketio] server has auto-assigned port ${customPort}`);
46
+ }
47
+ this.app.listen(customPort, this.configurationOptions);
48
+ this.socketServerPort = customPort;
49
+ this.logger.info(`[midway:socketio] Socket.io server port = ${customPort} start success`);
42
50
  }
43
51
  else if (this.applicationContext.hasObject(core_1.HTTP_SERVER_KEY)) {
44
52
  this.app.attach(this.applicationContext.get(core_1.HTTP_SERVER_KEY), this.configurationOptions);
45
53
  this.logger.info('[midway:socketio] Socket.io server start success and attach to web server');
46
54
  }
47
55
  }
56
+ getSocketServerPort() {
57
+ return this.socketServerPort;
58
+ }
48
59
  async beforeStop() {
49
60
  return new Promise(resolve => {
50
61
  this.app.close(() => {
@@ -62,16 +73,53 @@ let MidwaySocketIOFramework = class MidwaySocketIOFramework extends core_1.BaseF
62
73
  }
63
74
  }
64
75
  async addNamespace(target) {
76
+ const traceService = this.applicationContext.get(core_1.MidwayTraceService);
77
+ const traceMetaResolver = this.configurationOptions?.tracing?.meta;
78
+ const traceEnabled = this.configurationOptions?.tracing?.enable !== false;
79
+ const traceExtractor = this.configurationOptions?.tracing
80
+ ?.extractor;
65
81
  const controllerOption = core_1.MetadataManager.getOwnMetadata(core_2.WS_CONTROLLER_KEY, target);
66
82
  const nsp = this.app.of(controllerOption.namespace);
67
83
  this.namespaceList.push(controllerOption.namespace);
68
84
  const controllerMiddleware = controllerOption.routerOptions.middleware ?? [];
69
85
  const controllerConnectionMiddleware = controllerOption.routerOptions.connectionMiddleware ?? [];
70
86
  nsp.use((socket, next) => {
71
- this.app.createAnonymousContext(socket);
72
- socket.requestContext.registerObject('socket', socket);
73
- socket.app = this.app;
74
- next();
87
+ const entryCarrierDefault = socket?.handshake?.headers ?? {};
88
+ const entryCarrier = typeof traceExtractor === 'function'
89
+ ? traceExtractor({
90
+ ctx: socket,
91
+ carrier: entryCarrierDefault,
92
+ request: socket?.handshake,
93
+ custom: {
94
+ namespace: controllerOption.namespace || '/',
95
+ eventName: 'connect',
96
+ },
97
+ })
98
+ : entryCarrierDefault;
99
+ traceService
100
+ .runWithEntrySpan(`socketio.connect ${controllerOption.namespace || '/'}`, {
101
+ enable: traceEnabled,
102
+ carrier: entryCarrier ?? entryCarrierDefault,
103
+ attributes: {
104
+ 'midway.protocol': 'socketio',
105
+ 'midway.socketio.namespace': controllerOption.namespace || '/',
106
+ },
107
+ meta: traceMetaResolver,
108
+ metaArgs: {
109
+ ctx: socket,
110
+ carrier: entryCarrier ?? entryCarrierDefault,
111
+ custom: {
112
+ namespace: controllerOption.namespace || '/',
113
+ eventName: 'connect',
114
+ },
115
+ },
116
+ }, async () => {
117
+ this.app.createAnonymousContext(socket);
118
+ socket.requestContext.registerObject('socket', socket);
119
+ socket.app = this.app;
120
+ next();
121
+ })
122
+ .catch(err => next(err));
75
123
  });
76
124
  // `connect`事件应该使用**同步**的方式调用以保证后续事件监听能够正常得到处理
77
125
  nsp.on('connect', (socket) => {
@@ -95,14 +143,40 @@ let MidwaySocketIOFramework = class MidwaySocketIOFramework extends core_1.BaseF
95
143
  methodMap[wsEventInfo.propertyName] = methodMap[wsEventInfo.propertyName] || { responseEvents: [] };
96
144
  const controller = await socket.requestContext.getAsync(target);
97
145
  try {
98
- const fn = await this.middlewareService.compose([
99
- ...(wsEventInfo?.eventOptions?.middleware || []),
100
- async (ctx, next) => {
101
- // eslint-disable-next-line prefer-spread
102
- return controller[wsEventInfo.propertyName].apply(controller, [socket]);
146
+ const onConnectionCarrierDefault = socket?.handshake?.headers ?? {};
147
+ const onConnectionCarrier = typeof traceExtractor === 'function'
148
+ ? traceExtractor({
149
+ ctx: socket,
150
+ carrier: onConnectionCarrierDefault,
151
+ custom: {
152
+ eventName: wsEventInfo.propertyName,
153
+ },
154
+ })
155
+ : onConnectionCarrierDefault;
156
+ const result = await traceService.runWithEntrySpan(`socketio.event ${wsEventInfo.propertyName}`, {
157
+ enable: traceEnabled,
158
+ carrier: onConnectionCarrier ?? onConnectionCarrierDefault,
159
+ attributes: {
160
+ 'midway.protocol': 'socketio',
161
+ 'midway.socketio.event': wsEventInfo.propertyName,
162
+ },
163
+ meta: traceMetaResolver,
164
+ metaArgs: {
165
+ ctx: socket,
166
+ carrier: onConnectionCarrier ?? onConnectionCarrierDefault,
167
+ custom: {
168
+ eventName: wsEventInfo.propertyName,
169
+ },
103
170
  },
104
- ], this.app);
105
- const result = await fn(socket);
171
+ }, async () => {
172
+ const fn = await this.middlewareService.compose([
173
+ ...(wsEventInfo?.eventOptions?.middleware || []),
174
+ async (ctx, next) => {
175
+ return controller[wsEventInfo.propertyName].apply(controller, [socket]);
176
+ },
177
+ ], this.app);
178
+ return await fn(socket);
179
+ });
106
180
  await this.bindSocketResponse(result, socket, wsEventInfo.propertyName, methodMap);
107
181
  }
108
182
  catch (err) {
@@ -123,24 +197,51 @@ let MidwaySocketIOFramework = class MidwaySocketIOFramework extends core_1.BaseF
123
197
  const controller = await socket.requestContext.getAsync(target);
124
198
  debug('got message', wsEventInfo.messageEventName, args);
125
199
  try {
126
- const result = await (await this.applyMiddleware(async (ctx, next) => {
127
- // add controller middleware
128
- const fn = await this.middlewareService.compose([
129
- ...controllerMiddleware,
130
- ...(wsEventInfo?.eventOptions?.middleware || []),
131
- async (ctx, next) => {
132
- const isPassed = await this.app
133
- .getFramework()
134
- .runGuard(ctx, target, wsEventInfo.propertyName);
135
- if (!isPassed) {
136
- throw new core_1.MidwayInvokeForbiddenError(wsEventInfo.propertyName, target);
137
- }
138
- // eslint-disable-next-line prefer-spread
139
- return controller[wsEventInfo.propertyName].apply(controller, args);
200
+ const onMessageCarrierDefault = socket?.handshake?.headers ?? {};
201
+ const onMessageCarrier = typeof traceExtractor === 'function'
202
+ ? traceExtractor({
203
+ ctx: socket,
204
+ carrier: onMessageCarrierDefault,
205
+ custom: {
206
+ eventName: wsEventInfo.messageEventName,
207
+ },
208
+ })
209
+ : onMessageCarrierDefault;
210
+ const result = await traceService.runWithEntrySpan(`socketio.message ${wsEventInfo.messageEventName}`, {
211
+ enable: traceEnabled,
212
+ carrier: onMessageCarrier ?? onMessageCarrierDefault,
213
+ attributes: {
214
+ 'midway.protocol': 'socketio',
215
+ 'midway.socketio.event': wsEventInfo.messageEventName,
216
+ },
217
+ meta: traceMetaResolver,
218
+ metaArgs: {
219
+ ctx: socket,
220
+ carrier: onMessageCarrier ?? onMessageCarrierDefault,
221
+ custom: {
222
+ eventName: wsEventInfo.messageEventName,
140
223
  },
141
- ], this.app);
142
- return await fn(ctx, next);
143
- }))(socket);
224
+ },
225
+ }, async () => {
226
+ return await (await this.applyMiddleware(async (ctx, next) => {
227
+ // add controller middleware
228
+ const fn = await this.middlewareService.compose([
229
+ ...controllerMiddleware,
230
+ ...(wsEventInfo?.eventOptions?.middleware || []),
231
+ async (ctx, next) => {
232
+ const isPassed = await this.app
233
+ .getFramework()
234
+ .runGuard(ctx, target, wsEventInfo.propertyName);
235
+ if (!isPassed) {
236
+ throw new core_1.MidwayInvokeForbiddenError(wsEventInfo.propertyName, target);
237
+ }
238
+ // eslint-disable-next-line prefer-spread
239
+ return controller[wsEventInfo.propertyName].apply(controller, args);
240
+ },
241
+ ], this.app);
242
+ return await fn(ctx, next);
243
+ }))(socket);
244
+ });
144
245
  if (typeof args[args.length - 1] === 'function') {
145
246
  // ack
146
247
  args[args.length - 1](result);
@@ -160,7 +261,32 @@ let MidwaySocketIOFramework = class MidwaySocketIOFramework extends core_1.BaseF
160
261
  socket.on('disconnect', async (reason) => {
161
262
  const controller = await socket.requestContext.getAsync(target);
162
263
  try {
163
- const result = await controller[wsEventInfo.propertyName].apply(controller, [reason]);
264
+ const onDisconnectCarrierDefault = socket?.handshake?.headers ?? {};
265
+ const onDisconnectCarrier = typeof traceExtractor === 'function'
266
+ ? traceExtractor({
267
+ ctx: socket,
268
+ carrier: onDisconnectCarrierDefault,
269
+ custom: {
270
+ eventName: 'disconnect',
271
+ },
272
+ })
273
+ : onDisconnectCarrierDefault;
274
+ const result = await traceService.runWithEntrySpan(`socketio.disconnect ${wsEventInfo.propertyName}`, {
275
+ enable: traceEnabled,
276
+ carrier: onDisconnectCarrier ?? onDisconnectCarrierDefault,
277
+ attributes: {
278
+ 'midway.protocol': 'socketio',
279
+ 'midway.socketio.event': 'disconnect',
280
+ },
281
+ meta: traceMetaResolver,
282
+ metaArgs: {
283
+ ctx: socket,
284
+ carrier: onDisconnectCarrier ?? onDisconnectCarrierDefault,
285
+ custom: {
286
+ eventName: 'disconnect',
287
+ },
288
+ },
289
+ }, async () => await controller[wsEventInfo.propertyName].apply(controller, [reason]));
164
290
  await this.bindSocketResponse(result, socket, wsEventInfo.propertyName, methodMap);
165
291
  }
166
292
  catch (err) {
@@ -185,6 +311,10 @@ let MidwaySocketIOFramework = class MidwaySocketIOFramework extends core_1.BaseF
185
311
  });
186
312
  }
187
313
  async bindSocketResponse(result, socket, propertyName, methodMap) {
314
+ const traceService = this.applicationContext.get(core_1.MidwayTraceService);
315
+ const traceMetaResolver = this.configurationOptions?.tracing?.meta;
316
+ const traceEnabled = this.configurationOptions?.tracing?.enable !== false;
317
+ const traceInjector = this.configurationOptions?.tracing?.injector;
188
318
  if (result && methodMap[propertyName]) {
189
319
  for (const wsEventInfo of methodMap[propertyName].responseEvents) {
190
320
  if (wsEventInfo.eventType === core_2.WSEventTypeEnum.EMIT) {
@@ -193,12 +323,64 @@ let MidwaySocketIOFramework = class MidwaySocketIOFramework extends core_1.BaseF
193
323
  return socket.to(name);
194
324
  }, socket);
195
325
  }
196
- // eslint-disable-next-line prefer-spread
197
- socket.emit.apply(socket, [wsEventInfo.messageEventName].concat(result));
326
+ const carrier = typeof traceInjector === 'function'
327
+ ? traceInjector({
328
+ ctx: socket,
329
+ request: result,
330
+ custom: {
331
+ eventName: wsEventInfo.messageEventName,
332
+ },
333
+ }) || {}
334
+ : {};
335
+ await traceService.runWithExitSpan(`socketio.emit ${wsEventInfo.messageEventName}`, {
336
+ enable: traceEnabled,
337
+ carrier,
338
+ attributes: {
339
+ 'midway.protocol': 'socketio',
340
+ 'midway.socketio.event': wsEventInfo.messageEventName,
341
+ },
342
+ meta: traceMetaResolver,
343
+ metaArgs: {
344
+ ctx: socket,
345
+ carrier,
346
+ custom: {
347
+ eventName: wsEventInfo.messageEventName,
348
+ },
349
+ },
350
+ }, async () => {
351
+ // eslint-disable-next-line prefer-spread
352
+ socket.emit.apply(socket, [wsEventInfo.messageEventName].concat(result));
353
+ });
198
354
  }
199
355
  else if (wsEventInfo.eventType === core_2.WSEventTypeEnum.BROADCAST) {
200
- // eslint-disable-next-line prefer-spread
201
- socket.nsp.emit.apply(socket.nsp, [].concat(result));
356
+ const carrier = typeof traceInjector === 'function'
357
+ ? traceInjector({
358
+ ctx: socket,
359
+ request: result,
360
+ custom: {
361
+ eventName: propertyName,
362
+ },
363
+ }) || {}
364
+ : {};
365
+ await traceService.runWithExitSpan(`socketio.broadcast ${propertyName}`, {
366
+ enable: traceEnabled,
367
+ carrier,
368
+ attributes: {
369
+ 'midway.protocol': 'socketio',
370
+ 'midway.socketio.event': propertyName,
371
+ },
372
+ meta: traceMetaResolver,
373
+ metaArgs: {
374
+ ctx: socket,
375
+ carrier,
376
+ custom: {
377
+ eventName: propertyName,
378
+ },
379
+ },
380
+ }, async () => {
381
+ // eslint-disable-next-line prefer-spread
382
+ socket.nsp.emit.apply(socket.nsp, [].concat(result));
383
+ });
202
384
  }
203
385
  }
204
386
  }
@@ -0,0 +1,2 @@
1
+ export declare function getFreePort(): Promise<number>;
2
+ //# sourceMappingURL=utils.d.ts.map
package/dist/utils.js ADDED
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getFreePort = getFreePort;
4
+ const net_1 = require("net");
5
+ async function getFreePort() {
6
+ return new Promise((resolve, reject) => {
7
+ const server = (0, net_1.createServer)();
8
+ server.listen(0, () => {
9
+ try {
10
+ const port = server.address().port;
11
+ server.close();
12
+ resolve(port);
13
+ }
14
+ catch (err) {
15
+ reject(err);
16
+ }
17
+ });
18
+ });
19
+ }
20
+ //# sourceMappingURL=utils.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midwayjs/socketio",
3
- "version": "4.0.0-beta.8",
3
+ "version": "4.0.0",
4
4
  "description": "Midway Web Framework for socket.io",
5
5
  "main": "dist/index.js",
6
6
  "typings": "index.d.ts",
@@ -24,8 +24,8 @@
24
24
  ],
25
25
  "license": "MIT",
26
26
  "devDependencies": {
27
- "@midwayjs/core": "^4.0.0-beta.8",
28
- "fs-extra": "11.3.0",
27
+ "@midwayjs/core": "^4.0.0",
28
+ "fs-extra": "11.3.3",
29
29
  "socket.io-client": "4.8.1"
30
30
  },
31
31
  "dependencies": {
@@ -39,5 +39,5 @@
39
39
  "engines": {
40
40
  "node": ">=20"
41
41
  },
42
- "gitHead": "355e55949fdd132b0bdcb4830222a0a027e92ded"
42
+ "gitHead": "014f32c23ebc1d5ac21777c76be2fd373ce992d8"
43
43
  }