querysub 0.432.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 -512
  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,72 +1,72 @@
1
- import { isNode, list } from "socket-function/src/misc";
2
- import inspector from "inspector";
3
- import fs from "fs";
4
- import { getSubFolder } from "../fs";
5
- import { SocketFunction } from "socket-function/SocketFunction";
6
- import debugbreak from "debugbreak";
7
- import http from "http";
8
- import { lazy } from "socket-function/src/caching";
9
-
10
- let devToolsUrl = "";
11
-
12
- const listenOnDebugger = lazy(function listenOnDebugger() {
13
- if (devToolsUrl) return;
14
- if (!isNode()) return;
15
- // IMPORTANT! NEVER use the built-in port. This adds a tiny bit of security. Not much,
16
- // as port scanning is easier (there are only 65K ports!), but... at least port scanning
17
- // is loud, so if a site port scans all of it's users it will probably get flagged by
18
- // chrome fairly quickly as being malicious.
19
- let url = baseGetInspectorUrl();
20
-
21
- devToolsUrl = `devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&${url.replace("://", "=")}`;
22
- devToolsUrl = devToolsUrl.replace("devtools://devtools/bundled", "https://notdevtools.com/devtools");
23
- console.log(`Debugger listening on ${devToolsUrl}`);
24
-
25
- const ext = ".url";
26
- const debuggerFolder = getSubFolder("debugger");
27
- let otherDebuggers = fs.readdirSync(debuggerFolder);
28
- otherDebuggers = otherDebuggers.filter(x => x.endsWith(ext));
29
- // Delete all files for processes that no longer exist
30
- for (let other of otherDebuggers) {
31
- let pid = +other.split("-")[0];
32
- let ppid = +other.split("-")[1];
33
- if (!doesProcessExist(pid) || !doesProcessExist(ppid)) {
34
- try {
35
- fs.unlinkSync(debuggerFolder + other);
36
- } catch { }
37
- }
38
- }
39
- });
40
- export function getDebuggerUrl() {
41
- // NOTE: Very unfortunate, as this means that if a developer is debugging a server for a bit,
42
- // the inspector is left open. It's kind of hard to tell when they are done though.
43
- // - This is still somewhat secure, as only localhost can connect, but... having local network
44
- // accessing turning into remote execution access isn't great (especially for developers,
45
- // who could then get pwned just by clicking on a link).
46
- // TODO: The security of this can be improved, see NodeViewer.tsx:getExternalInspectURL
47
- listenOnDebugger();
48
- return devToolsUrl;
49
- }
50
- function doesProcessExist(pid: number) {
51
- try {
52
- process.kill(pid, 0);
53
- return true;
54
- } catch {
55
- return false;
56
- }
57
- }
58
- function baseGetInspectorUrl() {
59
- function getNextPort() {
60
- return 49152 + ~~((65535 - 49152) * Math.random());
61
- }
62
-
63
- while (true) {
64
- let url = inspector.url();
65
- if (url) return url;
66
- try {
67
- inspector.open(getNextPort());
68
- } catch {
69
- continue;
70
- }
71
- }
1
+ import { isNode, list } from "socket-function/src/misc";
2
+ import inspector from "inspector";
3
+ import fs from "fs";
4
+ import { getSubFolder } from "../fs";
5
+ import { SocketFunction } from "socket-function/SocketFunction";
6
+ import debugbreak from "debugbreak";
7
+ import http from "http";
8
+ import { lazy } from "socket-function/src/caching";
9
+
10
+ let devToolsUrl = "";
11
+
12
+ const listenOnDebugger = lazy(function listenOnDebugger() {
13
+ if (devToolsUrl) return;
14
+ if (!isNode()) return;
15
+ // IMPORTANT! NEVER use the built-in port. This adds a tiny bit of security. Not much,
16
+ // as port scanning is easier (there are only 65K ports!), but... at least port scanning
17
+ // is loud, so if a site port scans all of it's users it will probably get flagged by
18
+ // chrome fairly quickly as being malicious.
19
+ let url = baseGetInspectorUrl();
20
+
21
+ devToolsUrl = `devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&${url.replace("://", "=")}`;
22
+ devToolsUrl = devToolsUrl.replace("devtools://devtools/bundled", "https://notdevtools.com/devtools");
23
+ console.log(`Debugger listening on ${devToolsUrl}`);
24
+
25
+ const ext = ".url";
26
+ const debuggerFolder = getSubFolder("debugger");
27
+ let otherDebuggers = fs.readdirSync(debuggerFolder);
28
+ otherDebuggers = otherDebuggers.filter(x => x.endsWith(ext));
29
+ // Delete all files for processes that no longer exist
30
+ for (let other of otherDebuggers) {
31
+ let pid = +other.split("-")[0];
32
+ let ppid = +other.split("-")[1];
33
+ if (!doesProcessExist(pid) || !doesProcessExist(ppid)) {
34
+ try {
35
+ fs.unlinkSync(debuggerFolder + other);
36
+ } catch { }
37
+ }
38
+ }
39
+ });
40
+ export function getDebuggerUrl() {
41
+ // NOTE: Very unfortunate, as this means that if a developer is debugging a server for a bit,
42
+ // the inspector is left open. It's kind of hard to tell when they are done though.
43
+ // - This is still somewhat secure, as only localhost can connect, but... having local network
44
+ // accessing turning into remote execution access isn't great (especially for developers,
45
+ // who could then get pwned just by clicking on a link).
46
+ // TODO: The security of this can be improved, see NodeViewer.tsx:getExternalInspectURL
47
+ listenOnDebugger();
48
+ return devToolsUrl;
49
+ }
50
+ function doesProcessExist(pid: number) {
51
+ try {
52
+ process.kill(pid, 0);
53
+ return true;
54
+ } catch {
55
+ return false;
56
+ }
57
+ }
58
+ function baseGetInspectorUrl() {
59
+ function getNextPort() {
60
+ return 49152 + ~~((65535 - 49152) * Math.random());
61
+ }
62
+
63
+ while (true) {
64
+ let url = inspector.url();
65
+ if (url) return url;
66
+ try {
67
+ inspector.open(getNextPort());
68
+ } catch {
69
+ continue;
70
+ }
71
+ }
72
72
  }
@@ -1,112 +1,112 @@
1
- import { delay, runInfinitePoll, runInfinitePollCallAtStart, shutdownPolling } from "socket-function/src/batching";
2
- import { isNode, timeInMinute } from "socket-function/src/misc";
3
- import { logErrors, timeoutToError } from "../errors";
4
- import debugbreak from "debugbreak";
5
- import { nodeDiscoveryShutdown } from "../-f-node-discovery/NodeDiscovery";
6
- import { authorityStorage } from "../0-path-value-core/pathValueCore";
7
- import { red } from "socket-function/src/formatting/logColors";
8
-
9
- // Import querysub, so all the hooks we use will exist at some point
10
- setImmediate(async () => {
11
- await import("../4-querysub/QuerysubController");
12
- });
13
-
14
- let periodicFncs: (() => void)[] = [];
15
- export function registerPeriodic(fnc: () => void) {
16
- periodicFncs.push(fnc);
17
- }
18
-
19
- let shutdownHandlers: (() => Promise<void>)[] = [];
20
- // NOTE: Won't be always called, but at least makes it possible to gracefully shutdown.
21
- export function registerShutdownHandler(fnc: () => Promise<void>) {
22
- shutdownHandlers.push(fnc);
23
- }
24
- let preshutdownHandlers: (() => Promise<void>)[] = [];
25
- export function registerPreshutdownHandler(fnc: () => Promise<void>) {
26
- preshutdownHandlers.push(fnc);
27
- }
28
-
29
- function logAll() {
30
- for (let fnc of periodicFncs) {
31
- fnc();
32
- }
33
- }
34
-
35
- logErrors(runInfinitePollCallAtStart(timeInMinute * 5, logAll));
36
-
37
- let shuttingDown = false;
38
- export async function shutdown() {
39
- if (shuttingDown) {
40
- return;
41
- }
42
- console.log(red("Starting shutdown"));
43
- shuttingDown = true;
44
- const { authorityStorage } = await import("../0-path-value-core/pathValueCore");
45
- try {
46
- await Promise.allSettled([
47
- ...preshutdownHandlers,
48
- ].map(fnc => timeoutToError(timeInMinute, fnc(), () => new Error(`Preshutdown handler ${fnc.name} timed out`))));
49
- } catch (e) {
50
- console.log(`Error on preshutdown handlers`, e);
51
- }
52
- try {
53
- await Promise.allSettled([
54
- function authorityStorageShutdown() { return authorityStorage.onShutdown(); },
55
- nodeDiscoveryShutdown,
56
- shutdownPolling,
57
- ...shutdownHandlers,
58
- ].map(fnc => timeoutToError(timeInMinute, fnc(), () => new Error(`Shutdown handler ${fnc.name} timed out`))));
59
- } catch (e) {
60
- console.log("Error on shutdown", e);
61
- }
62
- // Wait to allow any logged errors to hopefully be written somewhere?
63
- await delay(2000);
64
- process.exit();
65
- }
66
-
67
- // IMPORTANT! Yarn detaches the processes, so they keep running when you ctrl+c, even though the shell shows back up. We can fix this by using `node -r ./node_modules/typenode/index.js ./test.ts`. However, it's probably fine, as we still run the shutdown code, it's just that the manager doesn't know if we've shutdown or not.
68
- if (isNode()) {
69
- let lineBuffer = "";
70
- process.stdin.on("data", data => {
71
- lineBuffer += data.toString();
72
- let lines = lineBuffer.split("\r");
73
- lineBuffer = lines.pop()!;
74
- for (let line of lines) {
75
- if (line === "SHUTDOWN_NOW_MULTIRUN") {
76
- logErrors(shutdown());
77
- }
78
- }
79
-
80
- if (data.toString().includes("\r")) {
81
- logAll();
82
- }
83
- });
84
-
85
-
86
- // NOTE: This extra code is required to actual capture ctrl+c
87
- if (process.platform === "win32") {
88
- var rl = require("readline").createInterface({
89
- input: process.stdin,
90
- output: process.stdout
91
- });
92
-
93
- rl.on("SIGINT", function () {
94
- process.emit("SIGINT");
95
- });
96
- }
97
- let killCount = 0;
98
- function doShutdown() {
99
- killCount++;
100
- console.log(`Caught interrupt signal. Attempt number ${killCount}`);
101
- if (killCount >= 3) {
102
- console.log("Force exit");
103
- process.exit();
104
- }
105
-
106
- logErrors(shutdown());
107
- }
108
- process.on("SIGINT", doShutdown);
109
-
110
- }
111
- (globalThis as any).logAll = logAll;
1
+ import { delay, runInfinitePoll, runInfinitePollCallAtStart, shutdownPolling } from "socket-function/src/batching";
2
+ import { isNode, timeInMinute } from "socket-function/src/misc";
3
+ import { logErrors, timeoutToError } from "../errors";
4
+ import debugbreak from "debugbreak";
5
+ import { nodeDiscoveryShutdown } from "../-f-node-discovery/NodeDiscovery";
6
+ import { authorityStorage } from "../0-path-value-core/pathValueCore";
7
+ import { red } from "socket-function/src/formatting/logColors";
8
+
9
+ // Import querysub, so all the hooks we use will exist at some point
10
+ setImmediate(async () => {
11
+ await import("../4-querysub/QuerysubController");
12
+ });
13
+
14
+ let periodicFncs: (() => void)[] = [];
15
+ export function registerPeriodic(fnc: () => void) {
16
+ periodicFncs.push(fnc);
17
+ }
18
+
19
+ let shutdownHandlers: (() => Promise<void>)[] = [];
20
+ // NOTE: Won't be always called, but at least makes it possible to gracefully shutdown.
21
+ export function registerShutdownHandler(fnc: () => Promise<void>) {
22
+ shutdownHandlers.push(fnc);
23
+ }
24
+ let preshutdownHandlers: (() => Promise<void>)[] = [];
25
+ export function registerPreshutdownHandler(fnc: () => Promise<void>) {
26
+ preshutdownHandlers.push(fnc);
27
+ }
28
+
29
+ function logAll() {
30
+ for (let fnc of periodicFncs) {
31
+ fnc();
32
+ }
33
+ }
34
+
35
+ logErrors(runInfinitePollCallAtStart(timeInMinute * 5, logAll));
36
+
37
+ let shuttingDown = false;
38
+ export async function shutdown() {
39
+ if (shuttingDown) {
40
+ return;
41
+ }
42
+ console.log(red("Starting shutdown"));
43
+ shuttingDown = true;
44
+ const { authorityStorage } = await import("../0-path-value-core/pathValueCore");
45
+ try {
46
+ await Promise.allSettled([
47
+ ...preshutdownHandlers,
48
+ ].map(fnc => timeoutToError(timeInMinute, fnc(), () => new Error(`Preshutdown handler ${fnc.name} timed out`))));
49
+ } catch (e) {
50
+ console.log(`Error on preshutdown handlers`, e);
51
+ }
52
+ try {
53
+ await Promise.allSettled([
54
+ function authorityStorageShutdown() { return authorityStorage.onShutdown(); },
55
+ nodeDiscoveryShutdown,
56
+ shutdownPolling,
57
+ ...shutdownHandlers,
58
+ ].map(fnc => timeoutToError(timeInMinute, fnc(), () => new Error(`Shutdown handler ${fnc.name} timed out`))));
59
+ } catch (e) {
60
+ console.log("Error on shutdown", e);
61
+ }
62
+ // Wait to allow any logged errors to hopefully be written somewhere?
63
+ await delay(2000);
64
+ process.exit();
65
+ }
66
+
67
+ // IMPORTANT! Yarn detaches the processes, so they keep running when you ctrl+c, even though the shell shows back up. We can fix this by using `node -r ./node_modules/typenode/index.js ./test.ts`. However, it's probably fine, as we still run the shutdown code, it's just that the manager doesn't know if we've shutdown or not.
68
+ if (isNode()) {
69
+ let lineBuffer = "";
70
+ process.stdin.on("data", data => {
71
+ lineBuffer += data.toString();
72
+ let lines = lineBuffer.split("\r");
73
+ lineBuffer = lines.pop()!;
74
+ for (let line of lines) {
75
+ if (line === "SHUTDOWN_NOW_MULTIRUN") {
76
+ logErrors(shutdown());
77
+ }
78
+ }
79
+
80
+ if (data.toString().includes("\r")) {
81
+ logAll();
82
+ }
83
+ });
84
+
85
+
86
+ // NOTE: This extra code is required to actual capture ctrl+c
87
+ if (process.platform === "win32") {
88
+ var rl = require("readline").createInterface({
89
+ input: process.stdin,
90
+ output: process.stdout
91
+ });
92
+
93
+ rl.on("SIGINT", function () {
94
+ process.emit("SIGINT");
95
+ });
96
+ }
97
+ let killCount = 0;
98
+ function doShutdown() {
99
+ killCount++;
100
+ console.log(`Caught interrupt signal. Attempt number ${killCount}`);
101
+ if (killCount >= 3) {
102
+ console.log("Force exit");
103
+ process.exit();
104
+ }
105
+
106
+ logErrors(shutdown());
107
+ }
108
+ process.on("SIGINT", doShutdown);
109
+
110
+ }
111
+ (globalThis as any).logAll = logAll;
112
112
  (globalThis as any).logNow = logAll;
@@ -1,92 +1,92 @@
1
- import { runInfinitePoll } from "socket-function/src/batching";
2
- import { lazy } from "socket-function/src/caching";
3
- import { formatNumber } from "socket-function/src/formatting/format";
4
- import { blue } from "socket-function/src/formatting/logColors";
5
- import { isNode } from "socket-function/src/misc";
6
- import { registerPeriodic } from "./periodic";
7
- import { registerMeasureInfo } from "socket-function/src/profiling/measure";
8
- import { logNodeStateStats } from "../-0-hooks/hooks";
9
-
10
- let resources: {
11
- name: string;
12
- getCount: () => number;
13
- }[] = [];
14
-
15
- export function registerResource<T extends Set<unknown> | Map<unknown, unknown> | unknown[]>(name: string, data: T): T {
16
- let getCount: () => number;
17
- if (Array.isArray(data)) {
18
- getCount = () => data.length;
19
- } else {
20
- getCount = () => data.size;
21
- }
22
- resources.push({ name, getCount });
23
- return data;
24
- }
25
- export function registerMapArrayResource<T extends Map<unknown, unknown[]>>(name: string, data: T): T {
26
- let getCount = () => {
27
- let sum = 0;
28
- for (let value of data.values()) {
29
- sum += value.length;
30
- }
31
- return sum;
32
- };
33
- resources.push({ name, getCount });
34
- return data;
35
- }
36
- export function registerDynamicResource(name: string, getCount: () => number) {
37
- resources.push({ name, getCount });
38
- }
39
-
40
- function getHeapSize() {
41
- if (isNode()) {
42
- let usage = process.memoryUsage();
43
- // Not really the heap size, but it is more what we are looking for
44
- return usage.rss;
45
- } else {
46
- return (window.performance as any).memory.totalJSHeapSize;
47
- }
48
- }
49
- function getUsedHeapSize() {
50
- if (isNode()) {
51
- let usage = process.memoryUsage();
52
- return usage.heapUsed + usage.arrayBuffers;
53
- } else {
54
- if (!window.performance) return 0;
55
- return (window.performance as any).memory.usedJSHeapSize;
56
- }
57
- }
58
- function getBufferUsage() {
59
- if (isNode()) {
60
- let usage = process.memoryUsage();
61
- return usage.arrayBuffers;
62
- } else {
63
- return 0;
64
- }
65
- }
66
-
67
- registerDynamicResource("Heap", getUsedHeapSize);
68
- registerDynamicResource("Buffers", getBufferUsage);
69
- registerDynamicResource("Used Memory", getHeapSize);
70
-
71
- function logResourcesNow() {
72
- let resourcesWithCounts = resources.map(resource => ({ ...resource, count: resource.getCount() }));
73
- resourcesWithCounts.sort((a, b) => b.count - a.count);
74
- if (!isNode()) {
75
- console.log(`Memory usage ${blue(formatNumber(getUsedHeapSize()) + "B")}/${blue(formatNumber(getHeapSize()) + "B")} at ${new Date().toISOString()}`);
76
- for (let resource of resourcesWithCounts) {
77
- if (resource.count === 0) continue;
78
- console.log(` ${resource.name}: ${formatNumber(resource.count)}`);
79
- }
80
- } else {
81
- for (let resource of resourcesWithCounts) {
82
- if (resource.count === 0) continue;
83
- logNodeStateStats(resource.name, formatNumber, resource.count);
84
- }
85
- }
86
- }
87
-
88
- registerMeasureInfo(() => {
89
- return `MEM ${formatNumber(getUsedHeapSize())}B+${formatNumber(getBufferUsage())}B/${formatNumber(getHeapSize())}B `;
90
- });
91
-
1
+ import { runInfinitePoll } from "socket-function/src/batching";
2
+ import { lazy } from "socket-function/src/caching";
3
+ import { formatNumber } from "socket-function/src/formatting/format";
4
+ import { blue } from "socket-function/src/formatting/logColors";
5
+ import { isNode } from "socket-function/src/misc";
6
+ import { registerPeriodic } from "./periodic";
7
+ import { registerMeasureInfo } from "socket-function/src/profiling/measure";
8
+ import { logNodeStateStats } from "../-0-hooks/hooks";
9
+
10
+ let resources: {
11
+ name: string;
12
+ getCount: () => number;
13
+ }[] = [];
14
+
15
+ export function registerResource<T extends Set<unknown> | Map<unknown, unknown> | unknown[]>(name: string, data: T): T {
16
+ let getCount: () => number;
17
+ if (Array.isArray(data)) {
18
+ getCount = () => data.length;
19
+ } else {
20
+ getCount = () => data.size;
21
+ }
22
+ resources.push({ name, getCount });
23
+ return data;
24
+ }
25
+ export function registerMapArrayResource<T extends Map<unknown, unknown[]>>(name: string, data: T): T {
26
+ let getCount = () => {
27
+ let sum = 0;
28
+ for (let value of data.values()) {
29
+ sum += value.length;
30
+ }
31
+ return sum;
32
+ };
33
+ resources.push({ name, getCount });
34
+ return data;
35
+ }
36
+ export function registerDynamicResource(name: string, getCount: () => number) {
37
+ resources.push({ name, getCount });
38
+ }
39
+
40
+ function getHeapSize() {
41
+ if (isNode()) {
42
+ let usage = process.memoryUsage();
43
+ // Not really the heap size, but it is more what we are looking for
44
+ return usage.rss;
45
+ } else {
46
+ return (window.performance as any).memory.totalJSHeapSize;
47
+ }
48
+ }
49
+ function getUsedHeapSize() {
50
+ if (isNode()) {
51
+ let usage = process.memoryUsage();
52
+ return usage.heapUsed + usage.arrayBuffers;
53
+ } else {
54
+ if (!window.performance) return 0;
55
+ return (window.performance as any).memory.usedJSHeapSize;
56
+ }
57
+ }
58
+ function getBufferUsage() {
59
+ if (isNode()) {
60
+ let usage = process.memoryUsage();
61
+ return usage.arrayBuffers;
62
+ } else {
63
+ return 0;
64
+ }
65
+ }
66
+
67
+ registerDynamicResource("Heap", getUsedHeapSize);
68
+ registerDynamicResource("Buffers", getBufferUsage);
69
+ registerDynamicResource("Used Memory", getHeapSize);
70
+
71
+ function logResourcesNow() {
72
+ let resourcesWithCounts = resources.map(resource => ({ ...resource, count: resource.getCount() }));
73
+ resourcesWithCounts.sort((a, b) => b.count - a.count);
74
+ if (!isNode()) {
75
+ console.log(`Memory usage ${blue(formatNumber(getUsedHeapSize()) + "B")}/${blue(formatNumber(getHeapSize()) + "B")} at ${new Date().toISOString()}`);
76
+ for (let resource of resourcesWithCounts) {
77
+ if (resource.count === 0) continue;
78
+ console.log(` ${resource.name}: ${formatNumber(resource.count)}`);
79
+ }
80
+ } else {
81
+ for (let resource of resourcesWithCounts) {
82
+ if (resource.count === 0) continue;
83
+ logNodeStateStats(resource.name, formatNumber, resource.count);
84
+ }
85
+ }
86
+ }
87
+
88
+ registerMeasureInfo(() => {
89
+ return `MEM ${formatNumber(getUsedHeapSize())}B+${formatNumber(getBufferUsage())}B/${formatNumber(getHeapSize())}B `;
90
+ });
91
+
92
92
  registerPeriodic(logResourcesNow);