querysub 0.2.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 (169) hide show
  1. package/.dependency-cruiser.js +304 -0
  2. package/.eslintrc.js +51 -0
  3. package/.github/copilot-instructions.md +1 -0
  4. package/.vscode/settings.json +25 -0
  5. package/bin/deploy.js +4 -0
  6. package/bin/function.js +4 -0
  7. package/bin/server.js +4 -0
  8. package/costsBenefits.txt +112 -0
  9. package/deploy.ts +3 -0
  10. package/inject.ts +1 -0
  11. package/package.json +60 -0
  12. package/prompts.txt +54 -0
  13. package/spec.txt +820 -0
  14. package/src/-a-archives/archiveCache.ts +913 -0
  15. package/src/-a-archives/archives.ts +148 -0
  16. package/src/-a-archives/archivesBackBlaze.ts +792 -0
  17. package/src/-a-archives/archivesDisk.ts +418 -0
  18. package/src/-a-archives/copyLocalToBackblaze.ts +24 -0
  19. package/src/-a-auth/certs.ts +517 -0
  20. package/src/-a-auth/der.ts +122 -0
  21. package/src/-a-auth/ed25519.ts +1015 -0
  22. package/src/-a-auth/node-forge-ed25519.d.ts +17 -0
  23. package/src/-b-authorities/dnsAuthority.ts +203 -0
  24. package/src/-b-authorities/emailAuthority.ts +57 -0
  25. package/src/-c-identity/IdentityController.ts +200 -0
  26. package/src/-d-trust/NetworkTrust2.ts +150 -0
  27. package/src/-e-certs/EdgeCertController.ts +288 -0
  28. package/src/-e-certs/certAuthority.ts +192 -0
  29. package/src/-f-node-discovery/NodeDiscovery.ts +543 -0
  30. package/src/-g-core-values/NodeCapabilities.ts +134 -0
  31. package/src/-g-core-values/oneTimeForward.ts +91 -0
  32. package/src/-h-path-value-serialize/PathValueSerializer.ts +769 -0
  33. package/src/-h-path-value-serialize/stringSerializer.ts +176 -0
  34. package/src/0-path-value-core/LoggingClient.tsx +24 -0
  35. package/src/0-path-value-core/NodePathAuthorities.ts +978 -0
  36. package/src/0-path-value-core/PathController.ts +1 -0
  37. package/src/0-path-value-core/PathValueCommitter.ts +565 -0
  38. package/src/0-path-value-core/PathValueController.ts +231 -0
  39. package/src/0-path-value-core/archiveLocks/ArchiveLocks.ts +154 -0
  40. package/src/0-path-value-core/archiveLocks/ArchiveLocks2.ts +820 -0
  41. package/src/0-path-value-core/archiveLocks/archiveSnapshots.ts +180 -0
  42. package/src/0-path-value-core/debugLogs.ts +90 -0
  43. package/src/0-path-value-core/pathValueArchives.ts +483 -0
  44. package/src/0-path-value-core/pathValueCore.ts +2217 -0
  45. package/src/1-path-client/RemoteWatcher.ts +558 -0
  46. package/src/1-path-client/pathValueClientWatcher.ts +702 -0
  47. package/src/2-proxy/PathValueProxyWatcher.ts +1857 -0
  48. package/src/2-proxy/archiveMoveHarness.ts +376 -0
  49. package/src/2-proxy/garbageCollection.ts +753 -0
  50. package/src/2-proxy/pathDatabaseProxyBase.ts +37 -0
  51. package/src/2-proxy/pathValueProxy.ts +139 -0
  52. package/src/2-proxy/schema2.ts +518 -0
  53. package/src/3-path-functions/PathFunctionHelpers.ts +129 -0
  54. package/src/3-path-functions/PathFunctionRunner.ts +619 -0
  55. package/src/3-path-functions/PathFunctionRunnerMain.ts +67 -0
  56. package/src/3-path-functions/deployBlock.ts +10 -0
  57. package/src/3-path-functions/deployCheck.ts +7 -0
  58. package/src/3-path-functions/deployMain.ts +160 -0
  59. package/src/3-path-functions/pathFunctionLoader.ts +282 -0
  60. package/src/3-path-functions/syncSchema.ts +475 -0
  61. package/src/3-path-functions/tests/functionsTest.ts +135 -0
  62. package/src/3-path-functions/tests/rejectTest.ts +77 -0
  63. package/src/4-dom/css.tsx +29 -0
  64. package/src/4-dom/cssTypes.d.ts +212 -0
  65. package/src/4-dom/qreact.tsx +2322 -0
  66. package/src/4-dom/qreactTest.tsx +417 -0
  67. package/src/4-querysub/Querysub.ts +877 -0
  68. package/src/4-querysub/QuerysubController.ts +620 -0
  69. package/src/4-querysub/copyEvent.ts +0 -0
  70. package/src/4-querysub/permissions.ts +289 -0
  71. package/src/4-querysub/permissionsShared.ts +1 -0
  72. package/src/4-querysub/querysubPrediction.ts +525 -0
  73. package/src/5-diagnostics/FullscreenModal.tsx +67 -0
  74. package/src/5-diagnostics/GenericFormat.tsx +165 -0
  75. package/src/5-diagnostics/Modal.tsx +79 -0
  76. package/src/5-diagnostics/Table.tsx +183 -0
  77. package/src/5-diagnostics/TimeGrouper.tsx +114 -0
  78. package/src/5-diagnostics/diskValueAudit.ts +216 -0
  79. package/src/5-diagnostics/memoryValueAudit.ts +442 -0
  80. package/src/5-diagnostics/nodeMetadata.ts +135 -0
  81. package/src/5-diagnostics/qreactDebug.tsx +309 -0
  82. package/src/5-diagnostics/shared.ts +26 -0
  83. package/src/5-diagnostics/synchronousLagTracking.ts +47 -0
  84. package/src/TestController.ts +35 -0
  85. package/src/allowclient.flag +0 -0
  86. package/src/bits.ts +86 -0
  87. package/src/buffers.ts +69 -0
  88. package/src/config.ts +53 -0
  89. package/src/config2.ts +48 -0
  90. package/src/diagnostics/ActionsHistory.ts +56 -0
  91. package/src/diagnostics/NodeViewer.tsx +503 -0
  92. package/src/diagnostics/SizeLimiter.ts +62 -0
  93. package/src/diagnostics/TimeDebug.tsx +18 -0
  94. package/src/diagnostics/benchmark.ts +139 -0
  95. package/src/diagnostics/errorLogs/ErrorLogController.ts +515 -0
  96. package/src/diagnostics/errorLogs/ErrorLogCore.ts +274 -0
  97. package/src/diagnostics/errorLogs/LogClassifiers.tsx +302 -0
  98. package/src/diagnostics/errorLogs/LogFilterUI.tsx +84 -0
  99. package/src/diagnostics/errorLogs/LogNotify.tsx +101 -0
  100. package/src/diagnostics/errorLogs/LogTimeSelector.tsx +724 -0
  101. package/src/diagnostics/errorLogs/LogViewer.tsx +757 -0
  102. package/src/diagnostics/errorLogs/hookErrors.ts +60 -0
  103. package/src/diagnostics/errorLogs/logFiltering.tsx +149 -0
  104. package/src/diagnostics/heapTag.ts +13 -0
  105. package/src/diagnostics/listenOnDebugger.ts +77 -0
  106. package/src/diagnostics/logs/DiskLoggerPage.tsx +572 -0
  107. package/src/diagnostics/logs/ObjectDisplay.tsx +165 -0
  108. package/src/diagnostics/logs/ansiFormat.ts +108 -0
  109. package/src/diagnostics/logs/diskLogGlobalContext.ts +38 -0
  110. package/src/diagnostics/logs/diskLogger.ts +305 -0
  111. package/src/diagnostics/logs/diskShimConsoleLogs.ts +32 -0
  112. package/src/diagnostics/logs/injectFileLocationToConsole.ts +50 -0
  113. package/src/diagnostics/logs/logGitHashes.ts +30 -0
  114. package/src/diagnostics/managementPages.tsx +289 -0
  115. package/src/diagnostics/periodic.ts +89 -0
  116. package/src/diagnostics/runSaturationTest.ts +416 -0
  117. package/src/diagnostics/satSchema.ts +64 -0
  118. package/src/diagnostics/trackResources.ts +82 -0
  119. package/src/diagnostics/watchdog.ts +55 -0
  120. package/src/errors.ts +132 -0
  121. package/src/forceProduction.ts +3 -0
  122. package/src/fs.ts +72 -0
  123. package/src/heapDumps.ts +666 -0
  124. package/src/https.ts +2 -0
  125. package/src/inject.ts +1 -0
  126. package/src/library-components/ATag.tsx +84 -0
  127. package/src/library-components/Button.tsx +344 -0
  128. package/src/library-components/ButtonSelector.tsx +64 -0
  129. package/src/library-components/DropdownCustom.tsx +151 -0
  130. package/src/library-components/DropdownSelector.tsx +32 -0
  131. package/src/library-components/Input.tsx +334 -0
  132. package/src/library-components/InputLabel.tsx +198 -0
  133. package/src/library-components/InputPicker.tsx +125 -0
  134. package/src/library-components/LazyComponent.tsx +62 -0
  135. package/src/library-components/MeasureHeightCSS.tsx +48 -0
  136. package/src/library-components/MeasuredDiv.tsx +47 -0
  137. package/src/library-components/ShowMore.tsx +51 -0
  138. package/src/library-components/SyncedController.ts +171 -0
  139. package/src/library-components/TimeRangeSelector.tsx +407 -0
  140. package/src/library-components/URLParam.ts +263 -0
  141. package/src/library-components/colors.tsx +14 -0
  142. package/src/library-components/drag.ts +114 -0
  143. package/src/library-components/icons.tsx +692 -0
  144. package/src/library-components/niceStringify.ts +50 -0
  145. package/src/library-components/renderToString.ts +52 -0
  146. package/src/misc/PromiseRace.ts +101 -0
  147. package/src/misc/color.ts +30 -0
  148. package/src/misc/getParentProcessId.cs +53 -0
  149. package/src/misc/getParentProcessId.ts +53 -0
  150. package/src/misc/hash.ts +83 -0
  151. package/src/misc/ipPong.js +13 -0
  152. package/src/misc/networking.ts +2 -0
  153. package/src/misc/random.ts +45 -0
  154. package/src/misc.ts +19 -0
  155. package/src/noserverhotreload.flag +0 -0
  156. package/src/path.ts +226 -0
  157. package/src/persistentLocalStore.ts +37 -0
  158. package/src/promise.ts +15 -0
  159. package/src/server.ts +73 -0
  160. package/src/src.d.ts +1 -0
  161. package/src/test/heapProcess.ts +36 -0
  162. package/src/test/mongoSatTest.tsx +55 -0
  163. package/src/test/satTest.ts +193 -0
  164. package/src/test/test.tsx +552 -0
  165. package/src/zip.ts +92 -0
  166. package/src/zipThreaded.ts +106 -0
  167. package/src/zipThreadedWorker.js +19 -0
  168. package/tsconfig.json +27 -0
  169. package/yarnSpec.txt +56 -0
