@nestjs/websockets 11.1.6 → 11.1.7

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/Readme.md CHANGED
@@ -8,7 +8,7 @@
8
8
  <p align="center">A progressive <a href="https://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
9
9
  <p align="center">
10
10
  <a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
11
- <a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
11
+ <a href="https://github.com/nestjs/nest/blob/master/LICENSE" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
12
12
  <a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
13
13
  <a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
14
14
  <a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
@@ -78,10 +78,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
78
78
  </tr>
79
79
  <tr>
80
80
  <td><a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/logos/snyk-logo-black.png" width="185" valign="middle" /></a></td>
81
- <td><a href="https://fuseautotech.com/" target="_blank"><img src="https://nestjs.com/img/logos/fuse-logo.svg" width="105" valign="middle" /></a></td>
82
- <td><a href="https://ridicorp.com/career/" target="_blank"><img src="https://nestjs.com/img/logos/ridi-logo.svg" width="105" valign="middle" /></a></td>
83
81
  <td><a href="https://www.movavi.com/imovie-for-windows.html" target="_blank"><img src="https://nestjs.com/img/logos/movavi-logo.svg" width="105" valign="middle" /></a></td>
84
- <td><a href="https://skunk.team" target="_blank"><img src="https://nestjs.com/img/logos/skunk-logo.png" height="60" valign="middle" /></a></td>
85
82
  </tr>
86
83
  </table>
87
84
 
@@ -91,10 +88,10 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
91
88
  <tr>
92
89
  <td><a href="https://www.mercedes-benz.com/" target="_blank"><img src="https://nestjs.com/img/logos/mercedes-logo.png" width="100" valign="middle" /></a></td>
93
90
  <td><a href="https://www.dinii.jp/" target="_blank"><img src="https://nestjs.com/img/logos/dinii-logo.png" width="65" valign="middle" /></a></td>
94
- <td><a href="https://bloodycase.com/?promocode=NEST" target="_blank"><img src="https://nestjs.com/img/logos/bloodycase-logo.png" width="65" valign="middle" /></a></td>
95
91
  <td><a href="https://handsontable.com/docs/react-data-grid/?utm_source=NestJS_GH&utm_medium=sponsorship&utm_campaign=library_sponsorship_2024" target="_blank"><img src="https://nestjs.com/img/logos/handsontable-dark-logo.svg#2" width="150" valign="middle" /></a></td>
96
92
  <td align="center" valign="middle"><a href="https://www.itflashcards.com/" target="_blank"><img src="https://nestjs.com/img/logos/it_flashcards-logo.png" width="170" valign="middle" /></a></td>
97
93
  <td align="center" valign="middle"><a href="https://arcjet.com/?ref=nestjs" target="_blank"><img src="https://nestjs.com/img/logos/arcjet-logo.svg" width="170" valign="middle" /></a></td>
94
+ <td align="center" valign="middle"><a href="https://crawljobs.com" target="_blank"><img src="https://nestjs.com/img/logos/crawljobs-logo.svg" width="130" valign="middle" /></a></td>
98
95
  </tr>
99
96
  </table>
100
97
 
@@ -118,19 +115,16 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
118
115
  <td align="center" valign="middle"><a href="https://triplecore.io" target="_blank"><img src="https://nestjs.com/img/logos/triplecore-logo.svg" width="50" valign="middle" /></a></td>
119
116
  </tr>
120
117
  <tr>
121
- <td align="center" valign="middle"><a href="https://thecasinowizard.com/bonuses/no-deposit-bonuses/" target="_blank"><img src="https://nestjs.com/img/logos/casinowizard-logo.png" width="120" valign="middle" /></a></td>
122
118
  <td align="center" valign="middle"><a href="https://polygon-software.ch/" target="_blank"><img src="https://nestjs.com/img/logos/polygon-logo.svg" width="120" valign="middle" /></a></td>
