@adaptic/utils 0.0.904 → 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.
Files changed (32) hide show
  1. package/dist/index.cjs +52 -35
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.mjs +52 -35
  4. package/dist/index.mjs.map +1 -1
  5. package/dist/test.js +38 -6
  6. package/dist/test.js.map +1 -1
  7. package/dist/types/adaptic.d.ts +4 -4
  8. package/dist/types/adaptic.d.ts.map +1 -1
  9. package/dist/types/alpaca/crypto/data.d.ts.map +1 -1
  10. package/dist/types/alpaca/crypto/orders.d.ts.map +1 -1
  11. package/dist/types/alpaca/index.d.ts.map +1 -1
  12. package/dist/types/alpaca/market-data/bars.d.ts.map +1 -1
  13. package/dist/types/alpaca/market-data/news.d.ts.map +1 -1
  14. package/dist/types/alpaca/market-data/quotes.d.ts.map +1 -1
  15. package/dist/types/alpaca/market-data/trades.d.ts.map +1 -1
  16. package/dist/types/alpaca/streams/crypto-stream.d.ts.map +1 -1
  17. package/dist/types/alpaca/streams/option-stream.d.ts.map +1 -1
  18. package/dist/types/alpaca/streams/stock-stream.d.ts.map +1 -1
  19. package/dist/types/alpaca/trading/account.d.ts.map +1 -1
  20. package/dist/types/alpaca/trading/oco-orders.d.ts.map +1 -1
  21. package/dist/types/alpaca/trading/order-utils.d.ts.map +1 -1
  22. package/dist/types/alpaca/trading/orders.d.ts.map +1 -1
  23. package/dist/types/alpaca/trading/oto-orders.d.ts.map +1 -1
  24. package/dist/types/alpaca/trading/trailing-stops.d.ts.map +1 -1
  25. package/dist/types/alpaca-market-data-api.d.ts +3 -0
  26. package/dist/types/alpaca-market-data-api.d.ts.map +1 -1
  27. package/dist/types/index.d.ts +2 -2
  28. package/dist/types/index.d.ts.map +1 -1
  29. package/dist/types/schemas/polygon-schemas.d.ts +6 -6
  30. package/dist/types/types/alpaca-types.d.ts +18 -1
  31. package/dist/types/types/alpaca-types.d.ts.map +1 -1
  32. package/package.json +2 -2
