querysub 0.459.0 → 0.461.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/.claude/settings.local.json +2 -1
- package/package.json +2 -2
- package/src/-b-authorities/dnsAuthority.ts +23 -15
- package/src/-g-core-values/NodeCapabilities.ts +3 -0
- package/src/-h-path-value-serialize/PathValueSerializer.ts +11 -3
- package/src/0-path-value-core/PathRouter.ts +6 -0
- package/src/0-path-value-core/PathWatcher.ts +1 -1
- package/src/0-path-value-core/pathValueCore.ts +4 -7
- package/src/1-path-client/RemoteWatcher.ts +8 -3
- package/src/1-path-client/pathValueClientWatcher.ts +3 -0
- package/src/2-proxy/PathValueProxyWatcher.ts +1 -1
- package/src/2-proxy/TransactionDelayer.ts +1 -1
- package/src/3-path-functions/PathFunctionHelpers.ts +13 -8
- package/src/3-path-functions/PathFunctionRunner.ts +2 -0
- package/src/4-querysub/Querysub.ts +0 -1
- package/src/4-querysub/QuerysubController.ts +1 -7
- package/src/config.ts +9 -0
- package/src/config2.ts +7 -1
- package/src/deployManager/components/MachinePicker.tsx +40 -0
- package/src/deployManager/components/ServiceDetailPage.tsx +2 -5
- package/src/deployManager/components/ServicesListPage.tsx +2 -0
- package/src/deployManager/components/Tools.tsx +165 -0
- package/src/deployManager/setupMachineMain.ts +74 -23
- package/src/diagnostics/charts/Chart.tsx +240 -0
- package/src/diagnostics/grossStats/GrossStatsPage.tsx +48 -83
- package/src/diagnostics/logs/IndexedLogs/BufferIndex.ts +22 -35
- package/src/diagnostics/logs/IndexedLogs/BufferUnitIndex.ts +39 -47
- package/src/diagnostics/logs/IndexedLogs/IndexedLogs.ts +3 -3
- package/src/diagnostics/logs/IndexedLogs/MCPIndexedLogs.ts +18 -3
- package/src/diagnostics/logs/IndexedLogs/MCPIndexedLogsEntry.ts +1 -0
- package/src/diagnostics/managementPages.tsx +58 -58
- package/src/diagnostics/misc-pages/DNSPage.tsx +344 -0
- package/test.ts +46 -70
- package/src/diagnostics/AuditLogPage.tsx +0 -147
- package/src/diagnostics/NodeConnectionsPage.tsx +0 -167
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { SocketFunction } from "socket-function/SocketFunction";
|
|
2
|
-
import { qreact } from "../4-dom/qreact";
|
|
3
|
-
import { assertIsManagementUser } from "./managementPages";
|
|
4
|
-
import { css } from "typesafecss";
|
|
5
|
-
import { getSyncedController } from "../library-components/SyncedController";
|
|
6
|
-
import { DebugLog, DebugLogController, getLogHistoryEquals, getLogHistoryIncludes } from "../0-path-value-core/auditLogs";
|
|
7
|
-
import { remoteWatcher } from "../1-path-client/RemoteWatcher";
|
|
8
|
-
import { getBrowserUrlNode, getOwnNodeId } from "../-f-node-discovery/NodeDiscovery";
|
|
9
|
-
import { nextId, sort } from "socket-function/src/misc";
|
|
10
|
-
import { t } from "../2-proxy/schema2";
|
|
11
|
-
import { InputLabelURL } from "../library-components/InputLabel";
|
|
12
|
-
import { URLParam } from "../library-components/URLParam";
|
|
13
|
-
import { Table } from "../5-diagnostics/Table";
|
|
14
|
-
import { ObjectDisplay } from "./logs/ObjectDisplay";
|
|
15
|
-
import { PathRouter } from "../0-path-value-core/PathRouter";
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
TODO:
|
|
19
|
-
1) Support watching multiple paths at once
|
|
20
|
-
2) Show extra metadata for the paths
|
|
21
|
-
- Current value (raw, as in, don't sync it)
|
|
22
|
-
- If it is synced
|
|
23
|
-
- The authority of it
|
|
24
|
-
- An expander which shows a table of the full history of values, with valid state, etc
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
type DebugLogWithSource = DebugLog & {
|
|
28
|
-
sourceType: "local" | "remote";
|
|
29
|
-
sourceNodeId: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
let path = new URLParam("path", "");
|
|
33
|
-
let includeDescendants = new URLParam("includeDescendants", false);
|
|
34
|
-
export class AuditLogPage extends qreact.Component {
|
|
35
|
-
loadId = nextId();
|
|
36
|
-
state = t.state({
|
|
37
|
-
loadedId: t.string
|
|
38
|
-
});
|
|
39
|
-
render() {
|
|
40
|
-
let logs: DebugLogWithSource[] = [];
|
|
41
|
-
let loaded = this.loadId === this.state.loadedId;
|
|
42
|
-
if (loaded) {
|
|
43
|
-
let obj = auditLogController(getBrowserUrlNode()).getPathHistory({
|
|
44
|
-
path: path.value,
|
|
45
|
-
includeDescendants: includeDescendants.value,
|
|
46
|
-
});
|
|
47
|
-
if (obj) {
|
|
48
|
-
logs = obj.fullLogs;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return (
|
|
52
|
-
<div class={css.pad2(10).vbox(10).fillWidth}>
|
|
53
|
-
<InputLabelURL
|
|
54
|
-
label="Path"
|
|
55
|
-
url={path}
|
|
56
|
-
fillWidth
|
|
57
|
-
onChange={() => this.loadId = nextId()}
|
|
58
|
-
/>
|
|
59
|
-
<InputLabelURL
|
|
60
|
-
label="Include Descendants"
|
|
61
|
-
url={includeDescendants}
|
|
62
|
-
checkbox
|
|
63
|
-
onChange={() => this.loadId = nextId()}
|
|
64
|
-
/>
|
|
65
|
-
{!loaded && <button onClick={() => this.state.loadedId = this.loadId}>Load</button>}
|
|
66
|
-
<Table
|
|
67
|
-
rows={logs}
|
|
68
|
-
columns={{
|
|
69
|
-
type: {},
|
|
70
|
-
time: {},
|
|
71
|
-
sourceType: {},
|
|
72
|
-
sourceNodeId: {},
|
|
73
|
-
values: {
|
|
74
|
-
formatter(value) {
|
|
75
|
-
return <ObjectDisplay value={value} />;
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
}}
|
|
79
|
-
/>
|
|
80
|
-
</div>
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
class AuditLogControllerBase {
|
|
87
|
-
public async getPathHistory(config: {
|
|
88
|
-
path: string;
|
|
89
|
-
includeDescendants?: boolean;
|
|
90
|
-
}) {
|
|
91
|
-
let { path, includeDescendants } = config;
|
|
92
|
-
let authorityNodeId = remoteWatcher.getExistingWatchRemoteNodeId(path);
|
|
93
|
-
if (!authorityNodeId) {
|
|
94
|
-
authorityNodeId = await PathRouter.getReadyAuthority(path)?.nodeId;
|
|
95
|
-
}
|
|
96
|
-
let logs: DebugLog[] = [];
|
|
97
|
-
let remoteLogs: DebugLog[] = [];
|
|
98
|
-
if (includeDescendants) {
|
|
99
|
-
// Also look for the parent, so we can capture keys() syncs as well
|
|
100
|
-
// (this should give us child paths too, because that's how includes works)
|
|
101
|
-
logs = getLogHistoryIncludes(path);
|
|
102
|
-
if (authorityNodeId) {
|
|
103
|
-
remoteLogs = await DebugLogController.nodes[authorityNodeId].getLogHistoryEquals(path);
|
|
104
|
-
}
|
|
105
|
-
} else {
|
|
106
|
-
logs = getLogHistoryEquals(path);
|
|
107
|
-
if (authorityNodeId) {
|
|
108
|
-
remoteLogs = await DebugLogController.nodes[authorityNodeId].getLogHistoryEquals(path);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
let fullLogs: DebugLogWithSource[] = [];
|
|
113
|
-
let ownNodeId = getOwnNodeId();
|
|
114
|
-
for (let log of logs) {
|
|
115
|
-
fullLogs.push({
|
|
116
|
-
...log,
|
|
117
|
-
sourceType: "local",
|
|
118
|
-
sourceNodeId: ownNodeId,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
if (authorityNodeId) {
|
|
122
|
-
for (let log of remoteLogs) {
|
|
123
|
-
fullLogs.push({
|
|
124
|
-
...log,
|
|
125
|
-
sourceType: "remote",
|
|
126
|
-
sourceNodeId: authorityNodeId,
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
sort(fullLogs, x => x.time);
|
|
131
|
-
return {
|
|
132
|
-
fullLogs,
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export const AuditLogController = SocketFunction.register(
|
|
138
|
-
"AuditLogController-bf798faf-c803-4add-ac2c-99d0f44e753a",
|
|
139
|
-
new AuditLogControllerBase(),
|
|
140
|
-
() => ({
|
|
141
|
-
getPathHistory: {},
|
|
142
|
-
}),
|
|
143
|
-
() => ({
|
|
144
|
-
hooks: [assertIsManagementUser],
|
|
145
|
-
})
|
|
146
|
-
);
|
|
147
|
-
export const auditLogController = getSyncedController(AuditLogController);
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { SocketFunction } from "socket-function/SocketFunction";
|
|
2
|
-
import { qreact } from "../4-dom/qreact";
|
|
3
|
-
import { assertIsManagementUser } from "./managementPages";
|
|
4
|
-
import { css } from "typesafecss";
|
|
5
|
-
import { getSyncedController } from "../library-components/SyncedController";
|
|
6
|
-
import { getAllNodeIds, getBrowserUrlNode } from "../-f-node-discovery/NodeDiscovery";
|
|
7
|
-
import { debugGetAllCallFactories } from "socket-function/src/nodeCache";
|
|
8
|
-
import { debugNodeId } from "../-c-identity/IdentityController";
|
|
9
|
-
import { fastHash } from "../misc/hash";
|
|
10
|
-
import { NodeCapabilitiesController } from "../-g-core-values/NodeCapabilities";
|
|
11
|
-
import { sort } from "socket-function/src/misc";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
function getColorForNodeId(friendlyNodeId: string): string {
|
|
16
|
-
let hash = fastHash(friendlyNodeId);
|
|
17
|
-
let hue = hash % 360;
|
|
18
|
-
return `hsl(${hue}, 70%, 60%)`;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class NodeConnectionsPage extends qreact.Component {
|
|
22
|
-
render() {
|
|
23
|
-
let browserNode = getBrowserUrlNode();
|
|
24
|
-
let controller = nodeConnectionsController(browserNode);
|
|
25
|
-
|
|
26
|
-
let nodeIds = controller.getAllNodeIds();
|
|
27
|
-
if (!nodeIds) {
|
|
28
|
-
return <div class={css.pad2(10)}>Loading...</div>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let connectableNodes: Array<{ nodeId: string; friendlyNodeId: string; entryPoint: string | undefined; connections: Array<{ nodeId: string; friendlyNodeId: string }> }> = [];
|
|
32
|
-
let nonConnectableNodes: string[] = [];
|
|
33
|
-
|
|
34
|
-
for (let nodeId of nodeIds) {
|
|
35
|
-
try {
|
|
36
|
-
let result = controller.getNodeConnections_forBrowser(nodeId);
|
|
37
|
-
if (result) {
|
|
38
|
-
let friendlyNodeId = debugNodeId(nodeId);
|
|
39
|
-
let entryPoint: string | undefined;
|
|
40
|
-
try {
|
|
41
|
-
entryPoint = controller.getEntryPoint_forBrowser(nodeId);
|
|
42
|
-
} catch (e) {
|
|
43
|
-
entryPoint = undefined;
|
|
44
|
-
}
|
|
45
|
-
connectableNodes.push({
|
|
46
|
-
nodeId,
|
|
47
|
-
friendlyNodeId,
|
|
48
|
-
entryPoint,
|
|
49
|
-
connections: result.connections,
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
} catch (e) {
|
|
53
|
-
nonConnectableNodes.push(nodeId);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<div class={css.pad2(10).vbox(20).fillWidth}>
|
|
59
|
-
<h1>Connectable Nodes</h1>
|
|
60
|
-
<div class={css.hbox(20).wrap.fillWidth}>
|
|
61
|
-
{connectableNodes.map(node => {
|
|
62
|
-
let color = getColorForNodeId(node.friendlyNodeId);
|
|
63
|
-
return (
|
|
64
|
-
<div class={css.vbox(5).pad2(10).maxHeight(400).overflowAuto.bord(1, { h: 0, s: 0, l: 80 })}>
|
|
65
|
-
<div class={css.vbox(3)}>
|
|
66
|
-
{node.entryPoint && (
|
|
67
|
-
<div class={css.fontSize(14).fontWeight("bold")}>
|
|
68
|
-
{node.entryPoint}
|
|
69
|
-
</div>
|
|
70
|
-
)}
|
|
71
|
-
<div class={css.hbox(5)}>
|
|
72
|
-
<span class={css.background(color).pad2(4, 2).fontWeight("bold")}>
|
|
73
|
-
{node.friendlyNodeId}
|
|
74
|
-
</span>
|
|
75
|
-
<span class={css.color("gray").fontSize(12)}>
|
|
76
|
-
({node.nodeId})
|
|
77
|
-
</span>
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|
|
80
|
-
<div class={css.vbox(3).paddingLeft(20)}>
|
|
81
|
-
{node.connections.length === 0 && (
|
|
82
|
-
<div class={css.color("gray")}>No connections</div>
|
|
83
|
-
)}
|
|
84
|
-
{node.connections.map(conn => {
|
|
85
|
-
let connColor = getColorForNodeId(conn.friendlyNodeId);
|
|
86
|
-
return (
|
|
87
|
-
<div class={css.hbox(5)}>
|
|
88
|
-
<span>→ Connected to:</span>
|
|
89
|
-
<span class={css.background(connColor).pad2(4, 2).fontWeight("bold")}>
|
|
90
|
-
{conn.friendlyNodeId}
|
|
91
|
-
</span>
|
|
92
|
-
<span class={css.color("gray").fontSize(12)}>
|
|
93
|
-
({conn.nodeId})
|
|
94
|
-
</span>
|
|
95
|
-
</div>
|
|
96
|
-
);
|
|
97
|
-
})}
|
|
98
|
-
</div>
|
|
99
|
-
</div>
|
|
100
|
-
);
|
|
101
|
-
})}
|
|
102
|
-
</div>
|
|
103
|
-
|
|
104
|
-
<div class={css.vbox(10).fillWidth}>
|
|
105
|
-
<h1>Non-Connectable Nodes</h1>
|
|
106
|
-
<div class={css.vbox(5).pad2(10).maxHeight(600).overflowAuto.bord(1, { h: 0, s: 0, l: 80 })}>
|
|
107
|
-
{nonConnectableNodes.map(nodeId => {
|
|
108
|
-
let friendlyNodeId = debugNodeId(nodeId);
|
|
109
|
-
return (
|
|
110
|
-
<div class={css.hbox(5)}>
|
|
111
|
-
<span class={css.background("lightgray").pad2(4, 2).fontWeight("bold")}>
|
|
112
|
-
{friendlyNodeId}
|
|
113
|
-
</span>
|
|
114
|
-
<span class={css.color("gray").fontSize(12)}>
|
|
115
|
-
({nodeId})
|
|
116
|
-
</span>
|
|
117
|
-
<span class={css.color("gray")}>- Can't connect</span>
|
|
118
|
-
</div>
|
|
119
|
-
);
|
|
120
|
-
})}
|
|
121
|
-
</div>
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
class NodeConnectionsControllerBase {
|
|
129
|
-
public async getNodeConnections() {
|
|
130
|
-
let factories = debugGetAllCallFactories();
|
|
131
|
-
let connections = factories.filter(x => x.isConnected).map(factory => ({
|
|
132
|
-
nodeId: factory.nodeId,
|
|
133
|
-
friendlyNodeId: debugNodeId(factory.nodeId),
|
|
134
|
-
}));
|
|
135
|
-
return { connections };
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
public async getNodeConnections_forBrowser(nodeId: string) {
|
|
139
|
-
let result = await NodeConnectionsController.nodes[nodeId].getNodeConnections();
|
|
140
|
-
sort(result.connections, x => x.friendlyNodeId);
|
|
141
|
-
return result;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
public async getEntryPoint_forBrowser(nodeId: string) {
|
|
145
|
-
return (await NodeCapabilitiesController.nodes[nodeId].getMetadata()).entryPoint;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
public async getAllNodeIds() {
|
|
149
|
-
return await getAllNodeIds();
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export const NodeConnectionsController = SocketFunction.register(
|
|
154
|
-
"NodeConnectionsController-8f3e2a1b-4c5d-4f2e-9a3b-7c8d1e2f3a4b",
|
|
155
|
-
new NodeConnectionsControllerBase(),
|
|
156
|
-
() => ({
|
|
157
|
-
getNodeConnections: {},
|
|
158
|
-
getNodeConnections_forBrowser: {},
|
|
159
|
-
getEntryPoint_forBrowser: {},
|
|
160
|
-
getAllNodeIds: {},
|
|
161
|
-
}),
|
|
162
|
-
() => ({
|
|
163
|
-
hooks: [assertIsManagementUser],
|
|
164
|
-
})
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
export const nodeConnectionsController = getSyncedController(NodeConnectionsController);
|