inspeffct 1.0.6 → 1.0.7

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 (2) hide show
  1. package/dist/bin.js +68 -192
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import * as NodeRuntime from '@effect/platform-node/NodeRuntime';
3
3
  import * as NodeServices from '@effect/platform-node/NodeServices';
4
4
  import * as Effect10 from 'effect/Effect';
5
- import * as Command6 from 'effect/unstable/cli/Command';
5
+ import * as Command5 from 'effect/unstable/cli/Command';
6
6
  import * as Argument3 from 'effect/unstable/cli/Argument';
7
7
  import * as Context4 from 'effect/Context';
8
8
  import * as Fiber from 'effect/Fiber';
@@ -30,14 +30,14 @@ import * as SchemaGetter from 'effect/SchemaGetter';
30
30
  import { flow } from 'effect/Function';
31
31
  import * as NodeFileSystem from '@effect/platform-node/NodeFileSystem';
32
32
  import * as NodePath from '@effect/platform-node/NodePath';
33
- import * as Flag3 from 'effect/unstable/cli/Flag';
33
+ import * as Flag from 'effect/unstable/cli/Flag';
34
34
  import * as NodeSocketServer from '@effect/platform-node/NodeSocketServer';
35
35
  import * as crypto from 'crypto';
36
36
  import * as fs from 'fs';
37
37
  import * as os from 'os';
38
38
  import * as path from 'path';
39
39
  import * as Console2 from 'effect/Console';
40
- import * as Option3 from 'effect/Option';
40
+ import * as Option4 from 'effect/Option';
41
41
  import * as ChildProcess from 'effect/unstable/process/ChildProcess';
42
42
  import * as Duration from 'effect/Duration';
43
43
  import * as Graph from 'effect/Graph';
@@ -1110,18 +1110,18 @@ Effect10.map(IpcServer, (server) => server.messages);
1110
1110
  Effect10.flatMap(IpcServer, (server) => server.subscribe);
1111
1111
 
1112
1112
  // src/cli/options.ts
