@pythnetwork/pyth-lazer-sdk 5.0.0 → 5.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.
Files changed (33) hide show
  1. package/dist/cjs/{client.js → client.cjs} +93 -98
  2. package/dist/cjs/constants.cjs +36 -0
  3. package/dist/cjs/index.cjs +20 -0
  4. package/dist/cjs/package.json +1 -1
  5. package/dist/cjs/protocol.cjs +33 -0
  6. package/dist/cjs/protocol.d.ts +1 -1
  7. package/dist/cjs/socket/{resilient-websocket.js → resilient-websocket.cjs} +47 -48
  8. package/dist/cjs/socket/{websocket-pool.js → websocket-pool.cjs} +68 -65
  9. package/dist/cjs/util/{buffer-util.js → buffer-util.cjs} +14 -14
  10. package/dist/cjs/util/env-util.cjs +33 -0
  11. package/dist/cjs/util/index.cjs +20 -0
  12. package/dist/cjs/util/url-util.cjs +17 -0
  13. package/dist/esm/{client.js → client.mjs} +76 -88
  14. package/dist/esm/index.mjs +3 -0
  15. package/dist/esm/package.json +1 -1
  16. package/dist/esm/protocol.d.ts +1 -1
  17. package/dist/esm/{protocol.js → protocol.mjs} +4 -4
  18. package/dist/esm/socket/{resilient-websocket.js → resilient-websocket.mjs} +27 -36
  19. package/dist/esm/socket/{websocket-pool.js → websocket-pool.mjs} +47 -53
  20. package/dist/esm/util/{buffer-util.js → buffer-util.mjs} +3 -6
  21. package/dist/esm/util/{env-util.js → env-util.mjs} +4 -8
  22. package/dist/esm/util/index.mjs +3 -0
  23. package/dist/esm/util/{url-util.js → url-util.mjs} +2 -4
  24. package/package.json +108 -15
  25. package/dist/cjs/constants.js +0 -9
  26. package/dist/cjs/index.js +0 -19
  27. package/dist/cjs/protocol.js +0 -15
  28. package/dist/cjs/util/env-util.js +0 -32
  29. package/dist/cjs/util/index.js +0 -19
  30. package/dist/cjs/util/url-util.js +0 -18
  31. package/dist/esm/index.js +0 -3
  32. package/dist/esm/util/index.js +0 -3
  33. /package/dist/esm/{constants.js → constants.mjs} +0 -0
@@ -1,11 +1,18 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PythLazerClient = void 0;
4
- const ts_log_1 = require("ts-log");
5
- const constants_js_1 = require("./constants.js");
6
- const protocol_js_1 = require("./protocol.js");
7
- const websocket_pool_js_1 = require("./socket/websocket-pool.js");
8
- const buffer_util_js_1 = require("./util/buffer-util.js");
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "PythLazerClient", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return PythLazerClient;
9
+ }
10
+ });
11
+ const _tslog = require("ts-log");
12
+ const _constants = require("./constants.cjs");
13
+ const _protocol = require("./protocol.cjs");
14
+ const _websocketpool = require("./socket/websocket-pool.cjs");
15
+ const _bufferutil = require("./util/buffer-util.cjs");
9
16
  const UINT16_NUM_BYTES = 2;
10
17
  const UINT32_NUM_BYTES = 4;
11
18
  const UINT64_NUM_BYTES = 8;
