inspeffct 0.1.1 → 1.0.1

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 (3) hide show
  1. package/dist/bin.js +1296 -31457
  2. package/dist/bootloader.cjs +185 -64
  3. package/package.json +5 -9
@@ -57,6 +57,41 @@
57
57
 
58
58
  // src/Encoder.ts
59
59
  var constFailure2 = { _tag: "Failure" };
60
+ var formatBestEffort = (value) => {
61
+ const seen = /* @__PURE__ */ new WeakSet();
62
+ const go = (input) => {
63
+ if (input === null) return "null";
64
+ switch (typeof input) {
65
+ case "string":
66
+ return JSON.stringify(input);
67
+ case "number":
68
+ case "boolean":
69
+ case "bigint":
70
+ return String(input);
71
+ case "undefined":
72
+ return "undefined";
73
+ case "symbol":
74
+ return String(input);
75
+ case "function":
76
+ return `[Function: ${input.name || "anonymous"}]`;
77
+ case "object": {
78
+ if (seen.has(input)) return "[Circular]";
79
+ seen.add(input);
80
+ if (Array.isArray(input)) {
81
+ return `[${input.map(go).join(", ")}]`;
82
+ }
83
+ if (input instanceof Error) {
84
+ return `${input.name}: ${input.message}`;
85
+ }
86
+ const entries = Object.keys(input).map((key) => `${key}: ${go(input[key])}`);
87
+ return `{ ${entries.join(", ")} }`;
88
+ }
89
+ default:
90
+ return String(input);
91
+ }
92
+ };
93
+ return go(value);
94
+ };
60
95
  var literal2 = (value) => (givenValue) => givenValue === value ? { _tag: "Success", value } : constFailure2;
61
96
  var string2 = (value) => typeof value === "string" ? { _tag: "Success", value } : constFailure2;
62
97
  var boolean = (value) => typeof value === "boolean" ? { _tag: "Success", value } : constFailure2;
@@ -105,6 +140,13 @@
105
140
  return { _tag: "Success", value: result };
106
141
  };
107
142
  var unknown = (value) => ({ _tag: "Success", value });
143
+ var bestEffortAny = (value) => {
144
+ try {
145
+ return { _tag: "Success", value: JSON.parse(JSON.stringify(value)) };
146
+ } catch {
147
+ return { _tag: "Success", value: formatBestEffort(value) };
148
+ }
149
+ };
108
150
  var lazy = (thunk) => (value) => thunk()(value);
109
151
 
110
152
  // src/ProtocolEncoder.generated.ts
@@ -113,23 +155,23 @@
113
155
  var InitNotification = struct2({ _tag: literal2("InitNotification"), protocolVersion: ProtocolVersion2, instrumentationId: InstrumentationId2, inspectorURL: union2(string2, literal2(null)), waitingForDebugger: boolean });
114
156
  var PingNotification = struct2({ _tag: literal2("PingNotification"), protocolVersion: ProtocolVersion2, instrumentationId: InstrumentationId2 });
115
157
  var SpanAttributes = array2(tuple(string2, unknown));
116
- var BigInt = bigint;
117
- var SpanStatusStarted = struct2({ _tag: literal2("Started"), startTime: BigInt });
158
+ var SpanStatusStarted = struct2({ _tag: literal2("Started"), startTime: bigint });
159
+ var BestEffortAny = bestEffortAny;
118
160
  var FiberIdNoneEncoded = struct2({ _tag: literal2("None") });
119
161
  var Int = number;
120
162
  var FiberIdRuntimeEncoded = struct2({ _tag: literal2("Runtime"), id: Int, startTimeMillis: Int });
121
163
  var FiberIdCompositeEncoded = struct2({ _tag: literal2("Composite"), left: lazy(() => FiberIdEncoded), right: lazy(() => FiberIdEncoded) });
122
164
  var FiberIdEncoded = union2(FiberIdNoneEncoded, FiberIdRuntimeEncoded, FiberIdCompositeEncoded);