123
119
  <td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/logos/boringowl-logo.svg" width="120" valign="middle" /></a></td>
124
120
  <td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/logos/nordbot-logo.png" width="120" valign="middle" /></a></td>
125
121
  <td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/logos/dopiosh-logo.png" width="50" valign="middle" /></a></td>
126
122
  <td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/logos/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
123
+ <td align="center" valign="middle"><a href="https://www.tripoffice.com/" target="_blank"><img src="https://nestjs.com/img/logos/tripoffice-logo.png" width="140" valign="middle" /></a></td>
127
124
  </tr>
128
125
  <tr>
129
- <td align="center" valign="middle"><a href="https://julienferand.dev/" target="_blank"><img src="https://nestjs.com/img/logos/julienferand-logo.jpeg" width="55" valign="middle" /></a></td>
130
- <td align="center" valign="middle"><a href="https://www.tripoffice.com/" target="_blank"><img src="https://nestjs.com/img/logos/tripoffice-logo.png" width="140" valign="middle" /></a></td>
131
126
  <td align="center" valign="middle"><a href="https://solcellsforetag.se/" target="_blank"><img src="https://nestjs.com/img/logos/solcellsforetag-logo.svg" width="140" valign="middle" /></a></td>
132
127
  <td align="center" valign="middle"><a href="https://www.route4me.com/" target="_blank"><img src="https://nestjs.com/img/logos/route4me-logo.svg" width="100" valign="middle" /></a></td>
133
- <td align="center" valign="middle"><a href="https://www.slotsup.com/" target="_blank"><img src="https://nestjs.com/img/logos/slotsup-logo.png" width="60" valign="middle" /></a></td>
134
128
  </tr>
135
129
  </table>
136
130
 
