querysub 0.433.0 → 0.436.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.
Files changed (74) hide show
  1. package/.eslintrc.js +50 -50
  2. package/bin/deploy.js +0 -0
  3. package/bin/function.js +0 -0
  4. package/bin/server.js +0 -0
  5. package/costsBenefits.txt +115 -115
  6. package/deploy.ts +2 -2
  7. package/package.json +1 -1
  8. package/spec.txt +1192 -1192
  9. package/src/-a-archives/archives.ts +202 -202
  10. package/src/-a-archives/archivesBackBlaze.ts +1 -0
  11. package/src/-a-archives/archivesDisk.ts +454 -454
  12. package/src/-a-auth/certs.ts +540 -540
  13. package/src/-a-auth/node-forge-ed25519.d.ts +16 -16
  14. package/src/-b-authorities/dnsAuthority.ts +138 -138
  15. package/src/-c-identity/IdentityController.ts +258 -258
  16. package/src/-d-trust/NetworkTrust2.ts +180 -180
  17. package/src/-e-certs/EdgeCertController.ts +252 -252
  18. package/src/-e-certs/certAuthority.ts +201 -201
  19. package/src/-f-node-discovery/NodeDiscovery.ts +640 -640
  20. package/src/-g-core-values/NodeCapabilities.ts +200 -200
  21. package/src/-h-path-value-serialize/stringSerializer.ts +175 -175
  22. package/src/0-path-value-core/PathValueCommitter.ts +468 -468
  23. package/src/0-path-value-core/pathValueCore.ts +2 -2
  24. package/src/2-proxy/PathValueProxyWatcher.ts +2542 -2542
  25. package/src/2-proxy/TransactionDelayer.ts +94 -94
  26. package/src/2-proxy/pathDatabaseProxyBase.ts +36 -36
  27. package/src/2-proxy/pathValueProxy.ts +159 -159
  28. package/src/3-path-functions/PathFunctionRunnerMain.ts +87 -87
  29. package/src/3-path-functions/pathFunctionLoader.ts +516 -516
  30. package/src/3-path-functions/tests/rejectTest.ts +76 -76
  31. package/src/4-deploy/deployCheck.ts +6 -6
  32. package/src/4-dom/css.tsx +29 -29
  33. package/src/4-dom/cssTypes.d.ts +211 -211
  34. package/src/4-dom/qreact.tsx +2799 -2799
  35. package/src/4-dom/qreactTest.tsx +410 -410
  36. package/src/4-querysub/permissions.ts +335 -335
  37. package/src/4-querysub/querysubPrediction.ts +483 -483
  38. package/src/5-diagnostics/qreactDebug.tsx +346 -346
  39. package/src/TestController.ts +34 -34
  40. package/src/bits.ts +104 -104
  41. package/src/buffers.ts +69 -69
  42. package/src/diagnostics/ActionsHistory.ts +57 -57
  43. package/src/diagnostics/listenOnDebugger.ts +71 -71
  44. package/src/diagnostics/periodic.ts +111 -111
  45. package/src/diagnostics/trackResources.ts +91 -91
  46. package/src/diagnostics/watchdog.ts +120 -120
  47. package/src/errors.ts +133 -133
  48. package/src/forceProduction.ts +2 -2
  49. package/src/fs.ts +80 -80
  50. package/src/functional/diff.ts +857 -857
  51. package/src/functional/promiseCache.ts +78 -78
  52. package/src/functional/random.ts +8 -8
  53. package/src/functional/stats.ts +60 -60
  54. package/src/heapDumps.ts +665 -665
  55. package/src/https.ts +1 -1
  56. package/src/library-components/AspectSizedComponent.tsx +87 -87
  57. package/src/library-components/ButtonSelector.tsx +64 -64
  58. package/src/library-components/DropdownCustom.tsx +150 -150
  59. package/src/library-components/DropdownSelector.tsx +31 -31
  60. package/src/library-components/InlinePopup.tsx +66 -66
  61. package/src/misc/color.ts +29 -29
  62. package/src/misc/hash.ts +83 -83
  63. package/src/misc/ipPong.js +13 -13
  64. package/src/misc/networking.ts +1 -1
  65. package/src/misc/random.ts +44 -44
  66. package/src/misc.ts +196 -196
  67. package/src/path.ts +255 -255
  68. package/src/persistentLocalStore.ts +41 -41
  69. package/src/promise.ts +14 -14
  70. package/src/storage/fileSystemPointer.ts +71 -71
  71. package/src/test/heapProcess.ts +35 -35
  72. package/src/zip.ts +15 -15
  73. package/tsconfig.json +26 -26
  74. package/yarnSpec.txt +56 -56