@@ -15,7 +22,7 @@ class PythLazerClient {
15
22
  priceServiceUrl;
16
23
  logger;
17
24
  wsp;
18
- constructor(token, metadataServiceUrl, priceServiceUrl, logger, wsp) {
25
+ constructor(token, metadataServiceUrl, priceServiceUrl, logger, wsp){
19
26
  this.token = token;
20
27
  this.metadataServiceUrl = metadataServiceUrl;
21
28
  this.priceServiceUrl = priceServiceUrl;
@@ -23,91 +30,82 @@ class PythLazerClient {
23
30
  this.wsp = wsp;
24
31
  }
25
32
  /**
26
- * Gets the WebSocket pool. If the WebSocket pool is not configured, an error is thrown.
27
- * @throws Error if WebSocket pool is not configured
28
- * @returns The WebSocket pool
29
- */
30
- getWebSocketPool() {
33
+ * Gets the WebSocket pool. If the WebSocket pool is not configured, an error is thrown.
34
+ * @throws Error if WebSocket pool is not configured
35
+ * @returns The WebSocket pool
36
+ */ getWebSocketPool() {
31
37
  if (!this.wsp) {
32
38
  throw new Error("WebSocket pool is not available. Make sure to provide webSocketPoolConfig when creating the client.");
33
39
  }
34
40
  return this.wsp;
35
41
  }
36
42
  /**
37
- * Creates a new PythLazerClient instance.
38
- * @param config - Configuration including token, metadata service URL, and price service URL, and WebSocket pool configuration
39
- */
40
- static async create(config) {
43
+ * Creates a new PythLazerClient instance.
44
+ * @param config - Configuration including token, metadata service URL, and price service URL, and WebSocket pool configuration
45
+ */ static async create(config) {
41
46
  const token = config.token;
42
47
  // Collect and remove trailing slash from URLs
43
- const metadataServiceUrl = (config.metadataServiceUrl ?? constants_js_1.DEFAULT_METADATA_SERVICE_URL).replace(/\/+$/, "");
44
- const priceServiceUrl = (config.priceServiceUrl ?? constants_js_1.DEFAULT_PRICE_SERVICE_URL).replace(/\/+$/, "");
45
- const logger = config.logger ?? ts_log_1.dummyLogger;
48
+ const metadataServiceUrl = (config.metadataServiceUrl ?? _constants.DEFAULT_METADATA_SERVICE_URL).replace(/\/+$/, "");
49
+ const priceServiceUrl = (config.priceServiceUrl ?? _constants.DEFAULT_PRICE_SERVICE_URL).replace(/\/+$/, "");
50
+ const logger = config.logger ?? _tslog.dummyLogger;
46
51
  // If webSocketPoolConfig is provided, create a WebSocket pool and block until at least one connection is established.
47
52
  let wsp;
48
53
  if (config.webSocketPoolConfig) {
49
- wsp = await websocket_pool_js_1.WebSocketPool.create(config.webSocketPoolConfig, token, logger);
54
+ wsp = await _websocketpool.WebSocketPool.create(config.webSocketPoolConfig, token, logger);
50
55
  }
51
56
  return new PythLazerClient(token, metadataServiceUrl, priceServiceUrl, logger, wsp);
52
57
  }
53
58
  /**
54
- * Adds a message listener that receives either JSON or binary responses from the WebSocket connections.
55
- * The listener will be called for each message received, with deduplication across redundant connections.
56
- * @param handler - Callback function that receives the parsed message. The message can be either a JSON response
57
- * or a binary response containing EVM, Solana, or parsed payload data.
58
- */
59
- addMessageListener(handler) {
59
+ * Adds a message listener that receives either JSON or binary responses from the WebSocket connections.
60
+ * The listener will be called for each message received, with deduplication across redundant connections.
61
+ * @param handler - Callback function that receives the parsed message. The message can be either a JSON response
62
+ * or a binary response containing EVM, Solana, or parsed payload data.
63
+ */ addMessageListener(handler) {
60
64
  const wsp = this.getWebSocketPool();
61
- wsp.addMessageListener(async (data) => {
65
+ wsp.addMessageListener(async (data)=>{
62
66
  if (typeof data == "string") {
63
67
  handler({
64
68
  type: "json",
65
- value: JSON.parse(data),
69
+ value: JSON.parse(data)
66
70
  });
67
71
  return;
68
72
  }
69
- const buffData = await (0, buffer_util_js_1.bufferFromWebsocketData)(data);
73
+ const buffData = await (0, _bufferutil.bufferFromWebsocketData)(data);
70
74
  let pos = 0;
71
- const magic = buffData
72
- .subarray(pos, pos + UINT32_NUM_BYTES)
73
- .readUint32LE();
75
+ const magic = buffData.subarray(pos, pos + UINT32_NUM_BYTES).readUint32LE();
74
76
  pos += UINT32_NUM_BYTES;
75
- if (magic != protocol_js_1.BINARY_UPDATE_FORMAT_MAGIC_LE) {
77
+ if (magic != _protocol.BINARY_UPDATE_FORMAT_MAGIC_LE) {
76
78
  throw new Error("binary update format magic mismatch");
77
79
  }
78
80
  // TODO: some uint64 values may not be representable as Number.
79
81
  const subscriptionId = Number(buffData.subarray(pos, pos + UINT64_NUM_BYTES).readBigInt64BE());
80
82
  pos += UINT64_NUM_BYTES;
81
- const value = { subscriptionId };
82
- while (pos < buffData.length) {
83
- const len = buffData
84
- .subarray(pos, pos + UINT16_NUM_BYTES)
85
- .readUint16BE();
83
+ const value = {
84
+ subscriptionId
85
+ };
86
+ while(pos < buffData.length){
87
+ const len = buffData.subarray(pos, pos + UINT16_NUM_BYTES).readUint16BE();
86
88
  pos += UINT16_NUM_BYTES;
87
- const magic = buffData
88
- .subarray(pos, pos + UINT32_NUM_BYTES)
89
- .readUint32LE();
90
- if (magic == protocol_js_1.FORMAT_MAGICS_LE.EVM) {
89
+ const magic = buffData.subarray(pos, pos + UINT32_NUM_BYTES).readUint32LE();
90
+ if (magic == _protocol.FORMAT_MAGICS_LE.EVM) {
91
91
  value.evm = buffData.subarray(pos, pos + len);
92
- }
93
- else if (magic == protocol_js_1.FORMAT_MAGICS_LE.SOLANA) {
92
+ } else if (magic == _protocol.FORMAT_MAGICS_LE.SOLANA) {
94
93
  value.solana = buffData.subarray(pos, pos + len);
95
- }
96
- else if (magic == protocol_js_1.FORMAT_MAGICS_LE.LE_ECDSA) {
94
+ } else if (magic == _protocol.FORMAT_MAGICS_LE.LE_ECDSA) {
97
95
  value.leEcdsa = buffData.subarray(pos, pos + len);
98
- }
99
- else if (magic == protocol_js_1.FORMAT_MAGICS_LE.LE_UNSIGNED) {
96
+ } else if (magic == _protocol.FORMAT_MAGICS_LE.LE_UNSIGNED) {
100
97
  value.leUnsigned = buffData.subarray(pos, pos + len);
101
- }
102
- else if (magic == protocol_js_1.FORMAT_MAGICS_LE.JSON) {
98
+ } else if (magic == _protocol.FORMAT_MAGICS_LE.JSON) {
103
99
  value.parsed = JSON.parse(buffData.subarray(pos + UINT32_NUM_BYTES, pos + len).toString());
104
- }
105
- else {
100
+ } else {
106
101
  throw new Error(`unknown magic: ${magic.toString()}`);
107
102
  }
108
103
  pos += len;
109
104
  }
110
- handler({ type: "binary", value });
105
+ handler({
106
+ type: "binary",
107
+ value
108
+ });
111
109
  });
112
110
  }
113
111
  subscribe(request) {
@@ -126,11 +124,10 @@ class PythLazerClient {
126
124
  wsp.sendRequest(request);
127
125
  }
128
126
  /**
129
- * Registers a handler function that will be called whenever all WebSocket connections are down or attempting to reconnect.
130
- * The connections may still try to reconnect in the background. To shut down the pool, call `shutdown()`.
131
- * @param handler - Function to be called when all connections are down
132
- */
133
- addAllConnectionsDownListener(handler) {
127
+ * Registers a handler function that will be called whenever all WebSocket connections are down or attempting to reconnect.
128
+ * The connections may still try to reconnect in the background. To shut down the pool, call `shutdown()`.
129
+ * @param handler - Function to be called when all connections are down
130
+ */ addAllConnectionsDownListener(handler) {
134
131
  const wsp = this.getWebSocketPool();
135
132
  wsp.addAllConnectionsDownListener(handler);
136
133
  }
@@ -139,27 +136,25 @@ class PythLazerClient {
139
136
  wsp.shutdown();
140
137
  }
141
138
  /**
142
- * Private helper method to make authenticated HTTP requests with Bearer token
143
- * @param url - The URL to fetch
144
- * @param options - Additional fetch options
145
- * @returns Promise resolving to the fetch Response
146
- */
147
- async authenticatedFetch(url, options = {}) {
139
+ * Private helper method to make authenticated HTTP requests with Bearer token
140
+ * @param url - The URL to fetch
141
+ * @param options - Additional fetch options
142
+ * @returns Promise resolving to the fetch Response
143
+ */ async authenticatedFetch(url, options = {}) {
148
144
  const headers = {
149
145
  Authorization: `Bearer ${this.token}`,
150
- ...options.headers,
146
+ ...options.headers
151
147
  };
152
148
  return fetch(url, {
153
149
  ...options,
154
- headers,
150
+ headers
155
151
  });
156
152
  }
157
153
  /**
158
- * Queries the symbols endpoint to get available price feed symbols.
159
- * @param params - Optional query parameters to filter symbols
160
- * @returns Promise resolving to array of symbol information
161
- */
162
- async getSymbols(params) {
154
+ * Queries the symbols endpoint to get available price feed symbols.
155
+ * @param params - Optional query parameters to filter symbols
156
+ * @returns Promise resolving to array of symbol information
157
+ */ async getSymbols(params) {
163
158
  const url = new URL(`${this.metadataServiceUrl}/v1/symbols`);
164
159
  if (params?.query) {
165
160
  url.searchParams.set("query", params.query);
@@ -172,63 +167,63 @@ class PythLazerClient {
172
167
  if (!response.ok) {
173
168
  throw new Error(`HTTP error! status: ${String(response.status)} - ${await response.text()}`);
174
169
  }
175
- return (await response.json());
176
- }
177
- catch (error) {
170
+ return await response.json();
171
+ } catch (error) {
178
172
  throw new Error(`Failed to fetch symbols: ${error instanceof Error ? error.message : String(error)}`);
179
173
  }
180
174
  }
181
175
  /**
182
- * Queries the latest price endpoint to get current price data.
183
- * @param params - Parameters for the latest price request
184
- * @returns Promise resolving to JsonUpdate with current price data
185
- */
186
- async getLatestPrice(params) {
176
+ * Queries the latest price endpoint to get current price data.
177
+ * @param params - Parameters for the latest price request
178
+ * @returns Promise resolving to JsonUpdate with current price data
179
+ */ async getLatestPrice(params) {
187
180
  const url = `${this.priceServiceUrl}/v1/latest_price`;
188
181
  try {
189
182
  const body = JSON.stringify(params);
190
- this.logger.debug("getLatestPrice", { url, body });
183
+ this.logger.debug("getLatestPrice", {
184
+ url,
185
+ body
186
+ });
191
187
  const response = await this.authenticatedFetch(url, {
192
188
  method: "POST",
193
189
  headers: {
194
- "Content-Type": "application/json",
190
+ "Content-Type": "application/json"
195
191
  },
196
- body: body,
192
+ body: body
197
193
  });
198
194
  if (!response.ok) {
199
195
  throw new Error(`HTTP error! status: ${String(response.status)} - ${await response.text()}`);
200
196
  }
201
- return (await response.json());
202
- }
203
- catch (error) {
197
+ return await response.json();
198
+ } catch (error) {
204
199
  throw new Error(`Failed to fetch latest price: ${error instanceof Error ? error.message : String(error)}`);
205
200
  }
206
201
  }
207
202
  /**
208
- * Queries the price endpoint to get historical price data at a specific timestamp.
209
- * @param params - Parameters for the price request including timestamp
210
- * @returns Promise resolving to JsonUpdate with price data at the specified time
211
- */
212
- async getPrice(params) {
203
+ * Queries the price endpoint to get historical price data at a specific timestamp.
204
+ * @param params - Parameters for the price request including timestamp
205
+ * @returns Promise resolving to JsonUpdate with price data at the specified time
206
+ */ async getPrice(params) {
213
207
  const url = `${this.priceServiceUrl}/v1/price`;
214
208
  try {
215
209
  const body = JSON.stringify(params);
216
- this.logger.debug("getPrice", { url, body });
210
+ this.logger.debug("getPrice", {
211
+ url,
212
+ body
213
+ });
217
214
  const response = await this.authenticatedFetch(url, {
218
215
  method: "POST",
219
216
  headers: {
220
- "Content-Type": "application/json",
217
+ "Content-Type": "application/json"
221
218
  },
222
- body: body,
219
+ body: body
223
220
  });
224
221
  if (!response.ok) {
225
222
  throw new Error(`HTTP error! status: ${String(response.status)} - ${await response.text()}`);
226
223
  }
227
- return (await response.json());
228
- }
229
- catch (error) {
224
+ return await response.json();
225
+ } catch (error) {
230
226
  throw new Error(`Failed to fetch price: ${error instanceof Error ? error.message : String(error)}`);
231
227
  }
232
228
  }
233
229
  }
234
- exports.PythLazerClient = PythLazerClient;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get DEFAULT_METADATA_SERVICE_URL () {
13
+ return DEFAULT_METADATA_SERVICE_URL;
14
+ },
15
+ get DEFAULT_PRICE_SERVICE_URL () {
16
+ return DEFAULT_PRICE_SERVICE_URL;
17
+ },
18
+ get DEFAULT_STREAM_SERVICE_0_URL () {
19
+ return DEFAULT_STREAM_SERVICE_0_URL;
20
+ },
21
+ get DEFAULT_STREAM_SERVICE_1_URL () {
22
+ return DEFAULT_STREAM_SERVICE_1_URL;
23
+ },
24
+ get SOLANA_LAZER_PROGRAM_ID () {
25
+ return SOLANA_LAZER_PROGRAM_ID;
26
+ },
27
+ get SOLANA_LAZER_STORAGE_ID () {
28
+ return SOLANA_LAZER_STORAGE_ID;
29
+ }
30
+ });
31
+ const SOLANA_LAZER_PROGRAM_ID = "pytd2yyk641x7ak7mkaasSJVXh6YYZnC7wTmtgAyxPt";
32
+ const SOLANA_LAZER_STORAGE_ID = "3rdJbqfnagQ4yx9HXJViD4zc4xpiSqmFsKpPuSCQVyQL";
33
+ const DEFAULT_METADATA_SERVICE_URL = "https://history.pyth-lazer.dourolabs.app/history";
34
+ const DEFAULT_PRICE_SERVICE_URL = "https://pyth-lazer-0.dourolabs.app";
35
+ const DEFAULT_STREAM_SERVICE_0_URL = "wss://pyth-lazer-0.dourolabs.app/v1/stream";
36
+ const DEFAULT_STREAM_SERVICE_1_URL = "wss://pyth-lazer-1.dourolabs.app/v1/stream";
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ _export_star(require("./client.cjs"), exports);
6
+ _export_star(require("./protocol.cjs"), exports);
7
+ _export_star(require("./constants.cjs"), exports);
8
+ function _export_star(from, to) {
9
+ Object.keys(from).forEach(function(k) {
10
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
11
+ Object.defineProperty(to, k, {
12
+ enumerable: true,
13
+ get: function() {
14
+ return from[k];
15
+ }
16
+ });
17
+ }
18
+ });
19
+ return from;
20
+ }
@@ -1 +1 @@
1
- {"type":"commonjs"}
1
+ { "type": "commonjs" }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get BINARY_UPDATE_FORMAT_MAGIC_LE () {
13
+ return BINARY_UPDATE_FORMAT_MAGIC_LE;
14
+ },
15
+ get CustomSocketClosureCodes () {
16
+ return CustomSocketClosureCodes;
17
+ },
18
+ get FORMAT_MAGICS_LE () {
19
+ return FORMAT_MAGICS_LE;
20
+ }
21
+ });
22
+ const BINARY_UPDATE_FORMAT_MAGIC_LE = 461_928_307;
23
+ const FORMAT_MAGICS_LE = {
24
+ JSON: 3_302_625_434,
25
+ EVM: 2_593_727_018,
26
+ SOLANA: 2_182_742_457,
27
+ LE_ECDSA: 1_296_547_300,
28
+ LE_UNSIGNED: 1_499_680_012
29
+ };
30
+ var CustomSocketClosureCodes = /*#__PURE__*/ function(CustomSocketClosureCodes) {
31
+ CustomSocketClosureCodes[CustomSocketClosureCodes["CLIENT_TIMEOUT_BUT_RECONNECTING"] = 4000] = "CLIENT_TIMEOUT_BUT_RECONNECTING";
32
+ return CustomSocketClosureCodes;
33
+ }({});
@@ -1,7 +1,7 @@
1
1
  export type Format = "evm" | "solana" | "leEcdsa" | "leUnsigned";
2
2
  export type DeliveryFormat = "json" | "binary";
3
3
  export type JsonBinaryEncoding = "base64" | "hex";
4
- export type PriceFeedProperty = "price" | "bestBidPrice" | "bestAskPrice" | "exponent" | "publisherCount" | "confidence";
4
+ export type PriceFeedProperty = "price" | "bestBidPrice" | "bestAskPrice" | "exponent" | "publisherCount" | "confidence" | "fundingRate" | "fundingTimestamp" | "fundingRateInterval";
5
5
  export type Channel = "real_time" | "fixed_rate@50ms" | "fixed_rate@200ms";
6
6
  export type Request = {
7
7
  type: "subscribe";
@@ -1,13 +1,22 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ResilientWebSocket = void 0;
7
- const isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));
8
- const ts_log_1 = require("ts-log");
9
- const protocol_js_1 = require("../protocol.js");
10
- const env_util_js_1 = require("../util/env-util.js");
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "ResilientWebSocket", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return ResilientWebSocket;
9
+ }
10
+ });
11
+ const _isomorphicws = /*#__PURE__*/ _interop_require_default(require("isomorphic-ws"));
12
+ const _tslog = require("ts-log");
13
+ const _protocol = require("../protocol.cjs");
14
+ const _envutil = require("../util/env-util.cjs");
15
+ function _interop_require_default(obj) {
16
+ return obj && obj.__esModule ? obj : {
17
+ default: obj
18
+ };
19
+ }
11
20
  const DEFAULT_HEARTBEAT_TIMEOUT_DURATION_MS = 5000; // 5 seconds
12
21
  const DEFAULT_MAX_RETRY_DELAY_MS = 1000; // 1 second'
13
22
  const DEFAULT_LOG_AFTER_RETRY_COUNT = 10;
@@ -28,7 +37,7 @@ class ResilientWebSocket {
28
37
  return this._isReconnecting;
29
38
  }
30
39
  isConnected() {
31
- return this.wsClient?.readyState === isomorphic_ws_1.default.OPEN;
40
+ return this.wsClient?.readyState === _isomorphicws.default.OPEN;
32
41
  }
33
42
  shouldLogRetry() {
34
43
  return this.wsFailedAttempts % this.logAfterRetryCount === 0;
@@ -36,33 +45,29 @@ class ResilientWebSocket {
36
45
  onError;
37
46
  onMessage;
38
47
  onReconnect;
39
- constructor(config) {
48
+ constructor(config){
40
49
  this.endpoint = config.endpoint;
41
50
  this.wsOptions = config.wsOptions;
42
- this.logger = config.logger ?? ts_log_1.dummyLogger;
43
- this.heartbeatTimeoutDurationMs =
44
- config.heartbeatTimeoutDurationMs ??
45
- DEFAULT_HEARTBEAT_TIMEOUT_DURATION_MS;
51
+ this.logger = config.logger ?? _tslog.dummyLogger;
52
+ this.heartbeatTimeoutDurationMs = config.heartbeatTimeoutDurationMs ?? DEFAULT_HEARTBEAT_TIMEOUT_DURATION_MS;
46
53
  this.maxRetryDelayMs = config.maxRetryDelayMs ?? DEFAULT_MAX_RETRY_DELAY_MS;
47
- this.logAfterRetryCount =
48
- config.logAfterRetryCount ?? DEFAULT_LOG_AFTER_RETRY_COUNT;
54
+ this.logAfterRetryCount = config.logAfterRetryCount ?? DEFAULT_LOG_AFTER_RETRY_COUNT;
49
55
  this.wsFailedAttempts = 0;
50
- this.onError = (error) => {
56
+ this.onError = (error)=>{
51
57
  void error;
52
58
  };
53
- this.onMessage = (data) => {
59
+ this.onMessage = (data)=>{
54
60
  void data;
55
61
  };
56
- this.onReconnect = () => {
57
- // Empty function, can be set by the user.
62
+ this.onReconnect = ()=>{
63
+ // Empty function, can be set by the user.
58
64
  };
59
65
  }
60
66
  send(data) {
61
67
  this.logger.debug(`Sending message`);
62
68
  if (this.isConnected()) {
63
69
  this.wsClient.send(data);
64
- }
65
- else {
70
+ } else {
66
71
  this.logger.warn(`WebSocket to ${this.endpoint} is not connected. Cannot send message.`);
67
72
  }
68
73
  }
@@ -85,34 +90,33 @@ class ResilientWebSocket {
85
90
  // browser constructor supports a different 2nd argument for the constructor,
86
91
  // so we need to ensure it's not included if we're running in that environment:
87
92
  // https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket#protocols
88
- this.wsClient = new isomorphic_ws_1.default(this.endpoint, (0, env_util_js_1.envIsBrowserOrWorker)() ? undefined : this.wsOptions);
89
- this.wsClient.addEventListener("open", () => {
93
+ this.wsClient = new _isomorphicws.default(this.endpoint, (0, _envutil.envIsBrowserOrWorker)() ? undefined : this.wsOptions);
94
+ this.wsClient.addEventListener("open", ()=>{
90
95
  this.logger.info("WebSocket connection established");
91
96
  this.wsFailedAttempts = 0;
92
97
  this._isReconnecting = false;
93
98
  this.resetHeartbeat();
94
99
  this.onReconnect();
95
100
  });
96
- this.wsClient.addEventListener("close", (e) => {
101
+ this.wsClient.addEventListener("close", (e)=>{
97
102
  if (this.wsUserClosed) {
98
103
  this.logger.info(`WebSocket connection to ${this.endpoint} closed by user`);
99
- }
100
- else {
104
+ } else {
101
105
  if (this.shouldLogRetry()) {
102
106
  this.logger.warn(`WebSocket connection to ${this.endpoint} closed unexpectedly: Code: ${e.code.toString()}`);
103
107
  }
104
108
  this.handleReconnect();
105
109
  }
106
110
  });
107
- this.wsClient.addEventListener("error", (event) => {
111
+ this.wsClient.addEventListener("error", (event)=>{
108
112
  this.onError(event);
109
113
  });
110
- this.wsClient.addEventListener("message", (event) => {
114
+ this.wsClient.addEventListener("message", (event)=>{
111
115
  this.resetHeartbeat();
112
116
  this.onMessage(event.data);
113
117
  });
114
118
  if ("on" in this.wsClient) {
115
- this.wsClient.on("ping", () => {
119
+ this.wsClient.on("ping", ()=>{
116
120
  this.logger.info("Ping received");
117
121
  this.resetHeartbeat();
118
122
  });
@@ -122,18 +126,17 @@ class ResilientWebSocket {
122
126
  if (this.heartbeatTimeout !== undefined) {
123
127
  clearTimeout(this.heartbeatTimeout);
124
128
  }
125
- this.heartbeatTimeout = setTimeout(() => {
129
+ this.heartbeatTimeout = setTimeout(()=>{
126
130
  const warnMsg = "Connection timed out. Reconnecting...";
127
131
  this.logger.warn(warnMsg);
128
132
  if (this.wsClient) {
129
133
  if (typeof this.wsClient.terminate === "function") {
130
134
  this.wsClient.terminate();
131
- }
132
- else {
135
+ } else {
133
136
  // terminate is an implementation detail of the node-friendly
134
137
  // https://www.npmjs.com/package/ws package, but is not a native WebSocket API,
135
138
  // so we have to use the close method
136
- this.wsClient.close(protocol_js_1.CustomSocketClosureCodes.CLIENT_TIMEOUT_BUT_RECONNECTING, warnMsg);
139
+ this.wsClient.close(_protocol.CustomSocketClosureCodes.CLIENT_TIMEOUT_BUT_RECONNECTING, warnMsg);
137
140
  }
138
141
  }
139
142
  this.handleReconnect();
@@ -154,11 +157,9 @@ class ResilientWebSocket {
154
157
  this.wsClient = undefined;
155
158
  this._isReconnecting = true;
156
159
  if (this.shouldLogRetry()) {
157
- this.logger.error("Connection closed unexpectedly or because of timeout. Reconnecting after " +
158
- String(this.retryDelayMs()) +
159
- "ms.");
160
+ this.logger.error("Connection closed unexpectedly or because of timeout. Reconnecting after " + String(this.retryDelayMs()) + "ms.");
160
161
  }
161
- this.retryTimeout = setTimeout(() => {
162
+ this.retryTimeout = setTimeout(()=>{
162
163
  this.startWebSocket();
163
164
  }, this.retryDelayMs());
164
165
  }
@@ -170,18 +171,16 @@ class ResilientWebSocket {
170
171
  this.wsUserClosed = true;
171
172
  }
172
173
  /**
173
- * Calculates the delay in milliseconds for exponential backoff based on the number of failed attempts.
174
- *
175
- * The delay increases exponentially with each attempt, starting at 20ms for the first attempt,
176
- * and is capped at maxRetryDelayMs for attempts greater than or equal to 10.
177
- *
178
- * @returns The calculated delay in milliseconds before the next retry.
179
- */
180
- retryDelayMs() {
174
+ * Calculates the delay in milliseconds for exponential backoff based on the number of failed attempts.
175
+ *
176
+ * The delay increases exponentially with each attempt, starting at 20ms for the first attempt,
177
+ * and is capped at maxRetryDelayMs for attempts greater than or equal to 10.
178
+ *
179
+ * @returns The calculated delay in milliseconds before the next retry.
180
+ */ retryDelayMs() {
181
181
  if (this.wsFailedAttempts >= 10) {
182
182
  return this.maxRetryDelayMs;
183
183
  }
184
184
  return Math.min(2 ** this.wsFailedAttempts * 10, this.maxRetryDelayMs);
185
185
  }
186
186
  }
187
- exports.ResilientWebSocket = ResilientWebSocket;