@stomp/stompjs 7.1.0 → 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 +130 -106
- package/bundles/stomp.umd.js +452 -200
- package/bundles/stomp.umd.js.map +1 -1
- package/bundles/stomp.umd.min.js +1 -1
- package/esm6/client.d.ts +638 -273
- package/esm6/client.js +445 -198
- package/esm6/client.js.map +1 -1
- package/esm6/i-transaction.d.ts +0 -2
- package/esm6/stomp-config.d.ts +15 -2
- 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 +664 -284
- package/src/compatibility/compat-client.ts +2 -2
- package/src/compatibility/stomp.ts +1 -1
- package/src/frame-impl.ts +6 -6
- package/src/i-transaction.ts +0 -2
- package/src/parser.ts +4 -4
- package/src/stomp-config.ts +17 -1
- 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,121 +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}.
|
|
195
|
+
*
|
|
196
|
+
* Example:
|
|
197
|
+
* ```javascript
|
|
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
|
|
201
|
+
* ```
|
|
87
202
|
*/
|
|
88
203
|
this.reconnectTimeMode = ReconnectionTimeMode.LINEAR;
|
|
89
204
|
/**
|
|
90
|
-
*
|
|
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
|
+
* ```
|
|
91
213
|
*/
|
|
92
214
|
this.heartbeatIncoming = 10000;
|
|
93
215
|
/**
|
|
94
|
-
*
|
|
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
|
+
* ```
|
|
95
228
|
*/
|
|
96
|
-
this.
|
|
229
|
+
this.heartbeatToleranceMultiplier = 2;
|
|
97
230
|
/**
|
|
98
|
-
*
|
|
99
|
-
*
|
|
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.
|
|
100
234
|
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
235
|
+
* Example:
|
|
236
|
+
* ```javascript
|
|
237
|
+
* client.heartbeatOutgoing = 5000; // Send a heartbeat every 5 seconds
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
this.heartbeatOutgoing = 10000;
|
|
241
|
+
/**
|
|
242
|
+
* Strategy for sending outgoing heartbeats.
|
|
103
243
|
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
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).
|
|
107
247
|
*
|
|
108
|
-
*
|
|
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.
|
|
109
251
|
*
|
|
110
|
-
*
|
|
252
|
+
* Example:
|
|
253
|
+
* ```javascript
|
|
254
|
+
* client.heartbeatStrategy = TickerStrategy.Worker;
|
|
255
|
+
* ```
|
|
111
256
|
*/
|
|
112
257
|
this.heartbeatStrategy = TickerStrategy.Interval;
|
|
113
258
|
/**
|
|
114
|
-
*
|
|
115
|
-
* It splits larger (text) packets into chunks of [maxWebSocketChunkSize]{@link Client#maxWebSocketChunkSize}.
|
|
116
|
-
* Only Java Spring brokers seem to support this mode.
|
|
259
|
+
* Enables splitting of large text WebSocket frames into smaller chunks.
|
|
117
260
|
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
* 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`.
|
|
121
263
|
*
|
|
122
|
-
*
|
|
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.
|
|
123
267
|
*
|
|
124
|
-
*
|
|
268
|
+
* Example:
|
|
269
|
+
* ```javascript
|
|
270
|
+
* client.splitLargeFrames = true;
|
|
271
|
+
* client.maxWebSocketChunkSize = 4096; // Allow chunks of 4 KB
|
|
272
|
+
* ```
|
|
125
273
|
*/
|
|
126
274
|
this.splitLargeFrames = false;
|
|
127
275
|
/**
|
|
128
|
-
*
|
|
129
|
-
*
|
|
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`.
|
|
130
279
|
*/
|
|
131
280
|
this.maxWebSocketChunkSize = 8 * 1024;
|
|
132
281
|
/**
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
* 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).
|
|
137
285
|
*
|
|
138
|
-
*
|
|
286
|
+
* Example:
|
|
287
|
+
* ```javascript
|
|
288
|
+
* client.forceBinaryWSFrames = true;
|
|
289
|
+
* ```
|
|
139
290
|
*/
|
|
140
291
|
this.forceBinaryWSFrames = false;
|
|
141
292
|
/**
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* this
|
|
148
|
-
*
|
|
149
|
-
*
|
|
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
|
+
* ```
|
|
150
304
|
*/
|
|
151
305
|
this.appendMissingNULLonIncoming = false;
|
|
152
306
|
/**
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
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`.
|
|
159
320
|
*/
|
|
160
321
|
this.discardWebsocketOnCommFailure = false;
|
|
161
322
|
/**
|
|
162
|
-
*
|
|
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.
|
|
163
329
|
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
330
|
+
* Note: The client may transition directly from `ACTIVE` to `INACTIVE` without entering
|
|
331
|
+
* the `DEACTIVATING` state.
|
|
166
332
|
*/
|
|
167
333
|
this.state = ActivationState.INACTIVE;
|
|
168
334
|
// No op callbacks
|
|
@@ -174,6 +340,8 @@ export class Client {
|
|
|
174
340
|
this.onUnhandledMessage = noOp;
|
|
175
341
|
this.onUnhandledReceipt = noOp;
|
|
176
342
|
this.onUnhandledFrame = noOp;
|
|
343
|
+
this.onHeartbeatReceived = noOp;
|
|
344
|
+
this.onHeartbeatLost = noOp;
|
|
177
345
|
this.onStompError = noOp;
|
|
178
346
|
this.onWebSocketClose = noOp;
|
|
179
347
|
this.onWebSocketError = noOp;
|
|
@@ -186,7 +354,22 @@ export class Client {
|
|
|
186
354
|
this.configure(conf);
|
|
187
355
|
}
|
|
188
356
|
/**
|
|
189
|
-
*
|
|
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.
|
|
190
373
|
*/
|
|
191
374
|
configure(conf) {
|
|
192
375
|
// bulk assign all properties to this
|
|
@@ -199,12 +382,20 @@ export class Client {
|
|
|
199
382
|
}
|
|
200
383
|
}
|
|
201
384
|
/**
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
* 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
|
+
* ```
|
|
206
397
|
*
|
|
207
|
-
*
|
|
398
|
+
* If the client is currently `DEACTIVATING`, connection is delayed until the deactivation process completes.
|
|
208
399
|
*/
|
|
209
400
|
activate() {
|
|
210
401
|
const _activate = () => {
|
|
@@ -262,6 +453,7 @@ export class Client {
|
|
|
262
453
|
connectHeaders: this.connectHeaders,
|
|
263
454
|
disconnectHeaders: this._disconnectHeaders,
|
|
264
455
|
heartbeatIncoming: this.heartbeatIncoming,
|
|
456
|
+
heartbeatGracePeriods: this.heartbeatToleranceMultiplier,
|
|
265
457
|
heartbeatOutgoing: this.heartbeatOutgoing,
|
|
266
458
|
heartbeatStrategy: this.heartbeatStrategy,
|
|
267
459
|
splitLargeFrames: this.splitLargeFrames,
|
|
@@ -314,6 +506,12 @@ export class Client {
|
|
|
314
506
|
onUnhandledFrame: frame => {
|
|
315
507
|
this.onUnhandledFrame(frame);
|
|
316
508
|
},
|
|
509
|
+
onHeartbeatReceived: () => {
|
|
510
|
+
this.onHeartbeatReceived();
|
|
511
|
+
},
|
|
512
|
+
onHeartbeatLost: () => {
|
|
513
|
+
this.onHeartbeatLost();
|
|
514
|
+
},
|
|
317
515
|
});
|
|
318
516
|
this._stompHandler.start();
|
|
319
517
|
}
|
|
@@ -347,27 +545,36 @@ export class Client {
|
|
|
347
545
|
}
|
|
348
546
|
}
|
|
349
547
|
/**
|
|
350
|
-
*
|
|
351
|
-
* Appropriate callbacks will be invoked if there is an underlying STOMP connection.
|
|
548
|
+
* Disconnects the client and stops the automatic reconnection loop.
|
|
352
549
|
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
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.
|
|
355
553
|
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
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}.
|
|
358
560
|
*
|
|
359
|
-
*
|
|
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.
|
|
566
|
+
*
|
|
567
|
+
* Example:
|
|
568
|
+
* ```javascript
|
|
569
|
+
* // Graceful disconnect
|
|
570
|
+
* await client.deactivate();
|
|
360
571
|
*
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
* if the underlying connection had gone stale.
|
|
365
|
-
* Using this mode can speed up.
|
|
366
|
-
* When this mode is used, the actual Websocket may linger for a while
|
|
367
|
-
* 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
|
+
* ```
|
|
368
575
|
*
|
|
369
|
-
*
|
|
370
|
-
*
|
|
576
|
+
* @param options Configuration options for deactivation. Use `force: true` for immediate shutdown.
|
|
577
|
+
* @returns A Promise that resolves when the deactivation process completes.
|
|
371
578
|
*/
|
|
372
579
|
async deactivate(options = {}) {
|
|
373
580
|
const force = options.force || false;
|
|
@@ -412,10 +619,18 @@ export class Client {
|
|
|
412
619
|
return retPromise;
|
|
413
620
|
}
|
|
414
621
|
/**
|
|
415
|
-
*
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
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
|
+
* ```
|
|
419
634
|
*/
|
|
420
635
|
forceDisconnect() {
|
|
421
636
|
if (this._stompHandler) {
|
|
@@ -429,39 +644,38 @@ export class Client {
|
|
|
429
644
|
}
|
|
430
645
|
}
|
|
431
646
|
/**
|
|
432
|
-
*
|
|
433
|
-
* and naming of destinations.
|
|
434
|
-
*
|
|
435
|
-
* STOMP protocol specifies and suggests some headers and also allows broker-specific headers.
|
|
436
|
-
*
|
|
437
|
-
* `body` must be String.
|
|
438
|
-
* You will need to covert the payload to string in case it is not string (e.g. JSON).
|
|
647
|
+
* Sends a message to the specified destination on the STOMP broker.
|
|
439
648
|
*
|
|
440
|
-
*
|
|
441
|
-
* [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array).
|
|
442
|
-
* Sometimes brokers may not support binary frames out of the box.
|
|
443
|
-
* Please check your broker documentation.
|
|
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).
|
|
444
651
|
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
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.
|
|
448
656
|
*
|
|
449
|
-
*
|
|
450
|
-
*
|
|
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.
|
|
451
660
|
*
|
|
661
|
+
* Example:
|
|
452
662
|
* ```javascript
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
*
|
|
456
|
-
*
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
*
|
|
461
|
-
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
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
|
+
* });
|
|
465
679
|
* ```
|
|
466
680
|
*/
|
|
467
681
|
publish(params) {
|
|
@@ -475,39 +689,27 @@ export class Client {
|
|
|
475
689
|
}
|
|
476
690
|
}
|
|
477
691
|
/**
|
|
478
|
-
*
|
|
479
|
-
* To request an acknowledgement, a `receipt` header needs to be sent with the actual request.
|
|
480
|
-
* The value (say receipt-id) for this header needs to be unique for each use.
|
|
481
|
-
* Typically, a sequence, a UUID, a random number or a combination may be used.
|
|
482
|
-
*
|
|
483
|
-
* A complaint broker will send a RECEIPT frame when an operation has actually been completed.
|
|
484
|
-
* The operation needs to be matched based on the value of the receipt-id.
|
|
692
|
+
* Monitors for a receipt acknowledgment from the broker for specific operations.
|
|
485
693
|
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
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.
|
|
488
696
|
*
|
|
489
|
-
* The
|
|
697
|
+
* The callback is invoked with the corresponding {@link IFrame} when the receipt is received.
|
|
490
698
|
*
|
|
491
699
|
* Example:
|
|
492
700
|
* ```javascript
|
|
493
|
-
*
|
|
494
|
-
* let receiptId = randomText();
|
|
701
|
+
* const receiptId = "unique-receipt-id";
|
|
495
702
|
*
|
|
496
|
-
*
|
|
497
|
-
*
|
|
498
|
-
*
|
|
703
|
+
* client.watchForReceipt(receiptId, (frame) => {
|
|
704
|
+
* console.log("Operation acknowledged by the broker:", frame);
|
|
705
|
+
* });
|
|
499
706
|
*
|
|
500
|
-
*
|
|
501
|
-
*
|
|
502
|
-
*
|
|
503
|
-
* // Publishing with acknowledgement
|
|
504
|
-
* receiptId = randomText();
|
|
505
|
-
*
|
|
506
|
-
* client.watchForReceipt(receiptId, function() {
|
|
507
|
-
* // Will be called after server acknowledges
|
|
508
|
-
* });
|
|
509
|
-
* 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" });
|
|
510
709
|
* ```
|
|
710
|
+
*
|
|
711
|
+
* @param receiptId Unique identifier for the receipt.
|
|
712
|
+
* @param callback Callback function invoked on receiving the RECEIPT frame.
|
|
511
713
|
*/
|
|
512
714
|
watchForReceipt(receiptId, callback) {
|
|
513
715
|
this._checkConnection();
|
|
@@ -515,28 +717,33 @@ export class Client {
|
|
|
515
717
|
this._stompHandler.watchForReceipt(receiptId, callback);
|
|
516
718
|
}
|
|
517
719
|
/**
|
|
518
|
-
*
|
|
519
|
-
*
|
|
720
|
+
* Subscribes to a destination on the STOMP broker.
|
|
721
|
+
*
|
|
722
|
+
* The callback is triggered for each message received from the subscribed destination. The message
|
|
723
|
+
* is passed as an {@link IMessage} instance.
|
|
520
724
|
*
|
|
521
|
-
*
|
|
522
|
-
*
|
|
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.
|
|
523
728
|
*
|
|
729
|
+
* Example:
|
|
524
730
|
* ```javascript
|
|
525
|
-
*
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
*
|
|
529
|
-
*
|
|
530
|
-
*
|
|
531
|
-
*
|
|
532
|
-
*
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
* // Explicit subscription id
|
|
537
|
-
* var mySubId = 'my-subscription-id-001';
|
|
538
|
-
* 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 });
|
|
539
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.
|
|
540
747
|
*/
|
|
541
748
|
subscribe(destination, callback, headers = {}) {
|
|
542
749
|
this._checkConnection();
|
|
@@ -544,16 +751,24 @@ export class Client {
|
|
|
544
751
|
return this._stompHandler.subscribe(destination, callback, headers);
|
|
545
752
|
}
|
|
546
753
|
/**
|
|
547
|
-
*
|
|
548
|
-
*
|
|
754
|
+
* Unsubscribes from a subscription on the STOMP broker.
|
|
755
|
+
*
|
|
756
|
+
* Prefer using the `unsubscribe` method directly on the {@link StompSubscription} returned from `subscribe` for cleaner management:
|
|
757
|
+
* ```javascript
|
|
758
|
+
* const subscription = client.subscribe("/queue/test", callback);
|
|
759
|
+
* // Unsubscribe using the subscription object
|
|
760
|
+
* subscription.unsubscribe();
|
|
761
|
+
* ```
|
|
762
|
+
*
|
|
763
|
+
* This method can also be used directly with the subscription ID.
|
|
549
764
|
*
|
|
765
|
+
* Example:
|
|
550
766
|
* ```javascript
|
|
551
|
-
*
|
|
552
|
-
* // ...
|
|
553
|
-
* subscription.unsubscribe();
|
|
767
|
+
* client.unsubscribe("my-subscription-id");
|
|
554
768
|
* ```
|
|
555
769
|
*
|
|
556
|
-
*
|
|
770
|
+
* @param id Subscription ID to unsubscribe.
|
|
771
|
+
* @param headers Optional headers to pass for the UNSUBSCRIBE frame.
|
|
557
772
|
*/
|
|
558
773
|
unsubscribe(id, headers = {}) {
|
|
559
774
|
this._checkConnection();
|
|
@@ -561,10 +776,21 @@ export class Client {
|
|
|
561
776
|
this._stompHandler.unsubscribe(id, headers);
|
|
562
777
|
}
|
|
563
778
|
/**
|
|
564
|
-
*
|
|
565
|
-
* 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
|
|
787
|
+
*
|
|
788
|
+
* // Or explicitly specify a transaction ID
|
|
789
|
+
* const tx = client.begin("my-transaction-id");
|
|
790
|
+
* ```
|
|
566
791
|
*
|
|
567
|
-
*
|
|
792
|
+
* @param transactionId Optional transaction ID.
|
|
793
|
+
* @returns An instance of {@link ITransaction}.
|
|
568
794
|
*/
|
|
569
795
|
begin(transactionId) {
|
|
570
796
|
this._checkConnection();
|
|
@@ -572,16 +798,19 @@ export class Client {
|
|
|
572
798
|
return this._stompHandler.begin(transactionId);
|
|
573
799
|
}
|
|
574
800
|
/**
|
|
575
|
-
*
|
|
801
|
+
* Commits a transaction.
|
|
576
802
|
*
|
|
577
|
-
* It is
|
|
578
|
-
*
|
|
803
|
+
* It is strongly recommended to call [commit]{@link ITransaction#commit} on
|
|
804
|
+
* the transaction object returned by [client#begin]{@link Client#begin}.
|
|
579
805
|
*
|
|
806
|
+
* Example:
|
|
580
807
|
* ```javascript
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
*
|
|
808
|
+
* const tx = client.begin();
|
|
809
|
+
* // Perform operations under this transaction
|
|
810
|
+
* tx.commit();
|
|
584
811
|
* ```
|
|
812
|
+
*
|
|
813
|
+
* @param transactionId The ID of the transaction to commit.
|
|
585
814
|
*/
|
|
586
815
|
commit(transactionId) {
|
|
587
816
|
this._checkConnection();
|
|
@@ -589,15 +818,19 @@ export class Client {
|
|
|
589
818
|
this._stompHandler.commit(transactionId);
|
|
590
819
|
}
|
|
591
820
|
/**
|
|
592
|
-
*
|
|
593
|
-
*
|
|
594
|
-
*
|
|
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}.
|
|
595
825
|
*
|
|
826
|
+
* Example:
|
|
596
827
|
* ```javascript
|
|
597
|
-
*
|
|
598
|
-
*
|
|
599
|
-
*
|
|
828
|
+
* const tx = client.begin();
|
|
829
|
+
* // Perform operations under this transaction
|
|
830
|
+
* tx.abort(); // Abort the transaction
|
|
600
831
|
* ```
|
|
832
|
+
*
|
|
833
|
+
* @param transactionId The ID of the transaction to abort.
|
|
601
834
|
*/
|
|
602
835
|
abort(transactionId) {
|
|
603
836
|
this._checkConnection();
|
|
@@ -605,17 +838,23 @@ export class Client {
|
|
|
605
838
|
this._stompHandler.abort(transactionId);
|
|
606
839
|
}
|
|
607
840
|
/**
|
|
608
|
-
*
|
|
609
|
-
* 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.
|
|
610
844
|
*
|
|
845
|
+
* Example:
|
|
611
846
|
* ```javascript
|
|
612
|
-
*
|
|
613
|
-
*
|
|
614
|
-
*
|
|
615
|
-
*
|
|
616
|
-
*
|
|
617
|
-
*
|
|
847
|
+
* const callback = (message) => {
|
|
848
|
+
* // Process the message
|
|
849
|
+
* message.ack(); // Acknowledge the message
|
|
850
|
+
* };
|
|
851
|
+
*
|
|
852
|
+
* client.subscribe("/queue/example", callback, { ack: "client" });
|
|
618
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.
|
|
619
858
|
*/
|
|
620
859
|
ack(messageId, subscriptionId, headers = {}) {
|
|
621
860
|
this._checkConnection();
|
|
@@ -623,17 +862,25 @@ export class Client {
|
|
|
623
862
|
this._stompHandler.ack(messageId, subscriptionId, headers);
|
|
624
863
|
}
|
|
625
864
|
/**
|
|
626
|
-
*
|
|
627
|
-
*
|
|
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.
|
|
628
868
|
*
|
|
869
|
+
* Example:
|
|
629
870
|
* ```javascript
|
|
630
|
-
*
|
|
631
|
-
*
|
|
632
|
-
*
|
|
633
|
-
*
|
|
634
|
-
*
|
|
635
|
-
*
|
|
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" });
|
|
636
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.
|
|
637
884
|
*/
|
|
638
885
|
nack(messageId, subscriptionId, headers = {}) {
|
|
639
886
|
this._checkConnection();
|