@telorun/debug-ui 0.5.0 → 0.6.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/app-dist/assets/{index-C9ZwjlYK.css → index-Bx9-Zdjf.css} +1 -1
- package/app-dist/assets/index-D_01vIS0.js +141 -0
- package/app-dist/index.html +2 -2
- package/app-single/index.html +37 -22
- package/package.json +2 -2
- package/src/components/DebugPanel.tsx +8 -2
- package/src/components/EndpointLinks.tsx +46 -6
- package/src/components/styles.css +20 -0
- package/src/endpoints.ts +6 -0
- package/app-dist/assets/index-D2M9P905.js +0 -126
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telorun/debug-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Browser-safe debug event UI for Telo: wire types, filtering, SSE client, and React components for watching a running app's event stream.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"telo",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"@dagrejs/dagre": "^3.0.0",
|
|
47
47
|
"@xyflow/react": "^12.10.2",
|
|
48
48
|
"lucide-react": "^1.8.0",
|
|
49
|
-
"@telorun/debug-wire": "0.
|
|
49
|
+
"@telorun/debug-wire": "0.4.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"react": ">=18",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ReactNode, useMemo, useState } from "react";
|
|
2
|
-
import type { AppEndpoint } from "../endpoints.js";
|
|
2
|
+
import type { AppEndpoint, EndpointReachability } from "../endpoints.js";
|
|
3
3
|
import { distinctSuffixes, type EventFilter, matchesFilter } from "../filter.js";
|
|
4
4
|
import { type DebugTheme, loadStoredTheme, storeTheme, useResolvedTheme } from "../theme.js";
|
|
5
5
|
import { type DebugEvent, type DebugFrame, isLogFrame } from "../wire.js";
|
|
@@ -34,6 +34,9 @@ export interface DebugPanelProps {
|
|
|
34
34
|
* header. The standalone {@link DebugWatcher} sources these from the producer's
|
|
35
35
|
* handshake; the editor passes its resolved run endpoints. */
|
|
36
36
|
endpoints?: readonly AppEndpoint[];
|
|
37
|
+
/** Per-port reachability for the endpoint badges (spinner / ok / error). The
|
|
38
|
+
* editor sources it from the runner's `reachability` events. */
|
|
39
|
+
endpointReachability?: ReadonlyMap<number, EndpointReachability>;
|
|
37
40
|
/** Color theme. Defaults to `"system"` (follows the OS); an embedding host
|
|
38
41
|
* (e.g. the editor) passes its own resolved `"light"` / `"dark"`. */
|
|
39
42
|
theme?: DebugTheme;
|
|
@@ -58,6 +61,7 @@ export function DebugPanel({
|
|
|
58
61
|
logsSlot,
|
|
59
62
|
defaultTab = "graph",
|
|
60
63
|
endpoints,
|
|
64
|
+
endpointReachability,
|
|
61
65
|
theme,
|
|
62
66
|
}: DebugPanelProps) {
|
|
63
67
|
const [tab, setTab] = useState<Tab>(defaultTab);
|
|
@@ -109,7 +113,9 @@ export function DebugPanel({
|
|
|
109
113
|
Logs{logsSlot ? null : <span className="tdbg-tabcount">{logs.length}</span>}
|
|
110
114
|
</button>
|
|
111
115
|
<span className="tdbg-tabs-spacer" />
|
|
112
|
-
{endpoints && endpoints.length > 0 &&
|
|
116
|
+
{endpoints && endpoints.length > 0 && (
|
|
117
|
+
<EndpointLinks endpoints={endpoints} reachability={endpointReachability} />
|
|
118
|
+
)}
|
|
113
119
|
<button className="tdbg-btn" onClick={onTogglePause}>
|
|
114
120
|
{paused ? "Resume" : "Pause"}
|
|
115
121
|
</button>
|
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
import { ExternalLink } from "lucide-react";
|
|
2
|
-
import {
|
|
1
|
+
import { CheckCircle2, ExternalLink, Loader2, XCircle } from "lucide-react";
|
|
2
|
+
import {
|
|
3
|
+
type AppEndpoint,
|
|
4
|
+
type EndpointReachability,
|
|
5
|
+
endpointHref,
|
|
6
|
+
endpointLabel,
|
|
7
|
+
} from "../endpoints.js";
|
|
3
8
|
|
|
4
9
|
export interface EndpointLinksProps {
|
|
5
10
|
endpoints: readonly AppEndpoint[];
|
|
11
|
+
/** Per-port reachability, rendered as a status icon on each tcp link. A tcp
|
|
12
|
+
* endpoint with no entry yet shows the `checking` spinner. */
|
|
13
|
+
reachability?: ReadonlyMap<number, EndpointReachability>;
|
|
6
14
|
}
|
|
7
15
|
|
|
8
16
|
/** The running application's exposed addresses, rendered in the panel header.
|
|
9
|
-
* tcp endpoints are clickable links to the app
|
|
10
|
-
*
|
|
11
|
-
|
|
17
|
+
* tcp endpoints are clickable links to the app, each carrying a reachability
|
|
18
|
+
* status icon (spinner while checking, ok/error once known); udp endpoints show
|
|
19
|
+
* as a plain label. Renders nothing when there are no endpoints. */
|
|
20
|
+
export function EndpointLinks({ endpoints, reachability }: EndpointLinksProps) {
|
|
12
21
|
if (endpoints.length === 0) return null;
|
|
13
22
|
return (
|
|
14
23
|
<span className="tdbg-endpoints">
|
|
@@ -32,11 +41,42 @@ export function EndpointLinks({ endpoints }: EndpointLinksProps) {
|
|
|
32
41
|
rel="noreferrer"
|
|
33
42
|
title={`Open ${href}`}
|
|
34
43
|
>
|
|
35
|
-
|
|
44
|
+
{reachability && (
|
|
45
|
+
<ReachabilityIcon state={reachability.get(endpoint.port) ?? "checking"} />
|
|
46
|
+
)}
|
|
36
47
|
{label}
|
|
48
|
+
<ExternalLink size={11} aria-hidden />
|
|
37
49
|
</a>
|
|
38
50
|
);
|
|
39
51
|
})}
|
|
40
52
|
</span>
|
|
41
53
|
);
|
|
42
54
|
}
|
|
55
|
+
|
|
56
|
+
function ReachabilityIcon({ state }: { state: EndpointReachability }) {
|
|
57
|
+
if (state === "reachable") {
|
|
58
|
+
return (
|
|
59
|
+
<CheckCircle2
|
|
60
|
+
size={11}
|
|
61
|
+
className="tdbg-endpoint-status tdbg-endpoint-status--reachable"
|
|
62
|
+
aria-label="reachable"
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
if (state === "unreachable") {
|
|
67
|
+
return (
|
|
68
|
+
<XCircle
|
|
69
|
+
size={11}
|
|
70
|
+
className="tdbg-endpoint-status tdbg-endpoint-status--unreachable"
|
|
71
|
+
aria-label="not reachable"
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return (
|
|
76
|
+
<Loader2
|
|
77
|
+
size={11}
|
|
78
|
+
className="tdbg-endpoint-status tdbg-endpoint-status--checking tdbg-spin"
|
|
79
|
+
aria-label="checking reachability"
|
|
80
|
+
/>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
@@ -88,6 +88,26 @@
|
|
|
88
88
|
.tdbg-endpoint-link:hover {
|
|
89
89
|
border-color: var(--tdbg-accent);
|
|
90
90
|
}
|
|
91
|
+
.tdbg-endpoint-status {
|
|
92
|
+
flex: none;
|
|
93
|
+
}
|
|
94
|
+
.tdbg-endpoint-status--checking {
|
|
95
|
+
color: var(--tdbg-muted);
|
|
96
|
+
}
|
|
97
|
+
.tdbg-endpoint-status--reachable {
|
|
98
|
+
color: var(--tdbg-good);
|
|
99
|
+
}
|
|
100
|
+
.tdbg-endpoint-status--unreachable {
|
|
101
|
+
color: var(--tdbg-bad);
|
|
102
|
+
}
|
|
103
|
+
.tdbg-spin {
|
|
104
|
+
animation: tdbg-spin 0.8s linear infinite;
|
|
105
|
+
}
|
|
106
|
+
@keyframes tdbg-spin {
|
|
107
|
+
to {
|
|
108
|
+
transform: rotate(360deg);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
91
111
|
|
|
92
112
|
.tdbg-bar {
|
|
93
113
|
position: sticky;
|
package/src/endpoints.ts
CHANGED
|
@@ -13,6 +13,12 @@ export interface AppEndpoint {
|
|
|
13
13
|
url?: string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
/** Per-port reachability of a running app's endpoint, surfaced as a status icon
|
|
17
|
+
* beside the link: a spinner while `checking`, ok when `reachable`, error when
|
|
18
|
+
* `unreachable`. Mirrors the runner contract's `ReachabilityState`, kept local so
|
|
19
|
+
* debug-ui stays browser-safe with no dependency on the runner package. */
|
|
20
|
+
export type EndpointReachability = "checking" | "reachable" | "unreachable";
|
|
21
|
+
|
|
16
22
|
/** The link a tcp endpoint resolves to, or `null` for a non-linkable (udp)
|
|
17
23
|
* endpoint. Prefers an explicit `url`; otherwise derives `http://host:port`. */
|
|
18
24
|
export function endpointHref(endpoint: AppEndpoint): string | null {
|