@@ -1,4 +1,9 @@
1
1
  export declare const DEFAULT_CALLBACK_METADATA: {
2
+ "13:2": {
3
+ index: number;
4
+ data: undefined;
5
+ pipes: never[];
6
+ };
2
7
  "3:1": {
3
8
  index: number;
4
9
  data: undefined;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DEFAULT_CALLBACK_METADATA = void 0;
4
4
  const ws_paramtype_enum_1 = require("../enums/ws-paramtype.enum");
5
5
  exports.DEFAULT_CALLBACK_METADATA = {
6
+ [`${ws_paramtype_enum_1.WsParamtype.ACK}:2`]: { index: 2, data: undefined, pipes: [] },
6
7
  [`${ws_paramtype_enum_1.WsParamtype.PAYLOAD}:1`]: { index: 1, data: undefined, pipes: [] },
7
8
  [`${ws_paramtype_enum_1.WsParamtype.SOCKET}:0`]: { index: 0, data: undefined, pipes: [] },
8
9
  };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * WebSockets `ack` parameter decorator.
3
+ * Extracts the `ack` callback function from the arguments of a ws event.
4
+ *
5
+ * This decorator signals to the framework that the `ack` callback will be
6
+ * handled manually within the method, preventing the framework from
7
+ * automatically sending an acknowledgement based on the return value.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * @SubscribeMessage('events')
12
+ * onEvent(
13
+ * @MessageBody() data: string,
14
+ * @Ack() ack: (response: any) => void
15
+ * ) {
16
+ * // Manually call the ack callback
17
+ * ack({ status: 'ok' });
18
+ * }
19
+ * ```
20
+ *
21
+ * @publicApi
22
+ */
23
+ export declare function Ack(): ParameterDecorator;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Ack = Ack;
4
+ const ws_paramtype_enum_1 = require("../enums/ws-paramtype.enum");
5
+ const param_utils_1 = require("../utils/param.utils");
6
+ /**
7
+ * WebSockets `ack` parameter decorator.
8
+ * Extracts the `ack` callback function from the arguments of a ws event.
9
+ *
10
+ * This decorator signals to the framework that the `ack` callback will be
11
+ * handled manually within the method, preventing the framework from
12
+ * automatically sending an acknowledgement based on the return value.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * @SubscribeMessage('events')
17
+ * onEvent(
18
+ * @MessageBody() data: string,
19
+ * @Ack() ack: (response: any) => void
20
+ * ) {
21
+ * // Manually call the ack callback
22
+ * ack({ status: 'ok' });
23
+ * }
24
+ * ```
25
+ *
26
+ * @publicApi
27
+ */
28
+ function Ack() {
29
+ return (0, param_utils_1.createPipesWsParamDecorator)(ws_paramtype_enum_1.WsParamtype.ACK)();
30
+ }
@@ -3,3 +3,4 @@ export * from './gateway-server.decorator';
3
3
  export * from './message-body.decorator';
4
4
  export * from './socket-gateway.decorator';
5
5
  export * from './subscribe-message.decorator';
6
+ export * from './ack.decorator';
@@ -6,3 +6,4 @@ tslib_1.__exportStar(require("./gateway-server.decorator"), exports);
6
6
  tslib_1.__exportStar(require("./message-body.decorator"), exports);
7
7
  tslib_1.__exportStar(require("./socket-gateway.decorator"), exports);
8
8
  tslib_1.__exportStar(require("./subscribe-message.decorator"), exports);
9
+ tslib_1.__exportStar(require("./ack.decorator"), exports);
@@ -1,4 +1,5 @@
1
1
  export declare enum WsParamtype {
2
2
  SOCKET = 0,
3
- PAYLOAD = 3
3
+ PAYLOAD = 3,
4
+ ACK = 13
4
5
  }
@@ -5,4 +5,5 @@ var WsParamtype;
5
5
  (function (WsParamtype) {
6
6
  WsParamtype[WsParamtype["SOCKET"] = 0] = "SOCKET";
7
7
  WsParamtype[WsParamtype["PAYLOAD"] = 3] = "PAYLOAD";
8
+ WsParamtype[WsParamtype["ACK"] = 13] = "ACK";
8
9
  })(WsParamtype || (exports.WsParamtype = WsParamtype = {}));
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WsParamsFactory = void 0;
4
+ const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
4
5
  const ws_paramtype_enum_1 = require("../enums/ws-paramtype.enum");
5
6
  class WsParamsFactory {
6
7
  exchangeKeyForValue(type, data, args) {
@@ -12,6 +13,9 @@ class WsParamsFactory {
12
13
  return args[0];
13
14
  case ws_paramtype_enum_1.WsParamtype.PAYLOAD:
14
15
  return data ? args[1]?.[data] : args[1];
16
+ case ws_paramtype_enum_1.WsParamtype.ACK: {
17
+ return args.find(arg => (0, shared_utils_1.isFunction)(arg));
18
+ }
15
19
  default:
16
20
  return null;
17
21
  }
@@ -5,11 +5,14 @@ export interface MessageMappingProperties {
5
5
  message: any;
6
6
  methodName: string;
7
7
  callback: (...args: any[]) => Observable<any> | Promise<any>;
8
+ isAckHandledManually: boolean;
8
9
  }
9
10
  export declare class GatewayMetadataExplorer {
10
11
  private readonly metadataScanner;
12
+ private readonly contextUtils;
11
13
  constructor(metadataScanner: MetadataScanner);
12
14
  explore(instance: NestGateway): MessageMappingProperties[];
13
15
  exploreMethodMetadata(instancePrototype: object, methodName: string): MessageMappingProperties | null;
16
+ private hasAckDecorator;
14
17
  scanForServerHooks(instance: NestGateway): IterableIterator<string>;
15
18
  }
@@ -3,9 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GatewayMetadataExplorer = void 0;
4
4
  const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
5
5
  const constants_1 = require("./constants");
6
+ const ws_paramtype_enum_1 = require("./enums/ws-paramtype.enum");
7
+ const context_utils_1 = require("@nestjs/core/helpers/context-utils");
6
8
  class GatewayMetadataExplorer {
7
9
  constructor(metadataScanner) {
8
10
  this.metadataScanner = metadataScanner;
11
+ this.contextUtils = new context_utils_1.ContextUtils();
9
12
  }
10
13
  explore(instance) {
11
14
  const instancePrototype = Object.getPrototypeOf(instance);
@@ -21,12 +24,25 @@ class GatewayMetadataExplorer {
21
24
  return null;
22
25
  }
23
26
  const message = Reflect.getMetadata(constants_1.MESSAGE_METADATA, callback);
27
+ const isAckHandledManually = this.hasAckDecorator(instancePrototype, methodName);
24
28
  return {
25
29
  callback,
26
30
  message,
27
31
  methodName,
32
+ isAckHandledManually,
28
33
  };
29
34
  }
35
+ hasAckDecorator(instancePrototype, methodName) {
36
+ const paramsMetadata = Reflect.getMetadata(constants_1.PARAM_ARGS_METADATA, instancePrototype.constructor, methodName);
37
+ if (!paramsMetadata) {
38
+ return false;
39
+ }
40
+ const metadataKeys = Object.keys(paramsMetadata);
41
+ return metadataKeys.some(key => {
42
+ const type = this.contextUtils.mapParamType(key);
43
+ return Number(type) === ws_paramtype_enum_1.WsParamtype.ACK;
44
+ });
45
+ }
30
46
  *scanForServerHooks(instance) {
31
47
  for (const propertyKey in instance) {
32
48
  if ((0, shared_utils_1.isFunction)(propertyKey)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestjs/websockets",
3
- "version": "11.1.6",
3
+ "version": "11.1.7",
4
4
  "description": "Nest - modern, fast, powerful node.js web framework (@websockets)",
5
5
  "author": "Kamil Mysliwiec",
6
6
  "license": "MIT",
@@ -18,8 +18,8 @@
18
18
  "tslib": "2.8.1"
19
19
  },
20
20
  "devDependencies": {
21
- "@nestjs/common": "11.1.6",
22
- "@nestjs/core": "11.1.6"
21
+ "@nestjs/common": "11.1.7",
22
+ "@nestjs/core": "11.1.7"
23
23
  },
24
24
  "peerDependencies": {
25
25
  "@nestjs/common": "^11.0.0",
@@ -31,10 +31,11 @@ class WebSocketsController {
31
31
  }
32
32
  subscribeToServerEvents(instance, options, port, moduleKey, instanceWrapperId) {
33
33
  const nativeMessageHandlers = this.metadataExplorer.explore(instance);
34
- const messageHandlers = nativeMessageHandlers.map(({ callback, message, methodName }) => ({
34
+ const messageHandlers = nativeMessageHandlers.map(({ callback, isAckHandledManually, message, methodName }) => ({
35
35
  message,
36
36
  methodName,
37
37
  callback: this.contextCreator.create(instance, callback, moduleKey, methodName),
38
+ isAckHandledManually,
38
39
  }));
39
40
  this.inspectEntrypointDefinitions(instance, port, messageHandlers, instanceWrapperId);
40
41
  if (this.appOptions.preview) {
@@ -86,9 +87,10 @@ class WebSocketsController {
86
87
  }
87
88
  subscribeMessages(subscribersMap, client, instance) {
88
89
  const adapter = this.config.getIoAdapter();
89
- const handlers = subscribersMap.map(({ callback, message }) => ({
90
+ const handlers = subscribersMap.map(({ callback, message, isAckHandledManually }) => ({
90
91
  message,
91
92
  callback: callback.bind(instance, client),
93
+ isAckHandledManually,
92
94
  }));
93
95
  adapter.bindMessageHandlers(client, handlers, data => (0, rxjs_1.from)(this.pickResult(data)).pipe((0, operators_1.mergeAll)()));
94
96
  }