@pythnetwork/pyth-lazer-sdk 5.0.0 → 5.2.1

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 (41) hide show
  1. package/dist/cjs/{client.js → client.cjs} +93 -98
  2. package/dist/cjs/constants.cjs +36 -0
  3. package/dist/cjs/emitter/index.cjs +53 -0
  4. package/dist/cjs/emitter/index.d.ts +29 -0
  5. package/dist/cjs/index.cjs +20 -0
  6. package/dist/cjs/package.json +1 -1
  7. package/dist/cjs/protocol.cjs +33 -0
  8. package/dist/cjs/protocol.d.ts +1 -1
  9. package/dist/cjs/socket/{resilient-websocket.js → resilient-websocket.cjs} +47 -48
  10. package/dist/cjs/socket/websocket-pool.cjs +253 -0
  11. package/dist/cjs/socket/websocket-pool.d.ts +37 -3
  12. package/dist/cjs/util/{buffer-util.js → buffer-util.cjs} +14 -14
  13. package/dist/cjs/util/env-util.cjs +33 -0
  14. package/dist/cjs/util/index.cjs +20 -0
  15. package/dist/cjs/util/url-util.cjs +17 -0
  16. package/dist/esm/{client.js → client.mjs} +76 -88
  17. package/dist/esm/emitter/index.d.ts +29 -0
  18. package/dist/esm/emitter/index.mjs +43 -0
  19. package/dist/esm/index.mjs +3 -0
  20. package/dist/esm/package.json +1 -1
  21. package/dist/esm/protocol.d.ts +1 -1
  22. package/dist/esm/{protocol.js → protocol.mjs} +4 -4
  23. package/dist/esm/socket/{resilient-websocket.js → resilient-websocket.mjs} +27 -36
  24. package/dist/esm/socket/websocket-pool.d.ts +37 -3
  25. package/dist/esm/socket/websocket-pool.mjs +238 -0
  26. package/dist/esm/util/{buffer-util.js → buffer-util.mjs} +3 -6
  27. package/dist/esm/util/{env-util.js → env-util.mjs} +4 -8
  28. package/dist/esm/util/index.mjs +3 -0
  29. package/dist/esm/util/{url-util.js → url-util.mjs} +2 -4
  30. package/package.json +119 -15
  31. package/dist/cjs/constants.js +0 -9
  32. package/dist/cjs/index.js +0 -19
  33. package/dist/cjs/protocol.js +0 -15
  34. package/dist/cjs/socket/websocket-pool.js +0 -201
  35. package/dist/cjs/util/env-util.js +0 -32
  36. package/dist/cjs/util/index.js +0 -19
  37. package/dist/cjs/util/url-util.js +0 -18
  38. package/dist/esm/index.js +0 -3
  39. package/dist/esm/socket/websocket-pool.js +0 -195
  40. package/dist/esm/util/index.js +0 -3
  41. /package/dist/esm/{constants.js → constants.mjs} +0 -0