123
- var CauseEncoded3 = union2(struct2({ _tag: literal2("Empty") }), struct2({ _tag: literal2("Fail"), error: unknown }), struct2({ _tag: literal2("Die"), defect: unknown }), struct2({ _tag: literal2("Interrupt"), fiberId: FiberIdEncoded }), struct2({ _tag: literal2("Sequential"), left: lazy(() => CauseEncoded3), right: lazy(() => CauseEncoded3) }), struct2({ _tag: literal2("Parallel"), left: lazy(() => CauseEncoded3), right: lazy(() => CauseEncoded3) }));
124
- var SpanExit = union2(struct2({ _tag: literal2("Failure"), cause: CauseEncoded3 }), struct2({ _tag: literal2("Success"), value: unknown }));
125
- var SpanStatusEnded = struct2({ _tag: literal2("Ended"), startTime: BigInt, endTime: BigInt, exit: SpanExit });
165
+ var CauseEncoded3 = union2(struct2({ _tag: literal2("Empty") }), struct2({ _tag: literal2("Fail"), error: BestEffortAny }), struct2({ _tag: literal2("Die"), defect: BestEffortAny }), struct2({ _tag: literal2("Interrupt"), fiberId: FiberIdEncoded }), struct2({ _tag: literal2("Sequential"), left: lazy(() => CauseEncoded3), right: lazy(() => CauseEncoded3) }), struct2({ _tag: literal2("Parallel"), left: lazy(() => CauseEncoded3), right: lazy(() => CauseEncoded3) }));
166
+ var SpanExit = union2(struct2({ _tag: literal2("Failure"), cause: CauseEncoded3 }), struct2({ _tag: literal2("Success"), value: BestEffortAny }));
167
+ var SpanStatusEnded = struct2({ _tag: literal2("Ended"), startTime: bigint, endTime: bigint, exit: SpanExit });
126
168
  var SpanStatus = union2(SpanStatusStarted, SpanStatusEnded);
127
169
  var SpanAndTraceId = struct2({ traceId: string2, spanId: string2 });
128
170
  var Span = struct2({ _tag: literal2("Span"), spanId: string2, traceId: string2, name: string2, sampled: boolean, attributes: SpanAttributes, status: SpanStatus, parent: union2(SpanAndTraceId, literal2(null)) });
129
171
  var ExternalSpan = struct2({ _tag: literal2("ExternalSpan"), spanId: string2, traceId: string2, sampled: boolean });
130
172
  var AnySpan = union2(Span, ExternalSpan);
131
173
  var TracerSpanNotification = struct2({ _tag: literal2("TracerSpanNotification"), protocolVersion: ProtocolVersion2, instrumentationId: InstrumentationId2, span: AnySpan });
132
- var SpanEvent = struct2({ spanId: string2, traceId: string2, name: string2, time: BigInt, attributes: SpanAttributes });
174
+ var SpanEvent = struct2({ spanId: string2, traceId: string2, name: string2, time: bigint, attributes: SpanAttributes });
133
175
  var TracerSpanEventNotification = struct2({ _tag: literal2("TracerSpanEventNotification"), protocolVersion: ProtocolVersion2, instrumentationId: InstrumentationId2, event: SpanEvent });
134
176
  var SpanLink = struct2({ spanId: string2, traceId: string2, linkedSpanId: string2, linkedTraceId: string2, attributes: SpanAttributes });
135
177
  var TracerSpanLinkNotification = struct2({ _tag: literal2("TracerSpanLinkNotification"), protocolVersion: ProtocolVersion2, instrumentationId: InstrumentationId2, link: SpanLink });
@@ -269,28 +311,28 @@
269
311
  }
270
312
  }
