@adaptic/utils 0.0.905 → 0.0.906

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/dist/test.js CHANGED
@@ -6482,6 +6482,8 @@ class AlpacaMarketDataAPI extends EventEmitter {
6482
6482
  quotes: [],
6483
6483
  bars: [],
6484
6484
  };
6485
+ reconnectAttempts = {};
6486
+ reconnectTimers = {};
6485
6487
  setMode(mode = "production") {
6486
6488
  if (mode === "sandbox") {
6487
6489
  // sandbox mode
@@ -6520,7 +6522,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
6520
6522
  // when env vars are not available. Features will be unavailable until
6521
6523
  // credentials are provided at runtime.
6522
6524
  const apiKey = process.env.ALPACA_API_KEY || "";
6523
- const apiSecret = process.env.ALPACA_SECRET_KEY || "";
6525
+ const apiSecret = process.env.ALPACA_API_SECRET || process.env.ALPACA_SECRET_KEY || "";
6524
6526
  this.credentialsValid = validateAlpacaCredentials({
6525
6527
  apiKey,
6526
6528
  apiSecret,
@@ -6562,6 +6564,12 @@ class AlpacaMarketDataAPI extends EventEmitter {
6562
6564
  else {
6563
6565
  url = this.cryptoStreamUrl;
6564
6566
  }
6567
+ const apiKey = process.env.ALPACA_API_KEY || "";
6568
+ const apiSecret = process.env.ALPACA_API_SECRET || process.env.ALPACA_SECRET_KEY || "";
6569
+ if (!apiKey || !apiSecret) {
6570
+ log$1(`Cannot connect ${streamType} stream: missing Alpaca credentials (ALPACA_API_KEY=${apiKey ? "set" : "MISSING"}, ALPACA_API_SECRET/ALPACA_SECRET_KEY=${apiSecret ? "set" : "MISSING"})`, { type: "error" });
6571
+ return;
6572
+ }
6565
6573
  const ws = new WebSocket(url);
6566
6574
  if (streamType === "stock") {
6567
6575
  this.stockWs = ws;
@@ -6576,8 +6584,8 @@ class AlpacaMarketDataAPI extends EventEmitter {
6576
6584
  log$1(`${streamType} stream connected`, { type: "info" });
6577
6585
  const authMessage = {
6578
6586
  action: "auth",
6579
- key: process.env.ALPACA_API_KEY,
6580
- secret: process.env.ALPACA_SECRET_KEY,
6587
+ key: apiKey,
6588
+ secret: apiSecret,
6581
6589
  };
6582
6590
  ws.send(JSON.stringify(authMessage));
6583
6591
  });
@@ -6594,6 +6602,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
6594
6602
  for (const message of messages) {
6595
6603
  if (message.T === "success" && message.msg === "authenticated") {
6596
6604
  log$1(`${streamType} stream authenticated`, { type: "info" });
6605
+ this.reconnectAttempts[streamType] = 0;
6597
6606
  this.sendSubscription(streamType);
6598
6607
  }
6599
6608
  else if (message.T === "success" && message.msg === "connected") {
@@ -6616,8 +6625,8 @@ class AlpacaMarketDataAPI extends EventEmitter {
6616
6625
  }
6617
6626
  }
6618
6627
  });
6619
- ws.on("close", () => {
6620
- log$1(`${streamType} stream disconnected`, { type: "warn" });
6628
+ ws.on("close", (code) => {
6629
+ log$1(`${streamType} stream disconnected (code: ${code})`, { type: "warn" });
6621
6630
  if (streamType === "stock") {
6622
6631
  this.stockWs = null;
6623
6632
  }
@@ -6627,12 +6636,35 @@ class AlpacaMarketDataAPI extends EventEmitter {
6627
6636
  else {
6628
6637
  this.cryptoWs = null;
6629
6638
  }
6630
- // Optional: implement reconnect logic
6639
+ // Reconnect with exponential backoff (unless intentionally closed with code 1000)
6640
+ if (code !== 1000) {
6641
+ this.scheduleReconnect(streamType);
6642
+ }
6631
6643
  });
6632
6644
  ws.on("error", (error) => {
6633
6645
  log$1(`${streamType} stream error: ${error.message}`, { type: "error" });
6634
6646
  });
6635
6647
  }
6648
+ scheduleReconnect(streamType) {
6649
+ const attempts = this.reconnectAttempts[streamType] ?? 0;
6650
+ const maxAttempts = 10;
6651
+ if (attempts >= maxAttempts) {
6652
+ log$1(`${streamType} stream: max reconnect attempts (${maxAttempts}) reached, giving up`, { type: "error" });
6653
+ return;
6654
+ }
6655
+ // Exponential backoff: 1s, 2s, 4s, 8s, 16s, 30s (capped)
6656
+ const delayMs = Math.min(1000 * Math.pow(2, attempts), 30000);
6657
+ this.reconnectAttempts[streamType] = attempts + 1;
6658
+ log$1(`${streamType} stream: scheduling reconnect attempt ${attempts + 1}/${maxAttempts} in ${delayMs}ms`, { type: "info" });
6659
+ // Clear any existing reconnect timer for this stream
6660
+ if (this.reconnectTimers[streamType]) {
6661
+ clearTimeout(this.reconnectTimers[streamType]);
6662
+ }
6663
+ this.reconnectTimers[streamType] = setTimeout(() => {
6664
+ log$1(`${streamType} stream: reconnecting (attempt ${attempts + 1}/${maxAttempts})`, { type: "info" });
6665
+ this.connect(streamType);
6666
+ }, delayMs);
6667
+ }
6636
6668
  sendSubscription(streamType) {
6637
6669
  let ws;
6638
6670
  let subscriptions;