@@ -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;
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "WebSocketPool", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return WebSocketPool;
9
+ }
10
+ });
11
+ const _ttlcache = /*#__PURE__*/ _interop_require_default(require("@isaacs/ttlcache"));
12
+ const _tslog = require("ts-log");
13
+ const _resilientwebsocket = require("./resilient-websocket.cjs");
14
+ const _constants = require("../constants.cjs");
15
+ const _index = require("../emitter/index.cjs");
16
+ const _index1 = require("../util/index.cjs");
17
+ function _interop_require_default(obj) {
18
+ return obj && obj.__esModule ? obj : {
19
+ default: obj
20
+ };
21
+ }
22
+ const DEFAULT_NUM_CONNECTIONS = 4;
23
+ class WebSocketPool extends _index.IsomorphicEventEmitter {
24
+ logger;
25
+ rwsPool;
26
+ cache;
27
+ subscriptions;
28
+ messageListeners;
29
+ allConnectionsDownListeners;
30
+ wasAllDown = true;
31
+ checkConnectionStatesInterval;
32
+ constructor(logger){
33
+ super(), this.logger = logger;
34
+ this.rwsPool = [];
35
+ this.cache = new _ttlcache.default({
36
+ ttl: 1000 * 10
37
+ }); // TTL of 10 seconds
38
+ this.subscriptions = new Map();
39
+ this.messageListeners = [];
40
+ this.allConnectionsDownListeners = [];
41
+ // Start monitoring connection states
42
+ this.checkConnectionStatesInterval = setInterval(()=>{
43
+ this.checkConnectionStates();
44
+ }, 100);
45
+ }
46
+ /**
47
+ * Creates a new WebSocketPool instance that uses multiple redundant WebSocket connections for reliability.
48
+ * Usage semantics are similar to using a regular WebSocket client.
49
+ * @param urls - List of WebSocket URLs to connect to
50
+ * @param token - Authentication token to use for the connections
51
+ * @param numConnections - Number of parallel WebSocket connections to maintain (default: 3)
52
+ * @param logger - Optional logger to get socket level logs. Compatible with most loggers such as the built-in console and `bunyan`.
53
+ */ static async create(config, token, logger) {
54
+ const urls = config.urls ?? [
55
+ _constants.DEFAULT_STREAM_SERVICE_0_URL,
56
+ _constants.DEFAULT_STREAM_SERVICE_1_URL
57
+ ];
58
+ const log = logger ?? _tslog.dummyLogger;
59
+ const pool = new WebSocketPool(log);
60
+ const numConnections = config.numConnections ?? DEFAULT_NUM_CONNECTIONS;
61
+ // bind a handler to capture any emitted errors and send them to the user-provided
62
+ // onWebSocketPoolError callback (if it is present)
63
+ if (typeof config.onWebSocketPoolError === "function") {
64
+ pool.on("error", config.onWebSocketPoolError);
65
+ pool.once("shutdown", ()=>{
66
+ // unbind all error handlers so we don't leak memory
67
+ pool.off("error");
68
+ });
69
+ }
70
+ for(let i = 0; i < numConnections; i++){
71
+ const baseUrl = urls[i % urls.length];
72
+ const isBrowser = (0, _index1.envIsBrowserOrWorker)();
73
+ const url = isBrowser ? (0, _index1.addAuthTokenToWebSocketUrl)(baseUrl, token) : baseUrl;
74
+ if (!url) {
75
+ throw new Error(`URLs must not be null or empty`);
76
+ }
77
+ const wsOptions = {
78
+ ...config.rwsConfig?.wsOptions,
79
+ headers: isBrowser ? undefined : {
80
+ Authorization: `Bearer ${token}`
81
+ }
82
+ };
83
+ const rws = new _resilientwebsocket.ResilientWebSocket({
84
+ ...config.rwsConfig,
85
+ endpoint: url,
86
+ wsOptions,
87
+ logger: log
88
+ });
89
+ // If a websocket client unexpectedly disconnects, ResilientWebSocket will reestablish
90
+ // the connection and call the onReconnect callback.
91
+ rws.onReconnect = ()=>{
92
+ if (rws.wsUserClosed) {
93
+ return;
94
+ }
95
+ for (const [, request] of pool.subscriptions){
96
+ try {
97
+ rws.send(JSON.stringify(request));
98
+ } catch (error) {
99
+ pool.logger.error("Failed to resend subscription on reconnect:", error);
100
+ }
101
+ }
102
+ };
103
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
104
+ const onErrorHandler = config.onWebSocketError ?? config.onError;
105
+ if (typeof onErrorHandler === "function") {
106
+ rws.onError = onErrorHandler;
107
+ }
108
+ // Handle all client messages ourselves. Dedupe before sending to registered message handlers.
109
+ rws.onMessage = (data)=>{
110
+ pool.dedupeHandler(data).catch((error)=>{
111
+ pool.emitPoolError(error, "Error in WebSocketPool dedupeHandler");
112
+ });
113
+ };
114
+ pool.rwsPool.push(rws);
115
+ rws.startWebSocket();
116
+ }
117
+ pool.logger.info(`Started WebSocketPool with ${numConnections.toString()} connections. Waiting for at least one to connect...`);
118
+ while(!pool.isAnyConnectionEstablished()){
119
+ await new Promise((resolve)=>setTimeout(resolve, 100));
120
+ }
121
+ pool.logger.info(`At least one WebSocket connection is established. WebSocketPool is ready.`);
122
+ return pool;
123
+ }
124
+ emitPoolError(error, context) {
125
+ const err = error instanceof Error ? error : new Error(String(error));
126
+ if (context) {
127
+ this.logger.error(context, err);
128
+ } else {
129
+ this.logger.error("WebSocketPool error", err);
130
+ }
131
+ for (const errHandler of this.getListeners("error")){
132
+ try {
133
+ errHandler(err);
134
+ } catch (handlerError) {
135
+ this.logger.error("WebSocketPool error handler threw", handlerError);
136
+ }
137
+ }
138
+ }
139
+ /**
140
+ * Checks for error responses in JSON messages and throws appropriate errors
141
+ */ handleErrorMessages(data) {
142
+ const message = JSON.parse(data);
143
+ if (message.type === "subscriptionError") {
144
+ throw new Error(`Error occurred for subscription ID ${String(message.subscriptionId)}: ${message.error}`);
145
+ } else if (message.type === "error") {
146
+ throw new Error(`Error: ${message.error}`);
147
+ }
148
+ }
149
+ async constructCacheKeyFromWebsocketData(data) {
150
+ if (typeof data === "string") return data;
151
+ const buff = await (0, _index1.bufferFromWebsocketData)(data);
152
+ return buff.toString("hex");
153
+ }
154
+ /**
155
+ * Handles incoming websocket messages by deduplicating identical messages received across
156
+ * multiple connections before forwarding to registered handlers
157
+ */ dedupeHandler = async (data)=>{
158
+ const cacheKey = await this.constructCacheKeyFromWebsocketData(data);
159
+ if (this.cache.has(cacheKey)) {
160
+ this.logger.debug("Dropping duplicate message");
161
+ return;
162
+ }
163
+ this.cache.set(cacheKey, true);
164
+ if (typeof data === "string") {
165
+ this.handleErrorMessages(data);
166
+ }
167
+ try {
168
+ await Promise.all(this.messageListeners.map((handler)=>handler(data)));
169
+ } catch (error) {
170
+ this.emitPoolError(error, "Error in WebSocketPool message handler");
171
+ }
172
+ };
173
+ sendRequest(request) {
174
+ for (const rws of this.rwsPool){
175
+ try {
176
+ rws.send(JSON.stringify(request));
177
+ } catch (error) {
178
+ this.emitPoolError(error, "Failed to send WebSocket request");
179
+ }
180
+ }
181
+ }
182
+ addSubscription(request) {
183
+ if (request.type !== "subscribe") {
184
+ this.emitPoolError(new Error("Request must be a subscribe request"));
185
+ return;
186
+ }
187
+ this.subscriptions.set(request.subscriptionId, request);
188
+ this.sendRequest(request);
189
+ }
190
+ removeSubscription(subscriptionId) {
191
+ this.subscriptions.delete(subscriptionId);
192
+ const request = {
193
+ type: "unsubscribe",
194
+ subscriptionId
195
+ };
196
+ this.sendRequest(request);
197
+ }
198
+ addMessageListener(handler) {
199
+ this.messageListeners.push(handler);
200
+ }
201
+ /**
202
+ * Calls the handler if all websocket connections are currently down or in reconnecting state.
203
+ * The connections may still try to reconnect in the background.
204
+ */ addAllConnectionsDownListener(handler) {
205
+ this.allConnectionsDownListeners.push(handler);
206
+ }
207
+ areAllConnectionsDown() {
208
+ return this.rwsPool.every((ws)=>!ws.isConnected() || ws.isReconnecting());
209
+ }
210
+ isAnyConnectionEstablished() {
211
+ return this.rwsPool.some((ws)=>ws.isConnected());
212
+ }
213
+ checkConnectionStates() {
214
+ const allDown = this.areAllConnectionsDown();
215
+ // If all connections just went down
216
+ if (allDown && !this.wasAllDown) {
217
+ this.wasAllDown = true;
218
+ this.logger.error("All WebSocket connections are down or reconnecting");
219
+ // Notify all listeners
220
+ for (const listener of this.allConnectionsDownListeners){
221
+ try {
222
+ listener();
223
+ } catch (error) {
224
+ this.emitPoolError(error, "All-connections-down listener threw");
225
+ }
226
+ }
227
+ }
228
+ // If at least one connection was restored
229
+ if (!allDown && this.wasAllDown) {
230
+ this.wasAllDown = false;
231
+ }
232
+ }
233
+ shutdown() {
234
+ for (const rws of this.rwsPool){
235
+ rws.closeWebSocket();
236
+ }
237
+ this.rwsPool = [];
238
+ this.subscriptions.clear();
239
+ this.messageListeners = [];
240
+ this.allConnectionsDownListeners = [];
241
+ clearInterval(this.checkConnectionStatesInterval);
242
+ // execute all bound shutdown handlers
243
+ for (const shutdownHandler of this.getListeners("shutdown")){
244
+ try {
245
+ shutdownHandler();
246
+ } catch (error) {
247
+ this.emitPoolError(error, "Shutdown handler threw");
248
+ }
249
+ }
250
+ // ensure any error handlers are removed to avoid leaks
251
+ this.off("error");
252
+ }
253
+ }
@@ -4,14 +4,47 @@ import type { Logger } from "ts-log";
4
4
  import type { Request } from "../protocol.js";