@@ -1,201 +1,201 @@
1
- /*
2
- Find nodes that implement a specific controller.
3
- */
4
-
5
- import { SocketFunction } from "socket-function/SocketFunction";
6
- import { SocketRegistered } from "socket-function/SocketFunctionTypes";
7
- import { errorToUndefined, errorToUndefinedSilent, timeoutToUndefinedSilent } from "../errors";
8
- import { getAllNodeIds, isNodeIdOnOwnMachineId } from "../-f-node-discovery/NodeDiscovery";
9
- import { green, red, yellow } from "socket-function/src/formatting/logColors";
10
- import { shuffle } from "../misc/random";
11
- import { delay } from "socket-function/src/batching";
12
- import debugbreak from "debugbreak";
13
- import { formatTime } from "socket-function/src/formatting/format";
14
- import type { DebugFunctionShardInfo } from "../3-path-functions/PathFunctionRunner";
15
- import { requiresNetworkTrustHook } from "../-d-trust/NetworkTrust2";
16
- import { isNoNetwork } from "../config";
17
- import { getDebuggerUrl } from "../diagnostics/listenOnDebugger";
18
- import { hackDevtoolsWebsocketForward } from "./oneTimeForward";
19
- import { getOwnMachineId, decodeNodeId, decodeNodeIdAssert, getMachineId } from "../-a-auth/certs";
20
- import { sort } from "socket-function/src/misc";
21
- import { getPathStr2 } from "../path";
22
- import { PromiseObj } from "../promise";
23
- import { getTrueTimeOffset } from "socket-function/time/trueTimeShim";
24
- setImmediate(() => {
25
- import("../diagnostics/MachineThreadInfo");
26
- });
27
-
28
- let controllerNodeIdCache = new Map<string, string | Promise<string | undefined>>();
29
-
30
- // NOTE: If this becomes slow (because we are just trying all servers), we could start to store capabilities
31
- // in PersistedStorage. However, I don't think it will be a problem for quite some time.
32
- export async function getControllerNodeId(
33
- controller: SocketRegistered<{}>,
34
- quiet = false,
35
- retryCount = 1,
36
- initialTime = Date.now(),
37
- ): Promise<string | undefined> {
38
- let cached = controllerNodeIdCache.get(controller._classGuid);
39
- if (cached && typeof cached !== "string") {
40
- cached = await cached;
41
- }
42
- // TODO: We are relying on is node connected to do a lot of work here. If the node's connected, but somehow doesn't work, we can get in an unrecoverable state, even if there are plenty of other working nodes.
43
- if (cached && !SocketFunction.isNodeConnected(cached)) {
44
- controllerNodeIdCache.delete(controller._classGuid);
45
- cached = undefined;
46
- }
47
- if (cached) return cached;
48
- let promise = getInternal(retryCount);
49
- controllerNodeIdCache.set(controller._classGuid, promise);
50
- return promise;
51
-
52
- async function getInternal(retryCount: number) {
53
- let nodeIdsToTest = await getAllNodeIds();
54
- // Shuffle, so we aren't always using the same node!
55
- nodeIdsToTest = shuffle(nodeIdsToTest, Date.now());
56
- let resolvedNode = new PromiseObj<string>();
57
-
58
- if (!quiet) {
59
- console.log(`Checking ${nodeIdsToTest.length} nodes for capability ${controller._classGuid}`);
60
- }
61
- let allFinished = Promise.all(nodeIdsToTest.map(async nodeId => {
62
- if (await doesNodeExposeController(nodeId, controller)) {
63
- if (!quiet) {
64
- let duration = Date.now() - initialTime;
65
- console.log(green(`Resolved capability ${controller._classGuid} with node ${nodeId}, in ${formatTime(duration)}`));
66
- }
67
- resolvedNode.resolve(nodeId);
68
- }
69
- }));
70
- let result = await Promise.race([allFinished, resolvedNode.promise]);
71
- if (typeof result === "string") {
72
- return result;
73
- }
74
-
75
- if (retryCount > 0) {
76
- if (!quiet) {
77
- console.log(`Did not find capability in ${nodeIdsToTest.length} nodes, retrying... ${controller._classGuid}`);
78
- }
79
- await delay(2000);
80
- return getInternal(retryCount - 1);
81
- }
82
- if (!quiet) {
83
- console.warn(yellow(`Could not find a node that exposes controller ${controller._classGuid}, tried: ${JSON.stringify(nodeIdsToTest)}`));
84
- }
85
- return undefined;
86
- }
87
- }
88
-
89
- export async function getControllerNodeIdList(
90
- controller: SocketRegistered<{}>,
91
- ): Promise<{ nodeId: string; entryPoint: string }[]> {
92
- let nodeIdsToTest = await getAllNodeIds();
93
- let passedNodeIds = new Map<string, { machineId: string; entryPoint: string }>();
94
- await Promise.all(nodeIdsToTest.map(async nodeId => {
95
- let result = await doesNodeExposeController(nodeId, controller);
96
- if (result) {
97
- let entryPoint = await NodeCapabilitiesController.nodes[nodeId].getEntryPoint();
98
- passedNodeIds.set(nodeId, {
99
- machineId: getMachineId(nodeId),
100
- entryPoint,
101
- });
102
- }
103
- }));
104
-
105
- let results = Array.from(passedNodeIds.entries());
106
- // Prefer localhost connections as they're faster.
107
- sort(results, (x) => isNodeIdOnOwnMachineId(x[0]) ? 0 : 1);
108
- let lookup = new Map<string, { nodeId: string; entryPoint: string }>();
109
- for (let x of results) {
110
- let key = getPathStr2(x[1].machineId, decodeNodeIdAssert(x[0]).port.toString());
111
- if (key in lookup) continue;
112
- lookup.set(key, { nodeId: x[0], entryPoint: x[1].entryPoint });
113
- }
114
-
115
- return Array.from(lookup.values());
116
- }
117
-
118
-
119
- export async function doesNodeExposeController(reconnectNodeId: string, controller: SocketRegistered<{}>): Promise<boolean> {
120
- let exposedControllers = await timeoutToUndefinedSilent(10_000, NodeCapabilitiesController.nodes[reconnectNodeId].getExposedControllers());
121
-
122
- if (exposedControllers?.includes(controller._classGuid)) {
123
- return true;
124
- }
125
- return false;
126
- }
127
-
128
- const startupTime = Date.now();
129
- class NodeCapabilitiesControllerBase {
130
- public async getExposedControllers() {
131
- return Array.from(SocketFunction.exposedClasses);
132
- }
133
- public async getEntryPoint() {
134
- return process.argv[1];
135
- }
136
- public async getStartupTime() {
137
- return startupTime;
138
- }
139
- public async getMemoryUsage() {
140
- return process.memoryUsage();
141
- }
142
- public async getFunctionRunnerShards() {
143
- return getFunctionRunnerShards();
144
- }
145
-
146
- public async getTrueTimeOffset() {
147
- return getTrueTimeOffset();
148
- }
149
-
150
- public async getInspectURL() {
151
- return await getDebuggerUrl();
152
- }
153
-
154
- public async exposeExternalDebugPortOnce(forExternalIP: string) {
155
- // https://notdevtools.com/devtools/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:62448/22895aed-f8da-4dfb-8d50-e432a9c2d827
156
- let debugURL = await this.getInspectURL();
157
-
158
- const outerUrl = new URL(debugURL);
159
- const wsParam = outerUrl.searchParams.get("ws");
160
- if (!wsParam) throw new Error("No ws parameter found");
161
-
162
- // Add ws:// protocol to make it parseable by URL
163
- const innerUrl = new URL(`ws://${wsParam}`);
164
- const port = innerUrl.port;
165
- if (!port) throw new Error("No port found");
166
-
167
- const portNumber = parseInt(port, 10);
168
- if (isNaN(portNumber)) throw new Error("Invalid port number");
169
-
170
- let { externalPort, cancel } = await hackDevtoolsWebsocketForward({ internalPort: portNumber, externalIP: forExternalIP });
171
- lastExposed?.();
172
- lastExposed = cancel;
173
- return { externalPort, internalPort: portNumber, internalInspectURL: debugURL };
174
- }
175
- }
176
- let lastExposed: (() => void) | undefined;
177
-
178
-
179
- let getFunctionRunnerShards = () => [] as DebugFunctionShardInfo[];
180
- export function set_debug_getFunctionRunnerShards(fnc: () => DebugFunctionShardInfo[]) {
181
- getFunctionRunnerShards = fnc;
182
- }
183
-
184
- export const NodeCapabilitiesController = SocketFunction.register(
185
- "NodeCapabilitiesController-399b7067-75c3-4d92-8be3-8470bde32d3c",
186
- new NodeCapabilitiesControllerBase(),
187
- () => ({
188
- getExposedControllers: {},
189
- getEntryPoint: {},
190
- getStartupTime: {},
191
- getMemoryUsage: {},
192
- getFunctionRunnerShards: {},
193
- getTrueTimeOffset: {},
194
- getInspectURL: { hooks: [requiresNetworkTrustHook] },
195
- exposeExternalDebugPortOnce: { hooks: [requiresNetworkTrustHook] },
196
- }),
197
- () => ({
198
- // I think assert is management user didn't exist when we wrote these functions, and so we just made them public. But now that it does exist, we might as well use it. Servers will count as management users anyway, and I don't see any reason a non-management user or a non-server needs to access any of these functions.
199
- hooks: [(require("../diagnostics/managementPages") as typeof import("../diagnostics/managementPages")).assertIsManagementUser],
200
- })
1
+ /*
2
+ Find nodes that implement a specific controller.
3
+ */
4
+
5
+ import { SocketFunction } from "socket-function/SocketFunction";
6
+ import { SocketRegistered } from "socket-function/SocketFunctionTypes";
7
+ import { errorToUndefined, errorToUndefinedSilent, timeoutToUndefinedSilent } from "../errors";
8
+ import { getAllNodeIds, isNodeIdOnOwnMachineId } from "../-f-node-discovery/NodeDiscovery";
9
+ import { green, red, yellow } from "socket-function/src/formatting/logColors";
10
+ import { shuffle } from "../misc/random";
11
+ import { delay } from "socket-function/src/batching";
12
+ import debugbreak from "debugbreak";
13
+ import { formatTime } from "socket-function/src/formatting/format";
14
+ import type { DebugFunctionShardInfo } from "../3-path-functions/PathFunctionRunner";
15
+ import { requiresNetworkTrustHook } from "../-d-trust/NetworkTrust2";
16
+ import { isNoNetwork } from "../config";
17
+ import { getDebuggerUrl } from "../diagnostics/listenOnDebugger";
18
+ import { hackDevtoolsWebsocketForward } from "./oneTimeForward";
19
+ import { getOwnMachineId, decodeNodeId, decodeNodeIdAssert, getMachineId } from "../-a-auth/certs";
20
+ import { sort } from "socket-function/src/misc";
21
+ import { getPathStr2 } from "../path";
22
+ import { PromiseObj } from "../promise";
23
+ import { getTrueTimeOffset } from "socket-function/time/trueTimeShim";
24
+ setImmediate(() => {
25
+ import("../diagnostics/MachineThreadInfo");
26
+ });
27
+
28
+ let controllerNodeIdCache = new Map<string, string | Promise<string | undefined>>();
29
+
30
+ // NOTE: If this becomes slow (because we are just trying all servers), we could start to store capabilities
31
+ // in PersistedStorage. However, I don't think it will be a problem for quite some time.
32
+ export async function getControllerNodeId(
33
+ controller: SocketRegistered<{}>,
34
+ quiet = false,
35
+ retryCount = 1,
36
+ initialTime = Date.now(),
37
+ ): Promise<string | undefined> {
38
+ let cached = controllerNodeIdCache.get(controller._classGuid);
39
+ if (cached && typeof cached !== "string") {
40
+ cached = await cached;
41
+ }
42
+ // TODO: We are relying on is node connected to do a lot of work here. If the node's connected, but somehow doesn't work, we can get in an unrecoverable state, even if there are plenty of other working nodes.
43
+ if (cached && !SocketFunction.isNodeConnected(cached)) {
44
+ controllerNodeIdCache.delete(controller._classGuid);
45
+ cached = undefined;
46
+ }
47
+ if (cached) return cached;
48
+ let promise = getInternal(retryCount);
49
+ controllerNodeIdCache.set(controller._classGuid, promise);
50
+ return promise;
51
+
52
+ async function getInternal(retryCount: number) {
53
+ let nodeIdsToTest = await getAllNodeIds();
54
+ // Shuffle, so we aren't always using the same node!
55
+ nodeIdsToTest = shuffle(nodeIdsToTest, Date.now());
56
+ let resolvedNode = new PromiseObj<string>();
57
+
58
+ if (!quiet) {
59
+ console.log(`Checking ${nodeIdsToTest.length} nodes for capability ${controller._classGuid}`);
60
+ }
61
+ let allFinished = Promise.all(nodeIdsToTest.map(async nodeId => {
62
+ if (await doesNodeExposeController(nodeId, controller)) {
63
+ if (!quiet) {
64
+ let duration = Date.now() - initialTime;
65
+ console.log(green(`Resolved capability ${controller._classGuid} with node ${nodeId}, in ${formatTime(duration)}`));
66
+ }
67
+ resolvedNode.resolve(nodeId);
68
+ }
69
+ }));
70
+ let result = await Promise.race([allFinished, resolvedNode.promise]);
71
+ if (typeof result === "string") {
72
+ return result;
73
+ }
74
+
75
+ if (retryCount > 0) {
76
+ if (!quiet) {
77
+ console.log(`Did not find capability in ${nodeIdsToTest.length} nodes, retrying... ${controller._classGuid}`);
78
+ }
79
+ await delay(2000);
80
+ return getInternal(retryCount - 1);
81
+ }
82
+ if (!quiet) {
83
+ console.warn(yellow(`Could not find a node that exposes controller ${controller._classGuid}, tried: ${JSON.stringify(nodeIdsToTest)}`));
84
+ }
85
+ return undefined;
86
+ }
87
+ }
88
+
89
+ export async function getControllerNodeIdList(
90
+ controller: SocketRegistered<{}>,
91
+ ): Promise<{ nodeId: string; entryPoint: string }[]> {
92
+ let nodeIdsToTest = await getAllNodeIds();
93
+ let passedNodeIds = new Map<string, { machineId: string; entryPoint: string }>();
94
+ await Promise.all(nodeIdsToTest.map(async nodeId => {
95
+ let result = await doesNodeExposeController(nodeId, controller);
96
+ if (result) {
97
+ let entryPoint = await NodeCapabilitiesController.nodes[nodeId].getEntryPoint();
98
+ passedNodeIds.set(nodeId, {
99
+ machineId: getMachineId(nodeId),
100
+ entryPoint,
101
+ });
102
+ }
103
+ }));
104
+
105
+ let results = Array.from(passedNodeIds.entries());
106
+ // Prefer localhost connections as they're faster.
107
+ sort(results, (x) => isNodeIdOnOwnMachineId(x[0]) ? 0 : 1);
108
+ let lookup = new Map<string, { nodeId: string; entryPoint: string }>();
109
+ for (let x of results) {
110
+ let key = getPathStr2(x[1].machineId, decodeNodeIdAssert(x[0]).port.toString());
111
+ if (key in lookup) continue;
112
+ lookup.set(key, { nodeId: x[0], entryPoint: x[1].entryPoint });
113
+ }
114
+
115
+ return Array.from(lookup.values());
116
+ }
117
+
118
+
119
+ export async function doesNodeExposeController(reconnectNodeId: string, controller: SocketRegistered<{}>): Promise<boolean> {
120
+ let exposedControllers = await timeoutToUndefinedSilent(10_000, NodeCapabilitiesController.nodes[reconnectNodeId].getExposedControllers());
121
+
122
+ if (exposedControllers?.includes(controller._classGuid)) {
123
+ return true;
124
+ }
125
+ return false;
126
+ }
127
+
128
+ const startupTime = Date.now();
129
+ class NodeCapabilitiesControllerBase {
130
+ public async getExposedControllers() {
131
+ return Array.from(SocketFunction.exposedClasses);
132
+ }
133
+ public async getEntryPoint() {
134
+ return process.argv[1];
135
+ }
136
+ public async getStartupTime() {
137
+ return startupTime;
138
+ }
139
+ public async getMemoryUsage() {
140
+ return process.memoryUsage();
141
+ }
142
+ public async getFunctionRunnerShards() {
143
+ return getFunctionRunnerShards();
144
+ }
145
+
146
+ public async getTrueTimeOffset() {
147
+ return getTrueTimeOffset();
148
+ }
149
+
150
+ public async getInspectURL() {
151
+ return await getDebuggerUrl();
152
+ }
153
+
154
+ public async exposeExternalDebugPortOnce(forExternalIP: string) {
155
+ // https://notdevtools.com/devtools/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:62448/22895aed-f8da-4dfb-8d50-e432a9c2d827
156
+ let debugURL = await this.getInspectURL();
157
+
158
+ const outerUrl = new URL(debugURL);
159
+ const wsParam = outerUrl.searchParams.get("ws");
160
+ if (!wsParam) throw new Error("No ws parameter found");
161
+
162
+ // Add ws:// protocol to make it parseable by URL
163
+ const innerUrl = new URL(`ws://${wsParam}`);
164
+ const port = innerUrl.port;
165
+ if (!port) throw new Error("No port found");
166
+
167
+ const portNumber = parseInt(port, 10);
168
+ if (isNaN(portNumber)) throw new Error("Invalid port number");
169
+
170
+ let { externalPort, cancel } = await hackDevtoolsWebsocketForward({ internalPort: portNumber, externalIP: forExternalIP });
171
+ lastExposed?.();
172
+ lastExposed = cancel;
173
+ return { externalPort, internalPort: portNumber, internalInspectURL: debugURL };
174
+ }
175
+ }
176
+ let lastExposed: (() => void) | undefined;
177
+
178
+
179
+ let getFunctionRunnerShards = () => [] as DebugFunctionShardInfo[];
180
+ export function set_debug_getFunctionRunnerShards(fnc: () => DebugFunctionShardInfo[]) {
181
+ getFunctionRunnerShards = fnc;
182
+ }
183
+
184
+ export const NodeCapabilitiesController = SocketFunction.register(
185
+ "NodeCapabilitiesController-399b7067-75c3-4d92-8be3-8470bde32d3c",
186
+ new NodeCapabilitiesControllerBase(),
187
+ () => ({
188
+ getExposedControllers: {},
189
+ getEntryPoint: {},
190
+ getStartupTime: {},
191
+ getMemoryUsage: {},
192
+ getFunctionRunnerShards: {},
193
+ getTrueTimeOffset: {},
194
+ getInspectURL: { hooks: [requiresNetworkTrustHook] },
195
+ exposeExternalDebugPortOnce: { hooks: [requiresNetworkTrustHook] },
196
+ }),
197
+ () => ({
198
+ // I think assert is management user didn't exist when we wrote these functions, and so we just made them public. But now that it does exist, we might as well use it. Servers will count as management users anyway, and I don't see any reason a non-management user or a non-server needs to access any of these functions.
199
+ hooks: [(require("../diagnostics/managementPages") as typeof import("../diagnostics/managementPages")).assertIsManagementUser],
200
+ })
201
201
  );