271
313
  function serializeCause(cause) {
272
- switch (cause._tag) {
273
- case "Empty":
274
- return { _tag: "Empty" };
275
- case "Fail":
276
- return { _tag: "Fail", error: serializeToJson(cause.error) };
277
- case "Die":
278
- return { _tag: "Die", defect: serializeToJson(cause.defect) };
279
- case "Interrupt":
280
- return { _tag: "Interrupt", fiberId: serializeFiberId(cause.fiberId) };
281
- case "Sequential":
282
- return {
283
- _tag: "Sequential",
284
- left: cause.left ? serializeCause(cause.left) : { _tag: "Empty" },
285
- right: cause.right ? serializeCause(cause.right) : { _tag: "Empty" }
286
- };
287
- case "Parallel":
288
- return {
289
- _tag: "Parallel",
290
- left: cause.left ? serializeCause(cause.left) : { _tag: "Empty" },
291
- right: cause.right ? serializeCause(cause.right) : { _tag: "Empty" }
292
- };
314
+ const serializedReasons = cause.reasons.map((reason) => {
315
+ switch (reason._tag) {
316
+ case "Fail":
317
+ return { _tag: "Fail", error: serializeToJson(reason.error) };
318
+ case "Die":
319
+ return { _tag: "Die", defect: serializeToJson(reason.defect) };
320
+ case "Interrupt":
321
+ return { _tag: "Interrupt", fiberId: serializeFiberId(reason.fiberId) };
322
+ }
323
+ });
324
+ if (serializedReasons.length === 0) {
325
+ return { _tag: "Empty" };
326
+ }
327
+ let current = serializedReasons[0];
328
+ for (let i = 1; i < serializedReasons.length; i++) {
329
+ current = {
330
+ _tag: "Sequential",
331
+ left: current,
332
+ right: serializedReasons[i]
333
+ };
293
334
  }
335
+ return current;
294
336
  }
295
337
  function serializeExit(exit) {
296
338
  if (exit._tag === "Success") {
@@ -371,6 +413,8 @@ c.on("connect", () => {
371
413
  return false;
372
414
  }
373
415
  }
416
+ var CURRENT_FIBER_KEY = "~effect/Fiber/currentFiber";
417
+ var TRACER_KEY = "effect/Tracer";
374
418
  var _globalThis = globalThis;
375
419
  function getIpcSocketPath() {
376
420
  if (typeof process !== "undefined" && process.env) {
@@ -380,9 +424,9 @@ c.on("connect", () => {
380
424
  }
381
425
  function shouldWaitForDebugger() {
382
426
  if (typeof process !== "undefined" && process.env) {
383
- return process.env.INSPEFFCT_NO_WAIT !== "1";
427
+ return process.env.INSPEFFCT_WAIT === "1";
384
428
  }
385
- return true;
429
+ return false;
386
430
  }
387
431
  function waitForDebuggerNow() {
388
432
  try {
@@ -435,10 +479,11 @@ c.on("connect", () => {
435
479
  const ipcSocketPath = getIpcSocketPath();
436
480
  const inspectorInfo = getInspectorInfo();
437
481
  const bridgeAlreadyExists = typeof _globalThis.__inspeffct_bridge__ === "function";
438
- const shouldWait = shouldWaitForDebugger() && inspectorInfo.weOpenedInspector && !bridgeAlreadyExists;
482
+ const shouldWait = (shouldWaitForDebugger() || inspectorInfo.weOpenedInspector) && !bridgeAlreadyExists;
439
483
  const instrumentation = createInstrumentation({ inspectorURL: inspectorInfo.inspectorURL }, shouldWait, (message) => {
440
484
  _globalThis["__inspeffct__"]?.onmessage(message);
441
485
  });
486
+ instrumentation.installEffectModulePatch();
442
487
  _globalThis["__inspeffct__"] = {
443
488
  send: instrumentation.handleMessage,
444
489
  onmessage: (message) => {
@@ -456,11 +501,11 @@ c.on("connect", () => {
456
501
  console.log("[inspeffct] No transport available, message:", message);
457
502
  }
458
503
  };
459
- addSetInterceptor(_globalThis, "effect/FiberCurrent", (newFiber) => {
504
+ addSetInterceptor(_globalThis, CURRENT_FIBER_KEY, (newFiber) => {
460
505
  if (newFiber) instrumentation.ensureFiberIsTracked(newFiber);
461
506
  });
462
- if (_globalThis["effect/FiberCurrent"]) {
463
- instrumentation.ensureFiberIsTracked(_globalThis["effect/FiberCurrent"]);
507
+ if (_globalThis[CURRENT_FIBER_KEY]) {
508
+ instrumentation.ensureFiberIsTracked(_globalThis[CURRENT_FIBER_KEY]);
464
509
  }
465
510
  instrumentation.sendInitNotification();
466
511
  if (shouldWait && inspectorInfo.inspectorURL) {
@@ -479,6 +524,7 @@ c.on("connect", () => {
479
524
  parts.push(Math.random().toString(36).slice(2, 8));
480
525
  const instrumentationId = parts.join("-");
481
526
  const protocolVersion = 1;
527
+ const NATIVE_SPAN_PATCHED = "__inspeffct_native_span_patched__";
482
528
  function sendBack(event) {
483
529
  try {
484
530
  const encodedEvent = OutMessage(event);
@@ -510,12 +556,61 @@ c.on("connect", () => {
510
556
  }
511
557
  }
512
558
  const fibers = [];
559
+ const patchedFibers = /* @__PURE__ */ new WeakSet();
560
+ const patchedSpans = /* @__PURE__ */ new WeakSet();
561
+ function getFiberTracer(fiber) {
562
+ return fiber.context.mapUnsafe.get(TRACER_KEY);
563
+ }
564
+ function ensureSpanIsTracked(span) {
565
+ if (!span || span._tag !== "Span") {
566
+ return;
567
+ }
568
+ if (patchedSpans.has(span)) {
569
+ return;
570
+ }
571
+ patchedSpans.add(span);
572
+ sendTracerSpanNotification(span);
573
+ for (const link of span.links) {
574
+ sendTracerSpanLinkNotification(span, link);
575
+ }
576
+ const originalEnd = span.end;
577
+ span.end = function(...endArgs) {
578
+ originalEnd.apply(this, endArgs);
579
+ sendTracerSpanNotification(span);
580
+ };
581
+ const originalEvent = span.event;
582
+ span.event = function(name, time, attributes) {
583
+ originalEvent.apply(this, arguments);
584
+ sendTracerSpanEventNotification(span, name, time, attributes);
585
+ };
586
+ const originalAddLinks = span.addLinks;
587
+ span.addLinks = function(links) {
588
+ originalAddLinks.apply(this, arguments);
589
+ for (const link of links) {
590
+ sendTracerSpanLinkNotification(span, link);
591
+ }
592
+ };
593
+ }
594
+ function patchFiberContextTracking(fiber) {
595
+ if (patchedFibers.has(fiber)) {
596
+ return;
597
+ }
598
+ patchedFibers.add(fiber);
599
+ ensureSpanIsTracked(fiber.currentSpan);
600
+ const originalSetContext = fiber.setContext;
601
+ fiber.setContext = function(context) {
602
+ originalSetContext.call(this, context);
603
+ ensureSpanIsTracked(this.currentSpan);
604
+ };
605
+ }
513
606
  function ensureFiberIsTracked(fiber) {
514
607
  if (!fiber) return;
515
608
  if (fibers.indexOf(fiber) !== -1) return;
516
609
  fibers.push(fiber);
517
- ensureTracerIsTracked(fiber.currentTracer);
518
- if (fiber._children !== null) {
610
+ patchFiberContextTracking(fiber);
611
+ const tracer = getFiberTracer(fiber);
612
+ if (tracer) ensureTracerIsTracked(tracer);
613
+ if (fiber._children !== void 0) {
519
614
  fiber._children.forEach(ensureFiberIsTracked);
520
615
  }
521
616
  fiber.addObserver(() => {
@@ -531,36 +626,19 @@ c.on("connect", () => {
531
626
  const originalSpan = tracer.span;
532
627
  tracer.span = function(...args) {
533
628
  const span = originalSpan.apply(this, args);
534
- sendTracerSpanNotification(span);
535
- for (const link of span.links) {
536
- sendTracerSpanLinkNotification(span, link);
537
- }
538
- const originalEnd = span.end;
539
- span.end = function(...endArgs) {
540
- originalEnd.apply(this, endArgs);
541
- sendTracerSpanNotification(span);
542
- };
543
- const originalEvent = span.event;
544
- span.event = function(name, time, attributes) {
545
- originalEvent.apply(this, arguments);
546
- sendTracerSpanEventNotification(span, name, time, attributes);
547
- };
548
- const originalAddLinks = span.addLinks;
549
- span.addLinks = function(links) {
550
- originalAddLinks.apply(this, arguments);
551
- for (const link of links) {
552
- sendTracerSpanLinkNotification(span, link);
553
- }
554
- };
629
+ ensureSpanIsTracked(span);
555
630
  return span;
556
631
  };
557
632
  const originalContext = tracer.context;
558
- tracer.context = function(f, fiber) {
559
- const context = originalContext.apply(this, arguments);
560
- ensureFiberIsTracked(fiber);
561
- ensureTracerIsTracked(fiber.currentTracer);
562
- return context;
563
- };
633
+ if (originalContext) {
634
+ tracer.context = function(f, fiber) {
635
+ const context = originalContext.apply(this, arguments);
636
+ ensureFiberIsTracked(fiber);
637
+ const tracer2 = getFiberTracer(fiber);
638
+ if (tracer2) ensureTracerIsTracked(tracer2);
639
+ return context;
640
+ };
641
+ }
564
642
  }
565
643
  function sendTracerSpanNotification(span) {
566
644
  if (span._tag === "ExternalSpan") {
@@ -627,6 +705,48 @@ c.on("connect", () => {
627
705
  }
628
706
  });
629
707
  }
708
+ function patchNativeSpanPrototype(NativeSpan) {
709
+ if (!NativeSpan?.prototype || NativeSpan.prototype[NATIVE_SPAN_PATCHED]) {
710
+ return;
711
+ }
712
+ NativeSpan.prototype[NATIVE_SPAN_PATCHED] = true;
713
+ const originalEnd = NativeSpan.prototype.end;
714
+ NativeSpan.prototype.end = function(endTime, exit) {
715
+ originalEnd.call(this, endTime, exit);
716
+ sendTracerSpanNotification(this);
717
+ };
718
+ const originalEvent = NativeSpan.prototype.event;
719
+ NativeSpan.prototype.event = function(name, startTime, attributes) {
720
+ originalEvent.call(this, name, startTime, attributes);
721
+ sendTracerSpanEventNotification(this, name, startTime, attributes);
722
+ };
723
+ const originalAddLinks = NativeSpan.prototype.addLinks;
724
+ NativeSpan.prototype.addLinks = function(links) {
725
+ originalAddLinks.call(this, links);
726
+ for (const link of links) {
727
+ sendTracerSpanLinkNotification(this, link);
728
+ }
729
+ };
730
+ }
731
+ function installEffectModulePatch() {
732
+ try {
733
+ const Module = __require("module");
734
+ const originalLoad = Module._load;
735
+ if (!originalLoad || originalLoad.__inspeffct_patched__) {
736
+ return;
737
+ }
738
+ const patchedLoad = function(request, parent, isMain) {
739
+ const exports$1 = originalLoad.call(this, request, parent, isMain);
740
+ if (request === "effect") {
741
+ patchNativeSpanPrototype(exports$1?.Tracer?.NativeSpan);
742
+ }
743
+ return exports$1;
744
+ };
745
+ patchedLoad.__inspeffct_patched__ = true;
746
+ Module._load = patchedLoad;
747
+ } catch {
748
+ }
749
+ }
630
750
  const resources = /* @__PURE__ */ new Map();
631
751
  function handleVariableReferenceInfoRequest(req) {
632
752
  if (req.variableReferenceId.instrumentationId !== instrumentationId) return;
@@ -686,8 +806,8 @@ c.on("connect", () => {
686
806
  requestId: req.requestId,
687
807
  fibers: fibers.map((fiber) => ({
688
808
  _tag: "FiberInfo",
689
- id: globalThis.String(fiber.id().id),
690
- isCurrent: _globalThis["effect/FiberCurrent"] === fiber,
809
+ id: globalThis.String(fiber.id),
810
+ isCurrent: _globalThis[CURRENT_FIBER_KEY] === fiber,
691
811
  currentSpan: null
692
812
  // TODO: capture current span
693
813
  }))
@@ -713,6 +833,7 @@ c.on("connect", () => {
713
833
  ensureFiberIsTracked,
714
834
  ensureTracerIsTracked,
715
835
  handleMessage,
836
+ installEffectModulePatch,
716
837
  sendInitNotification,
717
838
  sendPingNotification,
718
839
  instrumentationId
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inspeffct",
3
- "version": "0.1.1",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "description": "A CLI to help agents and humans inspect Effect applications",
6
6
  "license": "MIT",
@@ -16,15 +16,11 @@
16
16
  "ws": "^8.18.3"
17
17
  },
18
18
  "devDependencies": {
19
- "@effect/cli": "^0.73.0",
20
- "@effect/platform": "^0.94.1",
21
- "@effect/platform-node": "^0.104.0",
22
- "@effect/printer-ansi": "^0.44.14",
23
- "@effect/sql": "^0.49.0",
24
- "@effect/sql-sqlite-node": "^0.50.0",
25
- "@effect/vitest": "^0.27.0",
19
+ "@effect/platform-node": "4.0.0-beta.70",
20
+ "@effect/sql-sqlite-node": "4.0.0-beta.70",
21
+ "@effect/vitest": "4.0.0-beta.70",
26
22
  "@types/ws": "^8.18.1",
27
- "effect": "^3.19.14",
23
+ "effect": "4.0.0-beta.70",
28
24
  "tsup": "^8.5.1"
29
25
  },
30
26
  "scripts": {