@adaptic/utils 0.0.905 → 0.0.907

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.cjs CHANGED
@@ -1317,7 +1317,7 @@ async function fetchWithRetry(url, options = {}, retries = 3, initialBackoff = 1
1317
1317
  */
1318
1318
  async function validatePolygonApiKey(apiKey) {
1319
1319
  try {
1320
- const response = await fetch(`https://api.polygon.io/v1/meta/symbols?apikey=${apiKey}&limit=1`);
1320
+ const response = await fetch(`https://api.massive.com/v1/meta/symbols?apikey=${apiKey}&limit=1`);
1321
1321
  if (response.status === 401) {
1322
1322
  throw new Error("Invalid or expired Polygon.io API key");
1323
1323
  }
@@ -5189,7 +5189,7 @@ const fetchTickerInfo = async (symbol, options) => {
5189
5189
  }
5190
5190
  const apiKey = options?.apiKey || POLYGON_API_KEY;
5191
5191
  validatePolygonApiKey$1(apiKey);
5192
- const baseUrl = `https://api.polygon.io/v3/reference/tickers/${encodeURIComponent(symbol)}`;
5192
+ const baseUrl = `https://api.massive.com/v3/reference/tickers/${encodeURIComponent(symbol)}`;
5193
5193
  const params = new URLSearchParams({
5194
5194
  apiKey,
5195
5195
  });
@@ -5276,7 +5276,7 @@ const fetchLastTrade = async (symbol, options) => {
5276
5276
  }
5277
5277
  const apiKey = options?.apiKey || POLYGON_API_KEY;
5278
5278
  validatePolygonApiKey$1(apiKey);
5279
- const baseUrl = `https://api.polygon.io/v2/last/trade/${encodeURIComponent(symbol)}`;
5279
+ const baseUrl = `https://api.massive.com/v2/last/trade/${encodeURIComponent(symbol)}`;
5280
5280
  const params = new URLSearchParams({
5281
5281
  apiKey,
5282
5282
  });
@@ -5341,7 +5341,7 @@ const fetchPrices = async (params, options) => {
5341
5341
  const apiKey = options?.apiKey || POLYGON_API_KEY;
5342
5342
  validatePolygonApiKey$1(apiKey);
5343
5343
  const { ticker, start, end = Date.now().valueOf(), multiplier, timespan, limit = 1000, } = params;
5344
- const baseUrl = `https://api.polygon.io/v2/aggs/ticker/${encodeURIComponent(ticker)}/range/${multiplier}/${timespan}/${start}/${end}`;
5344
+ const baseUrl = `https://api.massive.com/v2/aggs/ticker/${encodeURIComponent(ticker)}/range/${multiplier}/${timespan}/${start}/${end}`;
5345
5345
  const urlParams = new URLSearchParams({
5346
5346
  apiKey,
5347
5347
  adjusted: "true",
@@ -5463,7 +5463,7 @@ const fetchGroupedDaily = async (date, options) => {
5463
5463
  if (!options?.apiKey && !POLYGON_API_KEY) {
5464
5464
  throw new Error("Polygon API key is missing");
5465
5465
  }
5466
- const baseUrl = `https://api.polygon.io/v2/aggs/grouped/locale/us/market/stocks/${date}`;
5466
+ const baseUrl = `https://api.massive.com/v2/aggs/grouped/locale/us/market/stocks/${date}`;
5467
5467
  const params = new URLSearchParams({
5468
5468
  apiKey: options?.apiKey || POLYGON_API_KEY,
5469
5469
  adjusted: options?.adjusted !== false ? "true" : "false",
@@ -5556,7 +5556,7 @@ symbol, date = new Date(), options) => {
5556
5556
  throw new Error("Polygon API key is missing");
5557
5557
  }
5558
5558
  const formattedDate = date.toISOString().split("T")[0]; // Format as YYYY-MM-DD
5559
- const baseUrl = `https://api.polygon.io/v1/open-close/${encodeURIComponent(symbol)}/${formattedDate}`;
5559
+ const baseUrl = `https://api.massive.com/v1/open-close/${encodeURIComponent(symbol)}/${formattedDate}`;
5560
5560
  const params = new URLSearchParams({
5561
5561
  apiKey: options?.apiKey || POLYGON_API_KEY,
5562
5562
  adjusted: (options?.adjusted ?? true).toString(),
@@ -5606,7 +5606,7 @@ const fetchTrades = async (symbol, options) => {
5606
5606
  if (!options?.apiKey && !POLYGON_API_KEY) {
5607
5607
  throw new Error("Polygon API key is missing");
5608
5608
  }
5609
- const baseUrl = `https://api.polygon.io/v3/trades/${encodeURIComponent(symbol)}`;
5609
+ const baseUrl = `https://api.massive.com/v3/trades/${encodeURIComponent(symbol)}`;
5610
5610
  const params = new URLSearchParams({
5611
5611
  apiKey: options?.apiKey || POLYGON_API_KEY,
5612
5612
  });
@@ -5672,7 +5672,7 @@ const { ALPACA_INDICES_API_KEY } = process.env;
5672
5672
  const POLYGON_INDICES_CONCURRENCY_LIMIT = 5;
5673
5673
  const polygonIndicesLimit = pLimit(POLYGON_INDICES_CONCURRENCY_LIMIT);
5674
5674
  // Base URL for Polygon API
5675
- const POLYGON_API_BASE_URL = "https://api.polygon.io";
5675
+ const POLYGON_API_BASE_URL = "https://api.massive.com";
5676
5676
  /**
5677
5677
  * Validates that an API key is available
5678
5678
  * @param {string | undefined} apiKey - Optional API key to use
@@ -12359,6 +12359,8 @@ class AlpacaMarketDataAPI extends require$$0$4.EventEmitter {
12359
12359
  quotes: [],
12360
12360
  bars: [],
12361
12361
  };
12362
+ reconnectAttempts = {};
12363
+ reconnectTimers = {};
12362
12364
  setMode(mode = "production") {
12363
12365
  if (mode === "sandbox") {
12364
12366
  // sandbox mode
@@ -12397,7 +12399,7 @@ class AlpacaMarketDataAPI extends require$$0$4.EventEmitter {
12397
12399
  // when env vars are not available. Features will be unavailable until
12398
12400
  // credentials are provided at runtime.
12399
12401
  const apiKey = process.env.ALPACA_API_KEY || "";
12400
- const apiSecret = process.env.ALPACA_SECRET_KEY || "";
12402
+ const apiSecret = process.env.ALPACA_API_SECRET || process.env.ALPACA_SECRET_KEY || "";
12401
12403
  this.credentialsValid = validateAlpacaCredentials({
12402
12404
  apiKey,
12403
12405
  apiSecret,
@@ -12439,6 +12441,12 @@ class AlpacaMarketDataAPI extends require$$0$4.EventEmitter {
12439
12441
  else {
12440
12442
  url = this.cryptoStreamUrl;
12441
12443
  }
12444
+ const apiKey = process.env.ALPACA_API_KEY || "";
12445
+ const apiSecret = process.env.ALPACA_API_SECRET || process.env.ALPACA_SECRET_KEY || "";
12446
+ if (!apiKey || !apiSecret) {
12447
+ 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" });
12448
+ return;
12449
+ }
12442
12450
  const ws = new WebSocket(url);
12443
12451
  if (streamType === "stock") {
12444
12452
  this.stockWs = ws;
@@ -12453,8 +12461,8 @@ class AlpacaMarketDataAPI extends require$$0$4.EventEmitter {
12453
12461
  log$l(`${streamType} stream connected`, { type: "info" });
12454
12462
  const authMessage = {
12455
12463
  action: "auth",
12456
- key: process.env.ALPACA_API_KEY,
12457
- secret: process.env.ALPACA_SECRET_KEY,
12464
+ key: apiKey,
12465
+ secret: apiSecret,
12458
12466
  };
12459
12467
  ws.send(JSON.stringify(authMessage));
12460
12468
  });
@@ -12471,6 +12479,7 @@ class AlpacaMarketDataAPI extends require$$0$4.EventEmitter {
12471
12479
  for (const message of messages) {
12472
12480
  if (message.T === "success" && message.msg === "authenticated") {
12473
12481
  log$l(`${streamType} stream authenticated`, { type: "info" });
12482
+ this.reconnectAttempts[streamType] = 0;
12474
12483
  this.sendSubscription(streamType);
12475
12484
  }
12476
12485
  else if (message.T === "success" && message.msg === "connected") {
@@ -12493,8 +12502,8 @@ class AlpacaMarketDataAPI extends require$$0$4.EventEmitter {
12493
12502
  }
12494
12503
  }
12495
12504
  });
12496
- ws.on("close", () => {
12497
- log$l(`${streamType} stream disconnected`, { type: "warn" });
12505
+ ws.on("close", (code) => {
12506
+ log$l(`${streamType} stream disconnected (code: ${code})`, { type: "warn" });
12498
12507
  if (streamType === "stock") {
12499
12508
  this.stockWs = null;
12500
12509
  }
@@ -12504,12 +12513,35 @@ class AlpacaMarketDataAPI extends require$$0$4.EventEmitter {
12504
12513
  else {
12505
12514
  this.cryptoWs = null;
12506
12515
  }
12507
- // Optional: implement reconnect logic
12516
+ // Reconnect with exponential backoff (unless intentionally closed with code 1000)
12517
+ if (code !== 1000) {
12518
+ this.scheduleReconnect(streamType);
12519
+ }
12508
12520
  });
12509
12521
  ws.on("error", (error) => {
12510
12522
  log$l(`${streamType} stream error: ${error.message}`, { type: "error" });
12511
12523
  });
12512
12524
  }
12525
+ scheduleReconnect(streamType) {
12526
+ const attempts = this.reconnectAttempts[streamType] ?? 0;
12527
+ const maxAttempts = 10;
12528
+ if (attempts >= maxAttempts) {
12529
+ log$l(`${streamType} stream: max reconnect attempts (${maxAttempts}) reached, giving up`, { type: "error" });
12530
+ return;
12531
+ }
12532
+ // Exponential backoff: 1s, 2s, 4s, 8s, 16s, 30s (capped)
12533
+ const delayMs = Math.min(1000 * Math.pow(2, attempts), 30000);
12534
+ this.reconnectAttempts[streamType] = attempts + 1;
12535
+ log$l(`${streamType} stream: scheduling reconnect attempt ${attempts + 1}/${maxAttempts} in ${delayMs}ms`, { type: "info" });
12536
+ // Clear any existing reconnect timer for this stream
12537
+ if (this.reconnectTimers[streamType]) {
12538
+ clearTimeout(this.reconnectTimers[streamType]);
12539
+ }
12540
+ this.reconnectTimers[streamType] = setTimeout(() => {
12541
+ log$l(`${streamType} stream: reconnecting (attempt ${attempts + 1}/${maxAttempts})`, { type: "info" });
12542
+ this.connect(streamType);
12543
+ }, delayMs);
12544
+ }
12513
12545
  sendSubscription(streamType) {
12514
12546
  let ws;
12515
12547
  let subscriptions;
@@ -15204,7 +15236,7 @@ const rateLimiters = {
15204
15236
  *
15205
15237
  * Configured for 5 requests per second (basic plan).
15206
15238
  * Adjust if you have a different subscription tier.
15207
- * See: https://polygon.io/pricing
15239
+ * See: https://massive.com/pricing
15208
15240
  */
15209
15241
  polygon: new TokenBucketRateLimiter({
15210
15242
  maxTokens: 5,