package/dist/index.mjs CHANGED
@@ -212,7 +212,7 @@ const isAuthConfigured = () => {
212
212
  * Returns a shared Apollo client instance with connection pooling.
213
213
  * This should be used for all @adaptic/backend-legacy operations.
214
214
  *
215
- * @returns {Promise<ApolloClientType>} The shared Apollo client instance.
215
+ * @returns {Promise<ApolloClientInstance>} The shared Apollo client instance.
216
216
  */
217
217
  const getSharedApolloClient = async () => {
218
218
  if (!apolloClientInstance) {
@@ -12357,6 +12357,8 @@ class AlpacaMarketDataAPI extends EventEmitter {
12357
12357
  quotes: [],
12358
12358
  bars: [],
12359
12359
  };
12360
+ reconnectAttempts = {};
12361
+ reconnectTimers = {};
12360
12362
  setMode(mode = "production") {
12361
12363
  if (mode === "sandbox") {
12362
12364
  // sandbox mode
@@ -12395,7 +12397,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
12395
12397
  // when env vars are not available. Features will be unavailable until
12396
12398
  // credentials are provided at runtime.
12397
12399
  const apiKey = process.env.ALPACA_API_KEY || "";
12398
- const apiSecret = process.env.ALPACA_SECRET_KEY || "";
12400
+ const apiSecret = process.env.ALPACA_API_SECRET || process.env.ALPACA_SECRET_KEY || "";
12399
12401
  this.credentialsValid = validateAlpacaCredentials({
12400
12402
  apiKey,
12401
12403
  apiSecret,
@@ -12437,6 +12439,12 @@ class AlpacaMarketDataAPI extends EventEmitter {
12437
12439
  else {
12438
12440
  url = this.cryptoStreamUrl;
12439
12441
  }
12442
+ const apiKey = process.env.ALPACA_API_KEY || "";
12443
+ const apiSecret = process.env.ALPACA_API_SECRET || process.env.ALPACA_SECRET_KEY || "";
12444
+ if (!apiKey || !apiSecret) {
12445
+ log$l(`Cannot connect ${streamType} stream: missing Alpaca credentials (ALPACA_API_KEY=${apiKey ? "set" : "MISSING"}, ALPACA_API_SECRET/ALPACA_SECRET_KEY=${apiSecret ? "set" : "MISSING"})`, { type: "error" });
12446
+ return;
12447
+ }
12440
12448
  const ws = new WebSocket(url);
12441
12449
  if (streamType === "stock") {
12442
12450
  this.stockWs = ws;
@@ -12451,8 +12459,8 @@ class AlpacaMarketDataAPI extends EventEmitter {
12451
12459
  log$l(`${streamType} stream connected`, { type: "info" });
12452
12460
  const authMessage = {
12453
12461
  action: "auth",
12454
- key: process.env.ALPACA_API_KEY,
12455
- secret: process.env.ALPACA_SECRET_KEY,
12462
+ key: apiKey,
12463
+ secret: apiSecret,
12456
12464
  };
12457
12465
  ws.send(JSON.stringify(authMessage));
12458
12466
  });
@@ -12469,6 +12477,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
12469
12477
  for (const message of messages) {
12470
12478
  if (message.T === "success" && message.msg === "authenticated") {
12471
12479
  log$l(`${streamType} stream authenticated`, { type: "info" });
12480
+ this.reconnectAttempts[streamType] = 0;
12472
12481
  this.sendSubscription(streamType);
12473
12482
  }
12474
12483
  else if (message.T === "success" && message.msg === "connected") {
@@ -12491,8 +12500,8 @@ class AlpacaMarketDataAPI extends EventEmitter {
12491
12500
  }
12492
12501
  }
12493
12502
  });
12494
- ws.on("close", () => {
12495
- log$l(`${streamType} stream disconnected`, { type: "warn" });
12503
+ ws.on("close", (code) => {
12504
+ log$l(`${streamType} stream disconnected (code: ${code})`, { type: "warn" });
12496
12505
  if (streamType === "stock") {
12497
12506
  this.stockWs = null;
12498
12507
  }
@@ -12502,12 +12511,35 @@ class AlpacaMarketDataAPI extends EventEmitter {
12502
12511
  else {
12503
12512
  this.cryptoWs = null;
12504
12513
  }
12505
- // Optional: implement reconnect logic
12514
+ // Reconnect with exponential backoff (unless intentionally closed with code 1000)
12515
+ if (code !== 1000) {
12516
+ this.scheduleReconnect(streamType);
12517
+ }
12506
12518
  });
12507
12519
  ws.on("error", (error) => {
12508
12520
  log$l(`${streamType} stream error: ${error.message}`, { type: "error" });
12509
12521
  });
12510
12522
  }
12523
+ scheduleReconnect(streamType) {
12524
+ const attempts = this.reconnectAttempts[streamType] ?? 0;
12525
+ const maxAttempts = 10;
12526
+ if (attempts >= maxAttempts) {
12527
+ log$l(`${streamType} stream: max reconnect attempts (${maxAttempts}) reached, giving up`, { type: "error" });
12528
+ return;
12529
+ }
12530
+ // Exponential backoff: 1s, 2s, 4s, 8s, 16s, 30s (capped)
12531
+ const delayMs = Math.min(1000 * Math.pow(2, attempts), 30000);
12532
+ this.reconnectAttempts[streamType] = attempts + 1;
12533
+ log$l(`${streamType} stream: scheduling reconnect attempt ${attempts + 1}/${maxAttempts} in ${delayMs}ms`, { type: "info" });
12534
+ // Clear any existing reconnect timer for this stream
12535
+ if (this.reconnectTimers[streamType]) {
12536
+ clearTimeout(this.reconnectTimers[streamType]);
12537
+ }
12538
+ this.reconnectTimers[streamType] = setTimeout(() => {
12539
+ log$l(`${streamType} stream: reconnecting (attempt ${attempts + 1}/${maxAttempts})`, { type: "info" });
12540
+ this.connect(streamType);
12541
+ }, delayMs);
12542
+ }
12511
12543
  sendSubscription(streamType) {
12512
12544
  let ws;
12513
12545
  let subscriptions;
@@ -53811,7 +53843,6 @@ async function getPortfolioHistory(client, params) {
53811
53843
  log$i(`Fetching portfolio history with period: ${params.period || "default"}, timeframe: ${params.timeframe || "default"}`);
53812
53844
  try {
53813
53845
  const sdk = client.getSDK();
53814
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
53815
53846
  const history = await sdk.getPortfolioHistory(params);
53816
53847
  log$i(`Portfolio history fetched successfully with ${history.equity?.length || 0} data points`);
53817
53848
  return history;
@@ -55551,7 +55582,6 @@ async function getOpenTrailingStops(client, symbol) {
55551
55582
  if (symbol) {
55552
55583
  queryParams.symbols = symbol.toUpperCase();
55553
55584
  }
55554
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
55555
55585
  const orders = (await sdk.getOrders(queryParams));
55556
55586
  // Filter to only trailing stop orders
55557
55587
  const trailingStops = orders.filter((order) => order.type === "trailing_stop");
@@ -55789,12 +55819,11 @@ async function createOCOOrder(client, params) {
55789
55819
  limit_price: roundPriceForAlpaca$2(takeProfit.limitPrice).toString(),
55790
55820
  stop_loss: {
55791
55821
  stop_price: roundPriceForAlpaca$2(stopLoss.stopPrice).toString(),
55822
+ ...(stopLoss.limitPrice !== undefined
55823
+ ? { limit_price: roundPriceForAlpaca$2(stopLoss.limitPrice).toString() }
55824
+ : {}),
55792
55825
  },
55793
55826
  };
55794
- // Add stop-limit price if provided
55795
- if (stopLoss.limitPrice !== undefined) {
55796
- orderRequest.stop_loss.limit_price = roundPriceForAlpaca$2(stopLoss.limitPrice).toString();
55797
- }
55798
55827
  log$f(`Submitting OCO order request: ${JSON.stringify(orderRequest)}`, {
55799
55828
  symbol,
55800
55829
  type: "debug",
@@ -56209,14 +56238,14 @@ async function createOTOOrder(client, params) {
56209
56238
  }
56210
56239
  else if (dependent.type === "trailing_stop") {
56211
56240
  // Trailing stop order
56212
- orderRequest.stop_loss = {};
56241
+ const trailingStop = {};
56213
56242
  if (dependent.trailPercent !== undefined) {
56214
- orderRequest.stop_loss.trail_percent =
56215
- dependent.trailPercent.toString();
56243
+ trailingStop.trail_percent = dependent.trailPercent.toString();
56216
56244
  }
56217
56245
  if (dependent.trailPrice !== undefined) {
56218
- orderRequest.stop_loss.trail_price = roundPriceForAlpaca$1(dependent.trailPrice).toString();
56246
+ trailingStop.trail_price = roundPriceForAlpaca$1(dependent.trailPrice).toString();
56219
56247
  }
56248
+ orderRequest.stop_loss = trailingStop;
56220
56249
  }
56221
56250
  log$e(`Submitting OTO order request: ${JSON.stringify(orderRequest)}`, {
56222
56251
  symbol,
@@ -56637,7 +56666,6 @@ async function getLatestQuote(client, symbol, feed) {
56637
56666
  const config = client.getConfig();
56638
56667
  const dataFeed = feed || config.dataFeed || "iex";
56639
56668
  // Use SDK's getLatestQuote method
56640
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
56641
56669
  const response = await sdk.getLatestQuote(normalizedSymbol, {
56642
56670
  feed: dataFeed,
56643
56671
  });
@@ -56695,7 +56723,6 @@ async function getLatestQuotes(client, symbols, feed) {
56695
56723
  const config = client.getConfig();
56696
56724
  const dataFeed = feed || config.dataFeed || "iex";
56697
56725
  // Use SDK's getLatestQuotes method
56698
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
56699
56726
  const response = await sdk.getLatestQuotes(normalizedSymbols, {
56700
56727
  feed: dataFeed,
56701
56728
  });
@@ -56951,7 +56978,6 @@ async function getLatestBars(client, symbols) {
56951
56978
  const sdk = client.getSDK();
56952
56979
  const config = client.getConfig();
56953
56980
  const dataFeed = config.dataFeed || "iex";
56954
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
56955
56981
  const response = await sdk.getLatestBars(normalizedSymbols, {
56956
56982
  feed: dataFeed,
56957
56983
  });
@@ -57242,7 +57268,6 @@ async function getLatestTrade(client, symbol, feed) {
57242
57268
  const config = client.getConfig();
57243
57269
  const dataFeed = feed || config.dataFeed || "iex";
57244
57270
  // Use SDK's getLatestTrade method
57245
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
57246
57271
  const response = await sdk.getLatestTrade(normalizedSymbol, {
57247
57272
  feed: dataFeed,
57248
57273
  });
@@ -57298,7 +57323,6 @@ async function getLatestTrades(client, symbols, feed) {
57298
57323
  const config = client.getConfig();
57299
57324
  const dataFeed = feed || config.dataFeed || "iex";
57300
57325
  // Use SDK's getLatestTrades method
57301
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
57302
57326
  const response = await sdk.getLatestTrades(normalizedSymbols, {
57303
57327
  feed: dataFeed,
57304
57328
  });
@@ -57413,7 +57437,6 @@ async function getCurrentPrice(client, symbol, feed) {
57413
57437
  const dataFeed = feed || config.dataFeed || "iex";
57414
57438
  // Try to get quote first for mid-point price
57415
57439
  try {
57416
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
57417
57440
  const quote = await sdk.getLatestQuote(normalizedSymbol, {
57418
57441
  feed: dataFeed,
57419
57442
  });
@@ -57848,7 +57871,6 @@ async function getNews(client, params = {}) {
57848
57871
  // The SDK returns a slightly different structure, so we map the fields
57849
57872
  const articles = response.map((article) => {
57850
57873
  // SDK returns properties in different format
57851
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
57852
57874
  const sdkArticle = article;
57853
57875
  // Normalize to our expected format
57854
57876
  const normalizedArticle = {
@@ -61514,7 +61536,6 @@ async function getOpenCryptoOrders(client, symbols) {
61514
61536
  ? symbols.map(normalizeCryptoSymbol$1).join(",")
61515
61537
  : undefined,
61516
61538
  };
61517
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
61518
61539
  const orders = (await sdk.getOrders(queryParams));
61519
61540
  // Filter to only crypto orders (asset_class === 'crypto')
61520
61541
  const cryptoOrders = orders.filter((order) => order.asset_class === "crypto");
@@ -61716,9 +61737,7 @@ async function getCryptoBars(client, params) {
61716
61737
  result.set(symbol, []);
61717
61738
  }
61718
61739
  // Use SDK's getCryptoBars method
61719
- // The SDK may return an async iterator or a Promise depending on the version;
61720
- // cast to any so TypeScript does not constrain the runtime duck-typing below.
61721
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
61740
+ // The SDK may return an async iterator or a Promise depending on the version
61722
61741
  const barsResponse = sdk.getCryptoBars(normalizedSymbols, options);
61723
61742
  // Handle both async iterator and direct response formats
61724
61743
  if (barsResponse &&
@@ -61739,8 +61758,8 @@ async function getCryptoBars(client, params) {
61739
61758
  result.set(symbol, existingBars);
61740
61759
  }
61741
61760
  }
61742
- else if (barsResponse && barsResponse.then) {
61743
- // Handle Promise response
61761
+ else if (barsResponse && "then" in barsResponse) {
61762
+ // Handle Promise response (SDK returns thenable in some versions)
61744
61763
  const response = await barsResponse;
61745
61764
  if (response && response.bars) {
61746
61765
  for (const [symbol, bars] of Object.entries(response.bars)) {
@@ -62054,9 +62073,7 @@ async function getCryptoTrades(client, symbol, start, end, limit) {
62054
62073
  options.limit = limit;
62055
62074
  }
62056
62075
  const trades = [];
62057
- // The SDK may return an async iterator or a Promise depending on the version;
62058
- // cast to any so TypeScript does not constrain the runtime duck-typing below.
62059
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
62076
+ // The SDK may return an async iterator or a Promise depending on the version
62060
62077
  const tradesResponse = sdk.getCryptoTrades(normalizedSymbol, options);
62061
62078
  // Handle both async iterator and direct response formats
62062
62079
  if (tradesResponse &&
@@ -62075,8 +62092,8 @@ async function getCryptoTrades(client, symbol, start, end, limit) {
62075
62092
  }
62076
62093
  }
62077
62094
  }
62078
- else if (tradesResponse && tradesResponse.then) {
62079
- // Handle Promise response
62095
+ else if (tradesResponse && "then" in tradesResponse) {
62096
+ // Handle Promise response (SDK returns thenable in some versions)
62080
62097
  const response = await tradesResponse;
62081
62098
  if (response && response.trades) {
62082
62099
  const tradeArray = response.trades;