nansen-cli 1.2.0 → 1.3.0

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/nansen-cli.svg)](https://www.npmjs.com/package/nansen-cli)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
- [![Tests](https://img.shields.io/badge/tests-356%20passing-brightgreen.svg)]()
5
+ [![Tests](https://img.shields.io/badge/tests-323%20passing-brightgreen.svg)]()
6
6
  [![Coverage](https://img.shields.io/badge/coverage-80%25-brightgreen.svg)]()
7
7
 
8
8
  > **Built by agents, for agents.** We prioritize the best possible AI agent experience.
@@ -156,6 +156,7 @@ nansen cache clear
156
156
  | `--cache` | Enable response caching |
157
157
  | `--no-cache` | Bypass cache for this request |
158
158
  | `--cache-ttl <s>` | Cache TTL in seconds (default: 300) |
159
+ | `--stream` | Output as JSON lines (NDJSON) for incremental processing |
159
160
  | `--chain <chain>` | Blockchain to query |
160
161
  | `--chains <json>` | Multiple chains as JSON array |
161
162
  | `--limit <n>` | Number of results |
package/TODO.md CHANGED
@@ -2,17 +2,6 @@
2
2
 
3
3
  > **Built by agents, for agents.** We prioritize improvements that create the best possible AI agent experience.
4
4
 
5
- ## P1 - Should Have
6
-
7
- ### Test Cleanup
8
- - [ ] Remove duplicated `parseArgs` in unit.test.js (now exported from cli.js)
9
- - [ ] Reduce cli.test.js subprocess tests to ~10 smoke tests
10
-
11
- ### Streaming Output
12
- - [ ] `--stream` flag for large result sets
13
- - [ ] Output as JSON lines (newline-delimited JSON)
14
- - [ ] Enable incremental processing by agents
15
-
16
5
  ## P2 - Nice to Have
17
6
 
18
7
  ### Test Coverage Gaps
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nansen-cli",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Command-line interface for Nansen API - designed for AI agents",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/cli.js CHANGED
@@ -278,7 +278,7 @@ export function parseArgs(args) {
278
278
  const key = arg.slice(2);
279
279
  const next = args[i + 1];
280
280
 
281
- if (key === 'pretty' || key === 'help' || key === 'table' || key === 'no-retry' || key === 'cache' || key === 'no-cache') {
281
+ if (key === 'pretty' || key === 'help' || key === 'table' || key === 'no-retry' || key === 'cache' || key === 'no-cache' || key === 'stream') {
282
282
  result.flags[key] = true;
283
283
  } else if (next && !next.startsWith('-')) {
284
284
  // Try to parse as JSON first
@@ -411,6 +411,34 @@ export function formatError(error) {
411
411
  };
412
412
  }
413
413
 
414
+ /**
415
+ * Format data as JSON lines (NDJSON) for streaming output
416
+ * Each record is output as a separate JSON line
417
+ */
418
+ export function formatStream(data) {
419
+ // Extract array of records from various response shapes
420
+ let records = [];
421
+ if (Array.isArray(data)) {
422
+ records = data;
423
+ } else if (data?.data && Array.isArray(data.data)) {
424
+ records = data.data;
425
+ } else if (data?.results && Array.isArray(data.results)) {
426
+ records = data.results;
427
+ } else if (data?.data?.results && Array.isArray(data.data.results)) {
428
+ records = data.data.results;
429
+ } else if (typeof data === 'object' && data !== null) {
430
+ // Single object - output as single line
431
+ records = [data];
432
+ }
433
+
434
+ if (records.length === 0) {
435
+ return '';
436
+ }
437
+
438
+ // Output each record as a separate JSON line
439
+ return records.map(record => JSON.stringify(record)).join('\n');
440
+ }
441
+
414
442
  // Parse simple sort syntax: "field:direction" or "field" (defaults to DESC)
415
443
  export function parseSort(sortOption, orderByOption) {
416
444
  // If --order-by is provided, use it (full JSON control)
@@ -463,6 +491,7 @@ GLOBAL OPTIONS:
463
491
  --cache Enable response caching (default: off)
464
492
  --no-cache Disable cache for this request
465
493
  --cache-ttl <s> Cache TTL in seconds (default: 300)
494
+ --stream Output as JSON lines (NDJSON) for incremental processing
466
495
 
467
496
  EXAMPLES:
468
497
  # Get Smart Money netflow on Solana
@@ -814,6 +843,7 @@ export async function runCLI(rawArgs, deps = {}) {
814
843
  const subArgs = positional.slice(1);
815
844
  const pretty = flags.pretty || flags.p;
816
845
  const table = flags.table || flags.t;
846
+ const stream = flags.stream || flags.s;
817
847
 
818
848
  const commands = { ...buildCommands(deps), ...commandOverrides };
819
849
 
@@ -868,6 +898,16 @@ export async function runCLI(rawArgs, deps = {}) {
868
898
  result = filterFields(result, fields);
869
899
  }
870
900
 
901
+ // Output in requested format
902
+ if (stream) {
903
+ // Stream mode: output each record as a JSON line (NDJSON)
904
+ const streamOutput = formatStream(result);
905
+ if (streamOutput) {
906
+ output(streamOutput);
907
+ }
908
+ return { type: 'stream', data: result };
909
+ }
910
+
871
911
  const successData = { success: true, data: result };
872
912
  const formatted = formatOutput(successData, { pretty, table });
873
913
  output(formatted.text);