@source-repo/rpc-cli 3.0.0
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 +1131 -0
- package/dist/bench.d.ts +66 -0
- package/dist/bench.d.ts.map +1 -0
- package/dist/bench.js +109 -0
- package/dist/bench.js.map +1 -0
- package/dist/broker.d.ts +61 -0
- package/dist/broker.d.ts.map +1 -0
- package/dist/broker.js +56 -0
- package/dist/broker.js.map +1 -0
- package/dist/bus.d.ts +142 -0
- package/dist/bus.d.ts.map +1 -0
- package/dist/bus.js +272 -0
- package/dist/bus.js.map +1 -0
- package/dist/bus.types.json +269 -0
- package/dist/conform.d.ts +75 -0
- package/dist/conform.d.ts.map +1 -0
- package/dist/conform.js +152 -0
- package/dist/conform.js.map +1 -0
- package/dist/console.d.ts +285 -0
- package/dist/console.d.ts.map +1 -0
- package/dist/console.js +686 -0
- package/dist/console.js.map +1 -0
- package/dist/console.types.json +1730 -0
- package/dist/extract.d.ts +37 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +272 -0
- package/dist/extract.js.map +1 -0
- package/dist/fake.d.ts +58 -0
- package/dist/fake.d.ts.map +1 -0
- package/dist/fake.js +164 -0
- package/dist/fake.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +905 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.d.ts +15 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +507 -0
- package/dist/mcp.js.map +1 -0
- package/dist/network.d.ts +58 -0
- package/dist/network.d.ts.map +1 -0
- package/dist/network.js +64 -0
- package/dist/network.js.map +1 -0
- package/dist/record.d.ts +74 -0
- package/dist/record.d.ts.map +1 -0
- package/dist/record.js +221 -0
- package/dist/record.js.map +1 -0
- package/dist/tapping.d.ts +11 -0
- package/dist/tapping.d.ts.map +1 -0
- package/dist/tapping.js +71 -0
- package/dist/tapping.js.map +1 -0
- package/dist/verbs.d.ts +59 -0
- package/dist/verbs.d.ts.map +1 -0
- package/dist/verbs.js +324 -0
- package/dist/verbs.js.map +1 -0
- package/dist/web/app.css +1 -0
- package/dist/web/app.js +2063 -0
- package/dist/web/app.js.map +1 -0
- package/dist/web/index.html +13 -0
- package/package.json +65 -0
package/dist/conform.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { namespaceProblems } from '@source-repo/rpc';
|
|
2
|
+
import { awaitPeer, connectNetwork } from './network.js';
|
|
3
|
+
import { signatureOf } from './verbs.js';
|
|
4
|
+
/**
|
|
5
|
+
* Checking a device rather than a build.
|
|
6
|
+
*
|
|
7
|
+
* `check` compares source against a stored contract, which catches a change before it ships. What it
|
|
8
|
+
* cannot answer is the question asked on site: the contract says this device offers
|
|
9
|
+
* `writeSetpoint(value, mode?)` - is that what the box on the wall is actually running? A peer that
|
|
10
|
+
* describes itself can be asked, and the answer runs through the same comparison the server applies
|
|
11
|
+
* to a caller declaring an older version, so a device behind its own contract is reported in exactly
|
|
12
|
+
* the words a stale caller would have been.
|
|
13
|
+
*/
|
|
14
|
+
/** The one namespace nobody's own contract covers; every server that describes itself has it. */
|
|
15
|
+
const INTROSPECTION = 'msgrpc';
|
|
16
|
+
/**
|
|
17
|
+
* A live peer's self-description as a schema the compatibility check can read.
|
|
18
|
+
*
|
|
19
|
+
* The two are nearly the same information in different shapes - describe() returns lists because a
|
|
20
|
+
* console renders them in order, a schema uses dictionaries because dispatch looks methods up by
|
|
21
|
+
* name.
|
|
22
|
+
*/
|
|
23
|
+
export const schemaFromDescription = (description) => ({
|
|
24
|
+
schema: 1,
|
|
25
|
+
...(description.version ? { version: description.version } : {}),
|
|
26
|
+
types: description.types ?? {},
|
|
27
|
+
namespaces: Object.fromEntries(description.namespaces.map((namespace) => [
|
|
28
|
+
namespace.name,
|
|
29
|
+
{
|
|
30
|
+
...(namespace.version ? { version: namespace.version } : {}),
|
|
31
|
+
methods: Object.fromEntries(namespace.methods.map((method) => [
|
|
32
|
+
method.name,
|
|
33
|
+
{
|
|
34
|
+
params: method.params ?? [],
|
|
35
|
+
...(method.paramNames ? { paramNames: method.paramNames } : {}),
|
|
36
|
+
...(method.rest ? { rest: method.rest } : {}),
|
|
37
|
+
...(method.returns ? { returns: method.returns } : {})
|
|
38
|
+
}
|
|
39
|
+
])),
|
|
40
|
+
events: Object.fromEntries(namespace.events.map((event) => [event.name, { params: event.params ?? [] }]))
|
|
41
|
+
}
|
|
42
|
+
]))
|
|
43
|
+
});
|
|
44
|
+
/** Whether a peer publishes enough of a contract for a comparison to mean anything. */
|
|
45
|
+
const describesItsMethods = (namespace) => namespace.methods.length === 0 || namespace.methods.some((method) => !!method.params);
|
|
46
|
+
const describe = async (connected, peer) => {
|
|
47
|
+
const proxy = await connected.network.proxy(INTROSPECTION, peer);
|
|
48
|
+
return await proxy.remote.describe();
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Compares what a peer says it serves with the contract callers were built against.
|
|
52
|
+
*
|
|
53
|
+
* The stored contract is the caller's side and the device is the current side, which is the same
|
|
54
|
+
* orientation `check` uses against source - so "argument 0 narrowed" means the same thing here as
|
|
55
|
+
* it does in CI, and means it about the box rather than the branch.
|
|
56
|
+
*/
|
|
57
|
+
export const checkPeerOn = async (connected, options) => {
|
|
58
|
+
{
|
|
59
|
+
if (!(await awaitPeer(connected, options.peer, options.wait ?? 5000)))
|
|
60
|
+
throw Object.assign(new Error(`${options.peer} did not appear within ${options.wait ?? 5000} ms`), { code: 'ClassNotFound' });
|
|
61
|
+
const description = await describe(connected, options.peer);
|
|
62
|
+
const live = schemaFromDescription(description);
|
|
63
|
+
const types = { ...options.stored.types, ...live.types };
|
|
64
|
+
const report = { peer: options.peer, undescribed: [], problems: [], missing: [], checked: [] };
|
|
65
|
+
for (const [name, stored] of Object.entries(options.stored.namespaces)) {
|
|
66
|
+
if (name === INTROSPECTION)
|
|
67
|
+
continue;
|
|
68
|
+
const served = description.namespaces.find((namespace) => namespace.name === name);
|
|
69
|
+
if (!served) {
|
|
70
|
+
report.missing.push(name);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
// A peer running without a schema describes its method names and nothing else. Comparing
|
|
74
|
+
// that would report every argument as removed, which is a statement about the peer's
|
|
75
|
+
// configuration rather than about its contract - so it is said plainly instead.
|
|
76
|
+
if (!describesItsMethods(served)) {
|
|
77
|
+
report.undescribed.push(name);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
report.checked.push(name);
|
|
81
|
+
report.problems.push(...namespaceProblems(stored, live.namespaces[name], types).map((problem) => ({ ...problem, namespace: name })));
|
|
82
|
+
}
|
|
83
|
+
return report;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
/** The same, opening a connection of its own - what the command line wants. */
|
|
87
|
+
export const checkPeer = async (options) => {
|
|
88
|
+
const connected = await connectNetwork(options);
|
|
89
|
+
try {
|
|
90
|
+
return await checkPeerOn(connected, options);
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
await connected.close();
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* What two live peers offer differently - the "why does cell 3 behave differently from cell 2"
|
|
98
|
+
* question, which is usually answered by one of them running last season's firmware.
|
|
99
|
+
*
|
|
100
|
+
* Signatures are compared as they read rather than structurally, because the answer is going to be
|
|
101
|
+
* read by a person standing in front of two cabinets.
|
|
102
|
+
*/
|
|
103
|
+
export const diffPeersOn = async (connected, options) => {
|
|
104
|
+
{
|
|
105
|
+
for (const peer of [options.left, options.right])
|
|
106
|
+
if (!(await awaitPeer(connected, peer, options.wait ?? 5000)))
|
|
107
|
+
throw Object.assign(new Error(`${peer} did not appear within ${options.wait ?? 5000} ms`), { code: 'ClassNotFound' });
|
|
108
|
+
const [left, right] = await Promise.all([describe(connected, options.left), describe(connected, options.right)]);
|
|
109
|
+
const differences = [];
|
|
110
|
+
const namespaces = [...new Set([...left.namespaces.map((n) => n.name), ...right.namespaces.map((n) => n.name)])].sort();
|
|
111
|
+
for (const name of namespaces) {
|
|
112
|
+
if (name === INTROSPECTION)
|
|
113
|
+
continue;
|
|
114
|
+
const here = left.namespaces.find((namespace) => namespace.name === name);
|
|
115
|
+
const there = right.namespaces.find((namespace) => namespace.name === name);
|
|
116
|
+
if (!here || !there) {
|
|
117
|
+
differences.push({ namespace: name, ...(here ? { left: 'served' } : {}), ...(there ? { right: 'served' } : {}) });
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (here.version !== there.version)
|
|
121
|
+
differences.push({ namespace: name, member: 'contract version', left: here.version ?? 'none', right: there.version ?? 'none' });
|
|
122
|
+
const members = [...new Set([...here.methods.map((m) => m.name), ...there.methods.map((m) => m.name)])].sort();
|
|
123
|
+
for (const member of members) {
|
|
124
|
+
const a = here.methods.find((method) => method.name === member);
|
|
125
|
+
const b = there.methods.find((method) => method.name === member);
|
|
126
|
+
const one = a ? signatureOf(a) : undefined;
|
|
127
|
+
const other = b ? signatureOf(b) : undefined;
|
|
128
|
+
if (one !== other)
|
|
129
|
+
differences.push({ namespace: name, member, ...(one ? { left: one } : {}), ...(other ? { right: other } : {}) });
|
|
130
|
+
}
|
|
131
|
+
const events = [...new Set([...here.events.map((e) => e.name), ...there.events.map((e) => e.name)])].sort();
|
|
132
|
+
for (const event of events) {
|
|
133
|
+
const a = here.events.some((entry) => entry.name === event);
|
|
134
|
+
const b = there.events.some((entry) => entry.name === event);
|
|
135
|
+
if (a !== b)
|
|
136
|
+
differences.push({ namespace: name, member: `event ${event}`, ...(a ? { left: 'emitted' } : {}), ...(b ? { right: 'emitted' } : {}) });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return { left: options.left, right: options.right, differences };
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
/** The same, opening a connection of its own - what the command line wants. */
|
|
143
|
+
export const diffPeers = async (options) => {
|
|
144
|
+
const connected = await connectNetwork(options);
|
|
145
|
+
try {
|
|
146
|
+
return await diffPeersOn(connected, options);
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
await connected.close();
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
//# sourceMappingURL=conform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conform.js","sourceRoot":"","sources":["../src/conform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { type ServerOptions as TlsServerOptions } from 'node:https';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import { RpcServer, type ServerDescription } from '@source-repo/rpc';
|
|
4
|
+
import { type NetworkOptions } from './network.js';
|
|
5
|
+
import { BusService, type TapFilter, type TappedFrame } from './bus.js';
|
|
6
|
+
/**
|
|
7
|
+
* A browser console for a live msgrpc network: which peers are up, what each one exposes, and a
|
|
8
|
+
* form to call it and watch its events.
|
|
9
|
+
*
|
|
10
|
+
* Peer discovery is nearly free. Every peer publishes retained presence, so subscribing to
|
|
11
|
+
* <prefix>/presence/+ hands over everyone already online immediately - no scanning, no probing.
|
|
12
|
+
*
|
|
13
|
+
* The browser reaches this over msgrpc itself. The CLI runs an RpcServer on the same HTTP server
|
|
14
|
+
* that serves the page, so calls and the event stream both ride the library rather than a REST and
|
|
15
|
+
* SSE pair written for the occasion - and the console becomes the library's own first client.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Where the page learns which peer to address. Everything else the console offers is RPC, but a
|
|
19
|
+
* client has to know the name before it can call anything, and the console's name is now its name
|
|
20
|
+
* on the network rather than a constant - two consoles on one bus cannot both be 'msgrpc-console'.
|
|
21
|
+
*/
|
|
22
|
+
export declare const consoleIdentityPath = "/console.json";
|
|
23
|
+
/**
|
|
24
|
+
* The network flags every command shares, plus where the console listens.
|
|
25
|
+
*
|
|
26
|
+
* A hub is how a network with no broker - and a server hosted in a browser page, which cannot
|
|
27
|
+
* listen at all - becomes visible: peers there announce themselves on connect. Without `sign` the
|
|
28
|
+
* console cannot talk to a server configured with `verify`; it still discovers peers, because
|
|
29
|
+
* presence is unsigned retained state, and then every call times out with nothing to say why.
|
|
30
|
+
*/
|
|
31
|
+
export interface ConsoleOptions extends NetworkOptions {
|
|
32
|
+
port: number;
|
|
33
|
+
host: string;
|
|
34
|
+
/**
|
|
35
|
+
* Certificate and key, which is what makes this console HTTPS - and its socket.io link WSS,
|
|
36
|
+
* since both ride the same listener. Absent means plain HTTP, which is right behind a proxy
|
|
37
|
+
* that has already terminated TLS.
|
|
38
|
+
*/
|
|
39
|
+
tls?: TlsServerOptions;
|
|
40
|
+
/**
|
|
41
|
+
* The path this console is published under, when a reverse proxy forwards the prefix instead of
|
|
42
|
+
* stripping it. `/tools/console` makes the page, its assets and socket.io all answer there.
|
|
43
|
+
*
|
|
44
|
+
* Not needed for the ordinary `proxy_pass http://console:7844/` rule, whose trailing slash
|
|
45
|
+
* strips the prefix before the console sees it - the page already resolves everything relative
|
|
46
|
+
* to where it was served, so that case needs no configuration at either end. This is for the
|
|
47
|
+
* proxy that passes `/tools/console/socket.io` through unchanged.
|
|
48
|
+
*/
|
|
49
|
+
basePath?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* A mount point as `/tools/console/`, or `/` for none: one leading slash, one trailing slash.
|
|
53
|
+
*
|
|
54
|
+
* The trailing slash is the load-bearing part. Everything the page asks for is relative to its
|
|
55
|
+
* mount, so the app has to be reached at a path ending in one or its requests resolve a level up.
|
|
56
|
+
*/
|
|
57
|
+
export declare const normaliseBasePath: (basePath?: string) => string;
|
|
58
|
+
/** An event the console forwarded from a peer it was asked to watch. */
|
|
59
|
+
export interface StreamedEvent {
|
|
60
|
+
peer: string;
|
|
61
|
+
namespace: string;
|
|
62
|
+
event: string;
|
|
63
|
+
args: unknown[];
|
|
64
|
+
at: number;
|
|
65
|
+
}
|
|
66
|
+
/** A peer arriving or leaving, on any of the console's links. */
|
|
67
|
+
export interface PeerChange {
|
|
68
|
+
peer: string;
|
|
69
|
+
state: string;
|
|
70
|
+
at: number;
|
|
71
|
+
/** The link it arrived on or left from, when the console knows it. */
|
|
72
|
+
link?: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* What a peer turned out to be, learned from a description the console had already made.
|
|
76
|
+
*
|
|
77
|
+
* Deliberately not discovered by describing every peer on sight: that is a round trip each on a
|
|
78
|
+
* network where the peer list is the cheap part. The console describes a peer when someone selects
|
|
79
|
+
* it, and when it goes looking for a bus to tap - so the labels fill in as the network is used, and
|
|
80
|
+
* cost nothing that was not already being spent.
|
|
81
|
+
*/
|
|
82
|
+
export type PeerRole = 'broker' | 'console' | 'page' | 'device' | 'undescribed';
|
|
83
|
+
/** A tap the console holds, and where it holds it. */
|
|
84
|
+
export interface ConsoleTap {
|
|
85
|
+
token: string;
|
|
86
|
+
/** The peers doing the watching: a broker's `bus`, this console's own MQTT tap, or both. */
|
|
87
|
+
sources: string[];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* A frame a transport refused or could not deliver, a name two peers claimed, or a link that
|
|
91
|
+
* failed - the four things that otherwise reach a caller only as an unexplained timeout.
|
|
92
|
+
*
|
|
93
|
+
* The transports have always emitted these. Nothing listened, so the console showed a call that
|
|
94
|
+
* never came back and no reason anywhere, which is the hardest kind of problem to diagnose and the
|
|
95
|
+
* one this tooling exists to make visible.
|
|
96
|
+
*/
|
|
97
|
+
export interface NetworkProblem {
|
|
98
|
+
at: number;
|
|
99
|
+
/** `rejected`, `unroutable`, `peerDisplaced` or `transportError`. */
|
|
100
|
+
kind: string;
|
|
101
|
+
/** The link it happened on: the page's own, the broker, or the hub. */
|
|
102
|
+
link: string;
|
|
103
|
+
/** Who the frame claimed to come from, or the name that was taken over. */
|
|
104
|
+
peer?: string;
|
|
105
|
+
/** Who an undeliverable frame was addressed to. */
|
|
106
|
+
target?: string;
|
|
107
|
+
reason?: string;
|
|
108
|
+
}
|
|
109
|
+
/** What a browser may ask this console to do. Everything else on the class stays local. */
|
|
110
|
+
export declare class ConsoleService extends EventEmitter {
|
|
111
|
+
/** Every peer the console can see, on any of its links. */
|
|
112
|
+
private readonly online;
|
|
113
|
+
/** How long this console waits on the network, reported so the browser can wait longer. */
|
|
114
|
+
private readonly callTimeout;
|
|
115
|
+
/**
|
|
116
|
+
* Declared rather than inferred from emit() calls, which cannot be read statically. Without
|
|
117
|
+
* this the console's own contract described its methods and none of its events, so a console
|
|
118
|
+
* pointed at another one saw an empty events list on a service that has three.
|
|
119
|
+
*/
|
|
120
|
+
rpcEvents: {
|
|
121
|
+
event: [event: StreamedEvent];
|
|
122
|
+
peer: [change: PeerChange];
|
|
123
|
+
frame: [frame: TappedFrame];
|
|
124
|
+
problem: [problem: NetworkProblem];
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Subscriptions this console holds on the network, keyed by peer/namespace/event. The handler
|
|
128
|
+
* is kept because removing a listener needs the same function reference that was registered.
|
|
129
|
+
*/
|
|
130
|
+
readonly watching: Map<string, (...args: unknown[]) => void>;
|
|
131
|
+
/**
|
|
132
|
+
* The console's own place on the network, set once it exists. Every call the browser asks for
|
|
133
|
+
* goes out through this: one server holding the browser link, the broker and the hub, so a
|
|
134
|
+
* peer's name is enough - the registry knows which link reaches it.
|
|
135
|
+
*/
|
|
136
|
+
private network?;
|
|
137
|
+
useNetwork(network: RpcServer): void;
|
|
138
|
+
/**
|
|
139
|
+
* This console's own tap, when it has an MQTT link. There is no broker of ours on an MQTT
|
|
140
|
+
* network to ask, so the console does the watching itself - see `startConsole`.
|
|
141
|
+
*/
|
|
142
|
+
private localBus?;
|
|
143
|
+
useLocalTap(bus: BusService): void;
|
|
144
|
+
/** Which link each peer was last seen on, written by startConsole as they arrive. */
|
|
145
|
+
readonly links: Map<string, string>;
|
|
146
|
+
/**
|
|
147
|
+
* The flags this console was started with, so the page can render a command line that actually
|
|
148
|
+
* runs. A call worth making in the browser is usually one worth putting in a script, and
|
|
149
|
+
* retyping `--hub http://…` from memory is where that stops happening.
|
|
150
|
+
*/
|
|
151
|
+
startedWith: {
|
|
152
|
+
broker?: string;
|
|
153
|
+
hub?: string;
|
|
154
|
+
prefix?: string;
|
|
155
|
+
};
|
|
156
|
+
/** What has gone wrong on the links, newest first and bounded. */
|
|
157
|
+
private readonly seen;
|
|
158
|
+
/**
|
|
159
|
+
* Peers arriving and leaving, newest first and bounded.
|
|
160
|
+
*
|
|
161
|
+
* Kept because a peer that comes and goes is one of the commonest faults on a plant and the
|
|
162
|
+
* hardest to catch in the act: the console showed it as a dot that changed colour and forgot,
|
|
163
|
+
* so a device flapping every thirty seconds looked exactly like one that was simply up.
|
|
164
|
+
*/
|
|
165
|
+
private readonly comings;
|
|
166
|
+
/** What each peer turned out to be, from descriptions already made. */
|
|
167
|
+
private readonly roles;
|
|
168
|
+
notePresence(change: PeerChange): void;
|
|
169
|
+
/** Records a problem and passes it on, so a page open now sees it and one opened later still can. */
|
|
170
|
+
noteProblem(problem: NetworkProblem): void;
|
|
171
|
+
/** Console-side token -> the taps it opened, here and on other peers, and when they lapse. */
|
|
172
|
+
private readonly held;
|
|
173
|
+
/** Peers whose `frame` event this console has already subscribed to, so it subscribes once. */
|
|
174
|
+
private readonly forwarding;
|
|
175
|
+
private tapCounter;
|
|
176
|
+
constructor(
|
|
177
|
+
/** Every peer the console can see, on any of its links. */
|
|
178
|
+
online: Set<string>,
|
|
179
|
+
/** How long this console waits on the network, reported so the browser can wait longer. */
|
|
180
|
+
callTimeout: number);
|
|
181
|
+
/** Refuses early for a peer nothing has announced, rather than waiting out a call timeout. */
|
|
182
|
+
private reach;
|
|
183
|
+
peers(): Promise<{
|
|
184
|
+
peers: string[];
|
|
185
|
+
watching: string[];
|
|
186
|
+
callTimeout: number;
|
|
187
|
+
network: {
|
|
188
|
+
broker?: string;
|
|
189
|
+
hub?: string;
|
|
190
|
+
prefix?: string;
|
|
191
|
+
};
|
|
192
|
+
roles: {
|
|
193
|
+
[k: string]: PeerRole;
|
|
194
|
+
};
|
|
195
|
+
links: {
|
|
196
|
+
[k: string]: string;
|
|
197
|
+
};
|
|
198
|
+
}>;
|
|
199
|
+
/**
|
|
200
|
+
* What has gone wrong on the links, newest first.
|
|
201
|
+
*
|
|
202
|
+
* Fetched as well as streamed, because these arrive whether or not anyone is watching and the
|
|
203
|
+
* interesting ones are usually the ones from before you went looking.
|
|
204
|
+
*/
|
|
205
|
+
problems(): Promise<{
|
|
206
|
+
problems: NetworkProblem[];
|
|
207
|
+
}>;
|
|
208
|
+
/**
|
|
209
|
+
* Peers arriving and leaving, newest first - including before this page was opened, which is
|
|
210
|
+
* the half that matters when the question is whether something has been flapping.
|
|
211
|
+
*/
|
|
212
|
+
presence(): Promise<{
|
|
213
|
+
changes: PeerChange[];
|
|
214
|
+
}>;
|
|
215
|
+
describe(peer: string): Promise<ServerDescription | {
|
|
216
|
+
error: string;
|
|
217
|
+
code?: string;
|
|
218
|
+
}>;
|
|
219
|
+
call(peer: string, namespace: string, method: string, args?: unknown[]): Promise<{
|
|
220
|
+
result?: unknown;
|
|
221
|
+
error?: string;
|
|
222
|
+
code?: string;
|
|
223
|
+
ms: number;
|
|
224
|
+
}>;
|
|
225
|
+
watch(peer: string, namespace: string, event: string): Promise<{
|
|
226
|
+
watching: boolean;
|
|
227
|
+
already: boolean;
|
|
228
|
+
}>;
|
|
229
|
+
unwatch(peer: string, namespace: string, event: string): Promise<{
|
|
230
|
+
watching: boolean;
|
|
231
|
+
already: boolean;
|
|
232
|
+
}>;
|
|
233
|
+
/**
|
|
234
|
+
* Peers that can watch traffic: any exposing a `bus`, which in practice is the broker.
|
|
235
|
+
*
|
|
236
|
+
* Found by describing rather than configured, because the broker is a peer like any other and
|
|
237
|
+
* the console has no idea which of them it is. Cached: the answer changes only when a broker
|
|
238
|
+
* joins or leaves, and describing every peer on each tap would be a round trip per peer.
|
|
239
|
+
*/
|
|
240
|
+
private busPeers;
|
|
241
|
+
private readonly knownBuses;
|
|
242
|
+
/** A peer that has gone is worth asking about again if it comes back under new software. */
|
|
243
|
+
forgetBus(peer: string): void;
|
|
244
|
+
/**
|
|
245
|
+
* Start watching traffic, wherever this console can watch it.
|
|
246
|
+
*
|
|
247
|
+
* A socket.io network is watched at the broker, which is the only thing that sees frames it is
|
|
248
|
+
* not party to; an MQTT network is watched by this console's own subscription, since there is
|
|
249
|
+
* no broker of ours there to ask. A console holding both links turns on both, and the frames
|
|
250
|
+
* arrive on one event either way - which is what keeps the page from having to know any of this.
|
|
251
|
+
*/
|
|
252
|
+
tap(filter?: TapFilter): Promise<ConsoleTap>;
|
|
253
|
+
untap(token: string): Promise<{
|
|
254
|
+
tapping: boolean;
|
|
255
|
+
already: boolean;
|
|
256
|
+
}>;
|
|
257
|
+
/** Everything this console is watching, and where. */
|
|
258
|
+
taps(): Promise<{
|
|
259
|
+
taps: ConsoleTap[];
|
|
260
|
+
sources: string[];
|
|
261
|
+
}>;
|
|
262
|
+
/**
|
|
263
|
+
* Drops taps whose life has run out, and the subscriptions they were holding.
|
|
264
|
+
*
|
|
265
|
+
* The taps themselves have already lapsed at the far end by now; this is what stops the console
|
|
266
|
+
* forwarding frames for them, and what keeps `held` from growing by one on every page reload.
|
|
267
|
+
*/
|
|
268
|
+
private expireTaps;
|
|
269
|
+
/**
|
|
270
|
+
* Drops the subscriptions on the peers doing the watching once nothing here wants them.
|
|
271
|
+
*
|
|
272
|
+
* Kept until then rather than per tap, since several taps share one subscription - and dropped
|
|
273
|
+
* when the last goes, so a broker is not left emitting frames into a console that stopped
|
|
274
|
+
* reading them.
|
|
275
|
+
*/
|
|
276
|
+
private stopForwardingIfIdle;
|
|
277
|
+
/** Drops every subscription this console holds, so servers that outlive it keep no listeners. */
|
|
278
|
+
releaseAll(): Promise<void>;
|
|
279
|
+
}
|
|
280
|
+
export declare const startConsole: (options: ConsoleOptions) => Promise<{
|
|
281
|
+
url: string;
|
|
282
|
+
service: ConsoleService;
|
|
283
|
+
close: () => Promise<void>;
|
|
284
|
+
}>;
|
|
285
|
+
//# sourceMappingURL=console.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../src/console.ts"],"names":[],"mappings":"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"}
|