5
5
  import type { ResilientWebSocketConfig } from "./resilient-websocket.js";
6
6
  import { ResilientWebSocket } from "./resilient-websocket.js";
7
+ import { IsomorphicEventEmitter } from "../emitter/index.js";
7
8
  type WebSocketOnMessageCallback = (data: WebSocket.Data) => void | Promise<void>;
8
9
  export type WebSocketPoolConfig = {
9
- urls?: string[];
10
+ /**
11
+ * Maximum number of open, parallel websocket connections
12
+ * @defaultValue 3
13
+ */
10
14
  numConnections?: number;
11
- rwsConfig?: Omit<ResilientWebSocketConfig, "logger" | "endpoint">;
15
+ /**
16
+ * Callback that will be executed whenever an error
17
+ * message or an error event occurs on an individual WebSocket connection
18
+ *
19
+ * @deprecated use onWebSocketError() instead
20
+ */
12
21
  onError?: (error: ErrorEvent) => void;
22
+ /**
23
+ * Callback that will be executed whenever an error
24
+ * message or an error event occurs on an individual WebSocket connection
25
+ */
26
+ onWebSocketError?: (error: ErrorEvent) => void;
27
+ /**
28
+ * Callback that will be executed whenever an error occurs
29
+ * directly within the WebSocket pool. These can typically
30
+ * be errors that would normally manifest as "unhandledRejection" or "uncaughtException"
31
+ * errors.
32
+ */
33
+ onWebSocketPoolError?: (error: Error) => void;
34
+ /**
35
+ * Additional websocket configuration
36
+ */
37
+ rwsConfig?: Omit<ResilientWebSocketConfig, "logger" | "endpoint">;
38
+ /**
39
+ * Pyth URLs to use when creating a connection
40
+ */
41
+ urls?: string[];
42
+ };
43
+ export type WebSocketPoolEvents = {
44
+ error: (error: Error) => void;
45
+ shutdown: () => void;
13
46
  };
