@stomp/stompjs 7.1.1 → 7.2.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.
- package/README.md +129 -106
- package/bundles/stomp.umd.js +449 -205
- package/bundles/stomp.umd.js.map +1 -1
- package/bundles/stomp.umd.min.js +1 -1
- package/esm6/client.d.ts +635 -278
- package/esm6/client.js +442 -203
- package/esm6/client.js.map +1 -1
- package/esm6/stomp-config.d.ts +13 -1
- package/esm6/stomp-config.js.map +1 -1
- package/esm6/stomp-handler.d.ts +4 -1
- package/esm6/stomp-handler.js +7 -2
- package/esm6/stomp-handler.js.map +1 -1
- package/esm6/stomp-headers.d.ts +1 -1
- package/esm6/stomp-headers.js +1 -1
- package/esm6/ticker.js +2 -2
- package/esm6/ticker.js.map +1 -1
- package/esm6/types.d.ts +11 -2
- package/esm6/types.js.map +1 -1
- package/package.json +8 -8
- package/src/augment-websocket.ts +2 -2
- package/src/client.ts +662 -290
- package/src/compatibility/compat-client.ts +2 -2
- package/src/compatibility/stomp.ts +1 -1
- package/src/frame-impl.ts +6 -6
- package/src/parser.ts +4 -4
- package/src/stomp-config.ts +15 -0
- package/src/stomp-handler.ts +30 -13
- package/src/stomp-headers.ts +1 -1
- package/src/ticker.ts +8 -6
- package/src/types.ts +14 -4
package/esm6/client.js
CHANGED
|
@@ -5,16 +5,52 @@ import { Versions } from './versions.js';
|
|
|
5
5
|
* STOMP Client Class.
|
|
6
6
|
*
|
|
7
7
|
* Part of `@stomp/stompjs`.
|
|
8
|
+
*
|
|
9
|
+
* This class provides a robust implementation for connecting to and interacting with a
|
|
10
|
+
* STOMP-compliant messaging broker over WebSocket. It supports STOMP versions 1.2, 1.1, and 1.0.
|
|
11
|
+
*
|
|
12
|
+
* Features:
|
|
13
|
+
* - Handles automatic reconnections.
|
|
14
|
+
* - Supports heartbeat mechanisms to detect and report communication failures.
|
|
15
|
+
* - Allows customization of connection and WebSocket behaviors through configurations.
|
|
16
|
+
* - Compatible with both browser environments and Node.js with polyfill support for WebSocket.
|
|
8
17
|
*/
|
|
9
18
|
export class Client {
|
|
10
19
|
/**
|
|
11
|
-
*
|
|
20
|
+
* Provides access to the underlying WebSocket instance.
|
|
21
|
+
* This property is **read-only**.
|
|
22
|
+
*
|
|
23
|
+
* Example:
|
|
24
|
+
* ```javascript
|
|
25
|
+
* const webSocket = client.webSocket;
|
|
26
|
+
* if (webSocket) {
|
|
27
|
+
* console.log('WebSocket is connected:', webSocket.readyState === WebSocket.OPEN);
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* **Caution:**
|
|
32
|
+
* Directly interacting with the WebSocket instance (e.g., sending or receiving frames)
|
|
33
|
+
* can interfere with the proper functioning of this library. Such actions may cause
|
|
34
|
+
* unexpected behavior, disconnections, or invalid state in the library's internal mechanisms.
|
|
35
|
+
*
|
|
36
|
+
* Instead, use the library's provided methods to manage STOMP communication.
|
|
37
|
+
*
|
|
38
|
+
* @returns The WebSocket instance used by the STOMP handler, or `undefined` if not connected.
|
|
12
39
|
*/
|
|
13
40
|
get webSocket() {
|
|
14
41
|
return this._stompHandler?._webSocket;
|
|
15
42
|
}
|
|
16
43
|
/**
|
|
17
|
-
*
|
|
44
|
+
* Allows customization of the disconnection headers.
|
|
45
|
+
*
|
|
46
|
+
* Any changes made during an active session will also be applied immediately.
|
|
47
|
+
*
|
|
48
|
+
* Example:
|
|
49
|
+
* ```javascript
|
|
50
|
+
* client.disconnectHeaders = {
|
|
51
|
+
* receipt: 'custom-receipt-id'
|
|
52
|
+
* };
|
|
53
|
+
* ```
|
|
18
54
|
*/
|
|
19
55
|
get disconnectHeaders() {
|
|
20
56
|
return this._disconnectHeaders;
|
|
@@ -26,19 +62,53 @@ export class Client {
|
|
|
26
62
|
}
|
|
27
63
|
}
|
|
28
64
|
/**
|
|
29
|
-
*
|
|
65
|
+
* Indicates whether there is an active connection to the STOMP broker.
|
|
66
|
+
*
|
|
67
|
+
* Usage:
|
|
68
|
+
* ```javascript
|
|
69
|
+
* if (client.connected) {
|
|
70
|
+
* console.log('Client is connected to the broker.');
|
|
71
|
+
* } else {
|
|
72
|
+
* console.log('No connection to the broker.');
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @returns `true` if the client is currently connected, `false` otherwise.
|
|
30
77
|
*/
|
|
31
78
|
get connected() {
|
|
32
79
|
return !!this._stompHandler && this._stompHandler.connected;
|
|
33
80
|
}
|
|
34
81
|
/**
|
|
35
|
-
* version of STOMP protocol negotiated with the server
|
|
82
|
+
* The version of the STOMP protocol negotiated with the server during connection.
|
|
83
|
+
*
|
|
84
|
+
* This is a **read-only** property and reflects the negotiated protocol version after
|
|
85
|
+
* a successful connection.
|
|
86
|
+
*
|
|
87
|
+
* Example:
|
|
88
|
+
* ```javascript
|
|
89
|
+
* console.log('Connected STOMP version:', client.connectedVersion);
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* @returns The negotiated STOMP protocol version or `undefined` if not connected.
|
|
36
93
|
*/
|
|
37
94
|
get connectedVersion() {
|
|
38
95
|
return this._stompHandler ? this._stompHandler.connectedVersion : undefined;
|
|
39
96
|
}
|
|
40
97
|
/**
|
|
41
|
-
*
|
|
98
|
+
* Indicates whether the client is currently active.
|
|
99
|
+
*
|
|
100
|
+
* A client is considered active if it is connected or actively attempting to reconnect.
|
|
101
|
+
*
|
|
102
|
+
* Example:
|
|
103
|
+
* ```javascript
|
|
104
|
+
* if (client.active) {
|
|
105
|
+
* console.log('The client is active.');
|
|
106
|
+
* } else {
|
|
107
|
+
* console.log('The client is inactive.');
|
|
108
|
+
* }
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* @returns `true` if the client is active, otherwise `false`.
|
|
42
112
|
*/
|
|
43
113
|
get active() {
|
|
44
114
|
return this.state === ActivationState.ACTIVE;
|
|
@@ -48,129 +118,217 @@ export class Client {
|
|
|
48
118
|
this.onChangeState(state);
|
|
49
119
|
}
|
|
50
120
|
/**
|
|
51
|
-
*
|
|
121
|
+
* Constructs a new STOMP client instance.
|
|
122
|
+
*
|
|
123
|
+
* The constructor initializes default values and sets up no-op callbacks for all events.
|
|
124
|
+
* Configuration can be passed during construction, or updated later using `configure`.
|
|
125
|
+
*
|
|
126
|
+
* Example:
|
|
127
|
+
* ```javascript
|
|
128
|
+
* const client = new Client({
|
|
129
|
+
* brokerURL: 'wss://broker.example.com',
|
|
130
|
+
* reconnectDelay: 5000
|
|
131
|
+
* });
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* @param conf Optional configuration object to initialize the client with.
|
|
52
135
|
*/
|
|
53
136
|
constructor(conf = {}) {
|
|
54
137
|
/**
|
|
55
|
-
* STOMP versions to
|
|
138
|
+
* STOMP protocol versions to use during the handshake. By default, the client will attempt
|
|
139
|
+
* versions `1.2`, `1.1`, and `1.0` in descending order of preference.
|
|
56
140
|
*
|
|
57
141
|
* Example:
|
|
58
142
|
* ```javascript
|
|
59
|
-
*
|
|
60
|
-
*
|
|
143
|
+
* // Configure the client to only use versions 1.1 and 1.0
|
|
144
|
+
* client.stompVersions = new Versions(['1.1', '1.0']);
|
|
61
145
|
* ```
|
|
62
146
|
*/
|
|
63
147
|
this.stompVersions = Versions.default;
|
|
64
148
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
149
|
+
* Timeout for establishing STOMP connection, in milliseconds.
|
|
150
|
+
*
|
|
151
|
+
* If the connection is not established within this period, the attempt will fail.
|
|
152
|
+
* The default is `0`, meaning no timeout is set for connection attempts.
|
|
153
|
+
*
|
|
154
|
+
* Example:
|
|
155
|
+
* ```javascript
|
|
156
|
+
* client.connectionTimeout = 5000; // Fail connection if not established in 5 seconds
|
|
157
|
+
* ```
|
|
67
158
|
*/
|
|
68
159
|
this.connectionTimeout = 0;
|
|
69
160
|
/**
|
|
70
|
-
*
|
|
161
|
+
* Delay (in milliseconds) between reconnection attempts if the connection drops.
|
|
162
|
+
*
|
|
163
|
+
* Set to `0` to disable automatic reconnections. The default value is `5000` ms (5 seconds).
|
|
164
|
+
*
|
|
165
|
+
* Example:
|
|
166
|
+
* ```javascript
|
|
167
|
+
* client.reconnectDelay = 3000; // Attempt reconnection every 3 seconds
|
|
168
|
+
* client.reconnectDelay = 0; // Disable automatic reconnection
|
|
169
|
+
* ```
|
|
71
170
|
*/
|
|
72
171
|
this.reconnectDelay = 5000;
|
|
73
172
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
173
|
+
* The next reconnection delay, used internally.
|
|
174
|
+
* Initialized to the value of [Client#reconnectDelay]{@link Client#reconnectDelay}, and it may
|
|
175
|
+
* dynamically change based on [Client#reconnectTimeMode]{@link Client#reconnectTimeMode}.
|
|
76
176
|
*/
|
|
77
177
|
this._nextReconnectDelay = 0;
|
|
78
178
|
/**
|
|
79
|
-
* Maximum
|
|
80
|
-
*
|
|
81
|
-
*
|
|
179
|
+
* Maximum delay (in milliseconds) between reconnection attempts when using exponential backoff.
|
|
180
|
+
*
|
|
181
|
+
* Default is 15 minutes (`15 * 60 * 1000` milliseconds). If `0`, there will be no upper limit.
|
|
182
|
+
*
|
|
183
|
+
* Example:
|
|
184
|
+
* ```javascript
|
|
185
|
+
* client.maxReconnectDelay = 10000; // Maximum wait time is 10 seconds
|
|
186
|
+
* ```
|
|
82
187
|
*/
|
|
83
|
-
this.maxReconnectDelay = 15 * 60 * 1000;
|
|
188
|
+
this.maxReconnectDelay = 15 * 60 * 1000;
|
|
84
189
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
190
|
+
* Mode for determining the time interval between reconnection attempts.
|
|
191
|
+
*
|
|
192
|
+
* Available modes:
|
|
193
|
+
* - `ReconnectionTimeMode.LINEAR` (default): Fixed delays between reconnection attempts.
|
|
194
|
+
* - `ReconnectionTimeMode.EXPONENTIAL`: Delay doubles after each attempt, capped by [maxReconnectDelay]{@link Client#maxReconnectDelay}.
|
|
87
195
|
*
|
|
196
|
+
* Example:
|
|
88
197
|
* ```javascript
|
|
89
|
-
* client.
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* maxReconnectDelay: 10000, // Optional, when provided, it will not wait more that these ms
|
|
93
|
-
* })
|
|
198
|
+
* client.reconnectTimeMode = ReconnectionTimeMode.EXPONENTIAL;
|
|
199
|
+
* client.reconnectDelay = 200; // Initial delay of 200 ms, doubles with each attempt
|
|
200
|
+
* client.maxReconnectDelay = 2 * 60 * 1000; // Cap delay at 10 minutes
|
|
94
201
|
* ```
|
|
95
202
|
*/
|
|
96
203
|
this.reconnectTimeMode = ReconnectionTimeMode.LINEAR;
|
|
97
204
|
/**
|
|
98
|
-
*
|
|
205
|
+
* Interval (in milliseconds) for receiving heartbeat signals from the server.
|
|
206
|
+
*
|
|
207
|
+
* Specifies the expected frequency of heartbeats sent by the server. Set to `0` to disable.
|
|
208
|
+
*
|
|
209
|
+
* Example:
|
|
210
|
+
* ```javascript
|
|
211
|
+
* client.heartbeatIncoming = 10000; // Expect a heartbeat every 10 seconds
|
|
212
|
+
* ```
|
|
99
213
|
*/
|
|
100
214
|
this.heartbeatIncoming = 10000;
|
|
101
215
|
/**
|
|
102
|
-
*
|
|
216
|
+
* Multiplier for adjusting tolerance when processing heartbeat signals.
|
|
217
|
+
*
|
|
218
|
+
* Tolerance level is calculated using the multiplier:
|
|
219
|
+
* `tolerance = heartbeatIncoming * heartbeatToleranceMultiplier`.
|
|
220
|
+
* This helps account for delays in network communication or variations in timings.
|
|
221
|
+
*
|
|
222
|
+
* Default value is `2`.
|
|
223
|
+
*
|
|
224
|
+
* Example:
|
|
225
|
+
* ```javascript
|
|
226
|
+
* client.heartbeatToleranceMultiplier = 2.5; // Tolerates longer delays
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
this.heartbeatToleranceMultiplier = 2;
|
|
230
|
+
/**
|
|
231
|
+
* Interval (in milliseconds) for sending heartbeat signals to the server.
|
|
232
|
+
*
|
|
233
|
+
* Specifies how frequently heartbeats should be sent to the server. Set to `0` to disable.
|
|
234
|
+
*
|
|
235
|
+
* Example:
|
|
236
|
+
* ```javascript
|
|
237
|
+
* client.heartbeatOutgoing = 5000; // Send a heartbeat every 5 seconds
|
|
238
|
+
* ```
|
|
103
239
|
*/
|
|
104
240
|
this.heartbeatOutgoing = 10000;
|
|
105
241
|
/**
|
|
106
|
-
*
|
|
107
|
-
* See https://github.com/stomp-js/stompjs/pull/579
|
|
108
|
-
*
|
|
109
|
-
* Can be worker or interval strategy, but will always use `interval`
|
|
110
|
-
* if web workers are unavailable, for example, in a non-browser environment.
|
|
242
|
+
* Strategy for sending outgoing heartbeats.
|
|
111
243
|
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
244
|
+
* Options:
|
|
245
|
+
* - `TickerStrategy.Worker`: Uses Web Workers for sending heartbeats (recommended for long-running or background sessions).
|
|
246
|
+
* - `TickerStrategy.Interval`: Uses standard JavaScript `setInterval` (default).
|
|
115
247
|
*
|
|
116
|
-
*
|
|
248
|
+
* Note:
|
|
249
|
+
* - If Web Workers are unavailable (e.g., in Node.js), the `Interval` strategy is used automatically.
|
|
250
|
+
* - Web Workers are preferable in browsers for reducing disconnects when tabs are in the background.
|
|
117
251
|
*
|
|
118
|
-
*
|
|
252
|
+
* Example:
|
|
253
|
+
* ```javascript
|
|
254
|
+
* client.heartbeatStrategy = TickerStrategy.Worker;
|
|
255
|
+
* ```
|
|
119
256
|
*/
|
|
120
257
|
this.heartbeatStrategy = TickerStrategy.Interval;
|
|
121
258
|
/**
|
|
122
|
-
*
|
|
123
|
-
* It splits larger (text) packets into chunks of [maxWebSocketChunkSize]{@link Client#maxWebSocketChunkSize}.
|
|
124
|
-
* Only Java Spring brokers seem to support this mode.
|
|
259
|
+
* Enables splitting of large text WebSocket frames into smaller chunks.
|
|
125
260
|
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* Setting it for such a broker will cause large messages to fail.
|
|
261
|
+
* This setting is enabled for brokers that support only chunked messages (e.g., Java Spring-based brokers).
|
|
262
|
+
* Default is `false`.
|
|
129
263
|
*
|
|
130
|
-
*
|
|
264
|
+
* Warning:
|
|
265
|
+
* - Should not be used with WebSocket-compliant brokers, as chunking may cause large message failures.
|
|
266
|
+
* - Binary WebSocket frames are never split.
|
|
131
267
|
*
|
|
132
|
-
*
|
|
268
|
+
* Example:
|
|
269
|
+
* ```javascript
|
|
270
|
+
* client.splitLargeFrames = true;
|
|
271
|
+
* client.maxWebSocketChunkSize = 4096; // Allow chunks of 4 KB
|
|
272
|
+
* ```
|
|
133
273
|
*/
|
|
134
274
|
this.splitLargeFrames = false;
|
|
135
275
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
276
|
+
* Maximum size (in bytes) for individual WebSocket chunks if [splitLargeFrames]{@link Client#splitLargeFrames} is enabled.
|
|
277
|
+
*
|
|
278
|
+
* Default is 8 KB (`8 * 1024` bytes). This value has no effect if [splitLargeFrames]{@link Client#splitLargeFrames} is `false`.
|
|
138
279
|
*/
|
|
139
280
|
this.maxWebSocketChunkSize = 8 * 1024;
|
|
140
281
|
/**
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* Default is `false`, which should work with all compliant brokers.
|
|
282
|
+
* Forces all WebSocket frames to use binary transport, irrespective of payload type.
|
|
283
|
+
*
|
|
284
|
+
* Default behavior determines frame type based on payload (e.g., binary data for ArrayBuffers).
|
|
145
285
|
*
|
|
146
|
-
*
|
|
286
|
+
* Example:
|
|
287
|
+
* ```javascript
|
|
288
|
+
* client.forceBinaryWSFrames = true;
|
|
289
|
+
* ```
|
|
147
290
|
*/
|
|
148
291
|
this.forceBinaryWSFrames = false;
|
|
149
292
|
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
* this
|
|
156
|
-
*
|
|
157
|
-
*
|
|
293
|
+
* Workaround for a React Native WebSocket bug, where messages containing `NULL` are chopped.
|
|
294
|
+
*
|
|
295
|
+
* Enabling this appends a `NULL` character to incoming frames to ensure they remain valid STOMP packets.
|
|
296
|
+
*
|
|
297
|
+
* Warning:
|
|
298
|
+
* - For brokers that split large messages, this may cause data loss or connection termination.
|
|
299
|
+
*
|
|
300
|
+
* Example:
|
|
301
|
+
* ```javascript
|
|
302
|
+
* client.appendMissingNULLonIncoming = true;
|
|
303
|
+
* ```
|
|
158
304
|
*/
|
|
159
305
|
this.appendMissingNULLonIncoming = false;
|
|
160
306
|
/**
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
307
|
+
* Instruct the library to immediately terminate the socket on communication failures, even
|
|
308
|
+
* before the WebSocket is completely closed.
|
|
309
|
+
*
|
|
310
|
+
* This is particularly useful in browser environments where WebSocket closure may get delayed,
|
|
311
|
+
* causing prolonged reconnection intervals under certain failure conditions.
|
|
312
|
+
*
|
|
313
|
+
*
|
|
314
|
+
* Example:
|
|
315
|
+
* ```javascript
|
|
316
|
+
* client.discardWebsocketOnCommFailure = true; // Enable aggressive closing of WebSocket
|
|
317
|
+
* ```
|
|
318
|
+
*
|
|
319
|
+
* Default value: `false`.
|
|
167
320
|
*/
|
|
168
321
|
this.discardWebsocketOnCommFailure = false;
|
|
169
322
|
/**
|
|
170
|
-
*
|
|
323
|
+
* Current activation state of the client.
|
|
324
|
+
*
|
|
325
|
+
* Possible states:
|
|
326
|
+
* - `ActivationState.ACTIVE`: Client is connected or actively attempting to connect.
|
|
327
|
+
* - `ActivationState.INACTIVE`: Client is disconnected and not attempting to reconnect.
|
|
328
|
+
* - `ActivationState.DEACTIVATING`: Client is in the process of disconnecting.
|
|
171
329
|
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
330
|
+
* Note: The client may transition directly from `ACTIVE` to `INACTIVE` without entering
|
|
331
|
+
* the `DEACTIVATING` state.
|
|
174
332
|
*/
|
|
175
333
|
this.state = ActivationState.INACTIVE;
|
|
176
334
|
// No op callbacks
|
|
@@ -182,6 +340,8 @@ export class Client {
|
|
|
182
340
|
this.onUnhandledMessage = noOp;
|
|
183
341
|
this.onUnhandledReceipt = noOp;
|
|
184
342
|
this.onUnhandledFrame = noOp;
|
|
343
|
+
this.onHeartbeatReceived = noOp;
|
|
344
|
+
this.onHeartbeatLost = noOp;
|
|
185
345
|
this.onStompError = noOp;
|
|
186
346
|
this.onWebSocketClose = noOp;
|
|
187
347
|
this.onWebSocketError = noOp;
|
|
@@ -194,7 +354,22 @@ export class Client {
|
|
|
194
354
|
this.configure(conf);
|
|
195
355
|
}
|
|
196
356
|
/**
|
|
197
|
-
*
|
|
357
|
+
* Updates the client's configuration.
|
|
358
|
+
*
|
|
359
|
+
* All properties in the provided configuration object will override the current settings.
|
|
360
|
+
*
|
|
361
|
+
* Additionally, a warning is logged if `maxReconnectDelay` is configured to a
|
|
362
|
+
* value lower than `reconnectDelay`, and `maxReconnectDelay` is adjusted to match `reconnectDelay`.
|
|
363
|
+
*
|
|
364
|
+
* Example:
|
|
365
|
+
* ```javascript
|
|
366
|
+
* client.configure({
|
|
367
|
+
* reconnectDelay: 3000,
|
|
368
|
+
* maxReconnectDelay: 10000
|
|
369
|
+
* });
|
|
370
|
+
* ```
|
|
371
|
+
*
|
|
372
|
+
* @param conf Configuration object containing the new settings.
|
|
198
373
|
*/
|
|
199
374
|
configure(conf) {
|
|
200
375
|
// bulk assign all properties to this
|
|
@@ -207,12 +382,20 @@ export class Client {
|
|
|
207
382
|
}
|
|
208
383
|
}
|
|
209
384
|
/**
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
* is
|
|
385
|
+
* Activates the client, initiating a connection to the STOMP broker.
|
|
386
|
+
*
|
|
387
|
+
* On activation, the client attempts to connect and sets its state to `ACTIVE`. If the connection
|
|
388
|
+
* is lost, it will automatically retry based on `reconnectDelay` or `maxReconnectDelay`. If
|
|
389
|
+
* `reconnectTimeMode` is set to `EXPONENTIAL`, the reconnect delay increases exponentially.
|
|
390
|
+
*
|
|
391
|
+
* To stop reconnection attempts and disconnect, call [Client#deactivate]{@link Client#deactivate}.
|
|
392
|
+
*
|
|
393
|
+
* Example:
|
|
394
|
+
* ```javascript
|
|
395
|
+
* client.activate(); // Connect to the broker
|
|
396
|
+
* ```
|
|
214
397
|
*
|
|
215
|
-
*
|
|
398
|
+
* If the client is currently `DEACTIVATING`, connection is delayed until the deactivation process completes.
|
|
216
399
|
*/
|
|
217
400
|
activate() {
|
|
218
401
|
const _activate = () => {
|
|
@@ -270,6 +453,7 @@ export class Client {
|
|
|
270
453
|
connectHeaders: this.connectHeaders,
|
|
271
454
|
disconnectHeaders: this._disconnectHeaders,
|
|
272
455
|
heartbeatIncoming: this.heartbeatIncoming,
|
|
456
|
+
heartbeatGracePeriods: this.heartbeatToleranceMultiplier,
|
|
273
457
|
heartbeatOutgoing: this.heartbeatOutgoing,
|
|
274
458
|
heartbeatStrategy: this.heartbeatStrategy,
|
|
275
459
|
splitLargeFrames: this.splitLargeFrames,
|
|
@@ -322,6 +506,12 @@ export class Client {
|
|
|
322
506
|
onUnhandledFrame: frame => {
|
|
323
507
|
this.onUnhandledFrame(frame);
|
|
324
508
|
},
|
|
509
|
+
onHeartbeatReceived: () => {
|
|
510
|
+
this.onHeartbeatReceived();
|
|
511
|
+
},
|
|
512
|
+
onHeartbeatLost: () => {
|
|
513
|
+
this.onHeartbeatLost();
|
|
514
|
+
},
|
|
325
515
|
});
|
|
326
516
|
this._stompHandler.start();
|
|
327
517
|
}
|
|
@@ -355,27 +545,36 @@ export class Client {
|
|
|
355
545
|
}
|
|
356
546
|
}
|
|
357
547
|
/**
|
|
358
|
-
*
|
|
359
|
-
*
|
|
548
|
+
* Disconnects the client and stops the automatic reconnection loop.
|
|
549
|
+
*
|
|
550
|
+
* If there is an active STOMP connection at the time of invocation, the appropriate callbacks
|
|
551
|
+
* will be triggered during the shutdown sequence. Once deactivated, the client will enter the
|
|
552
|
+
* `INACTIVE` state, and no further reconnection attempts will be made.
|
|
360
553
|
*
|
|
361
|
-
*
|
|
362
|
-
*
|
|
554
|
+
* **Behavior**:
|
|
555
|
+
* - If there is no active WebSocket connection, this method resolves immediately.
|
|
556
|
+
* - If there is an active connection, the method waits for the underlying WebSocket
|
|
557
|
+
* to properly close before resolving.
|
|
558
|
+
* - Multiple calls to this method are safe. Each invocation resolves upon completion.
|
|
559
|
+
* - To reactivate, call [Client#activate]{@link Client#activate}.
|
|
363
560
|
*
|
|
364
|
-
*
|
|
365
|
-
*
|
|
561
|
+
* **Experimental Option:**
|
|
562
|
+
* - By specifying the `force: true` option, the WebSocket connection is discarded immediately,
|
|
563
|
+
* bypassing both the STOMP and WebSocket shutdown sequences.
|
|
564
|
+
* - **Caution:** Using `force: true` may leave the WebSocket in an inconsistent state,
|
|
565
|
+
* and brokers may not immediately detect the termination.
|
|
366
566
|
*
|
|
367
|
-
*
|
|
567
|
+
* Example:
|
|
568
|
+
* ```javascript
|
|
569
|
+
* // Graceful disconnect
|
|
570
|
+
* await client.deactivate();
|
|
368
571
|
*
|
|
369
|
-
*
|
|
370
|
-
*
|
|
371
|
-
*
|
|
372
|
-
* if the underlying connection had gone stale.
|
|
373
|
-
* Using this mode can speed up.
|
|
374
|
-
* When this mode is used, the actual Websocket may linger for a while
|
|
375
|
-
* and the broker may not realize that the connection is no longer in use.
|
|
572
|
+
* // Forced disconnect to speed up shutdown when the connection is stale
|
|
573
|
+
* await client.deactivate({ force: true });
|
|
574
|
+
* ```
|
|
376
575
|
*
|
|
377
|
-
*
|
|
378
|
-
*
|
|
576
|
+
* @param options Configuration options for deactivation. Use `force: true` for immediate shutdown.
|
|
577
|
+
* @returns A Promise that resolves when the deactivation process completes.
|
|
379
578
|
*/
|
|
380
579
|
async deactivate(options = {}) {
|
|
381
580
|
const force = options.force || false;
|
|
@@ -420,10 +619,18 @@ export class Client {
|
|
|
420
619
|
return retPromise;
|
|
421
620
|
}
|
|
422
621
|
/**
|
|
423
|
-
*
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
622
|
+
* Forces a disconnect by directly closing the WebSocket.
|
|
623
|
+
*
|
|
624
|
+
* Unlike a normal disconnect, this does not send a DISCONNECT sequence to the broker but
|
|
625
|
+
* instead closes the WebSocket connection directly. After forcing a disconnect, the client
|
|
626
|
+
* will automatically attempt to reconnect based on its `reconnectDelay` configuration.
|
|
627
|
+
*
|
|
628
|
+
* **Note:** To prevent further reconnect attempts, call [Client#deactivate]{@link Client#deactivate}.
|
|
629
|
+
*
|
|
630
|
+
* Example:
|
|
631
|
+
* ```javascript
|
|
632
|
+
* client.forceDisconnect();
|
|
633
|
+
* ```
|
|
427
634
|
*/
|
|
428
635
|
forceDisconnect() {
|
|
429
636
|
if (this._stompHandler) {
|
|
@@ -437,39 +644,38 @@ export class Client {
|
|
|
437
644
|
}
|
|
438
645
|
}
|
|
439
646
|
/**
|
|
440
|
-
*
|
|
441
|
-
* and naming of destinations.
|
|
442
|
-
*
|
|
443
|
-
* STOMP protocol specifies and suggests some headers and also allows broker-specific headers.
|
|
647
|
+
* Sends a message to the specified destination on the STOMP broker.
|
|
444
648
|
*
|
|
445
|
-
* `body` must be
|
|
446
|
-
*
|
|
649
|
+
* The `body` must be a `string`. For non-string payloads (e.g., JSON), encode it as a string before sending.
|
|
650
|
+
* If sending binary data, use the `binaryBody` parameter as a [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array).
|
|
447
651
|
*
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
*
|
|
652
|
+
* **Content-Length Behavior**:
|
|
653
|
+
* - For non-binary messages, the `content-length` header is added by default.
|
|
654
|
+
* - The `content-length` header can be skipped for text frames by setting `skipContentLengthHeader: true` in the parameters.
|
|
655
|
+
* - For binary messages, the `content-length` header is always included.
|
|
452
656
|
*
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
*
|
|
456
|
-
*
|
|
457
|
-
* Caution: The broker will, most likely, report an error and disconnect
|
|
458
|
-
* if the message body has NULL octet(s) and `content-length` header is missing.
|
|
657
|
+
* **Notes**:
|
|
658
|
+
* - Ensure that brokers support binary frames before using `binaryBody`.
|
|
659
|
+
* - Sending messages with NULL octets and missing `content-length` headers can cause brokers to disconnect and throw errors.
|
|
459
660
|
*
|
|
661
|
+
* Example:
|
|
460
662
|
* ```javascript
|
|
461
|
-
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
*
|
|
467
|
-
*
|
|
468
|
-
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
*
|
|
472
|
-
*
|
|
663
|
+
* // Basic text message
|
|
664
|
+
* client.publish({ destination: "/queue/test", body: "Hello, STOMP" });
|
|
665
|
+
*
|
|
666
|
+
* // Text message with additional headers
|
|
667
|
+
* client.publish({ destination: "/queue/test", headers: { priority: 9 }, body: "Hello, STOMP" });
|
|
668
|
+
*
|
|
669
|
+
* // Skip content-length header
|
|
670
|
+
* client.publish({ destination: "/queue/test", body: "Hello, STOMP", skipContentLengthHeader: true });
|
|
671
|
+
*
|
|
672
|
+
* // Binary message
|
|
673
|
+
* const binaryData = new Uint8Array([1, 2, 3, 4]);
|
|
674
|
+
* client.publish({
|
|
675
|
+
* destination: '/topic/special',
|
|
676
|
+
* binaryBody: binaryData,
|
|
677
|
+
* headers: { 'content-type': 'application/octet-stream' }
|
|
678
|
+
* });
|
|
473
679
|
* ```
|
|
474
680
|
*/
|
|
475
681
|
publish(params) {
|
|
@@ -483,39 +689,27 @@ export class Client {
|
|
|
483
689
|
}
|
|
484
690
|
}
|
|
485
691
|
/**
|
|
486
|
-
*
|
|
487
|
-
* To request an acknowledgement, a `receipt` header needs to be sent with the actual request.
|
|
488
|
-
* The value (say receipt-id) for this header needs to be unique for each use.
|
|
489
|
-
* Typically, a sequence, a UUID, a random number or a combination may be used.
|
|
692
|
+
* Monitors for a receipt acknowledgment from the broker for specific operations.
|
|
490
693
|
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
694
|
+
* Add a `receipt` header to the operation (like subscribe or publish), and use this method with
|
|
695
|
+
* the same receipt ID to detect when the broker has acknowledged the operation's completion.
|
|
493
696
|
*
|
|
494
|
-
*
|
|
495
|
-
* when the corresponding receipt has been received.
|
|
496
|
-
*
|
|
497
|
-
* The actual {@link IFrame} will be passed as parameter to the callback.
|
|
697
|
+
* The callback is invoked with the corresponding {@link IFrame} when the receipt is received.
|
|
498
698
|
*
|
|
499
699
|
* Example:
|
|
500
700
|
* ```javascript
|
|
501
|
-
*
|
|
502
|
-
* let receiptId = randomText();
|
|
503
|
-
*
|
|
504
|
-
* client.watchForReceipt(receiptId, function() {
|
|
505
|
-
* // Will be called after server acknowledges
|
|
506
|
-
* });
|
|
701
|
+
* const receiptId = "unique-receipt-id";
|
|
507
702
|
*
|
|
508
|
-
*
|
|
703
|
+
* client.watchForReceipt(receiptId, (frame) => {
|
|
704
|
+
* console.log("Operation acknowledged by the broker:", frame);
|
|
705
|
+
* });
|
|
509
706
|
*
|
|
510
|
-
*
|
|
511
|
-
*
|
|
512
|
-
* receiptId = randomText();
|
|
513
|
-
*
|
|
514
|
-
* client.watchForReceipt(receiptId, function() {
|
|
515
|
-
* // Will be called after server acknowledges
|
|
516
|
-
* });
|
|
517
|
-
* client.publish({destination: TEST.destination, headers: {receipt: receiptId}, body: msg});
|
|
707
|
+
* // Attach the receipt header to an operation
|
|
708
|
+
* client.publish({ destination: "/queue/test", headers: { receipt: receiptId }, body: "Hello" });
|
|
518
709
|
* ```
|
|
710
|
+
*
|
|
711
|
+
* @param receiptId Unique identifier for the receipt.
|
|
712
|
+
* @param callback Callback function invoked on receiving the RECEIPT frame.
|
|
519
713
|
*/
|
|
520
714
|
watchForReceipt(receiptId, callback) {
|
|
521
715
|
this._checkConnection();
|
|
@@ -523,28 +717,33 @@ export class Client {
|
|
|
523
717
|
this._stompHandler.watchForReceipt(receiptId, callback);
|
|
524
718
|
}
|
|
525
719
|
/**
|
|
526
|
-
*
|
|
527
|
-
* received message with the {@link IMessage} as argument.
|
|
720
|
+
* Subscribes to a destination on the STOMP broker.
|
|
528
721
|
*
|
|
529
|
-
*
|
|
530
|
-
*
|
|
722
|
+
* The callback is triggered for each message received from the subscribed destination. The message
|
|
723
|
+
* is passed as an {@link IMessage} instance.
|
|
531
724
|
*
|
|
725
|
+
* **Subscription ID**:
|
|
726
|
+
* - If no `id` is provided in `headers`, the library generates a unique subscription ID automatically.
|
|
727
|
+
* - Provide an explicit `id` in `headers` if you wish to manage the subscription ID manually.
|
|
728
|
+
*
|
|
729
|
+
* Example:
|
|
532
730
|
* ```javascript
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
*
|
|
537
|
-
*
|
|
538
|
-
*
|
|
539
|
-
*
|
|
540
|
-
*
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
* // Explicit subscription id
|
|
545
|
-
* var mySubId = 'my-subscription-id-001';
|
|
546
|
-
* var subscription = client.subscribe(destination, callback, { id: mySubId });
|
|
731
|
+
* const callback = (message) => {
|
|
732
|
+
* console.log("Received message:", message.body);
|
|
733
|
+
* };
|
|
734
|
+
*
|
|
735
|
+
* // Auto-generated subscription ID
|
|
736
|
+
* const subscription = client.subscribe("/queue/test", callback);
|
|
737
|
+
*
|
|
738
|
+
* // Explicit subscription ID
|
|
739
|
+
* const mySubId = "my-subscription-id";
|
|
740
|
+
* const subscription = client.subscribe("/queue/test", callback, { id: mySubId });
|
|
547
741
|
* ```
|
|
742
|
+
*
|
|
743
|
+
* @param destination Destination to subscribe to.
|
|
744
|
+
* @param callback Function invoked for each received message.
|
|
745
|
+
* @param headers Optional headers for subscription, such as `id`.
|
|
746
|
+
* @returns A {@link StompSubscription} which can be used to manage the subscription.
|
|
548
747
|
*/
|
|
549
748
|
subscribe(destination, callback, headers = {}) {
|
|
550
749
|
this._checkConnection();
|
|
@@ -552,16 +751,24 @@ export class Client {
|
|
|
552
751
|
return this._stompHandler.subscribe(destination, callback, headers);
|
|
553
752
|
}
|
|
554
753
|
/**
|
|
555
|
-
*
|
|
556
|
-
* `unsubscribe()` directly on {@link StompSubscription} returned by `client.subscribe()`:
|
|
754
|
+
* Unsubscribes from a subscription on the STOMP broker.
|
|
557
755
|
*
|
|
756
|
+
* Prefer using the `unsubscribe` method directly on the {@link StompSubscription} returned from `subscribe` for cleaner management:
|
|
558
757
|
* ```javascript
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
758
|
+
* const subscription = client.subscribe("/queue/test", callback);
|
|
759
|
+
* // Unsubscribe using the subscription object
|
|
760
|
+
* subscription.unsubscribe();
|
|
562
761
|
* ```
|
|
563
762
|
*
|
|
564
|
-
*
|
|
763
|
+
* This method can also be used directly with the subscription ID.
|
|
764
|
+
*
|
|
765
|
+
* Example:
|
|
766
|
+
* ```javascript
|
|
767
|
+
* client.unsubscribe("my-subscription-id");
|
|
768
|
+
* ```
|
|
769
|
+
*
|
|
770
|
+
* @param id Subscription ID to unsubscribe.
|
|
771
|
+
* @param headers Optional headers to pass for the UNSUBSCRIBE frame.
|
|
565
772
|
*/
|
|
566
773
|
unsubscribe(id, headers = {}) {
|
|
567
774
|
this._checkConnection();
|
|
@@ -569,10 +776,21 @@ export class Client {
|
|
|
569
776
|
this._stompHandler.unsubscribe(id, headers);
|
|
570
777
|
}
|
|
571
778
|
/**
|
|
572
|
-
*
|
|
573
|
-
* and [abort]{@link ITransaction#abort}.
|
|
779
|
+
* Starts a new transaction. The returned {@link ITransaction} object provides
|
|
780
|
+
* methods for [commit]{@link ITransaction#commit} and [abort]{@link ITransaction#abort}.
|
|
781
|
+
*
|
|
782
|
+
* If `transactionId` is not provided, the library generates a unique ID internally.
|
|
783
|
+
*
|
|
784
|
+
* Example:
|
|
785
|
+
* ```javascript
|
|
786
|
+
* const tx = client.begin(); // Auto-generated ID
|
|
574
787
|
*
|
|
575
|
-
*
|
|
788
|
+
* // Or explicitly specify a transaction ID
|
|
789
|
+
* const tx = client.begin("my-transaction-id");
|
|
790
|
+
* ```
|
|
791
|
+
*
|
|
792
|
+
* @param transactionId Optional transaction ID.
|
|
793
|
+
* @returns An instance of {@link ITransaction}.
|
|
576
794
|
*/
|
|
577
795
|
begin(transactionId) {
|
|
578
796
|
this._checkConnection();
|
|
@@ -580,16 +798,19 @@ export class Client {
|
|
|
580
798
|
return this._stompHandler.begin(transactionId);
|
|
581
799
|
}
|
|
582
800
|
/**
|
|
583
|
-
*
|
|
801
|
+
* Commits a transaction.
|
|
584
802
|
*
|
|
585
|
-
* It is
|
|
586
|
-
*
|
|
803
|
+
* It is strongly recommended to call [commit]{@link ITransaction#commit} on
|
|
804
|
+
* the transaction object returned by [client#begin]{@link Client#begin}.
|
|
587
805
|
*
|
|
806
|
+
* Example:
|
|
588
807
|
* ```javascript
|
|
589
|
-
*
|
|
590
|
-
*
|
|
591
|
-
*
|
|
808
|
+
* const tx = client.begin();
|
|
809
|
+
* // Perform operations under this transaction
|
|
810
|
+
* tx.commit();
|
|
592
811
|
* ```
|
|
812
|
+
*
|
|
813
|
+
* @param transactionId The ID of the transaction to commit.
|
|
593
814
|
*/
|
|
594
815
|
commit(transactionId) {
|
|
595
816
|
this._checkConnection();
|
|
@@ -597,15 +818,19 @@ export class Client {
|
|
|
597
818
|
this._stompHandler.commit(transactionId);
|
|
598
819
|
}
|
|
599
820
|
/**
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
821
|
+
* Aborts a transaction.
|
|
822
|
+
*
|
|
823
|
+
* It is strongly recommended to call [abort]{@link ITransaction#abort} directly
|
|
824
|
+
* on the transaction object returned by [client#begin]{@link Client#begin}.
|
|
603
825
|
*
|
|
826
|
+
* Example:
|
|
604
827
|
* ```javascript
|
|
605
|
-
*
|
|
606
|
-
*
|
|
607
|
-
*
|
|
828
|
+
* const tx = client.begin();
|
|
829
|
+
* // Perform operations under this transaction
|
|
830
|
+
* tx.abort(); // Abort the transaction
|
|
608
831
|
* ```
|
|
832
|
+
*
|
|
833
|
+
* @param transactionId The ID of the transaction to abort.
|
|
609
834
|
*/
|
|
610
835
|
abort(transactionId) {
|
|
611
836
|
this._checkConnection();
|
|
@@ -613,17 +838,23 @@ export class Client {
|
|
|
613
838
|
this._stompHandler.abort(transactionId);
|
|
614
839
|
}
|
|
615
840
|
/**
|
|
616
|
-
*
|
|
617
|
-
* on the {@link IMessage}
|
|
841
|
+
* Acknowledges receipt of a message. Typically, this should be done by calling
|
|
842
|
+
* [ack]{@link IMessage#ack} directly on the {@link IMessage} instance passed
|
|
843
|
+
* to the subscription callback.
|
|
618
844
|
*
|
|
845
|
+
* Example:
|
|
619
846
|
* ```javascript
|
|
620
|
-
*
|
|
621
|
-
*
|
|
622
|
-
*
|
|
623
|
-
*
|
|
624
|
-
*
|
|
625
|
-
*
|
|
847
|
+
* const callback = (message) => {
|
|
848
|
+
* // Process the message
|
|
849
|
+
* message.ack(); // Acknowledge the message
|
|
850
|
+
* };
|
|
851
|
+
*
|
|
852
|
+
* client.subscribe("/queue/example", callback, { ack: "client" });
|
|
626
853
|
* ```
|
|
854
|
+
*
|
|
855
|
+
* @param messageId The ID of the message to acknowledge.
|
|
856
|
+
* @param subscriptionId The ID of the subscription.
|
|
857
|
+
* @param headers Optional headers for the acknowledgment frame.
|
|
627
858
|
*/
|
|
628
859
|
ack(messageId, subscriptionId, headers = {}) {
|
|
629
860
|
this._checkConnection();
|
|
@@ -631,17 +862,25 @@ export class Client {
|
|
|
631
862
|
this._stompHandler.ack(messageId, subscriptionId, headers);
|
|
632
863
|
}
|
|
633
864
|
/**
|
|
634
|
-
*
|
|
635
|
-
*
|
|
865
|
+
* Rejects a message (negative acknowledgment). Like acknowledgments, this should
|
|
866
|
+
* typically be done by calling [nack]{@link IMessage#nack} directly on the {@link IMessage}
|
|
867
|
+
* instance passed to the subscription callback.
|
|
636
868
|
*
|
|
869
|
+
* Example:
|
|
637
870
|
* ```javascript
|
|
638
|
-
*
|
|
639
|
-
*
|
|
640
|
-
*
|
|
641
|
-
*
|
|
642
|
-
*
|
|
643
|
-
*
|
|
871
|
+
* const callback = (message) => {
|
|
872
|
+
* // Process the message
|
|
873
|
+
* if (isError(message)) {
|
|
874
|
+
* message.nack(); // Reject the message
|
|
875
|
+
* }
|
|
876
|
+
* };
|
|
877
|
+
*
|
|
878
|
+
* client.subscribe("/queue/example", callback, { ack: "client" });
|
|
644
879
|
* ```
|
|
880
|
+
*
|
|
881
|
+
* @param messageId The ID of the message to negatively acknowledge.
|
|
882
|
+
* @param subscriptionId The ID of the subscription.
|
|
883
|
+
* @param headers Optional headers for the NACK frame.
|
|
645
884
|
*/
|
|
646
885
|
nack(messageId, subscriptionId, headers = {}) {
|
|
647
886
|
this._checkConnection();
|