querysub 0.437.0 → 0.438.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 (73) 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/archivesDisk.ts +454 -454
  11. package/src/-a-auth/certs.ts +540 -540
  12. package/src/-a-auth/node-forge-ed25519.d.ts +16 -16
  13. package/src/-b-authorities/dnsAuthority.ts +138 -138
  14. package/src/-c-identity/IdentityController.ts +258 -258
  15. package/src/-d-trust/NetworkTrust2.ts +180 -180
  16. package/src/-e-certs/EdgeCertController.ts +252 -252
  17. package/src/-e-certs/certAuthority.ts +201 -201
  18. package/src/-f-node-discovery/NodeDiscovery.ts +640 -640
  19. package/src/-g-core-values/NodeCapabilities.ts +200 -200
  20. package/src/-h-path-value-serialize/stringSerializer.ts +175 -175
  21. package/src/0-path-value-core/PathValueCommitter.ts +468 -468
  22. package/src/0-path-value-core/PathValueController.ts +0 -2
  23. package/src/2-proxy/PathValueProxyWatcher.ts +2542 -2542
  24. package/src/2-proxy/TransactionDelayer.ts +94 -94
  25. package/src/2-proxy/pathDatabaseProxyBase.ts +36 -36
  26. package/src/2-proxy/pathValueProxy.ts +159 -159
  27. package/src/3-path-functions/PathFunctionRunnerMain.ts +87 -87
  28. package/src/3-path-functions/pathFunctionLoader.ts +516 -516
  29. package/src/3-path-functions/tests/rejectTest.ts +76 -76
  30. package/src/4-deploy/deployCheck.ts +6 -6
  31. package/src/4-dom/css.tsx +29 -29
  32. package/src/4-dom/cssTypes.d.ts +211 -211
  33. package/src/4-dom/qreact.tsx +2799 -2799
  34. package/src/4-dom/qreactTest.tsx +410 -410
  35. package/src/4-querysub/permissions.ts +335 -335
  36. package/src/4-querysub/querysubPrediction.ts +483 -483
  37. package/src/5-diagnostics/qreactDebug.tsx +377 -346
  38. package/src/TestController.ts +34 -34
  39. package/src/bits.ts +104 -104
  40. package/src/buffers.ts +69 -69
  41. package/src/diagnostics/ActionsHistory.ts +57 -57
  42. package/src/diagnostics/listenOnDebugger.ts +71 -71
  43. package/src/diagnostics/periodic.ts +111 -111
  44. package/src/diagnostics/trackResources.ts +91 -91
  45. package/src/diagnostics/watchdog.ts +120 -120
  46. package/src/errors.ts +133 -133
  47. package/src/forceProduction.ts +2 -2
  48. package/src/fs.ts +80 -80
  49. package/src/functional/diff.ts +857 -857
  50. package/src/functional/promiseCache.ts +78 -78
  51. package/src/functional/random.ts +8 -8
  52. package/src/functional/stats.ts +60 -60
  53. package/src/heapDumps.ts +665 -665
  54. package/src/https.ts +1 -1
  55. package/src/library-components/AspectSizedComponent.tsx +87 -87
  56. package/src/library-components/ButtonSelector.tsx +64 -64
  57. package/src/library-components/DropdownCustom.tsx +150 -150
  58. package/src/library-components/DropdownSelector.tsx +31 -31
  59. package/src/library-components/InlinePopup.tsx +66 -66
  60. package/src/misc/color.ts +29 -29
  61. package/src/misc/hash.ts +83 -83
  62. package/src/misc/ipPong.js +13 -13
  63. package/src/misc/networking.ts +1 -1
  64. package/src/misc/random.ts +44 -44
  65. package/src/misc.ts +196 -196
  66. package/src/path.ts +255 -255
  67. package/src/persistentLocalStore.ts +41 -41
  68. package/src/promise.ts +14 -14
  69. package/src/storage/fileSystemPointer.ts +71 -71
  70. package/src/test/heapProcess.ts +35 -35
  71. package/src/zip.ts +15 -15
  72. package/tsconfig.json +26 -26
  73. 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
  }