@adaptic/utils 0.0.960 → 0.0.962

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
@@ -309,6 +309,22 @@ const fetchAssetOverview = async (symbol) => {
309
309
  };
310
310
  }
311
311
  };
312
+ /**
313
+ * Gracefully disconnects the shared Apollo client and releases its resources.
314
+ * Call this during process shutdown to close keep-alive HTTP connections
315
+ * and drain in-flight operations.
316
+ *
317
+ * After calling `disconnectClient()`, the next call to `getSharedApolloClient()`
318
+ * will create a fresh instance.
319
+ */
320
+ const disconnectClient = () => {
321
+ if (apolloClientInstance) {
322
+ apolloClientInstance = null;
323
+ getLogger().info("[adaptic] Shared Apollo client reference cleared");
324
+ }
325
+ // Delegate to backend-legacy's stopClient() which calls .stop() on the underlying singleton
326
+ adaptic$1.stopClient();
327
+ };
312
328
 
313
329
  const ANSI_BACKGROUND_OFFSET = 10;
314
330
 
@@ -8002,8 +8018,9 @@ const fetchTickerInfo = async (symbol, options) => {
8002
8018
  apiKey,
8003
8019
  });
8004
8020
  return massiveLimit(async () => {
8021
+ await rateLimiters.massive.acquire();
8005
8022
  try {
8006
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8023
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8007
8024
  const data = await response.json();
8008
8025
  // Check for "NOT_FOUND" status and return null
8009
8026
  if (data.status === "NOT_FOUND") {
@@ -8114,8 +8131,9 @@ const fetchLastTradeImpl = async (symbol, options) => {
8114
8131
  order: "desc",
8115
8132
  });
8116
8133
  return massiveLimit(async () => {
8134
+ await rateLimiters.massive.acquire();
8117
8135
  try {
8118
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8136
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8119
8137
  const data = (await response.json());
8120
8138
  if ("message" in data) {
8121
8139
  throw new Error(`Massive.com API error: ${data.message}`);
@@ -8184,8 +8202,9 @@ const fetchLastQuote = async (symbol, options) => {
8184
8202
  order: "desc",
8185
8203
  });
8186
8204
  return massiveLimit(async () => {
8205
+ await rateLimiters.massive.acquire();
8187
8206
  try {
8188
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8207
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8189
8208
  const data = (await response.json());
8190
8209
  if ("message" in data) {
8191
8210
  throw new Error(`Massive.com API error: ${data.message}`);
@@ -8268,7 +8287,7 @@ const fetchPrices = async (params, options) => {
8268
8287
  while (nextUrl) {
8269
8288
  //getLogger().info(`Debug: Fetching ${nextUrl}`);
8270
8289
  await rateLimiters.massive.acquire();
8271
- const response = await fetchWithRetry(nextUrl, {}, 3, 1000);
8290
+ const response = await fetchWithRetry(nextUrl, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8272
8291
  const data = await response.json();
8273
8292
  if (!MASSIVE_VALID_STATUSES.has(data.status)) {
8274
8293
  throw new Error(`Massive.com API responded with status: ${data.status}`);
@@ -8389,8 +8408,9 @@ const fetchGroupedDaily = async (date, options) => {
8389
8408
  include_otc: options?.includeOTC ? "true" : "false",
8390
8409
  });
8391
8410
  return massiveLimit(async () => {
8411
+ await rateLimiters.massive.acquire();
8392
8412
  try {
8393
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8413
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8394
8414
  const data = await response.json();
8395
8415
  if (!MASSIVE_VALID_STATUSES.has(data.status)) {
8396
8416
  throw new Error(`Massive.com API responded with status: ${data.status}`);
@@ -8482,12 +8502,20 @@ symbol, date = new Date(), options) => {
8482
8502
  adjusted: (options?.adjusted ?? true).toString(),
8483
8503
  });
8484
8504
  return massiveLimit(async () => {
8485
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8486
- const data = await response.json();
8487
- if (!MASSIVE_VALID_STATUSES.has(data.status)) {
8488
- throw new Error(`Failed to fetch daily open/close data for ${symbol}: ${data.status}`);
8505
+ await rateLimiters.massive.acquire();
8506
+ try {
8507
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8508
+ const data = await response.json();
8509
+ if (!MASSIVE_VALID_STATUSES.has(data.status)) {
8510
+ throw new Error(`Failed to fetch daily open/close data for ${symbol}: ${data.status}`);
8511
+ }
8512
+ return data;
8513
+ }
8514
+ catch (error) {
8515
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
8516
+ getLogger().error(`Error fetching daily open/close for ${symbol}: ${errorMessage}`);
8517
+ throw error;
8489
8518
  }
8490
- return data;
8491
8519
  });
8492
8520
  };
8493
8521
  /**
@@ -8548,10 +8576,11 @@ const fetchTrades = async (symbol, options) => {
8548
8576
  if (options?.sort)
8549
8577
  params.append("sort", options.sort);
8550
8578
  return massiveLimit(async () => {
8579
+ await rateLimiters.massive.acquire();
8551
8580
  const url = `${baseUrl}?${params.toString()}`;
8552
8581
  try {
8553
8582
  logIfDebug(`Fetching trades for ${symbol} from ${url}`);
8554
- const response = await fetchWithRetry(url, {}, 3, 1000);
8583
+ const response = await fetchWithRetry(url, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8555
8584
  const data = (await response.json());
8556
8585
  if ("message" in data) {
8557
8586
  // This is an error response
@@ -8627,8 +8656,9 @@ const fetchIndicesAggregates = async (params, options) => {
8627
8656
  }
8628
8657
  url.search = queryParams.toString();
8629
8658
  return massiveIndicesLimit(async () => {
8659
+ await rateLimiters.massive.acquire();
8630
8660
  try {
8631
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8661
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8632
8662
  const data = await response.json();
8633
8663
  if (data.status === "ERROR") {
8634
8664
  throw new Error(`Massive API Error: ${data.error}`);
@@ -8656,8 +8686,9 @@ const fetchIndicesPreviousClose = async (indicesTicker, options) => {
8656
8686
  queryParams.append("apiKey", apiKey);
8657
8687
  url.search = queryParams.toString();
8658
8688
  return massiveIndicesLimit(async () => {
8689
+ await rateLimiters.massive.acquire();
8659
8690
  try {
8660
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8691
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8661
8692
  const data = await response.json();
8662
8693
  if (data.status === "ERROR") {
8663
8694
  throw new Error(`Massive API Error: ${data.error}`);
@@ -8686,8 +8717,9 @@ const fetchIndicesDailyOpenClose = async (indicesTicker, date, options) => {
8686
8717
  queryParams.append("apiKey", apiKey);
8687
8718
  url.search = queryParams.toString();
8688
8719
  return massiveIndicesLimit(async () => {
8720
+ await rateLimiters.massive.acquire();
8689
8721
  try {
8690
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8722
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8691
8723
  const data = await response.json();
8692
8724
  if (data.status === "ERROR") {
8693
8725
  throw new Error(`Massive API Error: ${data.error}`);
@@ -8727,8 +8759,9 @@ const fetchIndicesSnapshot = async (params, options) => {
8727
8759
  }
8728
8760
  url.search = queryParams.toString();
8729
8761
  return massiveIndicesLimit(async () => {
8762
+ await rateLimiters.massive.acquire();
8730
8763
  try {
8731
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8764
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8732
8765
  const data = await response.json();
8733
8766
  if (data.status === "ERROR") {
8734
8767
  throw new Error(`Massive API Error: ${data.error}`);
@@ -8775,8 +8808,9 @@ const fetchUniversalSnapshot = async (tickers, options) => {
8775
8808
  }
8776
8809
  url.search = queryParams.toString();
8777
8810
  return massiveIndicesLimit(async () => {
8811
+ await rateLimiters.massive.acquire();
8778
8812
  try {
8779
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8813
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8780
8814
  const data = await response.json();
8781
8815
  if (data.status === "ERROR") {
8782
8816
  throw new Error(`Massive API Error: ${data.error}`);
@@ -8840,10 +8874,11 @@ const calculateFees = async (action, trade, alpacaAccount) => {
8840
8874
  };
8841
8875
  const computeTotalFees = async (trade) => {
8842
8876
  let totalFees = 0;
8843
- // fetch alpaca account details using adaptic.alpacaAccount.get({id: trade.alpacaAccountId})
8877
+ // Use the shared singleton Apollo client to avoid creating orphaned connections
8878
+ const client = await getSharedApolloClient();
8844
8879
  const alpacaAccount = (await adaptic$1.alpacaAccount.get({
8845
8880
  id: trade.alpacaAccountId,
8846
- }));
8881
+ }, client));
8847
8882
  if (!alpacaAccount)
8848
8883
  return totalFees;
8849
8884
  const feePromises = trade?.actions?.map((action) => calculateFees(action, trade, alpacaAccount));
@@ -48964,6 +48999,25 @@ class AlpacaClient {
48964
48999
  isPaper() {
48965
49000
  return this.config.accountType === "PAPER";
48966
49001
  }
49002
+ /**
49003
+ * Execute an Alpaca SDK operation with rate limiting and retry.
49004
+ * Use this for all SDK calls to prevent rate limit breaches and handle
49005
+ * transient failures during market hours.
49006
+ *
49007
+ * @param operation - Async function that calls the SDK
49008
+ * @param label - Human-readable label for logging
49009
+ * @returns Result of the operation
49010
+ */
49011
+ async executeWithRateLimit(operation, label) {
49012
+ await rateLimiters.alpaca.acquire();
49013
+ return withRetry(operation, {
49014
+ maxRetries: 2,
49015
+ baseDelayMs: 1000,
49016
+ maxDelayMs: 10000,
49017
+ retryableStatusCodes: [429, 500, 502, 503, 504],
49018
+ retryOnNetworkError: true,
49019
+ }, `Alpaca SDK: ${label}`);
49020
+ }
48967
49021
  /**
48968
49022
  * Validate credentials by fetching account info
48969
49023
  */
@@ -49014,6 +49068,7 @@ class AlpacaClient {
49014
49068
  * @returns Response data
49015
49069
  */
49016
49070
  async makeRequest(endpoint, method = "GET", body) {
49071
+ await rateLimiters.alpaca.acquire();
49017
49072
  const url = `${this.apiBaseUrl}${endpoint}`;
49018
49073
  const options = {
49019
49074
  method,
@@ -49022,14 +49077,26 @@ class AlpacaClient {
49022
49077
  if (body && (method === "POST" || method === "PUT")) {
49023
49078
  options.body = JSON.stringify(body);
49024
49079
  }
49025
- try {
49080
+ return withRetry(async () => {
49026
49081
  const response = await fetch(url, {
49027
49082
  ...options,
49028
49083
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
49029
49084
  });
49030
49085
  if (!response.ok) {
49031
49086
  const errorText = await response.text();
49032
- throw new Error(`API request failed (${response.status}): ${errorText}`);
49087
+ const statusCode = response.status;
49088
+ // Classify error for retry logic
49089
+ if (statusCode === 429) {
49090
+ const retryAfter = response.headers.get("Retry-After");
49091
+ throw new Error(`RATE_LIMIT: ${statusCode}${retryAfter ? `:${parseInt(retryAfter, 10) * 1000}` : ""}`);
49092
+ }
49093
+ if ([500, 502, 503, 504].includes(statusCode)) {
49094
+ throw new Error(`SERVER_ERROR: ${statusCode}`);
49095
+ }
49096
+ if ([401, 403].includes(statusCode)) {
49097
+ throw new Error(`AUTH_ERROR: ${statusCode}: ${errorText}`);
49098
+ }
49099
+ throw new Error(`CLIENT_ERROR: ${statusCode}: ${errorText}`);
49033
49100
  }
49034
49101
  // Handle empty responses (e.g., DELETE requests)
49035
49102
  const contentType = response.headers.get("content-type");
@@ -49038,14 +49105,13 @@ class AlpacaClient {
49038
49105
  return emptyObj;
49039
49106
  }
49040
49107
  return (await response.json());
49041
- }
49042
- catch (error) {
49043
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
49044
- log$k(`API request to ${endpoint} failed: ${errorMessage}`, {
49045
- type: "error",
49046
- });
49047
- throw error;
49048
- }
49108
+ }, {
49109
+ maxRetries: 2,
49110
+ baseDelayMs: 1000,
49111
+ maxDelayMs: 10000,
49112
+ retryableStatusCodes: [429, 500, 502, 503, 504],
49113
+ retryOnNetworkError: true,
49114
+ }, `Alpaca ${method} ${endpoint}`);
49049
49115
  }
49050
49116
  }
49051
49117
  // Client cache for connection pooling
@@ -49382,7 +49448,7 @@ async function getAccountDetails(client) {
49382
49448
  log$i("Fetching account details");
49383
49449
  try {
49384
49450
  const sdk = client.getSDK();
49385
- const account = await sdk.getAccount();
49451
+ const account = await client.executeWithRateLimit(() => sdk.getAccount(), "getAccount");
49386
49452
  log$i(`Account details fetched successfully for account ${account.account_number}`);
49387
49453
  return account;
49388
49454
  }
@@ -49401,7 +49467,7 @@ async function getAccountConfiguration(client) {
49401
49467
  log$i("Fetching account configuration");
49402
49468
  try {
49403
49469
  const sdk = client.getSDK();
49404
- const config = await sdk.getAccountConfigurations();
49470
+ const config = await client.executeWithRateLimit(() => sdk.getAccountConfigurations(), "getAccountConfigurations");
49405
49471
  log$i("Account configuration fetched successfully");
49406
49472
  return config;
49407
49473
  }
@@ -49423,7 +49489,7 @@ async function updateAccountConfiguration(client, config) {
49423
49489
  log$i("Updating account configuration");
49424
49490
  try {
49425
49491
  const sdk = client.getSDK();
49426
- const updatedConfig = await sdk.updateAccountConfigurations(config);
49492
+ const updatedConfig = await client.executeWithRateLimit(() => sdk.updateAccountConfigurations(config), "updateAccountConfigurations");
49427
49493
  log$i("Account configuration updated successfully");
49428
49494
  return updatedConfig;
49429
49495
  }
@@ -49445,7 +49511,7 @@ async function getPortfolioHistory(client, params) {
49445
49511
  log$i(`Fetching portfolio history with period: ${params.period || "default"}, timeframe: ${params.timeframe || "default"}`);
49446
49512
  try {
49447
49513
  const sdk = client.getSDK();
49448
- const history = await sdk.getPortfolioHistory(params);
49514
+ const history = await client.executeWithRateLimit(() => sdk.getPortfolioHistory(params), "getPortfolioHistory");
49449
49515
  log$i(`Portfolio history fetched successfully with ${history.equity?.length || 0} data points`);
49450
49516
  return history;
49451
49517
  }
@@ -52161,7 +52227,7 @@ async function getAlpacaClock(client) {
52161
52227
  log$d("Fetching market clock");
52162
52228
  try {
52163
52229
  const sdk = client.getSDK();
52164
- const clock = await sdk.getClock();
52230
+ const clock = await client.executeWithRateLimit(() => sdk.getClock(), "getClock");
52165
52231
  log$d(`Market clock fetched: is_open=${clock.is_open}, next_open=${clock.next_open}`);
52166
52232
  return clock;
52167
52233
  }
@@ -52206,10 +52272,10 @@ async function getAlpacaCalendar(client, options) {
52206
52272
  log$d(`Fetching market calendar${startStr ? ` from ${startStr}` : ""}${endStr ? ` to ${endStr}` : ""}`);
52207
52273
  try {
52208
52274
  const sdk = client.getSDK();
52209
- const calendar = await sdk.getCalendar({
52275
+ const calendar = await client.executeWithRateLimit(() => sdk.getCalendar({
52210
52276
  start: startStr,
52211
52277
  end: endStr,
52212
- });
52278
+ }), "getCalendar");
52213
52279
  log$d(`Market calendar fetched: ${calendar.length} trading days`);
52214
52280
  return calendar;
52215
52281
  }
@@ -52268,9 +52334,9 @@ async function getLatestQuote(client, symbol, feed) {
52268
52334
  const config = client.getConfig();
52269
52335
  const dataFeed = feed || config.dataFeed || "iex";
52270
52336
  // Use SDK's getLatestQuote method
52271
- const response = await sdk.getLatestQuote(normalizedSymbol, {
52337
+ const response = await client.executeWithRateLimit(() => sdk.getLatestQuote(normalizedSymbol, {
52272
52338
  feed: dataFeed,
52273
- });
52339
+ }), "getLatestQuote");
52274
52340
  if (!response) {
52275
52341
  throw new QuoteError(`No quote data returned for ${normalizedSymbol}`, "NO_DATA", normalizedSymbol);
52276
52342
  }
@@ -52325,9 +52391,9 @@ async function getLatestQuotes(client, symbols, feed) {
52325
52391
  const config = client.getConfig();
52326
52392
  const dataFeed = feed || config.dataFeed || "iex";
52327
52393
  // Use SDK's getLatestQuotes method
52328
- const response = await sdk.getLatestQuotes(normalizedSymbols, {
52394
+ const response = await client.executeWithRateLimit(() => sdk.getLatestQuotes(normalizedSymbols, {
52329
52395
  feed: dataFeed,
52330
- });
52396
+ }), "getLatestQuotes");
52331
52397
  if (!response) {
52332
52398
  throw new QuoteError("No quote data returned", "NO_DATA");
52333
52399
  }
@@ -52530,7 +52596,8 @@ async function getBars(client, params) {
52530
52596
  for (const symbol of normalizedSymbols) {
52531
52597
  result.set(symbol, []);
52532
52598
  }
52533
- // Fetch bars - the SDK handles pagination internally via async iterator
52599
+ // Acquire rate limit token before starting the async iterator
52600
+ await client.executeWithRateLimit(() => Promise.resolve(), "getBarsV2");
52534
52601
  const barsIterator = sdk.getBarsV2(normalizedSymbols.join(","), options);
52535
52602
  for await (const bar of barsIterator) {
52536
52603
  const symbol = bar.Symbol;
@@ -52580,9 +52647,9 @@ async function getLatestBars(client, symbols) {
52580
52647
  const sdk = client.getSDK();
52581
52648
  const config = client.getConfig();
52582
52649
  const dataFeed = config.dataFeed || "iex";
52583
- const response = await sdk.getLatestBars(normalizedSymbols, {
52650
+ const response = await client.executeWithRateLimit(() => sdk.getLatestBars(normalizedSymbols, {
52584
52651
  feed: dataFeed,
52585
- });
52652
+ }), "getLatestBars");
52586
52653
  const result = new Map();
52587
52654
  for (const [symbol, bar] of Object.entries(response)) {
52588
52655
  const b = bar;
@@ -52870,9 +52937,9 @@ async function getLatestTrade(client, symbol, feed) {
52870
52937
  const config = client.getConfig();
52871
52938
  const dataFeed = feed || config.dataFeed || "iex";
52872
52939
  // Use SDK's getLatestTrade method
52873
- const response = await sdk.getLatestTrade(normalizedSymbol, {
52940
+ const response = await client.executeWithRateLimit(() => sdk.getLatestTrade(normalizedSymbol, {
52874
52941
  feed: dataFeed,
52875
- });
52942
+ }), "getLatestTrade");
52876
52943
  if (!response) {
52877
52944
  throw new TradeError(`No trade data returned for ${normalizedSymbol}`, "NO_DATA", normalizedSymbol);
52878
52945
  }
@@ -52925,9 +52992,9 @@ async function getLatestTrades(client, symbols, feed) {
52925
52992
  const config = client.getConfig();
52926
52993
  const dataFeed = feed || config.dataFeed || "iex";
52927
52994
  // Use SDK's getLatestTrades method
52928
- const response = await sdk.getLatestTrades(normalizedSymbols, {
52995
+ const response = await client.executeWithRateLimit(() => sdk.getLatestTrades(normalizedSymbols, {
52929
52996
  feed: dataFeed,
52930
- });
52997
+ }), "getLatestTrades");
52931
52998
  if (!response) {
52932
52999
  throw new TradeError("No trade data returned", "NO_DATA");
52933
53000
  }
@@ -52989,7 +53056,8 @@ async function getHistoricalTrades(client, params) {
52989
53056
  options.limit = limit;
52990
53057
  }
52991
53058
  const trades = [];
52992
- // Use SDK's getTradesV2 method with pagination (async iterator)
53059
+ // Acquire rate limit token before starting the async iterator
53060
+ await client.executeWithRateLimit(() => Promise.resolve(), "getTradesV2");
52993
53061
  const tradesIterator = sdk.getTradesV2(normalizedSymbol, options);
52994
53062
  for await (const trade of tradesIterator) {
52995
53063
  trades.push({
@@ -53464,7 +53532,7 @@ async function getNews(client, params = {}) {
53464
53532
  options.include_content = true;
53465
53533
  }
53466
53534
  // Use SDK's getNews method
53467
- const response = await sdk.getNews(options);
53535
+ const response = await client.executeWithRateLimit(() => sdk.getNews(options), "getNews");
53468
53536
  if (!response || !Array.isArray(response)) {
53469
53537
  log$9("No news data returned", { type: "debug" });
53470
53538
  return [];
@@ -55275,7 +55343,7 @@ async function createOrder(client, params) {
55275
55343
  });
55276
55344
  try {
55277
55345
  const sdk = client.getSDK();
55278
- const order = await sdk.createOrder(params);
55346
+ const order = await client.executeWithRateLimit(() => sdk.createOrder(params), `createOrder ${symbol}`);
55279
55347
  log$6(`Order created successfully: ${order.id}`, {
55280
55348
  type: "info",
55281
55349
  symbol,
@@ -55314,7 +55382,7 @@ async function getOrder(client, orderId) {
55314
55382
  log$6(`Fetching order: ${orderId}`, { type: "debug" });
55315
55383
  try {
55316
55384
  const sdk = client.getSDK();
55317
- const order = await sdk.getOrder(orderId);
55385
+ const order = await client.executeWithRateLimit(() => sdk.getOrder(orderId), `getOrder ${orderId}`);
55318
55386
  log$6(`Order retrieved: ${orderId} (${order.status})`, {
55319
55387
  type: "debug",
55320
55388
  symbol: order.symbol,
@@ -55377,7 +55445,7 @@ async function getOrders(client, params = {}) {
55377
55445
  }
55378
55446
  if (params.side)
55379
55447
  queryParams.side = params.side;
55380
- const orders = await sdk.getOrders(queryParams);
55448
+ const orders = await client.executeWithRateLimit(() => sdk.getOrders(queryParams), "getOrders");
55381
55449
  log$6(`Retrieved ${orders.length} orders`, {
55382
55450
  type: "debug",
55383
55451
  metadata: { count: orders.length, status: filterDescription },
@@ -55406,7 +55474,7 @@ async function cancelOrder(client, orderId) {
55406
55474
  log$6(`Canceling order: ${orderId}`, { type: "info" });
55407
55475
  try {
55408
55476
  const sdk = client.getSDK();
55409
- await sdk.cancelOrder(orderId);
55477
+ await client.executeWithRateLimit(() => sdk.cancelOrder(orderId), "cancelOrder");
55410
55478
  log$6(`Order canceled successfully: ${orderId}`, { type: "info" });
55411
55479
  }
55412
55480
  catch (error) {
@@ -55448,7 +55516,7 @@ async function cancelAllOrders(client) {
55448
55516
  log$6("Canceling all open orders", { type: "info" });
55449
55517
  try {
55450
55518
  const sdk = client.getSDK();
55451
- const result = await sdk.cancelAllOrders();
55519
+ const result = await client.executeWithRateLimit(() => sdk.cancelAllOrders(), "cancelAllOrders");
55452
55520
  // The SDK returns an array of canceled order statuses
55453
55521
  const canceled = Array.isArray(result) ? result.length : 0;
55454
55522
  const failed = [];
@@ -55508,7 +55576,7 @@ async function replaceOrder(client, orderId, params) {
55508
55576
  });
55509
55577
  try {
55510
55578
  const sdk = client.getSDK();
55511
- const newOrder = await sdk.replaceOrder(orderId, params);
55579
+ const newOrder = await client.executeWithRateLimit(() => sdk.replaceOrder(orderId, params), "replaceOrder");
55512
55580
  log$6(`Order replaced successfully: ${orderId} -> ${newOrder.id}`, {
55513
55581
  type: "info",
55514
55582
  symbol: newOrder.symbol,
@@ -55613,7 +55681,7 @@ async function getOrderByClientId(client, clientOrderId) {
55613
55681
  log$6(`Fetching order by client_order_id: ${clientOrderId}`, { type: "debug" });
55614
55682
  try {
55615
55683
  const sdk = client.getSDK();
55616
- const order = await sdk.getOrderByClientId(clientOrderId);
55684
+ const order = await client.executeWithRateLimit(() => sdk.getOrderByClientId(clientOrderId), "getOrderByClientId");
55617
55685
  log$6(`Order retrieved by client_order_id: ${clientOrderId} -> ${order.id}`, {
55618
55686
  type: "debug",
55619
55687
  symbol: order.symbol,
@@ -58554,7 +58622,7 @@ async function getPositions(client) {
58554
58622
  log("Fetching all open positions", { type: "debug" });
58555
58623
  try {
58556
58624
  const sdk = client.getSDK();
58557
- const positions = (await sdk.getPositions());
58625
+ const positions = (await client.executeWithRateLimit(() => sdk.getPositions(), "getPositions"));
58558
58626
  log(`Retrieved ${positions.length} positions`, { type: "info" });
58559
58627
  return positions;
58560
58628
  }
@@ -58608,7 +58676,7 @@ async function getPosition(client, symbol) {
58608
58676
  log(`Fetching position for symbol: ${symbol}`, { type: "debug", symbol });
58609
58677
  try {
58610
58678
  const sdk = client.getSDK();
58611
- const position = (await sdk.getPosition(symbol));
58679
+ const position = (await client.executeWithRateLimit(() => sdk.getPosition(symbol), "getPosition"));
58612
58680
  log(`Found position for ${symbol}: ${position.qty} shares`, {
58613
58681
  type: "info",
58614
58682
  symbol,
@@ -58755,10 +58823,10 @@ async function closePosition(client, symbol, options) {
58755
58823
  let order;
58756
58824
  if (Object.keys(queryParams).length > 0) {
58757
58825
  // SDK doesn't support params, use sendRequest directly
58758
- order = (await sdk.sendRequest(`/positions/${encodeURIComponent(normalizedSymbol)}`, queryParams, null, "DELETE"));
58826
+ order = (await client.executeWithRateLimit(() => sdk.sendRequest(`/positions/${encodeURIComponent(normalizedSymbol)}`, queryParams, null, "DELETE"), "closePosition"));
58759
58827
  }
58760
58828
  else {
58761
- order = (await sdk.closePosition(normalizedSymbol));
58829
+ order = (await client.executeWithRateLimit(() => sdk.closePosition(normalizedSymbol), "closePosition"));
58762
58830
  }
58763
58831
  log(`Position close order created for ${normalizedSymbol}: ${order.id}`, {
58764
58832
  type: "info",
@@ -58799,7 +58867,7 @@ async function closeAllPositions(client, options) {
58799
58867
  cancel_orders: cancelOrders.toString(),
58800
58868
  };
58801
58869
  // Use sendRequest to pass the cancel_orders parameter
58802
- const response = await sdk.sendRequest("/positions", queryParams, null, "DELETE");
58870
+ const response = await client.executeWithRateLimit(() => sdk.sendRequest("/positions", queryParams, null, "DELETE"), "closeAllPositions");
58803
58871
  // The SDK returns an array of objects with order info
58804
58872
  const orders = Array.isArray(response) ? response : [];
58805
58873
  log(`Closed ${orders.length} positions`, { type: "info" });
@@ -58834,7 +58902,7 @@ async function closeAllPositionsAfterHours(client, options) {
58834
58902
  return [];
58835
58903
  }
58836
58904
  // First cancel all open orders
58837
- await sdk.cancelAllOrders();
58905
+ await client.executeWithRateLimit(() => sdk.cancelAllOrders(), "cancelAllOrders");
58838
58906
  log("Cancelled all open orders", { type: "info" });
58839
58907
  const orders = [];
58840
58908
  const offsetMultiplier = limitPriceOffset / 100;
@@ -58855,7 +58923,7 @@ async function closeAllPositionsAfterHours(client, options) {
58855
58923
  : roundPriceForAlpaca(currentPrice * (1 + offsetMultiplier));
58856
58924
  log(`Creating limit order to close ${position.symbol}: ${side} ${qty} shares at $${limitPrice.toFixed(2)}`, { type: "info", symbol: position.symbol });
58857
58925
  try {
58858
- const order = (await sdk.createOrder({
58926
+ const order = (await client.executeWithRateLimit(() => sdk.createOrder({
58859
58927
  symbol: position.symbol,
58860
58928
  qty: qty,
58861
58929
  side: side,
@@ -58863,7 +58931,7 @@ async function closeAllPositionsAfterHours(client, options) {
58863
58931
  time_in_force: "day",
58864
58932
  limit_price: limitPrice,
58865
58933
  extended_hours: true,
58866
- }));
58934
+ }), `createOrder ${position.symbol}`));
58867
58935
  orders.push(order);
58868
58936
  }
58869
58937
  catch (orderError) {
@@ -67898,6 +67966,7 @@ const adaptic = {
67898
67966
  getApolloClient: getSharedApolloClient,
67899
67967
  configureAuth: configureAuth,
67900
67968
  isAuthConfigured: isAuthConfigured,
67969
+ disconnectClient: disconnectClient,
67901
67970
  },
67902
67971
  alpaca: {
67903
67972
  // New SDK-based client factory (RECOMMENDED)