@discomedia/utils 1.0.40 → 1.0.42

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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.0.40",
6
+ "version": "1.0.42",
7
7
  "author": "Disco Media",
8
8
  "description": "Utility functions used in Disco Media apps",
9
9
  "always-build-npm": true,
@@ -33,20 +33,20 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "dotenv": "^17.2.3",
36
- "openai": "^6.2.0",
37
- "p-limit": "^7.1.1",
36
+ "openai": "^6.5.0",
37
+ "p-limit": "^7.2.0",
38
38
  "tslib": "^2.8.1",
39
39
  "ws": "^8.18.3"
40
40
  },
41
41
  "license": "ISC",
42
42
  "devDependencies": {
43
- "@rollup/plugin-commonjs": "^28.0.6",
43
+ "@rollup/plugin-commonjs": "^28.0.8",
44
44
  "@rollup/plugin-json": "^6.1.0",
45
- "@rollup/plugin-node-resolve": "^16.0.2",
45
+ "@rollup/plugin-node-resolve": "^16.0.3",
46
46
  "@rollup/plugin-typescript": "^12.1.4",
47
47
  "@types/ws": "^8.18.1",
48
48
  "lightweight-charts": "^5.0.9",
49
- "rollup": "^4.52.4",
49
+ "rollup": "^4.52.5",
50
50
  "typescript": "^5.9.3"
51
51
  }
52
52
  }
package/dist/test.js CHANGED
@@ -532,8 +532,8 @@ function pLimit(concurrency) {
532
532
  },
533
533
  },
