@tsplc/debug 0.2.16 → 0.2.18
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/dist/format.js +36 -18
- package/dist/format.js.map +4 -4
- package/dist/index.js +768 -516
- package/dist/index.js.map +20 -17
- package/dist/manifest.js +6 -2
- package/dist/manifest.js.map +3 -3
- package/dist/paths.js +60 -28
- package/dist/paths.js.map +3 -3
- package/package.json +47 -46
- package/src/adapter.ts +43 -36
- package/src/api.ts +128 -126
- package/src/debugger.ts +584 -467
- package/src/errors.ts +3 -0
- package/src/hardware.ts +127 -96
- package/src/http.ts +147 -116
- package/src/index.ts +34 -4
- package/src/jobs.ts +102 -77
- package/src/login-value.ts +165 -0
- package/src/login.ts +233 -253
- package/src/manifest.ts +200 -194
- package/src/opcua.ts +55 -55
- package/src/paths.ts +230 -157
- package/src/requests.ts +86 -0
- package/src/telemetry.ts +104 -90
- package/src/timeline.ts +96 -61
- package/src/trace.ts +41 -31
- package/src/ui/bits.ts +45 -29
- package/src/ui/client.ts +33 -26
- package/src/ui/dom.ts +189 -108
- package/src/ui/format.ts +127 -72
- package/src/ui/hardware.ts +416 -343
- package/src/ui/header.ts +186 -164
- package/src/ui/index.ts +16 -9
- package/src/ui/jobs.ts +263 -214
- package/src/ui/main.ts +52 -48
- package/src/ui/overview.ts +152 -108
- package/src/ui/recent.ts +329 -276
- package/src/ui/requests.ts +69 -73
- package/src/ui/store.ts +236 -198
- package/src/ui/tree.ts +162 -130
- package/src/ui/variables.ts +557 -431
- package/src/watch.ts +22 -17
- package/src/ui/dev.ts +0 -579
- package/src/ui/fixture.ts +0 -548
package/src/errors.ts
ADDED
package/src/hardware.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type TargetRead, type TargetSample, worstQuality } from "./adapter.ts";
|
|
2
|
-
import type { DeviceState } from "./api.ts";
|
|
2
|
+
import type { DeviceState, Quality } from "./api.ts";
|
|
3
3
|
import type { DebugDevice, DebugIo, DebugType } from "./manifest.ts";
|
|
4
4
|
|
|
5
5
|
/** Driver state names that mean the connection isn't working. */
|
|
@@ -10,74 +10,102 @@ const untyped: DebugType = { kind: "scalar", iec: "ANY" };
|
|
|
10
10
|
|
|
11
11
|
/** What a device's health is read from: the driver's own state, when the build names it. */
|
|
12
12
|
export const healthReads = (device: DebugDevice): TargetRead[] => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
const { state, states, diagnostic, message } = device.health ?? {};
|
|
14
|
+
return [
|
|
15
|
+
...(state
|
|
16
|
+
? [
|
|
17
|
+
{
|
|
18
|
+
target: state,
|
|
19
|
+
type: states
|
|
20
|
+
? { kind: "enum" as const, name: "state", members: states }
|
|
21
|
+
: { kind: "scalar" as const, iec: "DINT" },
|
|
22
|
+
},
|
|
23
|
+
]
|
|
24
|
+
: []),
|
|
25
|
+
...(diagnostic
|
|
26
|
+
? [{ target: diagnostic, type: { kind: "scalar" as const, iec: "BOOL" } }]
|
|
27
|
+
: []),
|
|
28
|
+
...(message
|
|
29
|
+
? [{ target: message, type: { kind: "scalar" as const, iec: "STRING" } }]
|
|
30
|
+
: []),
|
|
31
|
+
];
|
|
28
32
|
};
|
|
29
33
|
|
|
30
34
|
/** Everything a device's page shows: its health, raw assembly bytes, bound channels and status symbols. */
|
|
31
35
|
export const deviceReads = (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
device: DebugDevice,
|
|
37
|
+
io: readonly DebugIo[],
|
|
38
|
+
typeOf: (id: string) => DebugType,
|
|
35
39
|
): TargetRead[] => [
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
...healthReads(device),
|
|
41
|
+
...device.assemblies.flatMap(({ raw, bytes }) =>
|
|
42
|
+
raw
|
|
43
|
+
? [
|
|
44
|
+
{
|
|
45
|
+
target: raw,
|
|
46
|
+
type: {
|
|
47
|
+
kind: "array" as const,
|
|
48
|
+
element: "BYTE",
|
|
49
|
+
length: bytes,
|
|
50
|
+
lower: 0,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
]
|
|
54
|
+
: [],
|
|
55
|
+
),
|
|
56
|
+
...io
|
|
57
|
+
.filter((binding) => binding.device === device.id)
|
|
58
|
+
.map(({ target, type }) => ({ target, type: typeOf(type) })),
|
|
59
|
+
...Object.values(device.status ?? {}).map((target) => ({
|
|
60
|
+
target,
|
|
61
|
+
type: untyped,
|
|
62
|
+
})),
|
|
51
63
|
];
|
|
52
64
|
|
|
65
|
+
/** A reading that is no longer good says nothing current, fault or not. */
|
|
66
|
+
const healthState = (quality: Quality, faulted: boolean) => {
|
|
67
|
+
if (quality !== "good") {
|
|
68
|
+
return "stale";
|
|
69
|
+
}
|
|
70
|
+
return faulted ? "fault" : "ok";
|
|
71
|
+
};
|
|
72
|
+
|
|
53
73
|
const health = (
|
|
54
|
-
|
|
55
|
-
|
|
74
|
+
device: DebugDevice,
|
|
75
|
+
value: (target: string) => TargetSample | undefined,
|
|
56
76
|
): DeviceState["health"] => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
const { state, states, diagnostic, message } = device.health ?? {};
|
|
78
|
+
if (!state && !diagnostic) {
|
|
79
|
+
return { state: "unknown", quality: "unavailable" };
|
|
80
|
+
}
|
|
81
|
+
const stateSample = state ? value(state) : undefined;
|
|
82
|
+
const diagnosticSample = diagnostic ? value(diagnostic) : undefined;
|
|
83
|
+
const messageSample = message ? value(message) : undefined;
|
|
84
|
+
const quality = worstQuality([
|
|
85
|
+
...(state ? [stateSample] : []),
|
|
86
|
+
...(diagnostic ? [diagnosticSample] : []),
|
|
87
|
+
]);
|
|
88
|
+
const number =
|
|
89
|
+
typeof stateSample?.value === "number" ? stateSample.value : undefined;
|
|
90
|
+
// The login names enum members the manifest may not list.
|
|
91
|
+
const name =
|
|
92
|
+
Object.entries(states ?? {}).find(([, member]) => member === number)?.[0] ??
|
|
93
|
+
(typeof stateSample?.value === "string" ? stateSample.value : undefined);
|
|
94
|
+
const faulted =
|
|
95
|
+
diagnosticSample?.value === true ||
|
|
96
|
+
(name !== undefined && faultyState.test(name));
|
|
97
|
+
return {
|
|
98
|
+
state: healthState(quality, faulted),
|
|
99
|
+
...(number !== undefined && { value: number }),
|
|
100
|
+
...(name && { name }),
|
|
101
|
+
...(typeof diagnosticSample?.value === "boolean" && {
|
|
102
|
+
diagnostic: diagnosticSample.value,
|
|
103
|
+
}),
|
|
104
|
+
...(typeof messageSample?.value === "string" && {
|
|
105
|
+
message: messageSample.value,
|
|
106
|
+
}),
|
|
107
|
+
quality,
|
|
108
|
+
};
|
|
81
109
|
};
|
|
82
110
|
|
|
83
111
|
/**
|
|
@@ -85,41 +113,44 @@ const health = (
|
|
|
85
113
|
* is "unknown" unless the manifest names the driver's own state.
|
|
86
114
|
*/
|
|
87
115
|
export const deviceState = (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
116
|
+
device: DebugDevice,
|
|
117
|
+
io: readonly DebugIo[],
|
|
118
|
+
value: (target: string) => TargetSample | undefined,
|
|
91
119
|
): DeviceState => ({
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
id: device.id,
|
|
121
|
+
health: health(device, value),
|
|
122
|
+
assemblies: device.assemblies.map(({ direction, address, raw }) => {
|
|
123
|
+
const sample = raw ? value(raw) : undefined;
|
|
124
|
+
return {
|
|
125
|
+
direction,
|
|
126
|
+
...(address && { address }),
|
|
127
|
+
bytes:
|
|
128
|
+
Array.isArray(sample?.value) &&
|
|
129
|
+
sample.value.every((byte): byte is number => typeof byte === "number")
|
|
130
|
+
? sample.value
|
|
131
|
+
: null,
|
|
132
|
+
quality: sample?.quality ?? "unavailable",
|
|
133
|
+
};
|
|
134
|
+
}),
|
|
135
|
+
channels: io.flatMap((binding) =>
|
|
136
|
+
binding.device === device.id && binding.channel
|
|
137
|
+
? [
|
|
138
|
+
{
|
|
139
|
+
id: binding.channel,
|
|
140
|
+
path: binding.path,
|
|
141
|
+
value: value(binding.target)?.value ?? null,
|
|
142
|
+
quality: value(binding.target)?.quality ?? "unavailable",
|
|
143
|
+
},
|
|
144
|
+
]
|
|
145
|
+
: [],
|
|
146
|
+
),
|
|
147
|
+
status: Object.fromEntries(
|
|
148
|
+
Object.entries(device.status ?? {}).map(([label, target]) => [
|
|
149
|
+
label,
|
|
150
|
+
{
|
|
151
|
+
value: value(target)?.value ?? null,
|
|
152
|
+
quality: value(target)?.quality ?? "unavailable",
|
|
153
|
+
},
|
|
154
|
+
]),
|
|
155
|
+
),
|
|
125
156
|
});
|
package/src/http.ts
CHANGED
|
@@ -11,76 +11,95 @@ const heartbeatMs = 5000;
|
|
|
11
11
|
const encoder = new TextEncoder();
|
|
12
12
|
|
|
13
13
|
const json = (body: unknown, status = 200) =>
|
|
14
|
-
|
|
14
|
+
Response.json(body, { status, headers: { "Cache-Control": "no-store" } });
|
|
15
15
|
|
|
16
16
|
const list = (value: string | null) =>
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
(value ?? "")
|
|
18
|
+
.split(",")
|
|
19
|
+
.map((item) => item.trim())
|
|
20
|
+
.filter(Boolean);
|
|
21
21
|
|
|
22
22
|
export const loadManifest = async (file: string) =>
|
|
23
|
-
|
|
23
|
+
debugManifest.parse(JSON.parse(await readFile(file, "utf8")));
|
|
24
24
|
|
|
25
25
|
/** What a stream's page shows, from its query. */
|
|
26
26
|
const interest = (search: URLSearchParams): Interest => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
const jobs = list(search.get("jobs")).map(Number);
|
|
28
|
+
if (!jobs.every(Number.isInteger)) {
|
|
29
|
+
throw new DebugError("jobs must be job ids", 400);
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
watch: list(search.get("watch")),
|
|
33
|
+
jobs,
|
|
34
|
+
health: list(search.get("health")),
|
|
35
|
+
devices: list(search.get("devices")),
|
|
36
|
+
};
|
|
35
37
|
};
|
|
36
38
|
|
|
37
39
|
/** Every stream event, plus samples of the watched paths and states of the shown jobs and devices. */
|
|
38
40
|
const stream = (debug: Debugger, { watch, ...shown }: Interest) => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
41
|
+
// Refuse a watch that matches too much before the stream starts.
|
|
42
|
+
debug.paths.expand(watch);
|
|
43
|
+
let stop = () => {};
|
|
44
|
+
return new Response(
|
|
45
|
+
new ReadableStream<Uint8Array>({
|
|
46
|
+
start: (controller) => {
|
|
47
|
+
let open = true;
|
|
48
|
+
const write = (text: string) => {
|
|
49
|
+
if (open) {
|
|
50
|
+
controller.enqueue(encoder.encode(text));
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const send = ({ event, data }: StreamMessage) =>
|
|
54
|
+
write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
|
|
55
|
+
send({ event: "session", data: debug.session() });
|
|
56
|
+
const latest = new Map<string, { sample: Sample; sentAt: number }>();
|
|
57
|
+
const sendSample = (sample: Sample) => {
|
|
58
|
+
latest.set(sample.path, { sample, sentAt: Date.now() });
|
|
59
|
+
send({ event: "sample", data: sample });
|
|
60
|
+
};
|
|
61
|
+
const unsubscribe = debug.subscribe(send);
|
|
62
|
+
const unwatch = debug.watch(watch, sendSample);
|
|
63
|
+
const unshow = debug.show(shown);
|
|
64
|
+
const heartbeat = setInterval(
|
|
65
|
+
() => write(": keepalive\n\n"),
|
|
66
|
+
heartbeatMs,
|
|
67
|
+
);
|
|
68
|
+
// Over OPC UA, samples come only on change. While the session holds, an unchanged value
|
|
69
|
+
// is still current, so it is sent again each interval; clients mark samples stale by their age.
|
|
70
|
+
const { intervalMs } = debug.session().reading;
|
|
71
|
+
const refresh = setInterval(() => {
|
|
72
|
+
if (debug.session().connection.state !== "connected") {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const now = Date.now();
|
|
76
|
+
for (const { sample, sentAt } of latest.values()) {
|
|
77
|
+
if (now - sentAt >= intervalMs) {
|
|
78
|
+
sendSample({
|
|
79
|
+
...sample,
|
|
80
|
+
receivedAt: new Date(now).toISOString(),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}, intervalMs);
|
|
85
|
+
stop = () => {
|
|
86
|
+
open = false;
|
|
87
|
+
clearInterval(heartbeat);
|
|
88
|
+
clearInterval(refresh);
|
|
89
|
+
unsubscribe();
|
|
90
|
+
unwatch();
|
|
91
|
+
unshow();
|
|
92
|
+
};
|
|
93
|
+
},
|
|
94
|
+
cancel: () => stop(),
|
|
95
|
+
}),
|
|
96
|
+
{
|
|
97
|
+
headers: {
|
|
98
|
+
"Content-Type": "text/event-stream",
|
|
99
|
+
"Cache-Control": "no-store",
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
);
|
|
84
103
|
};
|
|
85
104
|
|
|
86
105
|
/**
|
|
@@ -88,68 +107,80 @@ const stream = (debug: Debugger, { watch, ...shown }: Interest) => {
|
|
|
88
107
|
* the host mounts them. There is no route that writes to the controller; hosts authenticate.
|
|
89
108
|
*/
|
|
90
109
|
export const createDebugHandler =
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
110
|
+
(debug: Debugger, log: (message: string) => void) =>
|
|
111
|
+
async (request: Request, route: string): Promise<Response> => {
|
|
112
|
+
const { searchParams } = new URL(request.url);
|
|
113
|
+
const key = `${request.method} ${route}`;
|
|
114
|
+
try {
|
|
115
|
+
switch (key) {
|
|
116
|
+
case "GET /":
|
|
117
|
+
return new Response((await loadUi()).html, {
|
|
118
|
+
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
119
|
+
});
|
|
120
|
+
case "GET /ui.js":
|
|
121
|
+
return new Response((await loadUi()).script, {
|
|
122
|
+
headers: { "Content-Type": "text/javascript; charset=utf-8" },
|
|
123
|
+
});
|
|
124
|
+
case "GET /api/session":
|
|
125
|
+
return json(debug.session());
|
|
126
|
+
case "GET /api/manifest":
|
|
127
|
+
return json(debug.manifest);
|
|
128
|
+
case "GET /api/stream":
|
|
129
|
+
return stream(debug, interest(searchParams));
|
|
130
|
+
case "GET /api/values":
|
|
131
|
+
return json(await debug.values(list(searchParams.get("paths"))));
|
|
132
|
+
case "GET /api/jobs":
|
|
133
|
+
return json(debug.jobs());
|
|
134
|
+
case "GET /api/hardware":
|
|
135
|
+
return json(debug.hardware());
|
|
136
|
+
case "GET /api/timeline":
|
|
137
|
+
return json(debug.timeline(searchParams.get("since") ?? undefined));
|
|
138
|
+
case "GET /api/watch":
|
|
139
|
+
return json(debug.watchGroups());
|
|
140
|
+
case "PUT /api/watch":
|
|
141
|
+
return json(
|
|
142
|
+
await debug.saveWatchGroups(
|
|
143
|
+
watchGroupsSchema.parse(await request.json()),
|
|
144
|
+
),
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
return json({ error: `No route ${key}` }, 404);
|
|
148
|
+
} catch (error) {
|
|
149
|
+
if (error instanceof DebugError) {
|
|
150
|
+
return json({ error: error.message }, error.status);
|
|
151
|
+
}
|
|
152
|
+
// RangeError: a watch matches too many values; SyntaxError: a body isn't JSON.
|
|
153
|
+
if (error instanceof RangeError || error instanceof SyntaxError) {
|
|
154
|
+
return json({ error: error.message }, 400);
|
|
155
|
+
}
|
|
156
|
+
if (error instanceof z.ZodError) {
|
|
157
|
+
return json({ error: z.prettifyError(error) }, 400);
|
|
158
|
+
}
|
|
159
|
+
log(
|
|
160
|
+
`${key} failed: ${error instanceof Error ? error.stack : String(error)}`,
|
|
161
|
+
);
|
|
162
|
+
return json({ error: "The debugger failed; see its log" }, 500);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
135
165
|
|
|
136
166
|
/**
|
|
137
167
|
* Serves the debugger on 127.0.0.1 without a token. Requests that name another host are refused,
|
|
138
168
|
* so no website can reach it by rebinding a domain name to 127.0.0.1.
|
|
139
169
|
*/
|
|
140
170
|
export const serveDebugger = (
|
|
141
|
-
|
|
142
|
-
|
|
171
|
+
debug: Debugger,
|
|
172
|
+
options: { port: number; log: (message: string) => void },
|
|
143
173
|
) => {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
174
|
+
const handle = createDebugHandler(debug, options.log);
|
|
175
|
+
return Bun.serve({
|
|
176
|
+
hostname: "127.0.0.1",
|
|
177
|
+
port: options.port,
|
|
178
|
+
fetch: (request) => {
|
|
179
|
+
const host = request.headers.get("host")?.replace(/:\d+$/, "");
|
|
180
|
+
if (host !== "127.0.0.1" && host !== "localhost") {
|
|
181
|
+
return json({ error: "Use http://127.0.0.1 or http://localhost" }, 403);
|
|
182
|
+
}
|
|
183
|
+
return handle(request, new URL(request.url).pathname);
|
|
184
|
+
},
|
|
185
|
+
});
|
|
155
186
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,38 @@
|
|
|
1
|
-
export type
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export type {
|
|
2
|
+
ApiResponses,
|
|
3
|
+
AppRecord,
|
|
4
|
+
ConnectionState,
|
|
5
|
+
DeviceState,
|
|
6
|
+
Interest,
|
|
7
|
+
JobState,
|
|
8
|
+
Quality,
|
|
9
|
+
RequestTrace,
|
|
10
|
+
Sample,
|
|
11
|
+
Session,
|
|
12
|
+
StreamEvents,
|
|
13
|
+
TimelineEntry,
|
|
14
|
+
TraceEvent,
|
|
15
|
+
WatchGroups,
|
|
16
|
+
} from "./api.ts";
|
|
17
|
+
export type {
|
|
18
|
+
Connection,
|
|
19
|
+
TargetAdapter,
|
|
20
|
+
TargetRead,
|
|
21
|
+
TargetSample,
|
|
22
|
+
} from "./adapter.ts";
|
|
23
|
+
export {
|
|
24
|
+
createDebugger,
|
|
25
|
+
DebugError,
|
|
26
|
+
type Debugger,
|
|
27
|
+
type DebuggerOptions,
|
|
28
|
+
} from "./debugger.ts";
|
|
4
29
|
export { createDebugHandler, loadManifest, serveDebugger } from "./http.ts";
|
|
5
30
|
export { createLoginAdapter, LoginUnavailable, noLogin } from "./login.ts";
|
|
6
31
|
export { createOpcUaAdapter, opcUaConnection } from "./opcua.ts";
|
|
7
|
-
export {
|
|
32
|
+
export {
|
|
33
|
+
createPaths,
|
|
34
|
+
type PathNode,
|
|
35
|
+
type Paths,
|
|
36
|
+
type ResolvedPath,
|
|
37
|
+
} from "./paths.ts";
|
|
8
38
|
export { timelineEntries } from "./timeline.ts";
|