1113
- var dataOption = Flag3.string("data").pipe(
1114
- Flag3.withDescription("Path to SQLite database file"),
1115
- Flag3.withDefault(".inspeffct.db")
1113
+ var dataOption = Flag.string("data").pipe(
1114
+ Flag.withDescription("Path to SQLite database file"),
1115
+ Flag.withDefault(".inspeffct.db")
1116
1116
  );
1117
- var jsonOption = Flag3.boolean("json").pipe(
1118
- Flag3.withDescription("Output as JSON"),
1119
- Flag3.withDefault(false)
1117
+ var jsonOption = Flag.boolean("json").pipe(
1118
+ Flag.withDescription("Output as JSON"),
1119
+ Flag.withDefault(false)
1120
1120
  );
1121
- var limitOption = Flag3.integer("limit").pipe(
1122
- Flag3.withAlias("n"),
1123
- Flag3.withDescription("Maximum number of results"),
1124
- Flag3.optional
1121
+ var limitOption = Flag.integer("limit").pipe(
1122
+ Flag.withAlias("n"),
1123
+ Flag.withDescription("Maximum number of results"),
1124
+ Flag.optional
1125
1125
  );
1126
1126
  var buildEnv = (bootloaderPath, ipcPath) => {
1127
1127
  const requireFlag = `--require "${bootloaderPath}"`;
@@ -1163,7 +1163,7 @@ var makeServicesLayer = (dataPath) => {
1163
1163
  var makeReadOnlyLayer = (dataPath) => layer5({ filename: dataPath });
1164
1164
 
1165
1165
  // src/cli/connect.ts
1166
- var command = Command6.make(
1166
+ var command = Command5.make(
1167
1167
  "connect",
1168
1168
  {
1169
1169
  data: dataOption,
@@ -1183,8 +1183,8 @@ var command = Command6.make(
1183
1183
  Effect10.provide(makeServicesLayer(data))
1184
1184
  )
1185
1185
  ).pipe(
1186
- Command6.withDescription("Connect to an existing CDP inspector endpoint"),
1187
- Command6.withExamples([
1186
+ Command5.withDescription("Connect to an existing CDP inspector endpoint"),
1187
+ Command5.withExamples([
1188
1188
  {
1189
1189
  command: "inspeffct connect ws://127.0.0.1:9229/<id>",
1190
1190
  description: "Connect to a running Node.js inspector endpoint"
@@ -1209,13 +1209,13 @@ var parseInspectorUrl = (chunk, decoder) => {
1209
1209
  }
1210
1210
  return void 0;
1211
1211
  };
1212
- var command2 = Command6.make(
1212
+ var command2 = Command5.make(
1213
1213
  "run",
1214
1214
  {
1215
1215
  data: dataOption,
1216
- encodedCommand: Flag3.string("encoded-command").pipe(
1217
- Flag3.optional,
1218
- Flag3.withHidden
1216
+ encodedCommand: Flag.string("encoded-command").pipe(
1217
+ Flag.optional,
1218
+ Flag.withHidden
1219
1219
  ),
1220
1220
  args: Argument3.string("command").pipe(
1221
1221
  Argument3.withDescription("The command to run"),
@@ -1223,7 +1223,7 @@ var command2 = Command6.make(
1223
1223
  )
1224
1224
  },
1225
1225
  ({ args, data, encodedCommand }) => Effect10.gen(function* () {
1226
- const resolvedArgs = Option3.isSome(encodedCommand) ? JSON.parse(Buffer.from(encodedCommand.value, "base64url").toString("utf8")) : args;
1226
+ const resolvedArgs = Option4.isSome(encodedCommand) ? JSON.parse(Buffer.from(encodedCommand.value, "base64url").toString("utf8")) : args;
1227
1227
  const [rawExecutable, ...commandArgs] = resolvedArgs;
1228
1228
  const executable = rawExecutable === "node" ? process.execPath : rawExecutable;
1229
1229
  const runId = yield* RunId;
@@ -1281,8 +1281,8 @@ var command2 = Command6.make(
1281
1281
  Effect10.provide(makeServicesLayer(data))
1282
1282
  )
1283
1283
  ).pipe(
1284
- Command6.withDescription("Run a command with Effect instrumentation"),
1285
- Command6.withExamples([
1284
+ Command5.withDescription("Run a command with Effect instrumentation"),
1285
+ Command5.withExamples([
1286
1286
  {
1287
1287
  command: "inspeffct run -- node app.js",
1288
1288
  description: "Run a Node.js application with instrumentation"
@@ -1394,16 +1394,20 @@ var formatSpanAttributesLine = (span) => {
1394
1394
  if (attributes.length === 0) {
1395
1395
  return null;
1396
1396
  }
1397
- return attributes.map(([key, value]) => `${key}=${formatAttributeValue(value)}`).join(", ");
1397
+ const rendered = attributes.slice(0, 3).map(([key, value]) => `${key}=${formatAttributeValue(value)}`);
1398
+ if (attributes.length > 3) {
1399
+ rendered.push("...");
1400
+ }
1401
+ return rendered.join(", ");
1398
1402
  };
1399
1403
  var renderGraphNode = (graph, nodeIndex, prefix, isLast, isRoot) => {
1400
1404
  const spanOpt = Graph.getNode(graph, nodeIndex);
1401
- if (Option3.isNone(spanOpt)) return "";
1405
+ if (Option4.isNone(spanOpt)) return "";
1402
1406
  const span = spanOpt.value;
1403
1407
  const children = [];
1404
1408
  for (const childIndex of Graph.neighbors(graph, nodeIndex)) {
1405
1409
  const childSpanOpt = Graph.getNode(graph, childIndex);
1406
- if (Option3.isSome(childSpanOpt)) {
1410
+ if (Option4.isSome(childSpanOpt)) {
1407
1411
  children.push({ index: childIndex, span: childSpanOpt.value });
1408
1412
  }
1409
1413
  }
@@ -1434,7 +1438,10 @@ var renderSpanGraph = (graph) => {
1434
1438
 
1435
1439
  // src/cli/span.ts
1436
1440
  var attributesToObject = (attributes) => Object.fromEntries(attributes);
1437
- var command3 = Command6.make(
1441
+ var getSpanExit = (span) => span._tag === "Span" && span.status._tag === "Ended" ? span.status.exit : null;
1442
+ var stringifyJson = (value) => JSON.stringify(value, (_key, value2) => typeof value2 === "bigint" ? value2.toString() : value2, 2);
1443
+ var formatExitBlock = (exit) => ["Exit:", ...stringifyJson(exit).split("\n").map((line) => ` ${line}`)].join("\n");
1444
+ var command3 = Command5.make(
1438
1445
  "span",
1439
1446
  {
1440
1447
  data: dataOption,
@@ -1459,6 +1466,7 @@ var command3 = Command6.make(
1459
1466
  const startTime = getStartTime(span);
1460
1467
  const endTime = getEndTime(span);
1461
1468
  const durationNanos = endTime !== null ? endTime - startTime : null;
1469
+ const exit = getSpanExit(span);
1462
1470
  if (json) {
1463
1471
  const output = {
1464
1472
  span: {
@@ -1473,6 +1481,7 @@ var command3 = Command6.make(
1473
1481
  endTime: endTime !== null ? formatTimestamp(endTime) : null,
1474
1482
  durationMs: durationNanos !== null ? Number(durationNanos / 1000000n) : null,
1475
1483
  attributes: getAttributes(span),
1484
+ exit,
1476
1485
  isExternal: isExternalSpan(span)
1477
1486
  },
1478
1487
  events: events.map((event) => ({
@@ -1512,6 +1521,9 @@ var command3 = Command6.make(
1512
1521
  if (Object.keys(attrs).length > 0) {
1513
1522
  fields.push(field("Attrs", JSON.stringify(attrs)));
1514
1523
  }
1524
+ if (exit !== null) {
1525
+ fields.push(formatExitBlock(exit));
1526
+ }
1515
1527
  const eventDocs = events.length === 0 ? ["Events: none"] : [
1516
1528
  `Events (${events.length}):`,
1517
1529
  ...events.map((event) => {
@@ -1541,8 +1553,8 @@ var command3 = Command6.make(
1541
1553
  Effect10.provide(makeReadOnlyLayer(data))
1542
1554
  )
1543
1555
  ).pipe(
1544
- Command6.withDescription("Show detailed span information"),
1545
- Command6.withExamples([
1556
+ Command5.withDescription("Show detailed span information"),
1557
+ Command5.withExamples([
1546
1558
  {
1547
1559
  command: "inspeffct span <trace-id> <span-id>",
1548
1560
  description: "Show span details with events and links"
@@ -1553,143 +1565,7 @@ var command3 = Command6.make(
1553
1565
  }
1554
1566
  ])
1555
1567
  );
1556
- var command4 = Command6.make(
1557
- "spans",
1558
- {
1559
- data: dataOption,
1560
- runId: Flag3.string("run-id").pipe(
1561
- Flag3.withDescription("Filter by run ID"),
1562
- Flag3.optional
1563
- ),
1564
- json: jsonOption,
1565
- limit: limitOption,
1566
- minDuration: Flag3.string("min-duration").pipe(
1567
- Flag3.withDescription("Filter by minimum duration (e.g., '100ms', '1s')"),
1568
- Flag3.optional
1569
- ),
1570
- name: Flag3.string("name").pipe(
1571
- Flag3.withDescription("Filter by span name (use % for wildcards)"),
1572
- Flag3.optional
1573
- ),
1574
- spanId: Flag3.string("span-id").pipe(
1575
- Flag3.withDescription("Filter by span ID"),
1576
- Flag3.optional
1577
- ),
1578
- status: Flag3.string("status").pipe(
1579
- Flag3.withDescription("Filter by status: ok, error, unset"),
1580
- Flag3.optional
1581
- ),
1582
- trace: Flag3.string("trace-id").pipe(
1583
- Flag3.withAlias("t"),
1584
- Flag3.withDescription("Filter by trace ID"),
1585
- Flag3.optional
1586
- )
1587
- },
1588
- ({ data, json, limit, minDuration, name, runId, spanId, status, trace }) => Effect10.gen(function* () {
1589
- const storage = yield* Storage;
1590
- let statusCode;
1591
- if (Option3.isSome(status)) {
1592
- switch (status.value) {
1593
- case "ok":
1594
- statusCode = 1;
1595
- break;
1596
- case "error":
1597
- statusCode = 2;
1598
- break;
1599
- case "unset":
1600
- statusCode = 0;
1601
- break;
1602
- default:
1603
- yield* Effect10.logWarning(`Unknown status: ${status.value}, ignoring filter`);
1604
- }
1605
- }
1606
- const filters = {
1607
- ...Option3.isSome(runId) ? { runId: runId.value } : {},
1608
- ...Option3.isSome(spanId) ? { spanId: spanId.value } : {},
1609
- ...Option3.isSome(trace) ? { traceId: trace.value } : {},
1610
- ...Option3.isSome(name) ? { name: name.value } : {},
1611
- ...statusCode !== void 0 ? { status: statusCode } : {},
1612
- ...Option3.isSome(minDuration) ? { minDuration: parseDurationToNanos(minDuration.value) } : {},
1613
- ...Option3.isSome(limit) ? { limit: limit.value } : {}
1614
- };
1615
- const spans = yield* storage.getSpans(filters);
1616
- if (json) {
1617
- const output = spans.map((s) => {
1618
- const endTime = getEndTime(s);
1619
- const startTime = getStartTime(s);
1620
- return {
1621
- spanId: getSpanId(s),
1622
- traceId: getTraceId(s),
1623
- parentSpanId: getParentSpanId(s),
1624
- name: getSpanName(s),
1625
- kind: getSpanKind(s),
1626
- statusCode: getStatusCode(s),
1627
- statusMessage: getStatusMessage(s),
1628
- startTime: formatTimestamp(startTime),
1629
- endTime: endTime !== null ? formatTimestamp(endTime) : null,
1630
- durationMs: endTime !== null ? Number((endTime - startTime) / 1000000n) : null,
1631
- attributes: getAttributes(s),
1632
- isExternal: isExternalSpan(s)
1633
- };
1634
- });
1635
- yield* Console2.log(JSON.stringify(output, null, 2));
1636
- } else {
1637
- if (spans.length === 0) {
1638
- yield* Console2.log("No spans found.");
1639
- } else {
1640
- const spanItems = spans.map((s) => {
1641
- const endTime = getEndTime(s);
1642
- const startTime = getStartTime(s);
1643
- const duration = endTime !== null ? formatDuration(endTime - startTime) : "running";
1644
- const fields = [
1645
- field("Name", getSpanName(s)),
1646
- field("Trace", getTraceId(s))
1647
- ];
1648
- const parentSpanId = getParentSpanId(s);
1649
- if (parentSpanId) {
1650
- fields.push(field("Parent", parentSpanId));
1651
- }
1652
- fields.push(
1653
- field("Status", formatStatusDoc(getStatusCode(s))),
1654
- field("Started", formatTimestamp(startTime)),
1655
- field("Duration", duration)
1656
- );
1657
- const attrs = getAttributes(s);
1658
- if (Object.keys(attrs).length > 0) {
1659
- fields.push(field("Attrs", JSON.stringify(attrs)));
1660
- }
1661
- return [getSpanId(s), ...fields.map((field2) => ` ${field2}`)].join("\n");
1662
- });
1663
- const doc = [
1664
- `Found ${spans.length} span(s):`,
1665
- "",
1666
- ...spanItems
1667
- ].join("\n");
1668
- yield* Console2.log(renderDoc(doc));
1669
- }
1670
- }
1671
- }).pipe(
1672
- Effect10.scoped,
1673
- Effect10.provide(makeReadOnlyLayer(data))
1674
- )
1675
- ).pipe(
1676
- Command6.withDescription("List spans with optional filters (from multiple traces)"),
1677
- Command6.withExamples([
1678
- {
1679
- command: "inspeffct spans --trace-id <trace-id>",
1680
- description: "List spans for a trace"
1681
- },
1682
- {
1683
- command: "inspeffct spans --run-id <run-id>",
1684
- description: "List spans captured during a specific run"
1685
- },
1686
- {
1687
- command: "inspeffct spans --span-id <span-id>",
1688
- description: "Find a span directly by ID"
1689
- }
1690
- ])
1691
- );
1692
- var command5 = Command6.make(
1568
+ var command4 = Command5.make(
1693
1569
  "trace",
1694
1570
  {
1695
1571
  data: dataOption,
@@ -1711,7 +1587,7 @@ var command5 = Command6.make(
1711
1587
  if (json) {
1712
1588
  const buildJsonTree = (g, nodeIndex) => {
1713
1589
  const spanOpt = Graph.getNode(g, nodeIndex);
1714
- if (Option3.isNone(spanOpt)) return {};
1590
+ if (Option4.isNone(spanOpt)) return {};
1715
1591
  const span = spanOpt.value;
1716
1592
  const endTime = getEndTime(span);
1717
1593
  const startTime = getStartTime(span);
@@ -1719,7 +1595,7 @@ var command5 = Command6.make(
1719
1595
  const children = [];
1720
1596
  for (const childIndex of Graph.neighbors(g, nodeIndex)) {
1721
1597
  const childSpanOpt = Graph.getNode(g, childIndex);
1722
- if (Option3.isSome(childSpanOpt)) {
1598
+ if (Option4.isSome(childSpanOpt)) {
1723
1599
  children.push({ index: childIndex, span: childSpanOpt.value });
1724
1600
  }
1725
1601
  }
@@ -1759,11 +1635,11 @@ var command5 = Command6.make(
1759
1635
  Effect10.provide(makeReadOnlyLayer(data))
1760
1636
  )
1761
1637
  ).pipe(
1762
- Command6.withDescription("Show a trace as a tree view with its spans as well"),
1763
- Command6.withExamples([
1638
+ Command5.withDescription("Show a trace and all spans related to that trace as a tree view"),
1639
+ Command5.withExamples([
1764
1640
  {
1765
1641
  command: "inspeffct trace <trace-id>",
1766
- description: "Show a trace tree"
1642
+ description: "Show the trace tree with related spans"
1767
1643
  },
1768
1644
  {
1769
1645
  command: "inspeffct trace --json <trace-id>",
@@ -1771,29 +1647,29 @@ var command5 = Command6.make(
1771
1647
  }
1772
1648
  ])
1773
1649
  );
1774
- var command6 = Command6.make(
1650
+ var command5 = Command5.make(
1775
1651
  "traces",
1776
1652
  {
1777
1653
  data: dataOption,
1778
1654
  json: jsonOption,
1779
- runId: Flag3.string("run-id").pipe(
1780
- Flag3.withDescription("Filter by run ID"),
1781
- Flag3.optional
1655
+ runId: Flag.string("run-id").pipe(
1656
+ Flag.withDescription("Filter by run ID"),
1657
+ Flag.optional
1782
1658
  ),
1783
1659
  limit: limitOption,
1784
- since: Flag3.string("since").pipe(
1785
- Flag3.withDescription("Filter by time range (e.g., '1h', '30m')"),
1786
- Flag3.optional
1660
+ since: Flag.string("since").pipe(
1661
+ Flag.withDescription("Filter by time range (e.g., '1h', '30m')"),
1662
+ Flag.optional
1787
1663
  ),
1788
- status: Flag3.string("status").pipe(
1789
- Flag3.withDescription("Filter by status: ok, error, unset"),
1790
- Flag3.optional
1664
+ status: Flag.string("status").pipe(
1665
+ Flag.withDescription("Filter by status: ok, error, unset"),
1666
+ Flag.optional
1791
1667
  )
1792
1668
  },
1793
1669
  ({ data, json, limit, runId, since, status }) => Effect10.gen(function* () {
1794
1670
  const storage = yield* Storage;
1795
1671
  let statusCode;
1796
- if (Option3.isSome(status)) {
1672
+ if (Option4.isSome(status)) {
1797
1673
  switch (status.value) {
1798
1674
  case "ok":
1799
1675
  statusCode = 1;
@@ -1809,16 +1685,16 @@ var command6 = Command6.make(
1809
1685
  }
1810
1686
  }
1811
1687
  let sinceNanos;
1812
- if (Option3.isSome(since)) {
1688
+ if (Option4.isSome(since)) {
1813
1689
  const nowNanos = BigInt(Date.now()) * 1000000n;
1814
1690
  const durationNanos = parseDurationToNanos(since.value);
1815
1691
  sinceNanos = nowNanos - durationNanos;
1816
1692
  }
1817
1693
  const filters = {
1818
- ...Option3.isSome(runId) ? { runId: runId.value } : {},
1694
+ ...Option4.isSome(runId) ? { runId: runId.value } : {},
1819
1695
  ...statusCode !== void 0 ? { status: statusCode } : {},
1820
1696
  ...sinceNanos !== void 0 ? { since: sinceNanos } : {},
1821
- ...Option3.isSome(limit) ? { limit: limit.value } : {}
1697
+ ...Option4.isSome(limit) ? { limit: limit.value } : {}
1822
1698
  };
1823
1699
  const traces = yield* storage.getTraces(filters);
1824
1700
  if (json) {
@@ -1860,8 +1736,8 @@ var command6 = Command6.make(
1860
1736
  Effect10.provide(makeReadOnlyLayer(data))
1861
1737
  )
1862
1738
  ).pipe(
1863
- Command6.withDescription("List traces with optional filters"),
1864
- Command6.withExamples([
1739
+ Command5.withDescription("List traces with optional filters"),
1740
+ Command5.withExamples([
1865
1741
  {
1866
1742
  command: "inspeffct traces",
1867
1743
  description: "List recent traces"
@@ -1878,16 +1754,16 @@ var command6 = Command6.make(
1878
1754
  );
1879
1755
 
1880
1756
  // src/cli.ts
1881
- var command7 = Command6.make("inspeffct").pipe(
1882
- Command6.withDescription(
1757
+ var command6 = Command5.make("inspeffct").pipe(
1758
+ Command5.withDescription(
1883
1759
  "Run your Effect application with `npx inspeffct run ...` to start capturing data, and then inspect data with the CLI."
1884
1760
  ),
1885
- Command6.withSubcommands([
1761
+ Command5.withSubcommands([
1886
1762
  { group: "Capture", commands: [command2, command] },
1887
- { group: "Inspect", commands: [command6, command5, command4, command3] }
1763
+ { group: "Inspect", commands: [command5, command4, command3] }
1888
1764
  ])
1889
1765
  );
1890
- var cli = Command6.runWith(command7, {
1766
+ var cli = Command5.runWith(command6, {
1891
1767
  version: "0.0.1"
1892
1768
  });
1893
1769
  var encodeRunSeparator = (args) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inspeffct",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "type": "module",
5
5
  "description": "A CLI to help agents and humans inspect Effect applications",
6
6
  "license": "MIT",