@@ -0,0 +1,50 @@
1
+
2
+ let specialStringValuesDecode = new Map<string, unknown>([
3
+ // NOTE: Starting with `"`, but not ending with quotes will not be normally generated, as anything starting
4
+ // with a quote will be encoded as a string.
5
+ [`"undefined`, undefined],
6
+ [`"nan`, Number.NaN],
7
+ ]);
8
+ let specialStringValuesEncode = new Map([...specialStringValuesDecode].map(([key, value]) => [value, key]));
9
+
10
+ export function serializeURLParam(value: unknown): string | undefined {
11
+ if (value === true) return undefined;
12
+ // If it is a string and doesn't look JSON encoded, then just use it raw.
13
+ if (typeof value === "string" && !lookJSONEncoded(value)) {
14
+ return value;
15
+ }
16
+ let specialValue = specialStringValuesEncode.get(value);
17
+ if (specialValue) {
18
+ return specialValue;
19
+ }
20
+ return JSON.stringify(value);
21
+ }
22
+ export function deserializeURLParam(value: string | undefined) {
23
+ if (value === undefined) return true;
24
+ let specialValue = specialStringValuesDecode.get(value);
25
+ if (specialValue) {
26
+ return specialValue;
27
+ }
28
+ if (!lookJSONEncoded(value)) {
29
+ return value;
30
+ }
31
+
32
+ try {
33
+ return JSON.parse(value);
34
+ } catch {
35
+ return value;
36
+ }
37
+ }
38
+
39
+ function lookJSONEncoded(str: string) {
40
+ return (
41
+ str === "null"
42
+ || str === "true"
43
+ || str === "false"
44
+ || str[0] === `"` && str[str.length - 1] === `"`
45
+ || str[0] === `[` && str[str.length - 1] === `]`
46
+ || str[0] === `{` && str[str.length - 1] === `}`
47
+ || (48 <= str.charCodeAt(0) && str.charCodeAt(0) <= 57)
48
+ || str.length > 1 && str[0] === "-" && (48 <= str.charCodeAt(1) && str.charCodeAt(1) <= 57)
49
+ );
50
+ }
@@ -0,0 +1,52 @@
1
+ import debugbreak from "debugbreak";
2
+ import { IS_NON_DIMENSIONAL, VirtualDOM, isFragment } from "../../src/4-dom/qreact";
3
+ import { canHaveChildren } from "socket-function/src/types";
4
+
5
+ export function renderToString(component: VirtualDOM): string {
6
+ if (Array.isArray(component)) {
7
+ return component.map(renderToString).join("");
8
+ }
9
+ if (!canHaveChildren(component)) {
10
+ if (component === false) return "";
11
+ if (component === undefined || component === null) return "";
12
+ return String(component);
13
+ }
14
+ if (isFragment(component)) {
15
+ return renderToString((component as any).props.children);
16
+ }
17
+ if (typeof component.type !== "string") {
18
+ // TODO: Support rendering components, just by calling .render
19
+ // TODO: Support functional components
20
+ // TODO: Support synced components, by making a promise variant of renderToString
21
+ throw new Error("Only string components are presently supported in renderToString");
22
+ }
23
+ let attributes = "";
24
+ for (let key in component.props) {
25
+ if (key === "children") continue;
26
+ let value = component.props[key];
27
+ if (key === "style" && canHaveChildren(value)) {
28
+ let style = "";
29
+ for (let [key, v] of Object.entries(value)) {
30
+ // Convert to dash case
31
+ key = key.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
32
+ if (typeof v === "number" && !IS_NON_DIMENSIONAL.test(key)) {
33
+ v = v + "px";
34
+ }
35
+ style += `${key}:${v};`;
36
+ }
37
+ value = style;
38
+ }
39
+ if (value === true) {
40
+ attributes += ` ${key}`;
41
+ } else if (value !== false) {
42
+ attributes += ` ${key}="${value}"`;
43
+ }
44
+ }
45
+ let childrenRaw = component.props.children;
46
+ let childrenArray = Array.isArray(childrenRaw) ? childrenRaw : [childrenRaw];
47
+ let children = "";
48
+ for (let child of childrenArray) {
49
+ children += renderToString(child);
50
+ }
51
+ return `<${component.type}${attributes}>${children}</${component.type}>`;
52
+ }
@@ -0,0 +1,101 @@
1
+ /** Fixed Promise.race, which doesn't leak promises values. Promises still leak, but a Promise is < 100 bytes,
2
+ * where as the promise value might be huge.
3
+ */
4
+ export function PromiseRace<T extends any[]>(promises: { [K in keyof T]: Promise<T[K]> }): Promise<T[number]> {
5
+ return new PromiseLessLeaky((resolve: any, reject: any) => {
6
+ function onFinally() {
7
+ for (let promise of promises) {
8
+ if (promise && typeof promise === "object" && promise instanceof Promise) {
9
+ let callbackObj = promiseCallbacks.get(promise);
10
+ if (!callbackObj) continue;
11
+ remove(callbackObj.onResolve, resolve);
12
+ remove(callbackObj.onReject, reject);
13
+ remove(callbackObj.onFinally, onFinally);
14
+ }
15
+ }
16
+ }
17
+ for (let promise of promises) {
18
+ // NOTE: This "if" statement greatly reduce leaks, although it might
19
+ // reduce speed as well?
20
+ if (promise && typeof promise === "object" && promise instanceof Promise) {
21
+ let callbackObj = promiseCallbacks.get(promise);
22
+ if (!callbackObj) {
23
+ callbackObj = {
24
+ onResolve: [],
25
+ onReject: [],
26
+ onFinally: [],
27
+ };
28
+ promiseCallbacks.set(promise, callbackObj);
29
+ connectPromiseToCallbackObj(promise, callbackObj);
30
+ }
31
+ callbackObj.onResolve.push(resolve);
32
+ callbackObj.onReject.push(reject);
33
+ callbackObj.onFinally.push(onFinally);
34
+ continue;
35
+ }
36
+
37
+ Promise.resolve(promise).then(resolve, reject);
38
+ }
39
+ }) as any;
40
+ }
41
+
42
+ // Less leaky promise.
43
+ // See https://github.com/nodejs/node/issues/17469
44
+ // See https://bugs.chromium.org/p/v8/issues/detail?id=9858#c9
45
+ // Basically, make resolve/reject weakly reference the Promise, so that
46
+ // resolved promises aren't kept alive. The `resolve` function is still leaked
47
+ // itself, but at least it doesn't leak the underlying data.
48
+ // IMPORTANT! This still leaks! So... maybe don't even use Promise.race?
49
+ class PromiseLessLeaky extends Promise<any> {
50
+ constructor(executor: any) {
51
+ super((resolve, reject) => {
52
+ executor(
53
+ function PromiseLessLeakyResolved(value: any) {
54
+ let callback = resolve;
55
+ resolve = undefined as any;
56
+ reject = undefined as any;
57
+ if (callback) {
58
+ callback(value);
59
+ }
60
+ },
61
+ function PromiseLessLeakyRejected(value: any) {
62
+ let callback = reject;
63
+ resolve = undefined as any;
64
+ reject = undefined as any;
65
+ if (callback) {
66
+ callback(value);
67
+ }
68
+ }
69
+ );
70
+ executor = undefined;
71
+ });
72
+ }
73
+ }
74
+ function remove(list: any, value: any) {
75
+ let index = list.indexOf(value);
76
+ if (index >= 0) {
77
+ list.splice(index, 1);
78
+ }
79
+ }
80
+ const promiseCallbacks = new WeakMap();
81
+
82
+ function connectPromiseToCallbackObj(promise: any, callbackObj: any) {
83
+ // NOTE: If the promise stays alive forever... this will leak callbackObj. BUT,
84
+ // it is only called once per promise, ever, so... the leak isn't so bad!
85
+ promise.then(
86
+ (value: any) => {
87
+ for (let fnc of callbackObj.onResolve) {
88
+ try { fnc(value); } finally { }
89
+ }
90
+ },
91
+ (value: any) => {
92
+ for (let fnc of callbackObj.onReject) {
93
+ try { fnc(value); } finally { }
94
+ }
95
+ }
96
+ ).finally(() => {
97
+ for (let fnc of callbackObj.onFinally) {
98
+ try { fnc(); } finally { }
99
+ }
100
+ });
101
+ }
@@ -0,0 +1,30 @@
1
+
2
+ /** hue: 0-360, saturation: 0-100, lightness: 0-100 */
3
+ export function hslToRGB(color: { h: number; s: number; l: number }) {
4
+ let { h, s, l } = color;
5
+ h /= 360;
6
+ s /= 100;
7
+ l /= 100;
8
+ let r, g, b;
9
+ if (s === 0) {
10
+ r = g = b = l; // achromatic
11
+ } else {
12
+ const hue2rgb = (p: number, q: number, t: number) => {
13
+ if (t < 0) t += 1;
14
+ if (t > 1) t -= 1;
15
+ if (t < 1 / 6) return p + (q - p) * 6 * t;
16
+ if (t < 1 / 2) return q;
17
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
18
+ return p;
19
+ };
20
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
21
+ const p = 2 * l - q;
22
+ r = hue2rgb(p, q, h + 1 / 3);
23
+ g = hue2rgb(p, q, h);
24
+ b = hue2rgb(p, q, h - 1 / 3);
25
+ if (b < 0) {
26
+ b = 0;
27
+ }
28
+ }
29
+ return { r: Math.floor(r * 255), g: Math.floor(g * 255), b: Math.floor(b * 255) };
30
+ }
@@ -0,0 +1,53 @@
1
+ using System;
2
+ using System.Diagnostics;
3
+ using System.Text;
4
+ using System.Runtime.InteropServices;
5
+
6
+ public class PPIDService
7
+ {
8
+ [DllImport("kernel32.dll")]
9
+ static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
10
+
11
+ [DllImport("kernel32.dll")]
12
+ static extern bool CloseHandle(IntPtr hObject);
13
+
14
+ [DllImport("ntdll.dll")]
15
+ static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref PROCESS_BASIC_INFORMATION pbi, int processInformationLength, out int returnLength);
16
+
17
+ [StructLayout(LayoutKind.Sequential)]
18
+ internal struct PROCESS_BASIC_INFORMATION
19
+ {
20
+ public IntPtr Reserved1;
21
+ public IntPtr PebBaseAddress;
22
+ public IntPtr Reserved2_0;
23
+ public IntPtr Reserved2_1;
24
+ public IntPtr UniqueProcessId;
25
+ public IntPtr InheritedFromUniqueProcessId;
26
+ }
27
+
28
+ public static int GetParentProcessId(int pid)
29
+ {
30
+ IntPtr hProcess = OpenProcess(0x1000, false, pid);
31
+ if (hProcess == IntPtr.Zero)
32
+ {
33
+ return 0;
34
+ }
35
+
36
+ try
37
+ {
38
+ PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION();
39
+ int returnLength;
40
+ int status = NtQueryInformationProcess(hProcess, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength);
41
+ if (status == 0)
42
+ {
43
+ return pbi.InheritedFromUniqueProcessId.ToInt32();
44
+ }
45
+ }
46
+ finally
47
+ {
48
+ CloseHandle(hProcess);
49
+ }
50
+
51
+ return 0;
52
+ }
53
+ }
@@ -0,0 +1,53 @@
1
+ import fs from "fs";
2
+
3
+ import { lazy } from "socket-function/src/caching";
4
+ import { runInSerial } from "socket-function/src/batching";
5
+ import child_process from "child_process";
6
+ import os from "os";
7
+ import readline from "readline";
8
+ import net from "net";
9
+
10
+ const windowsGetPPID = lazy(async () => {
11
+ const powershellProcess = child_process.spawn("powershell.exe", [
12
+ "-NoProfile",
13
+ "-NonInteractive",
14
+ "-Command",
15
+ "-",
16
+ ], { stdio: ["pipe", "pipe", "pipe"] });
17
+ powershellProcess.stderr.pipe(process.stderr);
18
+ // powershellProcess.stdout.pipe(process.stdout);
19
+
20
+ powershellProcess.on("error", (error) => {
21
+ console.error("Failed to spawn powershell process", error);
22
+ });
23
+
24
+ powershellProcess.stdin.write(`$inject = Get-Content -Raw -Path ${JSON.stringify(__dirname + "/getParentProcessId.cs")};\n`);
25
+ powershellProcess.stdin.write(`Add-Type -TypeDefinition $inject\n`);
26
+
27
+ return runInSerial((pid: number): Promise<number> => {
28
+ return new Promise((resolve) => {
29
+ powershellProcess.stdin.write(`[PPIDService]::GetParentProcessId(${pid})\n`);
30
+ powershellProcess.stdout.once("data", (data) => {
31
+ resolve(parseInt(data.toString()) || 0);
32
+ });
33
+ });
34
+ });
35
+ });
36
+
37
+ export async function getPPID(pid: number): Promise<number> {
38
+ const platform = os.platform();
39
+ if (platform === "win32") {
40
+ let getPPID = await windowsGetPPID();
41
+ return getPPID(pid);
42
+ } else if (platform === "darwin" || platform === "linux") {
43
+ try {
44
+ const statContent = await fs.promises.readFile(`/proc/${pid}/stat`, "utf8");
45
+ const ppid = parseInt(statContent.split(" ")[3], 10);
46
+ return isNaN(ppid) ? 0 : ppid;
47
+ } catch (error) {
48
+ return 0;
49
+ }
50
+ } else {
51
+ throw new Error("Unsupported operating system");
52
+ }
53
+ }
@@ -0,0 +1,83 @@
1
+ import debugbreak from "debugbreak";
2
+
3
+ export function fastHash(text: string): number {
4
+ // Murmur, but we try to use more than 32 bits, as a double can store far more than 32 bits.
5
+ let hash1 = 5380942 ^ text.length;
6
+ let hash2 = 9143241 ^ text.length;
7
+ for (let i = 0; i < text.length; i++) {
8
+ let ch = text.charCodeAt(i);
9
+ hash1 = addToMurmurHash(hash1, ch);
10
+ hash2 = addToMurmurHash(hash2, ch);
11
+ }
12
+ hash1 = finishMurmurHash(hash1);
13
+ hash2 = finishMurmurHash(hash2);
14
+ return Math.abs(hash1 * (2 ** 20) + hash2);
15
+ }
16
+
17
+ /** Hashes an object so the result is the same independent of key order
18
+ * Ex, consistentHash({ x: 1, y: 2 }) === consistentHash({ y: 2, x: 1 })
19
+ * - Works with nested values
20
+ * - The hash isn't small, and is really just the JSON stringified re-ordered object
21
+ */
22
+ export function consistentHash(obj: unknown): string {
23
+ return JSON.stringify(orderObjectKeys(obj));
24
+ }
25
+ function orderObjectKeys(obj: unknown): unknown {
26
+ if (typeof obj !== "object" || obj === null) return obj;
27
+ if (Array.isArray(obj)) return obj.map(x => orderObjectKeys(x));
28
+ let keys = Object.keys(obj);
29
+ keys.sort();
30
+ let newObj: Record<string, unknown> = {};
31
+ for (let key of keys) {
32
+ newObj[key] = orderObjectKeys((obj as any)[key]);
33
+ }
34
+ return newObj;
35
+ }
36
+
37
+ function addToMurmurHash(curHash: number, next: number) {
38
+ // murmurhash, 32 bit
39
+ // https://github.com/mikolalysenko/murmurhash-js/blob/master/murmurhash2_gc.js
40
+ let h = curHash;
41
+ let k = next;
42
+ k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
43
+ k ^= k >>> 24;
44
+ k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
45
+ h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
46
+
47
+ return h;
48
+ }
49
+ function finishMurmurHash(curHash: number) {
50
+ let h = curHash;
51
+ h ^= h >>> 13;
52
+ h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
53
+ h ^= h >>> 15;
54
+ return h;
55
+ }
56
+
57
+ export function hashBufferRange32(buffer: Buffer, start: number, end: number) {
58
+ if (start < 0) start = 0;
59
+ if (end > buffer.byteLength) end = buffer.byteLength;
60
+
61
+ let len = end - start;
62
+ let len4 = len - (len % 4);
63
+ let hash = end - start;
64
+ for (let i = 0; i < len4; i += 4) {
65
+ hash = addToMurmurHash(hash, buffer.readUInt32LE(i + start));
66
+ }
67
+ for (let i = len4; i < len; i++) {
68
+ hash = addToMurmurHash(hash, buffer[i + start]);
69
+ }
70
+
71
+ return hash;
72
+ }
73
+
74
+ export function hashBufferRange64(buffer: Buffer, start: number, end: number) {
75
+ if (start < 0) start = 0;
76
+ if (end > buffer.byteLength) end = buffer.byteLength;
77
+ let size = end - start;
78
+ let middle = start + Math.ceil(size / 2);
79
+
80
+ let hash1 = hashBufferRange32(buffer, start, middle);
81
+ let hash2 = hashBufferRange32(buffer, middle, end);
82
+ return Math.abs(hash1 * (2 ** 20) + hash2);
83
+ }
@@ -0,0 +1,13 @@
1
+ // HTTP response with the caller IP
2
+
3
+ const http = require("http");
4
+ const port = 4283;
5
+
6
+ const server = http.createServer((req, res) => {
7
+ res.writeHead(200, { "Content-Type": "text/plain" });
8
+ res.end(req.socket.remoteAddress.split(":").pop());
9
+ });
10
+
11
+ server.listen(port, () => {
12
+ console.log(`Server running at http://localhost:${port}/`);
13
+ });
@@ -0,0 +1,2 @@
1
+ import { testTCPIsListening, getExternalIP, getPublicIP } from "socket-function/src/networking";
2
+ export { testTCPIsListening, getExternalIP, getPublicIP };
@@ -0,0 +1,45 @@
1
+ import { isNode } from "socket-function/src/misc";
2
+ import crypto from "crypto";
3
+
4
+ export function getSeededRandom(seed: number): () => number {
5
+ // Multiply seed by a large prime
6
+ seed = (seed + 0x1235234894) * 0x1fffffff % 0x7fffffff;
7
+ let rand = sfc32(seed, seed, seed, seed);
8
+ // Run a few time, to fully seed it
9
+ for (let i = 0; i < 10; i++) {
10
+ rand();
11
+ }
12
+ return rand;
13
+ function sfc32(a: number, b: number, c: number, d: number) {
14
+ return function () {
15
+ a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0;
16
+ var t = (a + b) | 0;
17
+ a = b ^ b >>> 9;
18
+ b = c + (c << 3) | 0;
19
+ c = (c << 21 | c >>> 11);
20
+ d = d + 1 | 0;
21
+ t = t + d | 0;
22
+ c = c + t | 0;
23
+ return (t >>> 0) / 4294967296;
24
+ };
25
+ }
26
+ }
27
+
28
+ export function shuffle<T>(array: T[], seed: number) {
29
+ let rand = getSeededRandom(seed);
30
+ let indexes = Array(array.length).fill(0).map((x, i) => i);
31
+ let shuffleValue = indexes.map(() => rand());
32
+ indexes.sort((a, b) => shuffleValue[a] - shuffleValue[b]);
33
+ return indexes.map(i => array[i]);
34
+ }
35
+
36
+ let randomData = new Uint8Array(8);
37
+ let randomDataF64 = new Float64Array(randomData.buffer);
38
+ export function secureRandom(): number {
39
+ if (!isNode()) {
40
+ window.crypto.getRandomValues(randomData);
41
+ } else {
42
+ crypto.getRandomValues(randomData);
43
+ }
44
+ return randomDataF64[0];
45
+ }
package/src/misc.ts ADDED
@@ -0,0 +1,19 @@
1
+ // TIMING: About 20MB/s
2
+ export function createRandomText(count: number): string {
3
+ let text = "";
4
+ let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
5
+ for (let i = 0; i < count; i++) {
6
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
7
+ }
8
+ return text;
9
+ }
10
+
11
+ export function isEmpty(obj: unknown): boolean {
12
+ if (!obj) return false;
13
+ if (typeof obj !== "object") return false;
14
+ return Object.keys(obj).length === 0;
15
+ }
16
+
17
+ export function isDefined<T>(value: T | undefined | null): value is T {
18
+ return value !== undefined && value !== null;
19
+ }
File without changes