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,32 +1,32 @@
1
- import preact from "preact";
2
- import { Querysub } from "../../src/4-querysub/QuerysubController";
3
- import { qreact } from "../../src/4-dom/qreact";
4
-
5
-
6
- export class DropdownSelector<T> extends qreact.Component<{
7
- title?: string;
8
- value: T;
9
- onChange: (value: T) => void;
10
- options: { value: T; label: string; }[];
11
- }> {
12
- render() {
13
- const { options, value, title, onChange } = this.props;
14
- let optionValues = options.map(o => String(o.value));
15
- return (
16
- <label style={{ display: "flex", gap: 10, alignItems: "center" }}>
17
- {title && <span>{title}</span>}
18
- <select
19
- value={String(value)}
20
- onChange={e => {
21
- let option = options[optionValues.indexOf(e.currentTarget.value)];
22
- onChange(option ? option.value : e.currentTarget.value as T);
23
- }}
24
- >
25
- {options.map(({ value, label }) =>
26
- <option value={String(value)}>{label}</option>
27
- )}
28
- </select>
29
- </label>
30
- );
31
- }
1
+ import preact from "preact";
2
+ import { Querysub } from "../../src/4-querysub/QuerysubController";
3
+ import { qreact } from "../../src/4-dom/qreact";
4
+
5
+
6
+ export class DropdownSelector<T> extends qreact.Component<{
7
+ title?: string;
8
+ value: T;
9
+ onChange: (value: T) => void;
10
+ options: { value: T; label: string; }[];
11
+ }> {
12
+ render() {
13
+ const { options, value, title, onChange } = this.props;
14
+ let optionValues = options.map(o => String(o.value));
15
+ return (
16
+ <label style={{ display: "flex", gap: 10, alignItems: "center" }}>
17
+ {title && <span>{title}</span>}
18
+ <select
19
+ value={String(value)}
20
+ onChange={e => {
21
+ let option = options[optionValues.indexOf(e.currentTarget.value)];
22
+ onChange(option ? option.value : e.currentTarget.value as T);
23
+ }}
24
+ >
25
+ {options.map(({ value, label }) =>
26
+ <option value={String(value)}>{label}</option>
27
+ )}
28
+ </select>
29
+ </label>
30
+ );
31
+ }
32
32
  }
@@ -1,67 +1,67 @@
1
- import preact from "preact";
2
- import { Querysub } from "../4-querysub/QuerysubController";
3
- import { qreact } from "../4-dom/qreact";
4
- import { Button } from "../library-components/Button";
5
- import { Icon } from "../library-components/icons";
6
- import { createURLSync } from "./URLParam";
7
-
8
- const popupURL = createURLSync<string>("popup", "");
9
-
10
-
11
- export class InlinePopup extends qreact.Component<{
12
- type: string;
13
- margin?: number;
14
- }> {
15
- render() {
16
- if (popupURL.value !== this.props.type) return undefined;
17
- let margin = this.props.margin ?? 100;
18
- return (
19
- <div
20
- style={{
21
- position: "fixed",
22
- left: 0, top: 0,
23
- width: "100vw", height: "100vh",
24
- zIndex: 1000,
25
- }}
26
- onClick={e => qreact.isTarget(e) && (popupURL.value = "")}
27
- >
28
- <div style={{
29
- margin,
30
- position: "relative",
31
- zIndex: 1,
32
- }}>
33
- <Button
34
- hotkeys={["Escape"]}
35
- showHotkeys
36
- onClick={() => popupURL.value = ""}
37
- style={{
38
- position: "absolute",
39
- right: 0, top: -10,
40
- transform: "translate(0%, -100%)",
41
- border: "1px solid hsl(0, 0%, 7%)",
42
- }}
43
- >
44
- {Icon.close()}
45
- </Button>
46
- <div style={{
47
- maxHeight: `calc(100vh - ${margin * 2}px)`,
48
- overflow: "auto",
49
- }}>
50
- {this.props.children}
51
- </div>
52
- </div>
53
- <div
54
- className="button"
55
- style={{
56
- position: "absolute",
57
- left: 0, top: 0,
58
- width: "100%", height: "100%",
59
- background: "hsl(0, 0%, 50%, 0.5)",
60
- zIndex: 0,
61
- }}
62
- onClick={e => popupURL.value = ""}
63
- />
64
- </div>
65
- );
66
- }
1
+ import preact from "preact";
2
+ import { Querysub } from "../4-querysub/QuerysubController";
3
+ import { qreact } from "../4-dom/qreact";
4
+ import { Button } from "../library-components/Button";
5
+ import { Icon } from "../library-components/icons";
6
+ import { createURLSync } from "./URLParam";
7
+
8
+ const popupURL = createURLSync<string>("popup", "");
9
+
10
+
11
+ export class InlinePopup extends qreact.Component<{
12
+ type: string;
13
+ margin?: number;
14
+ }> {
15
+ render() {
16
+ if (popupURL.value !== this.props.type) return undefined;
17
+ let margin = this.props.margin ?? 100;
18
+ return (
19
+ <div
20
+ style={{
21
+ position: "fixed",
22
+ left: 0, top: 0,
23
+ width: "100vw", height: "100vh",
24
+ zIndex: 1000,
25
+ }}
26
+ onClick={e => qreact.isTarget(e) && (popupURL.value = "")}
27
+ >
28
+ <div style={{
29
+ margin,
30
+ position: "relative",
31
+ zIndex: 1,
32
+ }}>
33
+ <Button
34
+ hotkeys={["Escape"]}
35
+ showHotkeys
36
+ onClick={() => popupURL.value = ""}
37
+ style={{
38
+ position: "absolute",
39
+ right: 0, top: -10,
40
+ transform: "translate(0%, -100%)",
41
+ border: "1px solid hsl(0, 0%, 7%)",
42
+ }}
43
+ >
44
+ {Icon.close()}
45
+ </Button>
46
+ <div style={{
47
+ maxHeight: `calc(100vh - ${margin * 2}px)`,
48
+ overflow: "auto",
49
+ }}>
50
+ {this.props.children}
51
+ </div>
52
+ </div>
53
+ <div
54
+ className="button"
55
+ style={{
56
+ position: "absolute",
57
+ left: 0, top: 0,
58
+ width: "100%", height: "100%",
59
+ background: "hsl(0, 0%, 50%, 0.5)",
60
+ zIndex: 0,
61
+ }}
62
+ onClick={e => popupURL.value = ""}
63
+ />
64
+ </div>
65
+ );
66
+ }
67
67
  }
package/src/misc/color.ts CHANGED
@@ -1,30 +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) };
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
30
  }
