@adaptic/utils 0.0.380 → 0.0.381

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/index.mjs CHANGED
@@ -11462,7 +11462,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
11462
11462
  cryptoWs = null;
11463
11463
  stockSubscriptions = { trades: [], quotes: [], bars: [] };
11464
11464
  optionSubscriptions = { trades: [], quotes: [], bars: [] };
11465
- cryptoSubscriptions = { trades: [], quotes: [], bars: [], dailyBars: [], updatedBars: [], orderbooks: [] };
11465
+ cryptoSubscriptions = { trades: [], quotes: [], bars: [] };
11466
11466
  setMode(mode = 'production') {
11467
11467
  if (mode === 'sandbox') { // sandbox mode
11468
11468
  this.stockStreamUrl = 'wss://stream.data.sandbox.alpaca.markets/v2/sip';
@@ -11519,7 +11519,16 @@ class AlpacaMarketDataAPI extends EventEmitter {
11519
11519
  return super.emit(event, ...args);
11520
11520
  }
11521
11521
  connect(streamType) {
11522
- const url = streamType === 'stock' ? this.stockStreamUrl : streamType === 'option' ? this.optionStreamUrl : this.cryptoStreamUrl;
11522
+ let url;
11523
+ if (streamType === 'stock') {
11524
+ url = this.stockStreamUrl;
11525
+ }
11526
+ else if (streamType === 'option') {
11527
+ url = this.optionStreamUrl;
11528
+ }
11529
+ else {
11530
+ url = this.cryptoStreamUrl;
11531
+ }
11523
11532
  const ws = new WebSocket(url);
11524
11533
  if (streamType === 'stock') {
11525
11534
  this.stockWs = ws;
@@ -11540,20 +11549,36 @@ class AlpacaMarketDataAPI extends EventEmitter {
11540
11549
  ws.send(JSON.stringify(authMessage));
11541
11550
  });
11542
11551
  ws.on('message', (data) => {
11543
- //log(`RAW MESSASGE: ${data.toString()}`);
11544
- const messages = JSON.parse(data.toString());
11552
+ const rawData = data.toString();
11553
+ let messages;
11554
+ try {
11555
+ messages = JSON.parse(rawData);
11556
+ }
11557
+ catch (e) {
11558
+ log(`${streamType} stream received invalid JSON: ${rawData.substring(0, 200)}`, { type: 'error' });
11559
+ return;
11560
+ }
11545
11561
  for (const message of messages) {
11546
11562
  if (message.T === 'success' && message.msg === 'authenticated') {
11547
11563
  log(`${streamType} stream authenticated`, { type: 'info' });
11548
11564
  this.sendSubscription(streamType);
11549
11565
  }
11566
+ else if (message.T === 'success' && message.msg === 'connected') {
11567
+ log(`${streamType} stream connected message received`, { type: 'debug' });
11568
+ }
11569
+ else if (message.T === 'subscription') {
11570
+ log(`${streamType} subscription confirmed: trades=${message.trades?.length || 0}, quotes=${message.quotes?.length || 0}, bars=${message.bars?.length || 0}`, { type: 'info' });
11571
+ }
11550
11572
  else if (message.T === 'error') {
11551
- log(`${streamType} stream error: ${message.msg}`, { type: 'error' });
11573
+ log(`${streamType} stream error: ${message.msg} (code: ${message.code}, raw: ${JSON.stringify(message)})`, { type: 'error' });
11552
11574
  }
11553
11575
  else if (message.S) {
11554
11576
  super.emit(`${streamType}-${message.T}`, message);
11555
11577
  super.emit(`${streamType}-data`, message);
11556
11578
  }
11579
+ else {
11580
+ log(`${streamType} received unknown message type: ${JSON.stringify(message)}`, { type: 'debug' });
11581
+ }
11557
11582
  }
11558
11583
  });
11559
11584
  ws.on('close', () => {
@@ -11574,38 +11599,49 @@ class AlpacaMarketDataAPI extends EventEmitter {
11574
11599
  });
11575
11600
  }
11576
11601
  sendSubscription(streamType) {
11577
- const ws = streamType === 'stock' ? this.stockWs : streamType === 'option' ? this.optionWs : this.cryptoWs;
11578
- const subscriptions = streamType === 'stock' ? this.stockSubscriptions : streamType === 'option' ? this.optionSubscriptions : this.cryptoSubscriptions;
11602
+ let ws;
11603
+ let subscriptions;
11604
+ if (streamType === 'stock') {
11605
+ ws = this.stockWs;
11606
+ subscriptions = this.stockSubscriptions;
11607
+ }
11608
+ else if (streamType === 'option') {
11609
+ ws = this.optionWs;
11610
+ subscriptions = this.optionSubscriptions;
11611
+ }
11612
+ else {
11613
+ ws = this.cryptoWs;
11614
+ subscriptions = this.cryptoSubscriptions;
11615
+ }
11616
+ log(`sendSubscription called for ${streamType} (wsReady=${ws?.readyState === WebSocket.OPEN}, trades=${subscriptions.trades?.length || 0}, quotes=${subscriptions.quotes?.length || 0}, bars=${subscriptions.bars?.length || 0})`, {
11617
+ type: 'debug',
11618
+ });
11579
11619
  if (ws && ws.readyState === WebSocket.OPEN) {
11580
11620
  const subMessagePayload = {};
11581
- if (subscriptions.trades && subscriptions.trades.length > 0) {
11621
+ if (subscriptions.trades.length > 0) {
11582
11622
  subMessagePayload.trades = subscriptions.trades;
11583
11623
  }
11584
- if (subscriptions.quotes && subscriptions.quotes.length > 0) {
11624
+ if (subscriptions.quotes.length > 0) {
11585
11625
  subMessagePayload.quotes = subscriptions.quotes;
11586
11626
  }
11587
- if (subscriptions.bars && subscriptions.bars.length > 0) {
11627
+ if (subscriptions.bars.length > 0) {
11588
11628
  subMessagePayload.bars = subscriptions.bars;
11589
11629
  }
11590
- // Crypto-specific subscription types
11591
- if (streamType === 'crypto') {
11592
- if (subscriptions.dailyBars && subscriptions.dailyBars.length > 0) {
11593
- subMessagePayload.dailyBars = subscriptions.dailyBars;
11594
- }
11595
- if (subscriptions.updatedBars && subscriptions.updatedBars.length > 0) {
11596
- subMessagePayload.updatedBars = subscriptions.updatedBars;
11597
- }
11598
- if (subscriptions.orderbooks && subscriptions.orderbooks.length > 0) {
11599
- subMessagePayload.orderbooks = subscriptions.orderbooks;
11600
- }
11601
- }
11602
11630
  if (Object.keys(subMessagePayload).length > 0) {
11603
11631
  const subMessage = {
11604
11632
  action: 'subscribe',
11605
11633
  ...subMessagePayload,
11606
11634
  };
11607
- ws.send(JSON.stringify(subMessage));
11635
+ const messageJson = JSON.stringify(subMessage);
11636
+ log(`Sending ${streamType} subscription: ${messageJson}`, { type: 'info' });
11637
+ ws.send(messageJson);
11608
11638
  }
11639
+ else {
11640
+ log(`No ${streamType} subscriptions to send (all arrays empty)`, { type: 'debug' });
11641
+ }
11642
+ }
11643
+ else {
11644
+ log(`Cannot send ${streamType} subscription: WebSocket not ready`, { type: 'warn' });
11609
11645
  }
11610
11646
  }
11611
11647
  connectStockStream() {
@@ -11618,6 +11654,11 @@ class AlpacaMarketDataAPI extends EventEmitter {
11618
11654
  this.connect('option');
11619
11655
  }
11620
11656
  }
11657
+ connectCryptoStream() {
11658
+ if (!this.cryptoWs) {
11659
+ this.connect('crypto');
11660
+ }
11661
+ }
11621
11662
  disconnectStockStream() {
11622
11663
  if (this.stockWs) {
11623
11664
  this.stockWs.close();
@@ -11628,18 +11669,38 @@ class AlpacaMarketDataAPI extends EventEmitter {
11628
11669
  this.optionWs.close();
11629
11670
  }
11630
11671
  }
11631
- connectCryptoStream() {
11632
- if (!this.cryptoWs) {
11633
- this.connect('crypto');
11634
- }
11635
- }
11636
11672
  disconnectCryptoStream() {
11637
11673
  if (this.cryptoWs) {
11638
11674
  this.cryptoWs.close();
11639
11675
  }
11640
11676
  }
11677
+ /**
11678
+ * Check if a specific stream is connected
11679
+ * @param streamType - The type of stream to check
11680
+ * @returns True if the stream is connected
11681
+ */
11682
+ isStreamConnected(streamType) {
11683
+ if (streamType === 'stock') {
11684
+ return this.stockWs !== null && this.stockWs.readyState === WebSocket.OPEN;
11685
+ }
11686
+ else if (streamType === 'option') {
11687
+ return this.optionWs !== null && this.optionWs.readyState === WebSocket.OPEN;
11688
+ }
11689
+ else {
11690
+ return this.cryptoWs !== null && this.cryptoWs.readyState === WebSocket.OPEN;
11691
+ }
11692
+ }
11641
11693
  subscribe(streamType, subscriptions) {
11642
- const currentSubscriptions = streamType === 'stock' ? this.stockSubscriptions : streamType === 'option' ? this.optionSubscriptions : this.cryptoSubscriptions;
11694
+ let currentSubscriptions;
11695
+ if (streamType === 'stock') {
11696
+ currentSubscriptions = this.stockSubscriptions;
11697
+ }
11698
+ else if (streamType === 'option') {
11699
+ currentSubscriptions = this.optionSubscriptions;
11700
+ }
11701
+ else {
11702
+ currentSubscriptions = this.cryptoSubscriptions;
11703
+ }
11643
11704
  Object.entries(subscriptions).forEach(([key, value]) => {
11644
11705
  if (value) {
11645
11706
  currentSubscriptions[key] = [...new Set([...(currentSubscriptions[key] || []), ...value])];
@@ -11648,7 +11709,16 @@ class AlpacaMarketDataAPI extends EventEmitter {
11648
11709
  this.sendSubscription(streamType);
11649
11710
  }
11650
11711
  unsubscribe(streamType, subscriptions) {
11651
- const currentSubscriptions = streamType === 'stock' ? this.stockSubscriptions : streamType === 'option' ? this.optionSubscriptions : this.cryptoSubscriptions;
11712
+ let currentSubscriptions;
11713
+ if (streamType === 'stock') {
11714
+ currentSubscriptions = this.stockSubscriptions;
11715
+ }
11716
+ else if (streamType === 'option') {
11717
+ currentSubscriptions = this.optionSubscriptions;
11718
+ }
11719
+ else {
11720
+ currentSubscriptions = this.cryptoSubscriptions;
11721
+ }
11652
11722
  Object.entries(subscriptions).forEach(([key, value]) => {
11653
11723
  if (value) {
11654
11724
  currentSubscriptions[key] = (currentSubscriptions[key] || []).filter(s => !value.includes(s));
@@ -11658,7 +11728,16 @@ class AlpacaMarketDataAPI extends EventEmitter {
11658
11728
  action: 'unsubscribe',
11659
11729
  ...subscriptions,
11660
11730
  };
11661
- const ws = streamType === 'stock' ? this.stockWs : streamType === 'option' ? this.optionWs : this.cryptoWs;
11731
+ let ws;
11732
+ if (streamType === 'stock') {
11733
+ ws = this.stockWs;
11734
+ }
11735
+ else if (streamType === 'option') {
11736
+ ws = this.optionWs;
11737
+ }
11738
+ else {
11739
+ ws = this.cryptoWs;
11740
+ }
11662
11741
  if (ws && ws.readyState === WebSocket.OPEN) {
11663
11742
  ws.send(JSON.stringify(unsubMessage));
11664
11743
  }