websocket-ts 1.1.1 → 2.1.2

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.
Files changed (181) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +157 -93
  3. package/dist/cjs/src/backoff/backoff.d.ts +24 -0
  4. package/dist/cjs/src/backoff/backoff.d.ts.map +1 -0
  5. package/{lib → dist/cjs/src}/backoff/backoff.js.map +1 -1
  6. package/dist/cjs/src/backoff/constantbackoff.d.ts +18 -0
  7. package/dist/cjs/src/backoff/constantbackoff.d.ts.map +1 -0
  8. package/dist/cjs/src/backoff/constantbackoff.js +43 -0
  9. package/dist/cjs/src/backoff/constantbackoff.js.map +1 -0
  10. package/dist/cjs/src/backoff/exponentialbackoff.d.ts +48 -0
  11. package/dist/cjs/src/backoff/exponentialbackoff.d.ts.map +1 -0
  12. package/dist/cjs/src/backoff/exponentialbackoff.js +81 -0
  13. package/dist/cjs/src/backoff/exponentialbackoff.js.map +1 -0
  14. package/dist/cjs/src/backoff/linearbackoff.d.ts +51 -0
  15. package/dist/cjs/src/backoff/linearbackoff.d.ts.map +1 -0
  16. package/dist/cjs/src/backoff/linearbackoff.js +89 -0
  17. package/dist/cjs/src/backoff/linearbackoff.js.map +1 -0
  18. package/dist/cjs/src/index.d.ts +14 -0
  19. package/dist/cjs/src/index.d.ts.map +1 -0
  20. package/dist/cjs/src/index.js +20 -0
  21. package/dist/cjs/src/index.js.map +1 -0
  22. package/dist/cjs/src/queue/array_queue.d.ts +17 -0
  23. package/dist/cjs/src/queue/array_queue.d.ts.map +1 -0
  24. package/dist/cjs/src/queue/array_queue.js +36 -0
  25. package/dist/cjs/src/queue/array_queue.js.map +1 -0
  26. package/dist/cjs/src/queue/queue.d.ts +41 -0
  27. package/dist/cjs/src/queue/queue.d.ts.map +1 -0
  28. package/{lib/buffer/buffer.js → dist/cjs/src/queue/queue.js} +1 -1
  29. package/dist/cjs/src/queue/queue.js.map +1 -0
  30. package/dist/cjs/src/queue/ring_queue.d.ts +20 -0
  31. package/dist/cjs/src/queue/ring_queue.d.ts.map +1 -0
  32. package/dist/cjs/src/queue/ring_queue.js +57 -0
  33. package/dist/cjs/src/queue/ring_queue.js.map +1 -0
  34. package/dist/cjs/src/websocket.d.ts +206 -0
  35. package/dist/cjs/src/websocket.d.ts.map +1 -0
  36. package/dist/cjs/src/websocket.js +434 -0
  37. package/dist/cjs/src/websocket.js.map +1 -0
  38. package/dist/cjs/src/websocket_buffer.d.ts +16 -0
  39. package/dist/cjs/src/websocket_buffer.d.ts.map +1 -0
  40. package/dist/cjs/src/websocket_buffer.js +3 -0
  41. package/dist/cjs/src/websocket_buffer.js.map +1 -0
  42. package/dist/cjs/src/websocket_builder.d.ts +147 -0
  43. package/dist/cjs/src/websocket_builder.d.ts.map +1 -0
  44. package/dist/cjs/src/websocket_builder.js +263 -0
  45. package/dist/cjs/src/websocket_builder.js.map +1 -0
  46. package/dist/cjs/src/websocket_event.d.ts +67 -0
  47. package/dist/cjs/src/websocket_event.d.ts.map +1 -0
  48. package/dist/cjs/src/websocket_event.js +22 -0
  49. package/dist/cjs/src/websocket_event.js.map +1 -0
  50. package/dist/cjs/src/websocket_options.d.ts +21 -0
  51. package/dist/cjs/src/websocket_options.d.ts.map +1 -0
  52. package/dist/cjs/src/websocket_options.js +3 -0
  53. package/dist/cjs/src/websocket_options.js.map +1 -0
  54. package/dist/cjs/src/websocket_retry_options.d.ts +20 -0
  55. package/dist/cjs/src/websocket_retry_options.d.ts.map +1 -0
  56. package/dist/cjs/src/websocket_retry_options.js +3 -0
  57. package/dist/cjs/src/websocket_retry_options.js.map +1 -0
  58. package/dist/esm/src/backoff/backoff.d.ts +24 -0
  59. package/dist/esm/src/backoff/backoff.d.ts.map +1 -0
  60. package/dist/esm/src/backoff/backoff.js +2 -0
  61. package/dist/esm/src/backoff/backoff.js.map +1 -0
  62. package/dist/esm/src/backoff/constantbackoff.d.ts +18 -0
  63. package/dist/esm/src/backoff/constantbackoff.d.ts.map +1 -0
  64. package/dist/esm/src/backoff/constantbackoff.js +30 -0
  65. package/dist/esm/src/backoff/constantbackoff.js.map +1 -0
  66. package/dist/esm/src/backoff/exponentialbackoff.d.ts +48 -0
  67. package/dist/esm/src/backoff/exponentialbackoff.d.ts.map +1 -0
  68. package/dist/esm/src/backoff/exponentialbackoff.js +68 -0
  69. package/dist/esm/src/backoff/exponentialbackoff.js.map +1 -0
  70. package/dist/esm/src/backoff/linearbackoff.d.ts +51 -0
  71. package/dist/esm/src/backoff/linearbackoff.d.ts.map +1 -0
  72. package/dist/esm/src/backoff/linearbackoff.js +76 -0
  73. package/dist/esm/src/backoff/linearbackoff.js.map +1 -0
  74. package/dist/esm/src/index.d.ts +14 -0
  75. package/dist/esm/src/index.d.ts.map +1 -0
  76. package/dist/esm/src/index.js +9 -0
  77. package/dist/esm/src/index.js.map +1 -0
  78. package/dist/esm/src/queue/array_queue.d.ts +17 -0
  79. package/dist/esm/src/queue/array_queue.d.ts.map +1 -0
  80. package/dist/esm/src/queue/array_queue.js +31 -0
  81. package/dist/esm/src/queue/array_queue.js.map +1 -0
  82. package/dist/esm/src/queue/queue.d.ts +41 -0
  83. package/dist/esm/src/queue/queue.d.ts.map +1 -0
  84. package/dist/esm/src/queue/queue.js +2 -0
  85. package/dist/esm/src/queue/queue.js.map +1 -0
  86. package/dist/esm/src/queue/ring_queue.d.ts +20 -0
  87. package/dist/esm/src/queue/ring_queue.d.ts.map +1 -0
  88. package/dist/esm/src/queue/ring_queue.js +52 -0
  89. package/dist/esm/src/queue/ring_queue.js.map +1 -0
  90. package/dist/esm/src/websocket.d.ts +206 -0
  91. package/dist/esm/src/websocket.d.ts.map +1 -0
  92. package/dist/esm/src/websocket.js +356 -0
  93. package/dist/esm/src/websocket.js.map +1 -0
  94. package/dist/esm/src/websocket_buffer.d.ts +16 -0
  95. package/dist/esm/src/websocket_buffer.d.ts.map +1 -0
  96. package/dist/esm/src/websocket_buffer.js +2 -0
  97. package/dist/esm/src/websocket_buffer.js.map +1 -0
  98. package/dist/esm/src/websocket_builder.d.ts +147 -0
  99. package/dist/esm/src/websocket_builder.d.ts.map +1 -0
  100. package/dist/esm/src/websocket_builder.js +213 -0
  101. package/dist/esm/src/websocket_builder.js.map +1 -0
  102. package/dist/esm/src/websocket_event.d.ts +67 -0
  103. package/dist/esm/src/websocket_event.d.ts.map +1 -0
  104. package/dist/esm/src/websocket_event.js +19 -0
  105. package/dist/esm/src/websocket_event.js.map +1 -0
  106. package/dist/esm/src/websocket_options.d.ts +21 -0
  107. package/dist/esm/src/websocket_options.d.ts.map +1 -0
  108. package/dist/esm/src/websocket_options.js +2 -0
  109. package/dist/esm/src/websocket_options.js.map +1 -0
  110. package/dist/esm/src/websocket_retry_options.d.ts +20 -0
  111. package/dist/esm/src/websocket_retry_options.d.ts.map +1 -0
  112. package/dist/esm/src/websocket_retry_options.js +2 -0
  113. package/dist/esm/src/websocket_retry_options.js.map +1 -0
  114. package/package.json +27 -14
  115. package/src/backoff/backoff.ts +21 -13
  116. package/src/backoff/constantbackoff.ts +29 -11
  117. package/src/backoff/exponentialbackoff.ts +68 -28
  118. package/src/backoff/linearbackoff.ts +77 -26
  119. package/src/index.ts +23 -9
  120. package/src/queue/array_queue.ts +41 -0
  121. package/src/queue/queue.ts +46 -0
  122. package/src/queue/ring_queue.ts +69 -0
  123. package/src/websocket.ts +463 -138
  124. package/src/websocket_buffer.ts +18 -0
  125. package/src/websocket_builder.ts +274 -0
  126. package/src/websocket_event.ts +88 -0
  127. package/src/websocket_options.ts +23 -0
  128. package/src/websocket_retry_options.ts +22 -0
  129. package/{tsconfig.json → tsconfig.cjs.json} +8 -8
  130. package/tsconfig.esm.json +71 -0
  131. package/jest.config.js +0 -9
  132. package/lib/backoff/backoff.d.ts +0 -18
  133. package/lib/backoff/backoff.d.ts.map +0 -1
  134. package/lib/backoff/constantbackoff.d.ts +0 -11
  135. package/lib/backoff/constantbackoff.d.ts.map +0 -1
  136. package/lib/backoff/constantbackoff.js +0 -20
  137. package/lib/backoff/constantbackoff.js.map +0 -1
  138. package/lib/backoff/exponentialbackoff.d.ts +0 -22
  139. package/lib/backoff/exponentialbackoff.d.ts.map +0 -1
  140. package/lib/backoff/exponentialbackoff.js +0 -35
  141. package/lib/backoff/exponentialbackoff.js.map +0 -1
  142. package/lib/backoff/linearbackoff.d.ts +0 -19
  143. package/lib/backoff/linearbackoff.d.ts.map +0 -1
  144. package/lib/backoff/linearbackoff.js +0 -34
  145. package/lib/backoff/linearbackoff.js.map +0 -1
  146. package/lib/buffer/buffer.d.ts +0 -41
  147. package/lib/buffer/buffer.d.ts.map +0 -1
  148. package/lib/buffer/buffer.js.map +0 -1
  149. package/lib/buffer/lrubuffer.d.ts +0 -24
  150. package/lib/buffer/lrubuffer.d.ts.map +0 -1
  151. package/lib/buffer/lrubuffer.js +0 -76
  152. package/lib/buffer/lrubuffer.js.map +0 -1
  153. package/lib/buffer/timebuffer.d.ts +0 -25
  154. package/lib/buffer/timebuffer.d.ts.map +0 -1
  155. package/lib/buffer/timebuffer.js +0 -92
  156. package/lib/buffer/timebuffer.js.map +0 -1
  157. package/lib/index.d.ts +0 -10
  158. package/lib/index.d.ts.map +0 -1
  159. package/lib/index.js +0 -22
  160. package/lib/index.js.map +0 -1
  161. package/lib/websocket.d.ts +0 -47
  162. package/lib/websocket.d.ts.map +0 -1
  163. package/lib/websocket.js +0 -120
  164. package/lib/websocket.js.map +0 -1
  165. package/lib/websocketBuilder.d.ts +0 -32
  166. package/lib/websocketBuilder.d.ts.map +0 -1
  167. package/lib/websocketBuilder.js +0 -68
  168. package/lib/websocketBuilder.js.map +0 -1
  169. package/src/buffer/buffer.ts +0 -45
  170. package/src/buffer/lrubuffer.ts +0 -80
  171. package/src/buffer/timebuffer.ts +0 -105
  172. package/src/websocketBuilder.ts +0 -98
  173. package/test/backoff/constantbackoff.test.ts +0 -21
  174. package/test/backoff/exponentialbackoff.test.ts +0 -13
  175. package/test/backoff/linearbackoff.test.ts +0 -32
  176. package/test/buffer/common.ts +0 -10
  177. package/test/buffer/lrubuffer.test.ts +0 -128
  178. package/test/buffer/timebuffer.test.ts +0 -115
  179. package/test/websocket.test.ts +0 -341
  180. package/test/websocketBuilder.test.ts +0 -36
  181. /package/{lib → dist/cjs/src}/backoff/backoff.js +0 -0
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021 J. Behrmann
3
+ Copyright (c) 2023 Joscha Behrmann
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,147 +1,211 @@
1
- # websocket-ts
2
- A client-websocket written in TypeScript for browser-applications. Focus is on simplicity, reliability and extensibility. It provides convenient features to automatically reconnect and buffer pending messages.
3
-
4
- [![Build Status](https://travis-ci.org/jjxxs/websocket-ts.svg?branch=master)](https://travis-ci.org/jjxxs/websocket-ts)
5
- [![Coverage Status](https://coveralls.io/repos/github/jjxxs/websocket-ts/badge.svg?branch=master&service=github)](https://coveralls.io/github/jjxxs/websocket-ts?branch=master)
6
- [![Release](https://img.shields.io/github/v/release/jjxxs/websocket-ts)](https://github.com/jjxxs/websocket-ts/releases/latest)
7
- [![License](https://img.shields.io/github/license/jjxxs/websocket-ts)](/LICENSE)
1
+ <div>
2
+ <div align="center">
3
+ <img src="https://raw.githubusercontent.com/jjxxs/websocket-ts/gh-pages/websocket-ts-logo.svg" alt="websocket-ts" width="300" height="65" />
4
+ </div>
5
+ <p align="center">
6
+ <img src="https://github.com/jjxxs/websocket-ts/actions/workflows/build.yml/badge.svg" alt="Build Status" />
7
+ <img src="https://github.com/jjxxs/websocket-ts/actions/workflows/test.yml/badge.svg" alt="Build Status" />
8
+ <a href="https://coveralls.io/github/jjxxs/websocket-ts?branch=master">
9
+ <img src="https://coveralls.io/repos/github/jjxxs/websocket-ts/badge.svg?branch=master&service=github" alt="Coverage Status" />
10
+ </a>
11
+ <a href="https://github.com/jjxxs/websocket-ts/releases/latest">
12
+ <img src="https://img.shields.io/github/v/release/jjxxs/websocket-ts" alt="Release" />
13
+ </a>
14
+ <a href="/LICENSE">
15
+ <img src="https://img.shields.io/github/license/jjxxs/websocket-ts" alt="License" />
16
+ </a>
17
+ </p>
18
+ </div>
19
+
20
+ <div align="center">
21
+ A <b>WebSocket</b> for browsers with <b>auto-reconnect</b> and <b>message buffering</b> written in <b>TypeScript</b>.
22
+ </div>
8
23
 
9
24
  ## Features
10
- - Dependency-free and small in size
11
- - Uses the browser-native WebSocket-functionality
12
- - Copies the event-based WebSocket-API
13
- - Provides access to the underlying WebSocket
14
- - When the connection is lost, it can optionally be configured to
15
- - Automatically try to reconnect in a smart way
16
- - Buffer messages that are sent when the connection is re-established
17
- - Builder-class for easy initialization and configuration
18
- - High test-coverage and in-code documentation
19
- - Enables you to easily modify and extend the code
25
+
26
+ - **Lightweight & Standalone**: No dependencies, 2.1 kB minified & gzipped.
27
+ - **Browser-native**: Utilizes WebSocket API, offers direct access.
28
+ - **Smart Reconnect**: Optional auto-reconnect and message buffering.
29
+ - **Easy Setup**: Optional builder class for quick initialization.
30
+ - **Well-Tested**: High test coverage, well-documented for extensibility.
31
+ - **Module Support**: Supports CommonJS, and ES6 modules.
20
32
 
21
33
  ## Installation
22
- In your project-root:
23
- ```
34
+
35
+ Install `websocket-ts` with npm:
36
+
37
+ ```bash
24
38
  $ npm install websocket-ts
25
39
  ```
26
40
 
27
- In your project-code:
41
+ ## Quickstart
42
+ This example shows how to use the package, complete with message buffering and automatic reconnection.
43
+ The created websocket will echo back any received messages. It will buffer messages when disconnected
44
+ and attempt to reconnect every 1 second.
45
+
28
46
  ```typescript
29
- import {WebsocketBuilder} from 'websocket-ts';
47
+ import {
48
+ ArrayQueue,
49
+ ConstantBackoff,
50
+ Websocket,
51
+ WebsocketBuilder,
52
+ WebsocketEvent,
53
+ } from "websocket-ts";
54
+
55
+ // Initialize WebSocket with buffering and 1s reconnection delay
56
+ const ws = new WebsocketBuilder("ws://localhost:8080")
57
+ .withBuffer(new ArrayQueue()) // buffer messages when disconnected
58
+ .withBackoff(new ConstantBackoff(1000)) // retry every 1s
59
+ .build();
60
+
61
+ // Function to output & echo received messages
62
+ const echoOnMessage = (i: Websocket, ev: MessageEvent) => {
63
+ console.log(`received message: ${ev.data}`);
64
+ i.send(`echo: ${ev.data}`);
65
+ };
66
+
67
+ // Add event listeners
68
+ ws.addEventListener(WebsocketEvent.open, () => console.log("opened!"));
69
+ ws.addEventListener(WebsocketEvent.close, () => console.log("closed!"));
70
+ ws.addEventListener(WebsocketEvent.message, echoOnMessage);
30
71
  ```
31
72
 
32
73
  ## Usage
74
+ This will demonstrate how to use `websocket-ts` in your project using the provided `WebsocketBuild`-class.
75
+
76
+ For a more detailed description of the API, please refer to the [API Documentation](https://jjxxs.github.io/websocket-ts/).
33
77
 
34
78
  #### Initialization
35
- Create a new instance with the provided `WebsocketBuilder`:
79
+
80
+ Create a new instance with the `WebsocketBuilder`:
36
81
 
37
82
  ```typescript
38
- const ws = new WebsocketBuilder('ws://localhost:42421').build();
83
+ const ws = new WebsocketBuilder("ws://localhost:42421").build();
39
84
  ```
40
85
 
41
- #### Events & Callbacks
42
- There are five events which can be subscribed to through callbacks:
86
+ #### Events
87
+
88
+ There are six events which can be subscribed to through with event listeners:
89
+
43
90
  ```typescript
44
- export enum WebsocketEvents {
45
- open = 'open', // Connection is opened or re-opened
46
- close = 'close', // Connection is closed
47
- error = 'error', // An error occurred
48
- message = 'message', // A message was received
49
- retry = 'retry' // A try to re-connect is made
91
+ export enum WebsocketEvent {
92
+ open = "open", // Connection opened
93
+ close = "close", // Connection closed
94
+ error = "error", // Error-induced closure
95
+ message = "message", // Message received
96
+ retry = "retry", // Reconnect attempt
97
+ reconnect = "reconnect" // Successful reconnect
50
98
  }
51
99
  ```
52
- The callbacks are called with the issuing websocket-instance and the causing event as arguments:
53
- ```typescript
54
- const ws = new WebsocketBuilder('ws://localhost:42421')
55
- .onOpen((i, ev) => { console.log("opened") })
56
- .onClose((i, ev) => { console.log("closed") })
57
- .onError((i, ev) => { console.log("error") })
58
- .onMessage((i, ev) => { console.log("message") })
59
- .onRetry((i, ev) => { console.log("retry") })
60
- .build();
61
- ```
62
100
 
63
- You can register multiple callbacks for the same event. They will be called in stack-order:
64
- ```typescript
65
- const ws = new WebsocketBuilder('ws://localhost:42421')
66
- .onMessage((i, e) => { console.log("echo sent") })
67
- .onMessage((i, e) => { i.send(e.data) })
68
- .onMessage((i, e) => { console.log("message received") })
69
- .build();
70
- ```
101
+ #### Add Event Listeners
102
+ Event listeners receive the websocket instance (`i`) and the triggering event (`ev`) as arguments.
103
+
104
+ ```typescript
105
+ const ws = new WebsocketBuilder("ws://localhost:42421")
106
+ .onOpen((i, ev) => console.log("opened"))
107
+ .onClose((i, ev) => console.log("closed"))
108
+ .onError((i, ev) => console.log("error"))
109
+ .onMessage((i, ev) => console.log("message"))
110
+ .onRetry((i, ev) => console.log("retry"))
111
+ .onReconnect((i, ev) => console.log("reconnect"))
112
+ .build();
113
+ ```
114
+
115
+ #### Remove Event Listeners
116
+
117
+ To unregister a specific event listener, use `removeEventListener`:
71
118
 
72
- You can remove event-listener with `removeEventListener`:
73
119
  ```typescript
74
120
  let ws: Websocket
75
121
  /* ... */
76
- ws.removeEventListener(WebsocketEvents.open, openEventListener);
122
+ ws.removeEventListener(WebsocketEvent.open, openEventListener);
77
123
  ```
78
124
 
79
- #### Send
80
- To send messages, use the websockets `send()`-method:
125
+ #### Send Message
126
+
127
+ Use the `send` method to send a message to the server:
128
+
81
129
  ```typescript
82
130
  let ws: Websocket;
83
131
  /* ... */
84
132
  ws.send("Hello World!");
85
133
  ```
86
134
 
87
- #### Reconnect & Backoff
88
- If you want the websocket to automatically try to re-connect when the connection is lost, you can provide it with a `Backoff`.
89
- The websocket will use the `Backoff` to determine how long it should wait between re-tries. There are currently three
90
- `Backoff`-implementations. You can also implement your own by inheriting from the `Backoff`-interface.
135
+ #### Reconnect & Backoff (Optional)
136
+
137
+ If you'd like the websocket to automatically reconnect upon disconnection, you can optionally provide a `Backoff` strategy.
138
+ This sets the delay between reconnection attempts. There are three built-in `Backoff` implementations, or you can create
139
+ your own by implementing the `Backoff` interface. If no Backoff is provided, the websocket will not attempt to reconnect.
91
140
 
92
141
  ##### ConstantBackoff
93
- The `ConstantBackoff` will make the websocket wait a constant time between each connection retry. To use the `ConstantBackoff`
94
- with a wait-time of `1 second`:
142
+
143
+ The `ConstantBackoff` strategy enforces a fixed delay between each reconnection attempt.
144
+ To set a constant 1-second wait time, use:
145
+
95
146
  ```typescript
96
- const ws = new WebsocketBuilder('ws://localhost:42421')
97
- .withBackoff(new ConstantBackoff(1000)) // 1000ms = 1s
98
- .build();
147
+ const ws = new WebsocketBuilder("ws://localhost:42421")
148
+ .withBackoff(new ConstantBackoff(1000)) // 1000ms = 1s
149
+ .build();
99
150
  ```
100
151
 
101
152
  ##### LinearBackoff
102
- The `LinearBackoff` linearly increases the wait-time between connection-retries until an optional maximum is reached.
103
- To use the `LinearBackoff` to initially wait `0 seconds` and increase the wait-time by `1 second` with every retry until
104
- a maximum of `8 seconds` is reached:
153
+
154
+ The `LinearBackoff` strategy increases the delay between reconnection attempts linearly,
155
+ up to an optional maximum. For example, to start with a 0-second delay and increase by
156
+ 10 second for each retry, capping at 60 seconds, use:
157
+
105
158
  ```typescript
106
- const ws = new WebsocketBuilder('ws://localhost:42421')
107
- .withBackoff(new LinearBackoff(0, 1000, 8000))
108
- .build();
159
+ const ws = new WebsocketBuilder("ws://localhost:42421")
160
+ .withBackoff(new LinearBackoff(0, 10000, 60000)) // 0ms, 10s, 20s, 30s, 40s, 50s, 60s
161
+ .build();
109
162
  ```
110
163
 
111
164
  ##### ExponentialBackoff
112
- The `ExponentialBackoff` doubles the backoff with every retry until a maximum is reached. This is modelled after the binary
113
- exponential-backoff algorithm used in computer-networking. To use the `ExponentialBackoff` that will produce the series
114
- `[100, 200, 400, 800, 1600, 3200, 6400]`:
165
+
166
+ The `ExponentialBackoff` strategy doubles the delay between each reconnection attempt, up
167
+ to a specified maximum. This approach is inspired by the binary exponential backoff algorithm
168
+ commonly used in networking. For example, to generate a backoff series like `[1s, 2s, 4s, 8s]`, use:
169
+
115
170
  ```typescript
116
- const ws = new WebsocketBuilder('ws://localhost:42421')
117
- .withBackoff(new ExponentialBackoff(100, 7))
118
- .build();
171
+ const ws = new WebsocketBuilder("ws://localhost:42421")
172
+ .withBackoff(new ExponentialBackoff(1000, 6)) // 1s, 2s, 4s, 8s, 16s, 32s, 64s
173
+ .build();
119
174
  ```
120
175
 
121
- #### Buffer
176
+ #### Buffer (Optional)
177
+
178
+ To buffer outgoing messages when the websocket is disconnected, you can optionally specify
179
+ a `Queue`. This queue will temporarily store your messages and send them in sequence when
180
+ the websocket (re)connects. Two built-in `Queue` implementations are available, or you can
181
+ create your own by implementing the `Queue` interface. If no queue is provided, messages
182
+ won't be buffered.
183
+
184
+ ##### RingQueue
122
185
 
123
- If you want to buffer to-be-send messages while the websocket is disconnected, you can provide it with a `Buffer`.
124
- The websocket will use the buffer to temporarily keep your messages and send them in order once the websocket
125
- (re-)connects. There are currently two `Buffer`-implementations. You can also implement your own
126
- by inheriting from the `Buffer`-interface.
186
+ The `RingQueue` is a fixed-capacity, first-in-first-out (FIFO) queue. When it reaches capacity,
187
+ the oldest element is removed to accommodate new ones. Reading from the queue returns and
188
+ removes the oldest element. For instance, to set up a `RingQueue` with a 100-element capacity,
189
+ use:
127
190
 
128
- ##### LRUBuffer
129
- The `LRUBuffer` keeps the last `n` messages. When the buffer is full, the oldest message in the buffer will be replaced.
130
- It uses an array as a circular-buffer for linear space- and time-requirements. To use the `LRUBuffer` with a capacity of `1000`:
131
191
  ```typescript
132
- const ws = new WebsocketBuilder('ws://localhost:42421')
133
- .withBuffer(new LRUBuffer(1000))
134
- .build();
192
+ const ws = new WebsocketBuilder("ws://localhost:42421")
193
+ .withBuffer(new RingQueue(100))
194
+ .build();
135
195
  ```
136
196
 
137
- ##### TimeBuffer
138
- The `TimeBuffer` will keep all messages that were written within the last `n` milliseconds. It will drop messages that are
139
- older than the specified amount. To use the `TimeBuffer` that keeps messages from the last `5 minutes`:
197
+ ##### ArrayQueue
198
+
199
+ The ArrayQueue offers an unbounded capacity, functioning as a first-in-first-out (FIFO) queue.
200
+ Reading from this queue returns and removes the oldest element. To use an `ArrayQueue`, use:
201
+
140
202
  ```typescript
141
- const ws = new WebsocketBuilder('ws://localhost:42421')
142
- .withBuffer(new TimeBuffer(5 * 60 * 1000))
143
- .build();
203
+ const ws = new WebsocketBuilder("ws://localhost:42421")
204
+ .withBuffer(new ArrayQueue())
205
+ .build();
144
206
  ```
145
207
 
146
- #### Build & Tests
147
- To build the project run `yarn build`. All provided components are covered with unit-tests. Run the tests with `yarn test`.
208
+ ## Build & Tests
209
+
210
+ To compile the project, execute `npm run build`. The codebase includes unit tests for all
211
+ components. To run these tests, use `npm run test`.
@@ -0,0 +1,24 @@
1
+ /**
2
+ * A Backoff produces a series of numbers that are used to determine
3
+ * the delay between connection-retries. Values are expected to be in milliseconds.
4
+ */
5
+ export interface Backoff {
6
+ /**
7
+ * The number of retries. Starts at 0, increases by 1 for each call to next(). Resets to 0 when reset() is called.
8
+ */
9
+ readonly retries: number;
10
+ /**
11
+ * Current number in the series.
12
+ */
13
+ readonly current: number;
14
+ /**
15
+ * Advances the series to the next number and returns it.
16
+ * @return the next number in the series
17
+ */
18
+ next(): number;
19
+ /**
20
+ * Resets the series to its initial state.
21
+ */
22
+ reset(): void;
23
+ }
24
+ //# sourceMappingURL=backoff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backoff.d.ts","sourceRoot":"","sources":["../../../../src/backoff/backoff.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,IAAI,IAAI,MAAM,CAAC;IAEf;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;CACf"}
@@ -1 +1 @@
1
- {"version":3,"file":"backoff.js","sourceRoot":"","sources":["../../src/backoff/backoff.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"backoff.js","sourceRoot":"","sources":["../../../../src/backoff/backoff.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { Backoff } from "./backoff";
2
+ /**
3
+ * ConstantBackoff always returns the same backoff-time.
4
+ */
5
+ export declare class ConstantBackoff implements Backoff {
6
+ private readonly backoff;
7
+ private _retries;
8
+ /**
9
+ * Creates a new ConstantBackoff.
10
+ * @param backoff the backoff-time to return
11
+ */
12
+ constructor(backoff: number);
13
+ get retries(): number;
14
+ get current(): number;
15
+ next(): number;
16
+ reset(): void;
17
+ }
18
+ //# sourceMappingURL=constantbackoff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constantbackoff.d.ts","sourceRoot":"","sources":["../../../../src/backoff/constantbackoff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;GAEG;AACH,qBAAa,eAAgB,YAAW,OAAO;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAa;IAE7B;;;OAGG;gBACS,OAAO,EAAE,MAAM;IAQ3B,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,IAAI,MAAM;IAKd,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConstantBackoff = void 0;
4
+ /**
5
+ * ConstantBackoff always returns the same backoff-time.
6
+ */
7
+ var ConstantBackoff = /** @class */ (function () {
8
+ /**
9
+ * Creates a new ConstantBackoff.
10
+ * @param backoff the backoff-time to return
11
+ */
12
+ function ConstantBackoff(backoff) {
13
+ this._retries = 0;
14
+ if (!Number.isInteger(backoff) || backoff < 0) {
15
+ throw new Error("Backoff must be a positive integer");
16
+ }
17
+ this.backoff = backoff;
18
+ }
19
+ Object.defineProperty(ConstantBackoff.prototype, "retries", {
20
+ get: function () {
21
+ return this._retries;
22
+ },
23
+ enumerable: false,
24
+ configurable: true
25
+ });
26
+ Object.defineProperty(ConstantBackoff.prototype, "current", {
27
+ get: function () {
28
+ return this.backoff;
29
+ },
30
+ enumerable: false,
31
+ configurable: true
32
+ });
33
+ ConstantBackoff.prototype.next = function () {
34
+ this._retries++;
35
+ return this.backoff;
36
+ };
37
+ ConstantBackoff.prototype.reset = function () {
38
+ this._retries = 0;
39
+ };
40
+ return ConstantBackoff;
41
+ }());
42
+ exports.ConstantBackoff = ConstantBackoff;
43
+ //# sourceMappingURL=constantbackoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constantbackoff.js","sourceRoot":"","sources":["../../../../src/backoff/constantbackoff.ts"],"names":[],"mappings":";;;AAEA;;GAEG;AACH;IAIE;;;OAGG;IACH,yBAAY,OAAe;QANnB,aAAQ,GAAW,CAAC,CAAC;QAO3B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE;YAC7C,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;SACvD;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,sBAAI,oCAAO;aAAX;YACE,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;;;OAAA;IAED,sBAAI,oCAAO;aAAX;YACE,OAAO,IAAI,CAAC,OAAO,CAAC;QACtB,CAAC;;;OAAA;IAED,8BAAI,GAAJ;QACE,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,+BAAK,GAAL;QACE,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;IACpB,CAAC;IACH,sBAAC;AAAD,CAAC,AAhCD,IAgCC;AAhCY,0CAAe"}
@@ -0,0 +1,48 @@
1
+ import { Backoff } from "./backoff";
2
+ /**
3
+ * ExponentialBackoff increases the backoff-time exponentially.
4
+ * An optional maximum can be provided as an upper bound to the
5
+ * exponent and thus to the returned backoff.
6
+ *
7
+ * The series can be described as ('i' is the current step/retry):
8
+ * backoff = base * 2^i | without bound
9
+ * backoff = base * 2^min(i, expMax) | with bound
10
+ *
11
+ * Example:
12
+ *
13
+ * 1) Without bound:
14
+ * base = 1000, expMax = undefined
15
+ * backoff = 1000 * 2^0 = 1000 // first retry
16
+ * backoff = 1000 * 2^1 = 2000 // second retry
17
+ * backoff = 1000 * 2^2 = 4000 // ...doubles with every retry
18
+ * backoff = 1000 * 2^3 = 8000
19
+ * backoff = 1000 * 2^4 = 16000
20
+ * ... // and so on
21
+ *
22
+ * 2) With bound:
23
+ * base = 1000, expMax = 3
24
+ * backoff = 1000 * 2^0 = 1000 // first retry
25
+ * backoff = 1000 * 2^1 = 2000 // second retry
26
+ * backoff = 1000 * 2^2 = 4000 // third retry
27
+ * backoff = 1000 * 2^3 = 8000 // maximum reached, don't increase further
28
+ * backoff = 1000 * 2^3 = 8000
29
+ * backoff = 1000 * 2^3 = 8000
30
+ * ... // and so on
31
+ */
32
+ export declare class ExponentialBackoff implements Backoff {
33
+ private readonly base;
34
+ private readonly expMax?;
35
+ private i;
36
+ private _retries;
37
+ /**
38
+ * Creates a new ExponentialBackoff.
39
+ * @param base the base of the exponentiation
40
+ * @param expMax the maximum exponent, no bound if undefined
41
+ */
42
+ constructor(base: number, expMax?: number);
43
+ get retries(): number;
44
+ get current(): number;
45
+ next(): number;
46
+ reset(): void;
47
+ }
48
+ //# sourceMappingURL=exponentialbackoff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exponentialbackoff.d.ts","sourceRoot":"","sources":["../../../../src/backoff/exponentialbackoff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,kBAAmB,YAAW,OAAO;IAChD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,CAAC,CAAS;IAClB,OAAO,CAAC,QAAQ,CAAa;IAE7B;;;;OAIG;gBACS,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAazC,IAAI,OAAO,WAEV;IAED,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,IAAI,MAAM;IASd,KAAK,IAAI,IAAI;CAId"}
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExponentialBackoff = void 0;
4
+ /**
5
+ * ExponentialBackoff increases the backoff-time exponentially.
6
+ * An optional maximum can be provided as an upper bound to the
7
+ * exponent and thus to the returned backoff.
8
+ *
9
+ * The series can be described as ('i' is the current step/retry):
10
+ * backoff = base * 2^i | without bound
11
+ * backoff = base * 2^min(i, expMax) | with bound
12
+ *
13
+ * Example:
14
+ *
15
+ * 1) Without bound:
16
+ * base = 1000, expMax = undefined
17
+ * backoff = 1000 * 2^0 = 1000 // first retry
18
+ * backoff = 1000 * 2^1 = 2000 // second retry
19
+ * backoff = 1000 * 2^2 = 4000 // ...doubles with every retry
20
+ * backoff = 1000 * 2^3 = 8000
21
+ * backoff = 1000 * 2^4 = 16000
22
+ * ... // and so on
23
+ *
24
+ * 2) With bound:
25
+ * base = 1000, expMax = 3
26
+ * backoff = 1000 * 2^0 = 1000 // first retry
27
+ * backoff = 1000 * 2^1 = 2000 // second retry
28
+ * backoff = 1000 * 2^2 = 4000 // third retry
29
+ * backoff = 1000 * 2^3 = 8000 // maximum reached, don't increase further
30
+ * backoff = 1000 * 2^3 = 8000
31
+ * backoff = 1000 * 2^3 = 8000
32
+ * ... // and so on
33
+ */
34
+ var ExponentialBackoff = /** @class */ (function () {
35
+ /**
36
+ * Creates a new ExponentialBackoff.
37
+ * @param base the base of the exponentiation
38
+ * @param expMax the maximum exponent, no bound if undefined
39
+ */
40
+ function ExponentialBackoff(base, expMax) {
41
+ this._retries = 0;
42
+ if (!Number.isInteger(base) || base < 0) {
43
+ throw new Error("Base must be a positive integer or zero");
44
+ }
45
+ if (expMax !== undefined && (!Number.isInteger(expMax) || expMax < 0)) {
46
+ throw new Error("ExpMax must be a undefined, a positive integer or zero");
47
+ }
48
+ this.base = base;
49
+ this.expMax = expMax;
50
+ this.i = 0;
51
+ }
52
+ Object.defineProperty(ExponentialBackoff.prototype, "retries", {
53
+ get: function () {
54
+ return this._retries;
55
+ },
56
+ enumerable: false,
57
+ configurable: true
58
+ });
59
+ Object.defineProperty(ExponentialBackoff.prototype, "current", {
60
+ get: function () {
61
+ return this.base * Math.pow(2, this.i);
62
+ },
63
+ enumerable: false,
64
+ configurable: true
65
+ });
66
+ ExponentialBackoff.prototype.next = function () {
67
+ this._retries++;
68
+ this.i =
69
+ this.expMax === undefined
70
+ ? this.i + 1
71
+ : Math.min(this.i + 1, this.expMax);
72
+ return this.current;
73
+ };
74
+ ExponentialBackoff.prototype.reset = function () {
75
+ this._retries = 0;
76
+ this.i = 0;
77
+ };
78
+ return ExponentialBackoff;
79
+ }());
80
+ exports.ExponentialBackoff = ExponentialBackoff;
81
+ //# sourceMappingURL=exponentialbackoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exponentialbackoff.js","sourceRoot":"","sources":["../../../../src/backoff/exponentialbackoff.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH;IAME;;;;OAIG;IACH,4BAAY,IAAY,EAAE,MAAe;QAPjC,aAAQ,GAAW,CAAC,CAAC;QAQ3B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE;YACvC,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;SAC5D;QACD,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,EAAE;YACrE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;SAC3E;QAED,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACb,CAAC;IAED,sBAAI,uCAAO;aAAX;YACE,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;;;OAAA;IAED,sBAAI,uCAAO;aAAX;YACE,OAAO,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;;;OAAA;IAED,iCAAI,GAAJ;QACE,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,IAAI,CAAC,CAAC;YACJ,IAAI,CAAC,MAAM,KAAK,SAAS;gBACvB,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC;gBACZ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,kCAAK,GAAL;QACE,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACb,CAAC;IACH,yBAAC;AAAD,CAAC,AA7CD,IA6CC;AA7CY,gDAAkB"}
@@ -0,0 +1,51 @@
1
+ import { Backoff } from "./backoff";
2
+ /**
3
+ * LinearBackoff returns a backoff-time that is incremented by a fixed amount
4
+ * with every step/retry. An optional maximum can be provided as an upper bound
5
+ * to the returned backoff.
6
+ *
7
+ * The series can be described as ('i' is the current step/retry):
8
+ * backoff = initial + increment * i | without bound
9
+ * backoff = initial + increment * min(i, max) | with bound
10
+ *
11
+ * Example:
12
+ *
13
+ * 1) Without bound:
14
+ * initial = 1000, increment = 1000
15
+ * backoff = 1000 + 1000 * 0 = 1000 // first retry
16
+ * backoff = 1000 + 1000 * 1 = 2000 // second retry
17
+ * backoff = 1000 + 1000 * 2 = 3000 // ...increases by 'increment' with every retry
18
+ * backoff = 1000 + 1000 * 3 = 4000
19
+ * backoff = 1000 + 1000 * 4 = 5000
20
+ * ... // and so on
21
+ *
22
+ * 2) With bound:
23
+ * initial = 1000, increment = 1000, max = 5000
24
+ * backoff = 1000 + 1000 * 0 = 1000 // first retry
25
+ * backoff = 1000 + 1000 * 1 = 2000 // second retry
26
+ * backoff = 1000 + 1000 * 2 = 3000 // third retry
27
+ * backoff = 1000 + 1000 * 3 = 4000 // fourth retry
28
+ * backoff = 1000 + 1000 * 4 = 5000 // maximum reached, don't increase further
29
+ * backoff = 1000 + 1000 * 4 = 5000
30
+ * backoff = 1000 + 1000 * 4 = 5000
31
+ * ... // and so on
32
+ */
33
+ export declare class LinearBackoff implements Backoff {
34
+ private readonly initial;
35
+ private readonly increment;
36
+ private readonly max?;
37
+ private i;
38
+ private _retries;
39
+ /**
40
+ * Creates a new LinearBackoff.
41
+ * @param initial the initial backoff-time in milliseconds
42
+ * @param increment the amount to increment the backoff-time with every step (in milliseconds)
43
+ * @param max the maximum backoff-time (in milliseconds), no bound if undefined
44
+ */
45
+ constructor(initial: number, increment: number, max?: number);
46
+ get retries(): number;
47
+ get current(): number;
48
+ next(): number;
49
+ reset(): void;
50
+ }
51
+ //# sourceMappingURL=linearbackoff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linearbackoff.d.ts","sourceRoot":"","sources":["../../../../src/backoff/linearbackoff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,aAAc,YAAW,OAAO;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAS;IAC9B,OAAO,CAAC,CAAC,CAAa;IACtB,OAAO,CAAC,QAAQ,CAAa;IAE7B;;;;;OAKG;gBACS,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM;IAqB5D,IAAI,OAAO,WAEV;IAED,IAAI,OAAO,IAAI,MAAM,CAIpB;IAED,IAAI,IAAI,MAAM;IAMd,KAAK,IAAI,IAAI;CAId"}