14
- export declare class WebSocketPool {
47
+ export declare class WebSocketPool extends IsomorphicEventEmitter<WebSocketPoolEvents> {
15
48
  private readonly logger;
16
49
  rwsPool: ResilientWebSocket[];
17
50
  private cache;
@@ -30,6 +63,7 @@ export declare class WebSocketPool {
30
63
  * @param logger - Optional logger to get socket level logs. Compatible with most loggers such as the built-in console and `bunyan`.
31
64
  */
32
65
  static create(config: WebSocketPoolConfig, token: string, logger?: Logger): Promise<WebSocketPool>;
66
+ private emitPoolError;
33
67
  /**
34
68
  * Checks for error responses in JSON messages and throws appropriate errors
35
69
  */
@@ -1,29 +1,29 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.bufferFromWebsocketData = bufferFromWebsocketData;
4
1
  // the linting rules don't allow importing anything that might clash with
5
2
  // a global, top-level import. we disable this rule because we need this
6
3
  // imported from our installed dependency
7
4
  // eslint-disable-next-line unicorn/prefer-node-protocol
8
- const buffer_1 = require("buffer");
9
- const BufferClassToUse = "Buffer" in globalThis ? globalThis.Buffer : buffer_1.Buffer;
10
- /**
11
- * given a relatively unknown websocket frame data object,
12
- * returns a valid Buffer instance that is safe to use
13
- * isomorphically in any JS runtime environment
14
- */
5
+ "use strict";
6
+ Object.defineProperty(exports, "__esModule", {
7
+ value: true
8
+ });
9
+ Object.defineProperty(exports, "bufferFromWebsocketData", {
10
+ enumerable: true,
11
+ get: function() {
12
+ return bufferFromWebsocketData;
13
+ }
14
+ });
15
+ const _buffer = require("buffer");
16
+ const BufferClassToUse = "Buffer" in globalThis ? globalThis.Buffer : _buffer.Buffer;
15
17
  async function bufferFromWebsocketData(data) {
16
18
  if (typeof data === "string") {
17
19
  return BufferClassToUse.from(new TextEncoder().encode(data).buffer);
18
20
  }
19
- if (data instanceof BufferClassToUse)
20
- return data;
21
+ if (data instanceof BufferClassToUse) return data;
21
22
  if (data instanceof Blob) {
22
23
  // let the uncaught promise exception bubble up if there's an issue
23
24
  return BufferClassToUse.from(await data.arrayBuffer());
24
25
  }
25
- if (data instanceof ArrayBuffer)
26
- return BufferClassToUse.from(data);
26
+ if (data instanceof ArrayBuffer) return BufferClassToUse.from(data);
27
27
  if (Array.isArray(data)) {
28
28
  // an array of buffers is highly unlikely, but it is a possibility
29
29
  // indicated by the WebSocket Data interface
@@ -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 envIsBrowser () {
13
+ return envIsBrowser;
14
+ },
15
+ get envIsBrowserOrWorker () {
16
+ return envIsBrowserOrWorker;
17
+ },
18
+ get envIsServiceOrWebWorker () {
19
+ return envIsServiceOrWebWorker;
20
+ }
21
+ });
22
+ // we create this local-only type, which has assertions made to indicate
23
+ // that we do not know and cannot guarantee which JS environment we are in
24
+ const g = globalThis;
25
+ function envIsServiceOrWebWorker() {
26
+ return typeof WorkerGlobalScope !== "undefined" && g.self instanceof WorkerGlobalScope;
27
+ }
28
+ function envIsBrowser() {
29
+ return g.window !== undefined;
30
+ }
31
+ function envIsBrowserOrWorker() {
32
+ return envIsServiceOrWebWorker() || envIsBrowser();
33
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ _export_star(require("./buffer-util.cjs"), exports);
6
+ _export_star(require("./env-util.cjs"), exports);
7
+ _export_star(require("./url-util.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
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "addAuthTokenToWebSocketUrl", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return addAuthTokenToWebSocketUrl;
9
+ }
10
+ });
11
+ const ACCESS_TOKEN_QUERY_PARAM_KEY = "ACCESS_TOKEN";
12
+ function addAuthTokenToWebSocketUrl(baseUrl, authToken) {
13
+ if (!baseUrl || !authToken) return baseUrl;
14
+ const parsedUrl = new URL(baseUrl);
15
+ parsedUrl.searchParams.set(ACCESS_TOKEN_QUERY_PARAM_KEY, authToken);
16
+ return parsedUrl.toString();
17
+ }