package/src/misc/hash.ts CHANGED
@@ -1,84 +1,84 @@
1
- import debugbreak from "debugbreak";
2
-
3
- /** Returns an integer */
4
- export function fastHash(text: string): number {
5
- // Murmur, but we try to use more than 32 bits, as a double can store far more than 32 bits.
6
- let hash1 = 5380942 ^ text.length;
7
- let hash2 = 9143241 ^ text.length;
8
- for (let i = 0; i < text.length; i++) {
9
- let ch = text.charCodeAt(i);
10
- hash1 = addToMurmurHash(hash1, ch);
11
- hash2 = addToMurmurHash(hash2, ch);
12
- }
13
- hash1 = finishMurmurHash(hash1);
14
- hash2 = finishMurmurHash(hash2);
15
- return Math.abs(hash1 * (2 ** 20) + hash2);
16
- }
17
-
18
- /** Hashes an object so the result is the same independent of key order
19
- * Ex, consistentHash({ x: 1, y: 2 }) === consistentHash({ y: 2, x: 1 })
20
- * - Works with nested values
21
- * - The hash isn't small, and is really just the JSON stringified re-ordered object
22
- */
23
- export function consistentHash(obj: unknown): string {
24
- return JSON.stringify(orderObjectKeys(obj));
25
- }
26
- function orderObjectKeys(obj: unknown): unknown {
27
- if (typeof obj !== "object" || obj === null) return obj;
28
- if (Array.isArray(obj)) return obj.map(x => orderObjectKeys(x));
29
- let keys = Object.keys(obj);
30
- keys.sort();
31
- let newObj: Record<string, unknown> = {};
32
- for (let key of keys) {
33
- newObj[key] = orderObjectKeys((obj as any)[key]);
34
- }
35
- return newObj;
36
- }
37
-
38
- function addToMurmurHash(curHash: number, next: number) {
39
- // murmurhash, 32 bit
40
- // https://github.com/mikolalysenko/murmurhash-js/blob/master/murmurhash2_gc.js
41
- let h = curHash;
42
- let k = next;
43
- k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
44
- k ^= k >>> 24;
45
- k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
46
- h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
47
-
48
- return h;
49
- }
50
- function finishMurmurHash(curHash: number) {
51
- let h = curHash;
52
- h ^= h >>> 13;
53
- h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
54
- h ^= h >>> 15;
55
- return h;
56
- }
57
-
58
- export function hashBufferRange32(buffer: Buffer, start: number, end: number) {
59
- if (start < 0) start = 0;
60
- if (end > buffer.byteLength) end = buffer.byteLength;
61
-
62
- let len = end - start;
63
- let len4 = len - (len % 4);
64
- let hash = end - start;
65
- for (let i = 0; i < len4; i += 4) {
66
- hash = addToMurmurHash(hash, buffer.readUInt32LE(i + start));
67
- }
68
- for (let i = len4; i < len; i++) {
69
- hash = addToMurmurHash(hash, buffer[i + start]);
70
- }
71
-
72
- return hash;
73
- }
74
-
75
- export function hashBufferRange64(buffer: Buffer, start: number, end: number) {
76
- if (start < 0) start = 0;
77
- if (end > buffer.byteLength) end = buffer.byteLength;
78
- let size = end - start;
79
- let middle = start + Math.ceil(size / 2);
80
-
81
- let hash1 = hashBufferRange32(buffer, start, middle);
82
- let hash2 = hashBufferRange32(buffer, middle, end);
83
- return Math.abs(hash1 * (2 ** 20) + hash2);
1
+ import debugbreak from "debugbreak";
2
+
3
+ /** Returns an integer */
4
+ export function fastHash(text: string): number {
5
+ // Murmur, but we try to use more than 32 bits, as a double can store far more than 32 bits.
6
+ let hash1 = 5380942 ^ text.length;
7
+ let hash2 = 9143241 ^ text.length;
8
+ for (let i = 0; i < text.length; i++) {
9
+ let ch = text.charCodeAt(i);
10
+ hash1 = addToMurmurHash(hash1, ch);
11
+ hash2 = addToMurmurHash(hash2, ch);
12
+ }
13
+ hash1 = finishMurmurHash(hash1);
14
+ hash2 = finishMurmurHash(hash2);
15
+ return Math.abs(hash1 * (2 ** 20) + hash2);
16
+ }
17
+
18
+ /** Hashes an object so the result is the same independent of key order
19
+ * Ex, consistentHash({ x: 1, y: 2 }) === consistentHash({ y: 2, x: 1 })
20
+ * - Works with nested values
21
+ * - The hash isn't small, and is really just the JSON stringified re-ordered object
22
+ */
23
+ export function consistentHash(obj: unknown): string {
24
+ return JSON.stringify(orderObjectKeys(obj));
25
+ }
26
+ function orderObjectKeys(obj: unknown): unknown {
27
+ if (typeof obj !== "object" || obj === null) return obj;
28
+ if (Array.isArray(obj)) return obj.map(x => orderObjectKeys(x));
29
+ let keys = Object.keys(obj);
30
+ keys.sort();
31
+ let newObj: Record<string, unknown> = {};
32
+ for (let key of keys) {
33
+ newObj[key] = orderObjectKeys((obj as any)[key]);
34
+ }
35
+ return newObj;
36
+ }
37
+
38
+ function addToMurmurHash(curHash: number, next: number) {
39
+ // murmurhash, 32 bit
40
+ // https://github.com/mikolalysenko/murmurhash-js/blob/master/murmurhash2_gc.js
41
+ let h = curHash;
42
+ let k = next;
43
+ k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
44
+ k ^= k >>> 24;
45
+ k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
46
+ h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
47
+
48
+ return h;
49
+ }
50
+ function finishMurmurHash(curHash: number) {
51
+ let h = curHash;
52
+ h ^= h >>> 13;
53
+ h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
54
+ h ^= h >>> 15;
55
+ return h;
56
+ }
57
+
58
+ export function hashBufferRange32(buffer: Buffer, start: number, end: number) {
59
+ if (start < 0) start = 0;
60
+ if (end > buffer.byteLength) end = buffer.byteLength;
61
+
62
+ let len = end - start;
63
+ let len4 = len - (len % 4);
64
+ let hash = end - start;
65
+ for (let i = 0; i < len4; i += 4) {
66
+ hash = addToMurmurHash(hash, buffer.readUInt32LE(i + start));
67
+ }
68
+ for (let i = len4; i < len; i++) {
69
+ hash = addToMurmurHash(hash, buffer[i + start]);
70
+ }
71
+
72
+ return hash;
73
+ }
74
+
75
+ export function hashBufferRange64(buffer: Buffer, start: number, end: number) {
76
+ if (start < 0) start = 0;
77
+ if (end > buffer.byteLength) end = buffer.byteLength;
78
+ let size = end - start;
79
+ let middle = start + Math.ceil(size / 2);
80
+
81
+ let hash1 = hashBufferRange32(buffer, start, middle);
82
+ let hash2 = hashBufferRange32(buffer, middle, end);
83
+ return Math.abs(hash1 * (2 ** 20) + hash2);
84
84
  }
@@ -1,13 +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
- });
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
+ });
@@ -1,2 +1,2 @@
1
- import { testTCPIsListening, getExternalIP, getPublicIP } from "socket-function/src/networking";
1
+ import { testTCPIsListening, getExternalIP, getPublicIP } from "socket-function/src/networking";
2
2
  export { testTCPIsListening, getExternalIP, getPublicIP };
@@ -1,45 +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];
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
45
  }