@effect-tui/react 0.1.0-alpha.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.
- package/LICENSE +21 -0
- package/README.md +138 -0
- package/dist/jsx-dev-runtime.d.ts +3 -0
- package/dist/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/jsx-dev-runtime.js +3 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.d.ts +47 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +6 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/src/codeblock.d.ts +9 -0
- package/dist/src/codeblock.d.ts.map +1 -0
- package/dist/src/codeblock.js +24 -0
- package/dist/src/codeblock.js.map +1 -0
- package/dist/src/constants.d.ts +3 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +3 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/debug/DiagnosticsPanel.d.ts +7 -0
- package/dist/src/debug/DiagnosticsPanel.d.ts.map +1 -0
- package/dist/src/debug/DiagnosticsPanel.js +13 -0
- package/dist/src/debug/DiagnosticsPanel.js.map +1 -0
- package/dist/src/highlight.d.ts +20 -0
- package/dist/src/highlight.d.ts.map +1 -0
- package/dist/src/highlight.js +51 -0
- package/dist/src/highlight.js.map +1 -0
- package/dist/src/hooks/index.d.ts +4 -0
- package/dist/src/hooks/index.d.ts.map +1 -0
- package/dist/src/hooks/index.js +3 -0
- package/dist/src/hooks/index.js.map +1 -0
- package/dist/src/hooks/use-keyboard.d.ts +18 -0
- package/dist/src/hooks/use-keyboard.d.ts.map +1 -0
- package/dist/src/hooks/use-keyboard.js +26 -0
- package/dist/src/hooks/use-keyboard.js.map +1 -0
- package/dist/src/hooks/use-paste.d.ts +5 -0
- package/dist/src/hooks/use-paste.d.ts.map +1 -0
- package/dist/src/hooks/use-paste.js +14 -0
- package/dist/src/hooks/use-paste.js.map +1 -0
- package/dist/src/hooks/useFrameStats.d.ts +7 -0
- package/dist/src/hooks/useFrameStats.d.ts.map +1 -0
- package/dist/src/hooks/useFrameStats.js +28 -0
- package/dist/src/hooks/useFrameStats.js.map +1 -0
- package/dist/src/hosts/base.d.ts +22 -0
- package/dist/src/hosts/base.d.ts.map +1 -0
- package/dist/src/hosts/base.js +53 -0
- package/dist/src/hosts/base.js.map +1 -0
- package/dist/src/hosts/box.d.ts +26 -0
- package/dist/src/hosts/box.d.ts.map +1 -0
- package/dist/src/hosts/box.js +84 -0
- package/dist/src/hosts/box.js.map +1 -0
- package/dist/src/hosts/canvas.d.ts +48 -0
- package/dist/src/hosts/canvas.d.ts.map +1 -0
- package/dist/src/hosts/canvas.js +109 -0
- package/dist/src/hosts/canvas.js.map +1 -0
- package/dist/src/hosts/codeblock.d.ts +32 -0
- package/dist/src/hosts/codeblock.d.ts.map +1 -0
- package/dist/src/hosts/codeblock.js +118 -0
- package/dist/src/hosts/codeblock.js.map +1 -0
- package/dist/src/hosts/hstack.d.ts +18 -0
- package/dist/src/hosts/hstack.d.ts.map +1 -0
- package/dist/src/hosts/hstack.js +45 -0
- package/dist/src/hosts/hstack.js.map +1 -0
- package/dist/src/hosts/index.d.ts +16 -0
- package/dist/src/hosts/index.d.ts.map +1 -0
- package/dist/src/hosts/index.js +40 -0
- package/dist/src/hosts/index.js.map +1 -0
- package/dist/src/hosts/spacer.d.ts +19 -0
- package/dist/src/hosts/spacer.d.ts.map +1 -0
- package/dist/src/hosts/spacer.js +28 -0
- package/dist/src/hosts/spacer.js.map +1 -0
- package/dist/src/hosts/text.d.ts +43 -0
- package/dist/src/hosts/text.d.ts.map +1 -0
- package/dist/src/hosts/text.js +148 -0
- package/dist/src/hosts/text.js.map +1 -0
- package/dist/src/hosts/vstack.d.ts +18 -0
- package/dist/src/hosts/vstack.d.ts.map +1 -0
- package/dist/src/hosts/vstack.js +45 -0
- package/dist/src/hosts/vstack.js.map +1 -0
- package/dist/src/hosts/zstack.d.ts +20 -0
- package/dist/src/hosts/zstack.d.ts.map +1 -0
- package/dist/src/hosts/zstack.js +65 -0
- package/dist/src/hosts/zstack.js.map +1 -0
- package/dist/src/index.d.ts +20 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +20 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/inline/index.d.ts +32 -0
- package/dist/src/inline/index.d.ts.map +1 -0
- package/dist/src/inline/index.js +111 -0
- package/dist/src/inline/index.js.map +1 -0
- package/dist/src/jsx.d.ts +2 -0
- package/dist/src/jsx.d.ts.map +1 -0
- package/dist/src/jsx.js +4 -0
- package/dist/src/jsx.js.map +1 -0
- package/dist/src/motion/color-motion-value.d.ts +32 -0
- package/dist/src/motion/color-motion-value.d.ts.map +1 -0
- package/dist/src/motion/color-motion-value.js +80 -0
- package/dist/src/motion/color-motion-value.js.map +1 -0
- package/dist/src/motion/color.d.ts +30 -0
- package/dist/src/motion/color.d.ts.map +1 -0
- package/dist/src/motion/color.js +172 -0
- package/dist/src/motion/color.js.map +1 -0
- package/dist/src/motion/color.test.d.ts +2 -0
- package/dist/src/motion/color.test.d.ts.map +1 -0
- package/dist/src/motion/color.test.js +97 -0
- package/dist/src/motion/color.test.js.map +1 -0
- package/dist/src/motion/event-emitter.d.ts +18 -0
- package/dist/src/motion/event-emitter.d.ts.map +1 -0
- package/dist/src/motion/event-emitter.js +30 -0
- package/dist/src/motion/event-emitter.js.map +1 -0
- package/dist/src/motion/frame.d.ts +9 -0
- package/dist/src/motion/frame.d.ts.map +1 -0
- package/dist/src/motion/frame.js +51 -0
- package/dist/src/motion/frame.js.map +1 -0
- package/dist/src/motion/hooks.d.ts +75 -0
- package/dist/src/motion/hooks.d.ts.map +1 -0
- package/dist/src/motion/hooks.js +190 -0
- package/dist/src/motion/hooks.js.map +1 -0
- package/dist/src/motion/index.d.ts +4 -0
- package/dist/src/motion/index.d.ts.map +1 -0
- package/dist/src/motion/index.js +7 -0
- package/dist/src/motion/index.js.map +1 -0
- package/dist/src/motion/motion-value.d.ts +40 -0
- package/dist/src/motion/motion-value.d.ts.map +1 -0
- package/dist/src/motion/motion-value.js +109 -0
- package/dist/src/motion/motion-value.js.map +1 -0
- package/dist/src/motion/motion-value.test.d.ts +2 -0
- package/dist/src/motion/motion-value.test.d.ts.map +1 -0
- package/dist/src/motion/motion-value.test.js +177 -0
- package/dist/src/motion/motion-value.test.js.map +1 -0
- package/dist/src/motion/spring-math.d.ts +28 -0
- package/dist/src/motion/spring-math.d.ts.map +1 -0
- package/dist/src/motion/spring-math.js +81 -0
- package/dist/src/motion/spring-math.js.map +1 -0
- package/dist/src/motion/types.d.ts +25 -0
- package/dist/src/motion/types.d.ts.map +1 -0
- package/dist/src/motion/types.js +13 -0
- package/dist/src/motion/types.js.map +1 -0
- package/dist/src/output.d.ts +47 -0
- package/dist/src/output.d.ts.map +1 -0
- package/dist/src/output.js +125 -0
- package/dist/src/output.js.map +1 -0
- package/dist/src/profiler.d.ts +6 -0
- package/dist/src/profiler.d.ts.map +1 -0
- package/dist/src/profiler.js +73 -0
- package/dist/src/profiler.js.map +1 -0
- package/dist/src/reconciler/host-config.d.ts +16 -0
- package/dist/src/reconciler/host-config.d.ts.map +1 -0
- package/dist/src/reconciler/host-config.js +174 -0
- package/dist/src/reconciler/host-config.js.map +1 -0
- package/dist/src/reconciler/types.d.ts +52 -0
- package/dist/src/reconciler/types.d.ts.map +1 -0
- package/dist/src/reconciler/types.js +2 -0
- package/dist/src/reconciler/types.js.map +1 -0
- package/dist/src/renderer.d.ts +101 -0
- package/dist/src/renderer.d.ts.map +1 -0
- package/dist/src/renderer.js +509 -0
- package/dist/src/renderer.js.map +1 -0
- package/dist/src/terminal.d.ts +37 -0
- package/dist/src/terminal.d.ts.map +1 -0
- package/dist/src/terminal.js +65 -0
- package/dist/src/terminal.js.map +1 -0
- package/dist/src/test/index.d.ts +3 -0
- package/dist/src/test/index.d.ts.map +1 -0
- package/dist/src/test/index.js +3 -0
- package/dist/src/test/index.js.map +1 -0
- package/dist/src/test/mock-streams.d.ts +44 -0
- package/dist/src/test/mock-streams.d.ts.map +1 -0
- package/dist/src/test/mock-streams.js +136 -0
- package/dist/src/test/mock-streams.js.map +1 -0
- package/dist/src/test/render-tui.d.ts +47 -0
- package/dist/src/test/render-tui.d.ts.map +1 -0
- package/dist/src/test/render-tui.js +76 -0
- package/dist/src/test/render-tui.js.map +1 -0
- package/dist/src/trace/SpanTree.d.ts +10 -0
- package/dist/src/trace/SpanTree.d.ts.map +1 -0
- package/dist/src/trace/SpanTree.js +104 -0
- package/dist/src/trace/SpanTree.js.map +1 -0
- package/dist/src/trace/index.d.ts +30 -0
- package/dist/src/trace/index.d.ts.map +1 -0
- package/dist/src/trace/index.js +142 -0
- package/dist/src/trace/index.js.map +1 -0
- package/dist/src/trace/location.d.ts +9 -0
- package/dist/src/trace/location.d.ts.map +1 -0
- package/dist/src/trace/location.js +88 -0
- package/dist/src/trace/location.js.map +1 -0
- package/dist/src/trace/span-processor.d.ts +16 -0
- package/dist/src/trace/span-processor.d.ts.map +1 -0
- package/dist/src/trace/span-processor.js +54 -0
- package/dist/src/trace/span-processor.js.map +1 -0
- package/dist/src/trace/span-state.d.ts +79 -0
- package/dist/src/trace/span-state.d.ts.map +1 -0
- package/dist/src/trace/span-state.js +229 -0
- package/dist/src/trace/span-state.js.map +1 -0
- package/dist/src/trace/tui-logger.d.ts +8 -0
- package/dist/src/trace/tui-logger.d.ts.map +1 -0
- package/dist/src/trace/tui-logger.js +70 -0
- package/dist/src/trace/tui-logger.js.map +1 -0
- package/dist/src/utils/border.d.ts +31 -0
- package/dist/src/utils/border.d.ts.map +1 -0
- package/dist/src/utils/border.js +81 -0
- package/dist/src/utils/border.js.map +1 -0
- package/dist/src/utils/flex-layout.d.ts +20 -0
- package/dist/src/utils/flex-layout.d.ts.map +1 -0
- package/dist/src/utils/flex-layout.js +85 -0
- package/dist/src/utils/flex-layout.js.map +1 -0
- package/dist/src/utils/index.d.ts +5 -0
- package/dist/src/utils/index.d.ts.map +1 -0
- package/dist/src/utils/index.js +5 -0
- package/dist/src/utils/index.js.map +1 -0
- package/dist/src/utils/padding.d.ts +26 -0
- package/dist/src/utils/padding.d.ts.map +1 -0
- package/dist/src/utils/padding.js +34 -0
- package/dist/src/utils/padding.js.map +1 -0
- package/dist/src/utils/styles.d.ts +13 -0
- package/dist/src/utils/styles.d.ts.map +1 -0
- package/dist/src/utils/styles.js +5 -0
- package/dist/src/utils/styles.js.map +1 -0
- package/dist/src/visualize/index.d.ts +50 -0
- package/dist/src/visualize/index.d.ts.map +1 -0
- package/dist/src/visualize/index.js +194 -0
- package/dist/src/visualize/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +94 -0
- package/src/codeblock.tsx +47 -0
- package/src/constants.ts +2 -0
- package/src/debug/DiagnosticsPanel.tsx +38 -0
- package/src/highlight.ts +76 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/use-keyboard.ts +37 -0
- package/src/hooks/use-paste.ts +14 -0
- package/src/hooks/useFrameStats.ts +32 -0
- package/src/hosts/base.ts +65 -0
- package/src/hosts/box.ts +105 -0
- package/src/hosts/canvas.ts +155 -0
- package/src/hosts/codeblock.ts +145 -0
- package/src/hosts/hstack.ts +64 -0
- package/src/hosts/index.ts +45 -0
- package/src/hosts/spacer.ts +40 -0
- package/src/hosts/text.ts +175 -0
- package/src/hosts/vstack.ts +64 -0
- package/src/hosts/zstack.ts +77 -0
- package/src/index.ts +62 -0
- package/src/inline/index.tsx +181 -0
- package/src/jsx.ts +3 -0
- package/src/motion/color-motion-value.ts +90 -0
- package/src/motion/color.test.ts +115 -0
- package/src/motion/color.ts +191 -0
- package/src/motion/event-emitter.ts +35 -0
- package/src/motion/frame.ts +59 -0
- package/src/motion/hooks.ts +237 -0
- package/src/motion/index.ts +17 -0
- package/src/motion/motion-value.test.ts +222 -0
- package/src/motion/motion-value.ts +140 -0
- package/src/motion/spring-math.ts +114 -0
- package/src/motion/types.ts +34 -0
- package/src/output.ts +156 -0
- package/src/profiler.ts +88 -0
- package/src/reconciler/host-config.ts +277 -0
- package/src/reconciler/types.ts +66 -0
- package/src/renderer.ts +661 -0
- package/src/terminal.ts +67 -0
- package/src/test/index.ts +8 -0
- package/src/test/mock-streams.ts +149 -0
- package/src/test/render-tui.ts +118 -0
- package/src/trace/SpanTree.tsx +195 -0
- package/src/trace/index.tsx +205 -0
- package/src/trace/location.ts +90 -0
- package/src/trace/span-processor.ts +65 -0
- package/src/trace/span-state.ts +286 -0
- package/src/trace/tui-logger.ts +72 -0
- package/src/utils/border.ts +108 -0
- package/src/utils/flex-layout.ts +125 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/padding.ts +45 -0
- package/src/utils/styles.ts +14 -0
- package/src/visualize/index.tsx +305 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SourceLocation } from "./span-state.js";
|
|
2
|
+
export declare function normalizeFile(file: string): string;
|
|
3
|
+
export declare function isAppPath(file: string): boolean;
|
|
4
|
+
export declare function isLibraryPath(file: string): boolean;
|
|
5
|
+
export declare function pickBestLocation(candidates: SourceLocation[]): SourceLocation | undefined;
|
|
6
|
+
export declare function parseStackLine(line: string): SourceLocation | undefined;
|
|
7
|
+
export declare function parseStackTrace(stack?: unknown): SourceLocation | undefined;
|
|
8
|
+
export declare function captureAppLocation(ignore?: Array<RegExp | string>): SourceLocation | undefined;
|
|
9
|
+
//# sourceMappingURL=location.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../../../src/trace/location.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAIrD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK/C;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,cAAc,EAAE,GAAG,cAAc,GAAG,SAAS,CAMzF;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAWvE;AAED,wBAAgB,eAAe,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAS3E;AAED,wBAAgB,kBAAkB,CAAC,MAAM,GAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAM,GAAG,cAAc,GAAG,SAAS,CA8BlG"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
const cwd = process.cwd();
|
|
4
|
+
export function normalizeFile(file) {
|
|
5
|
+
if (file.startsWith("file://"))
|
|
6
|
+
return fileURLToPath(file);
|
|
7
|
+
return file;
|
|
8
|
+
}
|
|
9
|
+
export function isAppPath(file) {
|
|
10
|
+
const normalized = normalizeFile(file);
|
|
11
|
+
if (normalized.includes(`${path.sep}node_modules${path.sep}`))
|
|
12
|
+
return false;
|
|
13
|
+
if (normalized.includes(`${path.sep}.bun${path.sep}`))
|
|
14
|
+
return false;
|
|
15
|
+
return normalized.startsWith(cwd);
|
|
16
|
+
}
|
|
17
|
+
export function isLibraryPath(file) {
|
|
18
|
+
const normalized = normalizeFile(file);
|
|
19
|
+
return (normalized.includes(`${path.sep}node_modules${path.sep}`) ||
|
|
20
|
+
normalized.includes("fiberRuntime") ||
|
|
21
|
+
normalized.includes("native"));
|
|
22
|
+
}
|
|
23
|
+
export function pickBestLocation(candidates) {
|
|
24
|
+
if (candidates.length === 0)
|
|
25
|
+
return undefined;
|
|
26
|
+
const app = candidates.find((c) => isAppPath(c.file));
|
|
27
|
+
if (app)
|
|
28
|
+
return app;
|
|
29
|
+
const nonLib = candidates.find((c) => !isLibraryPath(c.file));
|
|
30
|
+
return nonLib ?? candidates[0];
|
|
31
|
+
}
|
|
32
|
+
export function parseStackLine(line) {
|
|
33
|
+
const re = /at\s+(?:.+?\s+\()?((?:file:\/\/)?[^):]+):(\d+):(\d+)\)?$/;
|
|
34
|
+
const match = re.exec(line.trim());
|
|
35
|
+
if (match) {
|
|
36
|
+
const file = normalizeFile(match[1]);
|
|
37
|
+
return {
|
|
38
|
+
file,
|
|
39
|
+
line: Number(match[2]),
|
|
40
|
+
column: Number(match[3]),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function parseStackTrace(stack) {
|
|
45
|
+
if (typeof stack !== "string")
|
|
46
|
+
return;
|
|
47
|
+
const lines = stack.split("\n");
|
|
48
|
+
const parsed = [];
|
|
49
|
+
for (const line of lines) {
|
|
50
|
+
const loc = parseStackLine(line);
|
|
51
|
+
if (loc)
|
|
52
|
+
parsed.push(loc);
|
|
53
|
+
}
|
|
54
|
+
return pickBestLocation(parsed);
|
|
55
|
+
}
|
|
56
|
+
export function captureAppLocation(ignore = []) {
|
|
57
|
+
const prev = Error.prepareStackTrace;
|
|
58
|
+
try {
|
|
59
|
+
Error.prepareStackTrace = (_err, structured) => structured;
|
|
60
|
+
const err = new Error();
|
|
61
|
+
Error.captureStackTrace(err, captureAppLocation);
|
|
62
|
+
const stack = err.stack;
|
|
63
|
+
if (!stack)
|
|
64
|
+
return;
|
|
65
|
+
const isIgnored = (file) => {
|
|
66
|
+
if (!file)
|
|
67
|
+
return false;
|
|
68
|
+
return ignore.some((p) => typeof p === "string" ? file.includes(p) : p.test(file));
|
|
69
|
+
};
|
|
70
|
+
const candidates = [];
|
|
71
|
+
for (const frame of stack) {
|
|
72
|
+
const file = frame.getFileName() || frame.getScriptNameOrSourceURL();
|
|
73
|
+
if (!file || isIgnored(file))
|
|
74
|
+
continue;
|
|
75
|
+
const loc = {
|
|
76
|
+
file: normalizeFile(file),
|
|
77
|
+
line: frame.getLineNumber() ?? 0,
|
|
78
|
+
column: frame.getColumnNumber() ?? undefined,
|
|
79
|
+
};
|
|
80
|
+
candidates.push(loc);
|
|
81
|
+
}
|
|
82
|
+
return pickBestLocation(candidates);
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
Error.prepareStackTrace = prev;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=location.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"location.js","sourceRoot":"","sources":["../../../src/trace/location.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Context, Span } from "@opentelemetry/api";
|
|
2
|
+
import type { ReadableSpan, SpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
3
|
+
import type { SpanTreeState } from "./span-state.js";
|
|
4
|
+
/**
|
|
5
|
+
* OpenTelemetry SpanProcessor that updates SpanTreeState for TUI visualization.
|
|
6
|
+
*/
|
|
7
|
+
export declare class TuiSpanProcessor implements SpanProcessor {
|
|
8
|
+
private state;
|
|
9
|
+
private onUpdate;
|
|
10
|
+
constructor(state: SpanTreeState, onUpdate: () => void);
|
|
11
|
+
onStart(span: Span, parentContext: Context): void;
|
|
12
|
+
onEnd(span: ReadableSpan): void;
|
|
13
|
+
forceFlush(): Promise<void>;
|
|
14
|
+
shutdown(): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=span-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"span-processor.d.ts","sourceRoot":"","sources":["../../../src/trace/span-processor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAEhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAGpD;;GAEG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IAElD,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;gBADR,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,MAAM,IAAI;IAG9B,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,GAAG,IAAI;IAoBjD,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAoB/B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAG1B"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Custom SpanProcessor that feeds into TUI visualization
|
|
2
|
+
import { SpanStatusCode } from "@opentelemetry/api";
|
|
3
|
+
import { captureAppLocation, parseStackTrace } from "./location.js";
|
|
4
|
+
/**
|
|
5
|
+
* OpenTelemetry SpanProcessor that updates SpanTreeState for TUI visualization.
|
|
6
|
+
*/
|
|
7
|
+
export class TuiSpanProcessor {
|
|
8
|
+
state;
|
|
9
|
+
onUpdate;
|
|
10
|
+
constructor(state, onUpdate) {
|
|
11
|
+
this.state = state;
|
|
12
|
+
this.onUpdate = onUpdate;
|
|
13
|
+
}
|
|
14
|
+
onStart(span, parentContext) {
|
|
15
|
+
const spanContext = span.spanContext();
|
|
16
|
+
const parentSpanContext = parentContext.getValue(Symbol.for("OpenTelemetry Context Key SPAN"));
|
|
17
|
+
const location = captureAppLocation([/span-processor/, /SpanProcessor/, /@effect-tui\/react/]);
|
|
18
|
+
// Extract parent span ID if available
|
|
19
|
+
let parentId = null;
|
|
20
|
+
if (parentSpanContext && typeof parentSpanContext === "object" && "spanContext" in parentSpanContext) {
|
|
21
|
+
const parentCtx = parentSpanContext.spanContext();
|
|
22
|
+
parentId = parentCtx.spanId;
|
|
23
|
+
}
|
|
24
|
+
// Get span name - the span object has a private _name, but we can get it from ReadableSpan later
|
|
25
|
+
// For now use the spanId as placeholder, we'll update on end
|
|
26
|
+
const name = span.name || spanContext.spanId;
|
|
27
|
+
this.state.addSpan(spanContext.spanId, parentId, name, location);
|
|
28
|
+
this.onUpdate();
|
|
29
|
+
}
|
|
30
|
+
onEnd(span) {
|
|
31
|
+
const spanContext = span.spanContext();
|
|
32
|
+
const status = span.status;
|
|
33
|
+
let location = parseStackTrace(span.attributes?.["code.stacktrace"]);
|
|
34
|
+
if (!location) {
|
|
35
|
+
location = captureAppLocation([/span-processor/, /SpanProcessor/]);
|
|
36
|
+
if (!location && process.env.EFFECT_TUI_DEBUG_STACKS === "1") {
|
|
37
|
+
// eslint-disable-next-line no-console
|
|
38
|
+
console.error("[effect-tui] span end missing location; attributes stack:", span.attributes?.["code.stacktrace"]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Determine success/failure from span status
|
|
42
|
+
const isSuccess = status.code !== SpanStatusCode.ERROR;
|
|
43
|
+
const error = status.code === SpanStatusCode.ERROR ? status.message : undefined;
|
|
44
|
+
this.state.endSpan(spanContext.spanId, isSuccess ? "success" : "failure", error, location);
|
|
45
|
+
this.onUpdate();
|
|
46
|
+
}
|
|
47
|
+
forceFlush() {
|
|
48
|
+
return Promise.resolve();
|
|
49
|
+
}
|
|
50
|
+
shutdown() {
|
|
51
|
+
return Promise.resolve();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=span-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"span-processor.js","sourceRoot":"","sources":["../../../src/trace/span-processor.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAIzD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEnD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEnE;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAEjB;IACA;IAFV,YACU,KAAoB,EACpB,QAAoB;QADpB,UAAK,GAAL,KAAK,CAAe;QACpB,aAAQ,GAAR,QAAQ,CAAY;IAC3B,CAAC;IAEJ,OAAO,CAAC,IAAU,EAAE,aAAsB;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QACtC,MAAM,iBAAiB,GAAG,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC,CAAA;QAC9F,MAAM,QAAQ,GAAG,kBAAkB,CAAC,CAAC,gBAAgB,EAAE,eAAe,EAAE,oBAAoB,CAAC,CAAC,CAAA;QAE9F,sCAAsC;QACtC,IAAI,QAAQ,GAAkB,IAAI,CAAA;QAClC,IAAI,iBAAiB,IAAI,OAAO,iBAAiB,KAAK,QAAQ,IAAI,aAAa,IAAI,iBAAiB,EAAE,CAAC;YACrG,MAAM,SAAS,GAAI,iBAA0B,CAAC,WAAW,EAAE,CAAA;YAC3D,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAA;QAC7B,CAAC;QAED,iGAAiG;QACjG,6DAA6D;QAC7D,MAAM,IAAI,GAAI,IAAY,CAAC,IAAI,IAAI,WAAW,CAAC,MAAM,CAAA;QAErD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAA;QAChE,IAAI,CAAC,QAAQ,EAAE,CAAA;IACjB,CAAC;IAED,KAAK,CAAC,IAAkB;QACtB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAC1B,IAAI,QAAQ,GAAG,eAAe,CAAE,IAAI,CAAC,UAAkB,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAA;QAC7E,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,GAAG,kBAAkB,CAAC,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC,CAAA;YAClE,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,GAAG,EAAE,CAAC;gBAC7D,sCAAsC;gBACtC,OAAO,CAAC,KAAK,CAAC,2DAA2D,EAAG,IAAI,CAAC,UAAkB,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAA;YAC3H,CAAC;QACH,CAAC;QAED,6CAA6C;QAC7C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,KAAK,CAAA;QACtD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;QAE/E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAA;QAC1F,IAAI,CAAC,QAAQ,EAAE,CAAA;IACjB,CAAC;IAED,UAAU;QACR,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAC1B,CAAC;IAED,QAAQ;QACN,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAC1B,CAAC;CACF"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export type SpanStatus = "running" | "success" | "failure";
|
|
2
|
+
export type LogLevel = "INFO" | "WARN" | "ERROR" | "DEBUG" | "TRACE";
|
|
3
|
+
export interface SourceLocation {
|
|
4
|
+
file: string;
|
|
5
|
+
line: number;
|
|
6
|
+
column?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface LogEntry {
|
|
9
|
+
level: LogLevel;
|
|
10
|
+
message: string;
|
|
11
|
+
timestamp: number;
|
|
12
|
+
location?: SourceLocation;
|
|
13
|
+
}
|
|
14
|
+
export interface LogCounts {
|
|
15
|
+
info: number;
|
|
16
|
+
warn: number;
|
|
17
|
+
error: number;
|
|
18
|
+
debug: number;
|
|
19
|
+
total: number;
|
|
20
|
+
}
|
|
21
|
+
export interface SpanNode {
|
|
22
|
+
id: string;
|
|
23
|
+
parentId: string | null;
|
|
24
|
+
name: string;
|
|
25
|
+
status: SpanStatus;
|
|
26
|
+
startTime: number;
|
|
27
|
+
endTime?: number;
|
|
28
|
+
duration?: number;
|
|
29
|
+
error?: string;
|
|
30
|
+
logEntries: LogEntry[];
|
|
31
|
+
children: SpanNode[];
|
|
32
|
+
completedAt?: number;
|
|
33
|
+
opacity: number;
|
|
34
|
+
targetOpacity: number;
|
|
35
|
+
opacityVelocity: number;
|
|
36
|
+
location?: SourceLocation;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Manages span tree state for visualization.
|
|
40
|
+
* Tracks hierarchy, status, and notifies listeners on changes.
|
|
41
|
+
*/
|
|
42
|
+
export declare class SpanTreeState {
|
|
43
|
+
private roots;
|
|
44
|
+
private nodesById;
|
|
45
|
+
private listeners;
|
|
46
|
+
selectedSpanId: string | null;
|
|
47
|
+
expandedSpanIds: Set<string>;
|
|
48
|
+
spinnerIndex: number;
|
|
49
|
+
private lastSpinnerTime;
|
|
50
|
+
private lastTickTime;
|
|
51
|
+
/** Add a new running span */
|
|
52
|
+
addSpan(id: string, parentId: string | null, name: string, location?: SourceLocation): void;
|
|
53
|
+
/** Mark a span as completed */
|
|
54
|
+
endSpan(id: string, status: "success" | "failure", error?: string, location?: SourceLocation): void;
|
|
55
|
+
/** Add a log entry to a span (called by custom logger) */
|
|
56
|
+
addLog(spanId: string, level: LogLevel, message: string, location?: SourceLocation): void;
|
|
57
|
+
/** Get all spans that have logs or captured locations (for navigation) in tree order */
|
|
58
|
+
getSpansWithLogs(): SpanNode[];
|
|
59
|
+
/** Select next span with logs */
|
|
60
|
+
selectNext(): void;
|
|
61
|
+
/** Select previous span with logs */
|
|
62
|
+
selectPrev(): void;
|
|
63
|
+
/** Toggle expansion of selected span */
|
|
64
|
+
toggleExpand(): void;
|
|
65
|
+
/** Tick animations (spinner + fades). Call at 60fps for smooth rendering. */
|
|
66
|
+
tick(): void;
|
|
67
|
+
/** Get all root spans */
|
|
68
|
+
getRoots(): readonly SpanNode[];
|
|
69
|
+
/** Get a span by ID */
|
|
70
|
+
getSpan(id: string): SpanNode | undefined;
|
|
71
|
+
/** Best-effort source location for the currently selected span or its logs */
|
|
72
|
+
getOpenTarget(): SourceLocation | null;
|
|
73
|
+
/** Check if any spans are still running */
|
|
74
|
+
hasRunning(): boolean;
|
|
75
|
+
/** Subscribe to state changes */
|
|
76
|
+
subscribe(listener: () => void): () => void;
|
|
77
|
+
private notify;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=span-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"span-state.d.ts","sourceRoot":"","sources":["../../../src/trace/span-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { isAppPath } from "./location.js";
|
|
2
|
+
const SPINNER_FRAMES_COUNT = 6;
|
|
3
|
+
const SPIN_INTERVAL_MS = 80;
|
|
4
|
+
/**
|
|
5
|
+
* Manages span tree state for visualization.
|
|
6
|
+
* Tracks hierarchy, status, and notifies listeners on changes.
|
|
7
|
+
*/
|
|
8
|
+
export class SpanTreeState {
|
|
9
|
+
roots = [];
|
|
10
|
+
nodesById = new Map();
|
|
11
|
+
listeners = new Set();
|
|
12
|
+
// Selection state for log navigation
|
|
13
|
+
selectedSpanId = null;
|
|
14
|
+
expandedSpanIds = new Set();
|
|
15
|
+
// Animation timing (managed here to decouple from React)
|
|
16
|
+
spinnerIndex = 0;
|
|
17
|
+
lastSpinnerTime = performance.now();
|
|
18
|
+
lastTickTime = performance.now();
|
|
19
|
+
/** Add a new running span */
|
|
20
|
+
addSpan(id, parentId, name, location) {
|
|
21
|
+
const node = {
|
|
22
|
+
id,
|
|
23
|
+
parentId,
|
|
24
|
+
name,
|
|
25
|
+
status: "running",
|
|
26
|
+
startTime: Date.now(),
|
|
27
|
+
logEntries: [],
|
|
28
|
+
children: [],
|
|
29
|
+
opacity: 1,
|
|
30
|
+
targetOpacity: 1,
|
|
31
|
+
opacityVelocity: 0,
|
|
32
|
+
location,
|
|
33
|
+
};
|
|
34
|
+
this.nodesById.set(id, node);
|
|
35
|
+
if (parentId) {
|
|
36
|
+
const parent = this.nodesById.get(parentId);
|
|
37
|
+
if (parent) {
|
|
38
|
+
parent.children.push(node);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// Parent not found, add as root
|
|
42
|
+
this.roots.push(node);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.roots.push(node);
|
|
47
|
+
}
|
|
48
|
+
this.notify();
|
|
49
|
+
}
|
|
50
|
+
/** Mark a span as completed */
|
|
51
|
+
endSpan(id, status, error, location) {
|
|
52
|
+
const node = this.nodesById.get(id);
|
|
53
|
+
if (!node)
|
|
54
|
+
return;
|
|
55
|
+
const endTime = Date.now();
|
|
56
|
+
node.status = status;
|
|
57
|
+
node.endTime = endTime;
|
|
58
|
+
node.duration = endTime - node.startTime;
|
|
59
|
+
node.completedAt = performance.now(); // Use perf time for fade animation timing
|
|
60
|
+
// Keep opaque for now, fade will start after FADE_DELAY_MS in tickAnimations
|
|
61
|
+
node.targetOpacity = 1;
|
|
62
|
+
if (error)
|
|
63
|
+
node.error = error;
|
|
64
|
+
if (location)
|
|
65
|
+
node.location = location;
|
|
66
|
+
this.notify();
|
|
67
|
+
}
|
|
68
|
+
/** Add a log entry to a span (called by custom logger) */
|
|
69
|
+
addLog(spanId, level, message, location) {
|
|
70
|
+
const node = this.nodesById.get(spanId);
|
|
71
|
+
if (!node)
|
|
72
|
+
return;
|
|
73
|
+
node.logEntries.push({
|
|
74
|
+
level,
|
|
75
|
+
message,
|
|
76
|
+
timestamp: Date.now(),
|
|
77
|
+
location,
|
|
78
|
+
});
|
|
79
|
+
this.notify();
|
|
80
|
+
}
|
|
81
|
+
/** Get all spans that have logs or captured locations (for navigation) in tree order */
|
|
82
|
+
getSpansWithLogs() {
|
|
83
|
+
const result = [];
|
|
84
|
+
const visit = (node) => {
|
|
85
|
+
if (node.logEntries.length > 0 || node.location)
|
|
86
|
+
result.push(node);
|
|
87
|
+
for (const child of node.children)
|
|
88
|
+
visit(child);
|
|
89
|
+
};
|
|
90
|
+
for (const root of this.roots)
|
|
91
|
+
visit(root);
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
/** Select next span with logs */
|
|
95
|
+
selectNext() {
|
|
96
|
+
const spans = this.getSpansWithLogs();
|
|
97
|
+
if (spans.length === 0)
|
|
98
|
+
return;
|
|
99
|
+
if (this.selectedSpanId === null) {
|
|
100
|
+
this.selectedSpanId = spans[0]?.id;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const idx = spans.findIndex((s) => s.id === this.selectedSpanId);
|
|
104
|
+
if (idx < spans.length - 1) {
|
|
105
|
+
this.selectedSpanId = spans[idx + 1]?.id;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
this.notify();
|
|
109
|
+
}
|
|
110
|
+
/** Select previous span with logs */
|
|
111
|
+
selectPrev() {
|
|
112
|
+
const spans = this.getSpansWithLogs();
|
|
113
|
+
if (spans.length === 0)
|
|
114
|
+
return;
|
|
115
|
+
if (this.selectedSpanId === null) {
|
|
116
|
+
this.selectedSpanId = spans[spans.length - 1]?.id;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
const idx = spans.findIndex((s) => s.id === this.selectedSpanId);
|
|
120
|
+
if (idx > 0) {
|
|
121
|
+
this.selectedSpanId = spans[idx - 1]?.id;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
this.notify();
|
|
125
|
+
}
|
|
126
|
+
/** Toggle expansion of selected span */
|
|
127
|
+
toggleExpand() {
|
|
128
|
+
if (this.selectedSpanId === null)
|
|
129
|
+
return;
|
|
130
|
+
if (this.expandedSpanIds.has(this.selectedSpanId)) {
|
|
131
|
+
this.expandedSpanIds.delete(this.selectedSpanId);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
this.expandedSpanIds.add(this.selectedSpanId);
|
|
135
|
+
}
|
|
136
|
+
this.notify();
|
|
137
|
+
}
|
|
138
|
+
/** Tick animations (spinner + fades). Call at 60fps for smooth rendering. */
|
|
139
|
+
tick() {
|
|
140
|
+
const now = performance.now();
|
|
141
|
+
// Cap dt to prevent large jumps when frames are delayed (GC, etc.)
|
|
142
|
+
const dt = Math.min((now - this.lastTickTime) / 1000, 0.05);
|
|
143
|
+
this.lastTickTime = now;
|
|
144
|
+
// Advance spinner at its own rate
|
|
145
|
+
if (now - this.lastSpinnerTime >= SPIN_INTERVAL_MS) {
|
|
146
|
+
this.spinnerIndex = (this.spinnerIndex + 1) % SPINNER_FRAMES_COUNT;
|
|
147
|
+
this.lastSpinnerTime = now;
|
|
148
|
+
}
|
|
149
|
+
// Fade animations
|
|
150
|
+
const fadeDelayMs = 1000;
|
|
151
|
+
const halfLife = 0.3;
|
|
152
|
+
const decay = 0.5 ** (dt / halfLife);
|
|
153
|
+
const epsilon = 0.01;
|
|
154
|
+
for (const node of this.nodesById.values()) {
|
|
155
|
+
// Check if completed span should start fading
|
|
156
|
+
if (node.completedAt && node.targetOpacity === 1) {
|
|
157
|
+
if (now - node.completedAt >= fadeDelayMs) {
|
|
158
|
+
node.targetOpacity = 0.4; // Start fading
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const diff = Math.abs(node.opacity - node.targetOpacity);
|
|
162
|
+
if (diff > epsilon) {
|
|
163
|
+
// Exponential decay toward target - unconditionally stable
|
|
164
|
+
node.opacity = node.targetOpacity + (node.opacity - node.targetOpacity) * decay;
|
|
165
|
+
}
|
|
166
|
+
else if (diff > 0) {
|
|
167
|
+
// Snap to target when close enough
|
|
168
|
+
node.opacity = node.targetOpacity;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/** Get all root spans */
|
|
173
|
+
getRoots() {
|
|
174
|
+
return this.roots;
|
|
175
|
+
}
|
|
176
|
+
/** Get a span by ID */
|
|
177
|
+
getSpan(id) {
|
|
178
|
+
return this.nodesById.get(id);
|
|
179
|
+
}
|
|
180
|
+
/** Best-effort source location for the currently selected span or its logs */
|
|
181
|
+
getOpenTarget() {
|
|
182
|
+
if (!this.selectedSpanId)
|
|
183
|
+
return null;
|
|
184
|
+
const node = this.nodesById.get(this.selectedSpanId);
|
|
185
|
+
if (!node)
|
|
186
|
+
return null;
|
|
187
|
+
let fallback;
|
|
188
|
+
// Prefer app-path log entries (latest first)
|
|
189
|
+
for (let i = node.logEntries.length - 1; i >= 0; i--) {
|
|
190
|
+
const entry = node.logEntries[i];
|
|
191
|
+
if (entry.location) {
|
|
192
|
+
if (isAppPath(entry.location.file))
|
|
193
|
+
return entry.location;
|
|
194
|
+
if (!fallback)
|
|
195
|
+
fallback = entry.location;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (node.location) {
|
|
199
|
+
if (isAppPath(node.location.file))
|
|
200
|
+
return node.location;
|
|
201
|
+
if (!fallback)
|
|
202
|
+
fallback = node.location;
|
|
203
|
+
}
|
|
204
|
+
if (!fallback)
|
|
205
|
+
return null;
|
|
206
|
+
if (process.env.EFFECT_TUI_DEBUG_STACKS === "1") {
|
|
207
|
+
// eslint-disable-next-line no-console
|
|
208
|
+
console.error("[effect-tui] only non-app locations available", fallback);
|
|
209
|
+
}
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
/** Check if any spans are still running */
|
|
213
|
+
hasRunning() {
|
|
214
|
+
for (const node of this.nodesById.values()) {
|
|
215
|
+
if (node.status === "running")
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
/** Subscribe to state changes */
|
|
221
|
+
subscribe(listener) {
|
|
222
|
+
this.listeners.add(listener);
|
|
223
|
+
return () => this.listeners.delete(listener);
|
|
224
|
+
}
|
|
225
|
+
notify() {
|
|
226
|
+
this.listeners.forEach((l) => l());
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=span-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"span-state.js","sourceRoot":"","sources":["../../../src/trace/span-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Logger } from "effect";
|
|
2
|
+
import type { SpanTreeState } from "./span-state.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create a Logger that feeds log entries into SpanTreeState.
|
|
5
|
+
* Logs are associated with the current span and displayed in the TUI.
|
|
6
|
+
*/
|
|
7
|
+
export declare function makeTuiLogger(state: SpanTreeState, onUpdate: () => void): Logger.Logger<unknown, void>;
|
|
8
|
+
//# sourceMappingURL=tui-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-logger.d.ts","sourceRoot":"","sources":["../../../src/trace/tui-logger.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAA+C,MAAM,QAAQ,CAAA;AAC5E,OAAO,KAAK,EAA4B,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAqB9E;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CA2CtG"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Custom Effect logger that feeds logs into SpanTreeState for TUI visualization
|
|
2
|
+
import { Logger, FiberRef, FiberRefs, Cause, Context, Tracer } from "effect";
|
|
3
|
+
import { captureAppLocation, parseStackLine, pickBestLocation } from "./location.js";
|
|
4
|
+
function captureCallerLocation() {
|
|
5
|
+
const err = new Error();
|
|
6
|
+
const stack = err.stack;
|
|
7
|
+
if (!stack)
|
|
8
|
+
return;
|
|
9
|
+
const lines = stack.split("\n").slice(1);
|
|
10
|
+
const parsed = [];
|
|
11
|
+
for (const line of lines) {
|
|
12
|
+
if (line.includes("tui-logger") || line.includes("makeTuiLogger"))
|
|
13
|
+
continue;
|
|
14
|
+
const loc = parseStackLine(line);
|
|
15
|
+
if (loc)
|
|
16
|
+
parsed.push(loc);
|
|
17
|
+
}
|
|
18
|
+
const best = pickBestLocation(parsed);
|
|
19
|
+
if (best)
|
|
20
|
+
return best;
|
|
21
|
+
return captureAppLocation([/tui-logger/, /makeTuiLogger/]);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Create a Logger that feeds log entries into SpanTreeState.
|
|
25
|
+
* Logs are associated with the current span and displayed in the TUI.
|
|
26
|
+
*/
|
|
27
|
+
export function makeTuiLogger(state, onUpdate) {
|
|
28
|
+
return Logger.make(({ logLevel, message, cause, context }) => {
|
|
29
|
+
const debugStacks = process.env.EFFECT_TUI_DEBUG_STACKS === "1";
|
|
30
|
+
// Get current context from fiber refs
|
|
31
|
+
const ctx = FiberRefs.getOrDefault(context, FiberRef.currentContext);
|
|
32
|
+
// Get current span from context
|
|
33
|
+
const spanOption = Context.getOption(ctx, Tracer.ParentSpan);
|
|
34
|
+
if (spanOption._tag !== "Some")
|
|
35
|
+
return;
|
|
36
|
+
const span = spanOption.value;
|
|
37
|
+
if (!span || typeof span !== "object")
|
|
38
|
+
return;
|
|
39
|
+
// Get span ID - Effect spans have spanContext() method
|
|
40
|
+
const anySpan = span;
|
|
41
|
+
const spanId = typeof anySpan.spanContext === "function" ? anySpan.spanContext().spanId : anySpan.spanId;
|
|
42
|
+
if (!spanId)
|
|
43
|
+
return;
|
|
44
|
+
// Map Effect log level to our level
|
|
45
|
+
let level = "INFO";
|
|
46
|
+
const levelLabel = logLevel.label.toUpperCase();
|
|
47
|
+
if (levelLabel === "ERROR" || levelLabel === "FATAL")
|
|
48
|
+
level = "ERROR";
|
|
49
|
+
else if (levelLabel === "WARNING" || levelLabel === "WARN")
|
|
50
|
+
level = "WARN";
|
|
51
|
+
else if (levelLabel === "DEBUG")
|
|
52
|
+
level = "DEBUG";
|
|
53
|
+
else if (levelLabel === "TRACE")
|
|
54
|
+
level = "TRACE";
|
|
55
|
+
// Format message
|
|
56
|
+
let text = String(message);
|
|
57
|
+
// Add cause if present
|
|
58
|
+
if (cause && !Cause.isEmpty(cause)) {
|
|
59
|
+
text += ` ${Cause.pretty(cause)}`;
|
|
60
|
+
}
|
|
61
|
+
const location = captureCallerLocation();
|
|
62
|
+
state.addLog(spanId, level, text, location);
|
|
63
|
+
if (!location && debugStacks) {
|
|
64
|
+
// eslint-disable-next-line no-console
|
|
65
|
+
console.error("[effect-tui] no location for log; stack:", new Error().stack);
|
|
66
|
+
}
|
|
67
|
+
onUpdate();
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=tui-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-logger.js","sourceRoot":"","sources":["../../../src/trace/tui-logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Border utilities shared between box and canvas hosts.
|
|
3
|
+
*/
|
|
4
|
+
import type { CellBuffer } from "@effect-tui/core";
|
|
5
|
+
export type BorderKind = "none" | "rounded" | "square" | "ascii";
|
|
6
|
+
export interface BorderChars {
|
|
7
|
+
tl: string;
|
|
8
|
+
tr: string;
|
|
9
|
+
bl: string;
|
|
10
|
+
br: string;
|
|
11
|
+
h: string;
|
|
12
|
+
v: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get border characters for a given border style.
|
|
16
|
+
* Returns empty strings for "none" (drawing code should skip when border is "none").
|
|
17
|
+
*/
|
|
18
|
+
export declare function borderChars(kind: BorderKind): BorderChars;
|
|
19
|
+
export interface ClipRect {
|
|
20
|
+
ox: number;
|
|
21
|
+
oy: number;
|
|
22
|
+
w: number;
|
|
23
|
+
h: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Draw a border around a rectangle.
|
|
27
|
+
* If clip is provided, only draws within the clip bounds (for canvas).
|
|
28
|
+
* If clip is not provided, draws the full border (for box).
|
|
29
|
+
*/
|
|
30
|
+
export declare function drawBorder(buffer: CellBuffer, x: number, y: number, w: number, h: number, chars: BorderChars, style: number, clip?: ClipRect): void;
|
|
31
|
+
//# sourceMappingURL=border.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"border.d.ts","sourceRoot":"","sources":["../../../src/utils/border.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEhE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,CAWzD;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,UAAU,EAClB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,QAAQ,GACd,IAAI,CAoDN"}
|