534
534
  map: {
535
- async value(array, function_) {
536
- const promises = array.map((value, index) => this(function_, value, index));
535
+ async value(iterable, function_) {
536
+ const promises = Array.from(iterable, (value, index) => this(function_, value, index));
537
537
  return Promise.all(promises);
538
538
  },
539
539
  },
@@ -799,7 +799,7 @@ const safeJSON = (text) => {
799
799
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
800
800
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
801
801
 
802
- const VERSION = '6.2.0'; // x-release-please-version
802
+ const VERSION = '6.5.0'; // x-release-please-version
803
803
 
804
804
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
805
805
  const isRunningInBrowser = () => {
@@ -4354,19 +4354,6 @@ class ChatKit extends APIResource {
4354
4354
  this.sessions = new Sessions(this._client);
4355
4355
  this.threads = new Threads$1(this._client);
4356
4356
  }
4357
- /**
4358
- * Upload a ChatKit file
4359
- *
4360
- * @example
4361
- * ```ts
4362
- * const response = await client.beta.chatkit.uploadFile({
4363
- * file: fs.createReadStream('path/to/file'),
4364
- * });
4365
- * ```
4366
- */
4367
- uploadFile(body, options) {
4368
- return this._client.post('/chatkit/files', maybeMultipartFormRequestOptions({ body, ...options, headers: buildHeaders([{ 'OpenAI-Beta': 'chatkit_beta=v1' }, options?.headers]) }, this._client));
4369
- }
4370
4357
  }
4371
4358
  ChatKit.Sessions = Sessions;
4372
4359
  ChatKit.Threads = Threads$1;
@@ -5688,7 +5675,7 @@ let Files$1 = class Files extends APIResource {
5688
5675
  return this._client.getAPIList('/files', (CursorPage), { query, ...options });
5689
5676
  }
5690
5677
  /**
5691
- * Delete a file.
5678
+ * Delete a file and remove it from all vector stores.
5692
5679
  */
5693
5680
  delete(fileID, options) {
5694
5681
  return this._client.delete(path `/files/${fileID}`, options);
@@ -13225,7 +13212,11 @@ function requireConfig () {
13225
13212
 
13226
13213
  requireConfig();
13227
13214
 
13215
+ const DEBUG_LOGGING = process.env['DEBUG'] === 'true' || false;
13228
13216
  const log = (message, options = { type: 'info' }) => {
13217
+ if (!DEBUG_LOGGING && options.type === 'debug') {
13218
+ return;
13219
+ }
13229
13220
  log$1(message, { ...options, source: 'AlpacaMarketDataAPI' });
13230
13221
  };
13231
13222
  // Default settings for market data API
@@ -13315,7 +13306,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
13315
13306
  this.optionWs = ws;
13316
13307
  }
13317
13308
  ws.on('open', () => {
13318
- log(`${streamType} stream connected`, { type: 'info' });
13309
+ log(`${streamType} stream connected`);
13319
13310
  const authMessage = {
13320
13311
  action: 'auth',
13321
13312
  key: process.env.ALPACA_API_KEY,
@@ -13328,7 +13319,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
13328
13319
  const messages = JSON.parse(data.toString());
13329
13320
  for (const message of messages) {
13330
13321
  if (message.T === 'success' && message.msg === 'authenticated') {
13331
- log(`${streamType} stream authenticated`, { type: 'info' });
13322
+ log(`${streamType} stream authenticated`);
13332
13323
  this.sendSubscription(streamType);
13333
13324
  }
13334
13325
  else if (message.T === 'error') {
@@ -13478,9 +13469,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
13478
13469
  symbols.forEach((symbol) => {
13479
13470
  allBars[symbol] = [];
13480
13471
  });
13481
- log(`Starting historical bars fetch for ${symbolsStr.length} symbols (${params.timeframe}, ${params.start || 'no start'} to ${params.end || 'no end'})`, {
13482
- type: 'info',
13483
- });
13472
+ log(`Starting historical bars fetch for ${symbolsStr.length} symbols (${params.timeframe}, ${params.start || 'no start'} to ${params.end || 'no end'})`);
13484
13473
  while (hasMorePages) {
13485
13474
  pageCount++;
13486
13475
  const requestParams = {
@@ -13525,7 +13514,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
13525
13514
  const dateRangeStr = earliestTimestamp && latestTimestamp
13526
13515
  ? `${new Date(earliestTimestamp).toLocaleDateString('en-US', { timeZone: 'America/New_York' })} to ${new Date(latestTimestamp).toLocaleDateString('en-US', { timeZone: 'America/New_York' })}`
13527
13516
  : 'unknown range';
13528
- log(`Page ${pageCount}: Fetched ${pageBarsCount.toLocaleString()} bars (total: ${totalBarsCount.toLocaleString()}) for ${symbols.length} symbols, date range: ${dateRangeStr}${hasMorePages ? ', more pages available' : ', complete'}`);
13517
+ log(`Page ${pageCount}: Fetched ${pageBarsCount.toLocaleString()} bars (total: ${totalBarsCount.toLocaleString()}) for ${symbols.length} symbols, date range: ${dateRangeStr}${hasMorePages ? ', more pages available' : ', complete'}`, { type: 'debug' });
13529
13518
  // Prevent infinite loops
13530
13519
  if (pageCount > 1000) {
13531
13520
  log(`Stopping pagination after ${pageCount} pages to prevent infinite loop`, { type: 'warn' });
@@ -13536,7 +13525,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
13536
13525
  const symbolsJoined = Object.entries(allBars)
13537
13526
  .map(([symbol, bars]) => `${symbol}: ${bars.length}`)
13538
13527
  .join(', ');
13539
- log(`Historical bars fetch complete: ${totalBarsCount.toLocaleString()} total bars across ${pageCount} pages for ${symbolsJoined.length} symbols'}`);
13528
+ log(`Bars fetch complete: ${totalBarsCount.toLocaleString()} total bars across ${pageCount} pages for ${symbolsJoined.length} symbols'}`);
13540
13529
  return {
13541
13530
  bars: allBars,
13542
13531
  next_page_token: null, // Always null since we fetch all pages
@@ -13731,14 +13720,25 @@ class AlpacaMarketDataAPI extends EventEmitter {
13731
13720
  `Avg Volume: ${avgVolume.toLocaleString()}`);
13732
13721
  }
13733
13722
  /**
13734
- * Get all assets available for trade and data consumption from Alpaca
13735
- * @param params Optional query params: status (e.g. 'active'), asset_class (e.g. 'us_equity', 'crypto')
13723
+ * Get assets available for trade and data consumption from Alpaca
13724
+ * @param params Optional query params
13725
+ * - status: 'active' | 'inactive' (default 'active')
13726
+ * - asset_class: 'us_equity' | 'us_option' | 'crypto' (default 'us_equity')
13727
+ * - shortable: if true (default), filters to assets with shortable=true and easy_to_borrow=true
13736
13728
  * @returns Array of AlpacaAsset objects
13737
13729
  * @see https://docs.alpaca.markets/reference/get-v2-assets-1
13738
13730
  */
13739
13731
  async getAssets(params) {
13740
13732
  // Endpoint: GET /v2/assets
13741
- return this.makeRequest('/assets', 'GET', params, 'api'); // use apiURL
13733
+ const { status = 'active', asset_class = 'us_equity', shortable = true, } = {
13734
+ status: params?.status ?? 'active',
13735
+ asset_class: params?.asset_class ?? 'us_equity',
13736
+ shortable: params?.shortable ?? true,
13737
+ };
13738
+ const assets = await this.makeRequest('/assets', 'GET', { status, asset_class }, 'api');
13739
+ if (!shortable)
13740
+ return assets;
13741
+ return assets.filter((a) => a.shortable === true && a.easy_to_borrow === true);
13742
13742
  }
13743
13743
  /**
13744
13744
  * Get a single asset by symbol or asset_id
@@ -13806,9 +13806,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
13806
13806
  symbols.forEach((symbol) => {
13807
13807
  allBars[symbol] = [];
13808
13808
  });
13809
- log(`Starting historical options bars fetch for ${symbolsStr.length} symbols (${params.timeframe}, ${params.start || 'no start'} to ${params.end || 'no end'})`, {
13810
- type: 'info',
13811
- });
13809
+ log(`Starting historical options bars fetch for ${symbolsStr.length} symbols (${params.timeframe}, ${params.start || 'no start'} to ${params.end || 'no end'})`);
13812
13810
  while (hasMorePages) {
13813
13811
  pageCount++;
13814
13812
  const requestParams = {
@@ -13848,7 +13846,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
13848
13846
  ? `${earliestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })} to ${latestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })}`
13849
13847
  : 'unknown range';
13850
13848
  log(`Page ${pageCount}: Fetched ${pageBarsCount.toLocaleString()} option bars (total: ${totalBarsCount.toLocaleString()}) for ${symbolsStr}, date range: ${dateRangeStr}${hasMorePages ? ', more pages available' : ', complete'}`, {
13851
- type: 'info',
13849
+ type: 'debug',
13852
13850
  });
13853
13851
  // Prevent infinite loops
13854
13852
  if (pageCount > 1000) {
@@ -13860,9 +13858,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
13860
13858
  const symbolCounts = Object.entries(allBars)
13861
13859
  .map(([symbol, bars]) => `${symbol}: ${bars.length}`)
13862
13860
  .join(', ');
13863
- log(`Historical options bars fetch complete: ${totalBarsCount.toLocaleString()} total bars across ${pageCount} pages (${symbolCounts})`, {
13864
- type: 'info',
13865
- });
13861
+ log(`Options bars fetch complete: ${totalBarsCount.toLocaleString()} total bars across ${pageCount} pages (${symbolCounts})`);
13866
13862
  return {
13867
13863
  bars: allBars,
13868
13864
  next_page_token: undefined, // Always undefined since we fetch all pages
@@ -13888,9 +13884,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
13888
13884
  symbols.forEach((symbol) => {
13889
13885
  allTrades[symbol] = [];
13890
13886
  });
13891
- log(`Starting historical options trades fetch for ${symbolsStr.length} symbols (${params.start || 'no start'} to ${params.end || 'no end'})`, {
13892
- type: 'info',
13893
- });
13887
+ log(`Starting historical options trades fetch for ${symbolsStr.length} symbols (${params.start || 'no start'} to ${params.end || 'no end'})`);
13894
13888
  while (hasMorePages) {
13895
13889
  pageCount++;
13896
13890
  const requestParams = {
@@ -13930,7 +13924,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
13930
13924
  ? `${earliestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })} to ${latestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })}`
13931
13925
  : 'unknown range';
13932
13926
  log(`Page ${pageCount}: Fetched ${pageTradesCount.toLocaleString()} option trades (total: ${totalTradesCount.toLocaleString()}) for ${symbolsStr.length} symbols, date range: ${dateRangeStr}${hasMorePages ? ', more pages available' : ', complete'}`, {
13933
- type: 'info',
13927
+ type: 'debug',
13934
13928
  });
13935
13929
  // Prevent infinite loops
13936
13930
  if (pageCount > 1000) {
@@ -13942,9 +13936,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
13942
13936
  const symbolCounts = Object.entries(allTrades)
13943
13937
  .map(([symbol, trades]) => `${symbol}: ${trades.length}`)
13944
13938
  .join(', ');
13945
- log(`Historical options trades fetch complete: ${totalTradesCount.toLocaleString()} total trades across ${pageCount} pages (${symbolCounts})`, {
13946
- type: 'info',
13947
- });
13939
+ log(`Options trades fetch complete: ${totalTradesCount.toLocaleString()} total trades across ${pageCount} pages (${symbolCounts})`);
13948
13940
  return {
13949
13941
  trades: allTrades,
13950
13942
  next_page_token: undefined, // Always undefined since we fetch all pages
@@ -14152,7 +14144,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
14152
14144
  symbols.forEach((symbol) => {
14153
14145
  allBars[symbol] = [];
14154
14146
  });
14155
- log(`Starting crypto historical bars fetch for ${symbols.length} symbols (${params.timeframe}, ${params.start || 'no start'} to ${params.end || 'no end'})`, { type: 'info' });
14147
+ log(`Starting crypto historical bars fetch for ${symbols.length} symbols (${params.timeframe}, ${params.start || 'no start'} to ${params.end || 'no end'})`);
14156
14148
  while (hasMorePages) {
14157
14149
  pageCount++;
14158
14150
  const requestParams = {
@@ -14176,14 +14168,14 @@ class AlpacaMarketDataAPI extends EventEmitter {
14176
14168
  totalBarsCount += pageBarsCount;
14177
14169
  pageToken = response.next_page_token || null;
14178
14170
  hasMorePages = !!pageToken;
14179
- log(`Page ${pageCount}: Fetched ${pageBarsCount.toLocaleString()} crypto bars (total: ${totalBarsCount.toLocaleString()}) for ${symbols.length} symbols${hasMorePages ? ', more pages available' : ', complete'}`);
14171
+ log(`Page ${pageCount}: Fetched ${pageBarsCount.toLocaleString()} crypto bars (total: ${totalBarsCount.toLocaleString()}) for ${symbols.length} symbols${hasMorePages ? ', more pages available' : ', complete'}`, { type: 'debug' });
14180
14172
  // Prevent infinite loops
14181
14173
  if (pageCount > 1000) {
14182
14174
  log(`Stopping crypto bars pagination after ${pageCount} pages to prevent infinite loop`, { type: 'warn' });
14183
14175
  break;
14184
14176
  }
14185
14177
  }
14186
- log(`Crypto historical bars fetch complete: ${totalBarsCount.toLocaleString()} total bars across ${pageCount} pages`, { type: 'info' });
14178
+ log(`Crypto historical bars fetch complete: ${totalBarsCount.toLocaleString()} total bars across ${pageCount} pages`);
14187
14179
  return {
14188
14180
  bars: allBars,
14189
14181
  next_page_token: null, // Always null since we fetch all pages
@@ -14215,7 +14207,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
14215
14207
  symbols.forEach((symbol) => {
14216
14208
  allQuotes[symbol] = [];
14217
14209
  });
14218
- log(`Starting crypto historical quotes fetch for ${symbols.length} symbols (${params.start || 'no start'} to ${params.end || 'no end'})`, { type: 'info' });
14210
+ log(`Starting crypto historical quotes fetch for ${symbols.length} symbols (${params.start || 'no start'} to ${params.end || 'no end'})`);
14219
14211
  while (hasMorePages) {
14220
14212
  pageCount++;
14221
14213
  const requestParams = {
@@ -14239,14 +14231,14 @@ class AlpacaMarketDataAPI extends EventEmitter {
14239
14231
  totalQuotesCount += pageQuotesCount;
14240
14232
  pageToken = response.next_page_token || null;
14241
14233
  hasMorePages = !!pageToken;
14242
- log(`Page ${pageCount}: Fetched ${pageQuotesCount.toLocaleString()} crypto quotes (total: ${totalQuotesCount.toLocaleString()}) for ${symbols.length} symbols${hasMorePages ? ', more pages available' : ', complete'}`);
14234
+ log(`Page ${pageCount}: Fetched ${pageQuotesCount.toLocaleString()} crypto quotes (total: ${totalQuotesCount.toLocaleString()}) for ${symbols.length} symbols${hasMorePages ? ', more pages available' : ', complete'}`, { type: 'debug' });
14243
14235
  // Prevent infinite loops
14244
14236
  if (pageCount > 1000) {
14245
14237
  log(`Stopping crypto quotes pagination after ${pageCount} pages to prevent infinite loop`, { type: 'warn' });
14246
14238
  break;
14247
14239
  }
14248
14240
  }
14249
- log(`Crypto historical quotes fetch complete: ${totalQuotesCount.toLocaleString()} total quotes across ${pageCount} pages`, { type: 'info' });
14241
+ log(`Crypto historical quotes fetch complete: ${totalQuotesCount.toLocaleString()} total quotes across ${pageCount} pages`);
14250
14242
  return {
14251
14243
  quotes: allQuotes,
14252
14244
  next_page_token: null, // Always null since we fetch all pages
@@ -14282,7 +14274,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
14282
14274
  symbols.forEach((symbol) => {
14283
14275
  allTrades[symbol] = [];
14284
14276
  });
14285
- log(`Starting crypto historical trades fetch for ${symbols.length} symbols (${params.start || 'no start'} to ${params.end || 'no end'})`, { type: 'info' });
14277
+ log(`Starting crypto historical trades fetch for ${symbols.length} symbols (${params.start || 'no start'} to ${params.end || 'no end'})`);
14286
14278
  while (hasMorePages) {
14287
14279
  pageCount++;
14288
14280
  const requestParams = {
@@ -14306,14 +14298,14 @@ class AlpacaMarketDataAPI extends EventEmitter {
14306
14298
  totalTradesCount += pageTradesCount;
14307
14299
  pageToken = response.next_page_token || null;
14308
14300
  hasMorePages = !!pageToken;
14309
- log(`Page ${pageCount}: Fetched ${pageTradesCount.toLocaleString()} crypto trades (total: ${totalTradesCount.toLocaleString()}) for ${symbols.length} symbols${hasMorePages ? ', more pages available' : ', complete'}`);
14301
+ log(`Page ${pageCount}: Fetched ${pageTradesCount.toLocaleString()} crypto trades (total: ${totalTradesCount.toLocaleString()}) for ${symbols.length} symbols${hasMorePages ? ', more pages available' : ', complete'}`, { type: 'debug' });
14310
14302
  // Prevent infinite loops
14311
14303
  if (pageCount > 1000) {
14312
14304
  log(`Stopping crypto trades pagination after ${pageCount} pages to prevent infinite loop`, { type: 'warn' });
14313
14305
  break;
14314
14306
  }
14315
14307
  }
14316
- log(`Crypto historical trades fetch complete: ${totalTradesCount.toLocaleString()} total trades across ${pageCount} pages`, { type: 'info' });
14308
+ log(`Crypto historical trades fetch complete: ${totalTradesCount.toLocaleString()} total trades across ${pageCount} pages`);
14317
14309
  return {
14318
14310
  trades: allTrades,
14319
14311
  next_page_token: null, // Always null since we fetch all pages
@@ -14382,88 +14374,84 @@ class AlpacaMarketDataAPI extends EventEmitter {
14382
14374
  }
14383
14375
  }
14384
14376
  // Export the singleton instance
14385
- AlpacaMarketDataAPI.getInstance();
14377
+ const marketDataAPI = AlpacaMarketDataAPI.getInstance();
14378
+
14379
+ var alpacaMarketDataApi = /*#__PURE__*/Object.freeze({
14380
+ __proto__: null,
14381
+ AlpacaMarketDataAPI: AlpacaMarketDataAPI,
14382
+ marketDataAPI: marketDataAPI
14383
+ });
14386
14384
 
14387
14385
  // Test file for context functionality
14388
- //testOpenRouter();
14389
- //testGetMarketStatus();
14390
- //testCryptoMarketData();
14391
- //testGetPortfolioDailyHistory();
14392
- async function testWebSocketConnectAndDisconnect() {
14393
- console.log('\n--- Testing WebSocket Connect and Disconnect ---');
14386
+ async function testGetAssetsShortableFilter() {
14387
+ console.log('\n--- Testing getAssets params and shortable filter ---');
14394
14388
  const log = (message, options = { type: 'info' }) => {
14395
14389
  log$1(message, { ...options, source: 'Test' });
14396
14390
  };
14397
- // Ensure market data env vars are populated from TRADING_* if needed
14398
- if (!process.env.ALPACA_API_KEY && process.env.ALPACA_TRADING_API_KEY) {
14399
- process.env.ALPACA_API_KEY = process.env.ALPACA_TRADING_API_KEY;
14400
- }
14401
- if (!process.env.ALPACA_SECRET_KEY && process.env.ALPACA_TRADING_SECRET_KEY) {
14402
- process.env.ALPACA_SECRET_KEY = process.env.ALPACA_TRADING_SECRET_KEY;
14403
- }
14404
- if (!process.env.ALPACA_ACCOUNT_TYPE && process.env.ALPACA_TRADING_ACCOUNT_TYPE) {
14405
- process.env.ALPACA_ACCOUNT_TYPE = process.env.ALPACA_TRADING_ACCOUNT_TYPE;
14406
- }
14407
- const apiKey = process.env.ALPACA_API_KEY;
14408
- const secretKey = process.env.ALPACA_SECRET_KEY;
14409
- if (!apiKey || !secretKey) {
14410
- console.error('Missing Alpaca API credentials. Check .env ALPACA_TRADING_API_KEY/SECRET or ALPACA_API_KEY/SECRET.');
14391
+ if (!process.env.ALPACA_API_KEY || !process.env.ALPACA_SECRET_KEY) {
14392
+ console.log('Skipping getAssets test: Missing environment variables (ALPACA_API_KEY, ALPACA_SECRET_KEY)');
14411
14393
  return;
14412
14394
  }
14413
- const md = AlpacaMarketDataAPI.getInstance();
14414
- const symbols = ['SPY', 'TSLA', 'AAPL'];
14415
- // Track received minute bars per symbol
14416
- const barCounts = Object.fromEntries(symbols.map((s) => [s, 0]));
14417
- const firstSeenAt = {};
14418
- // Connect and subscribe to minute bars
14419
- log(`Connecting stock stream and subscribing to minute bars for ${symbols.join(', ')}`);
14420
- md.connectStockStream();
14421
- md.subscribe('stock', { bars: symbols });
14422
- const formatNY = (d) => d.toLocaleString('en-US', { timeZone: 'America/New_York' });
14423
- const onBar = (msg) => {
14424
- if (!symbols.includes(msg.S))
14425
- return;
14426
- barCounts[msg.S] += 1;
14427
- if (!firstSeenAt[msg.S]) {
14428
- firstSeenAt[msg.S] = formatNY(new Date(msg.t));
14395
+ try {
14396
+ const { marketDataAPI } = await Promise.resolve().then(function () { return alpacaMarketDataApi; });
14397
+ // 1) Default call: should filter to shortable && easy_to_borrow and default to active us_equity
14398
+ log('Calling getAssets() with defaults');
14399
+ const filtered = await marketDataAPI.getAssets();
14400
+ console.log(`Received ${filtered.length} filtered assets (default params)`);
14401
+ const allFilteredValid = filtered.every((a) => a.shortable === true && a.easy_to_borrow === true);
14402
+ if (!allFilteredValid) {
14403
+ console.error(' Default getAssets() included assets that are not shortable and easy_to_borrow');
14429
14404
  }
14430
- log(`Bar ${msg.S} o=${msg.o.toFixed(2)} h=${msg.h.toFixed(2)} l=${msg.l.toFixed(2)} c=${msg.c.toFixed(2)} @ ${formatNY(new Date(msg.t))}`, { type: 'debug', symbol: msg.S });
14431
- };
14432
- md.on('stock-b', onBar);
14433
- // Wait until we have at least 2 bars per symbol, or timeout after 3 minutes
14434
- const minBarsPerSymbol = 2;
14435
- const timeoutMs = 3 * 60 * 1000;
14436
- const done = await new Promise((resolve) => {
14437
- const startedAt = Date.now();
14438
- const interval = setInterval(() => {
14439
- const hasAll = symbols.every((s) => barCounts[s] >= minBarsPerSymbol);
14440
- const elapsed = Date.now() - startedAt;
14441
- if (hasAll) {
14442
- clearInterval(interval);
14443
- resolve(true);
14444
- }
14445
- else if (elapsed >= timeoutMs) {
14446
- clearInterval(interval);
14447
- resolve(false);
14448
- }
14449
- }, 1000);
14450
- });
14451
- // Unsubscribe and disconnect
14452
- md.unsubscribe('stock', { bars: symbols });
14453
- md.disconnectStockStream();
14454
- md.removeListener('stock-b', onBar);
14455
- // Report results
14456
- const nowNY = formatNY(new Date());
14457
- console.log('\nStock bars summary:');
14458
- symbols.forEach((s) => {
14459
- console.log(` ${s}: ${barCounts[s]} bars (first at ${firstSeenAt[s] ?? 'n/a'}; finished at ${nowNY})`);
14460
- });
14461
- if (done) {
14462
- console.log('✓ Received minimum bars for all symbols and disconnected.');
14463
- }
14464
- else {
14465
- console.warn('Completed with timeout before receiving minimum bars for all symbols.');
14466
- }
14467
- }
14468
- testWebSocketConnectAndDisconnect();
14405
+ else {
14406
+ console.log('✓ Default getAssets() correctly filtered shortable and easy_to_borrow assets');
14407
+ }
14408
+ // 2) Unfiltered call: shortable=false
14409
+ log('Calling getAssets({ shortable: false })');
14410
+ const unfiltered = await marketDataAPI.getAssets({ shortable: false });
14411
+ console.log(`Received ${unfiltered.length} unfiltered assets`);
14412
+ if (unfiltered.length < filtered.length) {
14413
+ console.warn('Unfiltered list is smaller than filtered. This is unexpected but not fatal.');
14414
+ }
14415
+ else {
14416
+ console.log('✓ Unfiltered list length is >= filtered list length');
14417
+ }
14418
+ // 3) Specific constraints: inactive crypto, not asserting non-empty
14419
+ log("Calling getAssets({ status: 'inactive', asset_class: 'crypto', shortable: false })");
14420
+ const inactiveCrypto = await marketDataAPI.getAssets({ status: 'inactive', asset_class: 'crypto', shortable: false });
14421
+ console.log(`Received ${inactiveCrypto.length} inactive crypto assets`);
14422
+ if (inactiveCrypto.length > 0) {
14423
+ const valid = inactiveCrypto.every((a) => a.class === 'crypto' && a.status === 'inactive');
14424
+ if (!valid) {
14425
+ console.error('✗ Inactive crypto request returned assets with mismatched class or status');
14426
+ }
14427
+ else {
14428
+ console.log('✓ Inactive crypto request returned only crypto with inactive status');
14429
+ }
14430
+ }
14431
+ else {
14432
+ console.log('No inactive crypto assets returned; skipping class/status assertions.');
14433
+ }
14434
+ }
14435
+ catch (error) {
14436
+ console.error('✗ getAssets test failed:', error);
14437
+ if (error instanceof Error) {
14438
+ console.error('Error message:', error.message);
14439
+ console.error('Stack trace:', error.stack);
14440
+ }
14441
+ }
14442
+ }
14443
+ // testGetTradingDate();
14444
+ // testGetTradingStartAndEndDates();
14445
+ // testGetLastFullTradingDate();
14446
+ // testGetMarketOpenClose();
14447
+ // testGetNYTimeZone();
14448
+ // testGetNextMarketDay();
14449
+ // testCountTradingDays();
14450
+ // testGetPreviousMarketDay();
14451
+ // testOpenRouter();
14452
+ // testGetMarketStatus();
14453
+ // testCryptoMarketData();
14454
+ // testGetPortfolioDailyHistory();
14455
+ // testWebSocketConnectAndDisconnect();
14456
+ testGetAssetsShortableFilter();
14469
14457
  //# sourceMappingURL=test.js.map