@fuzdev/fuz_util 0.42.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 (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/dist/array.d.ts +15 -0
  4. package/dist/array.d.ts.map +1 -0
  5. package/dist/array.js +25 -0
  6. package/dist/async.d.ts +62 -0
  7. package/dist/async.d.ts.map +1 -0
  8. package/dist/async.js +147 -0
  9. package/dist/colors.d.ts +41 -0
  10. package/dist/colors.d.ts.map +1 -0
  11. package/dist/colors.js +106 -0
  12. package/dist/counter.d.ts +7 -0
  13. package/dist/counter.d.ts.map +1 -0
  14. package/dist/counter.js +7 -0
  15. package/dist/deep_equal.d.ts +18 -0
  16. package/dist/deep_equal.d.ts.map +1 -0
  17. package/dist/deep_equal.js +152 -0
  18. package/dist/dom.d.ts +35 -0
  19. package/dist/dom.d.ts.map +1 -0
  20. package/dist/dom.js +95 -0
  21. package/dist/error.d.ts +15 -0
  22. package/dist/error.d.ts.map +1 -0
  23. package/dist/error.js +18 -0
  24. package/dist/fetch.d.ts +81 -0
  25. package/dist/fetch.d.ts.map +1 -0
  26. package/dist/fetch.js +162 -0
  27. package/dist/fs.d.ts +34 -0
  28. package/dist/fs.d.ts.map +1 -0
  29. package/dist/fs.js +73 -0
  30. package/dist/function.d.ts +27 -0
  31. package/dist/function.d.ts.map +1 -0
  32. package/dist/function.js +21 -0
  33. package/dist/git.d.ts +132 -0
  34. package/dist/git.d.ts.map +1 -0
  35. package/dist/git.js +288 -0
  36. package/dist/id.d.ts +18 -0
  37. package/dist/id.d.ts.map +1 -0
  38. package/dist/id.js +18 -0
  39. package/dist/iterator.d.ts +5 -0
  40. package/dist/iterator.d.ts.map +1 -0
  41. package/dist/iterator.js +9 -0
  42. package/dist/json.d.ts +30 -0
  43. package/dist/json.d.ts.map +1 -0
  44. package/dist/json.js +44 -0
  45. package/dist/library_json.d.ts +42 -0
  46. package/dist/library_json.d.ts.map +1 -0
  47. package/dist/library_json.js +76 -0
  48. package/dist/log.d.ts +188 -0
  49. package/dist/log.d.ts.map +1 -0
  50. package/dist/log.js +393 -0
  51. package/dist/map.d.ts +12 -0
  52. package/dist/map.d.ts.map +1 -0
  53. package/dist/map.js +14 -0
  54. package/dist/maths.d.ts +85 -0
  55. package/dist/maths.d.ts.map +1 -0
  56. package/dist/maths.js +87 -0
  57. package/dist/object.d.ts +46 -0
  58. package/dist/object.d.ts.map +1 -0
  59. package/dist/object.js +89 -0
  60. package/dist/package_json.d.ts +90 -0
  61. package/dist/package_json.d.ts.map +1 -0
  62. package/dist/package_json.js +112 -0
  63. package/dist/path.d.ts +63 -0
  64. package/dist/path.d.ts.map +1 -0
  65. package/dist/path.js +83 -0
  66. package/dist/print.d.ts +52 -0
  67. package/dist/print.d.ts.map +1 -0
  68. package/dist/print.js +89 -0
  69. package/dist/process.d.ts +77 -0
  70. package/dist/process.d.ts.map +1 -0
  71. package/dist/process.js +148 -0
  72. package/dist/random.d.ts +25 -0
  73. package/dist/random.d.ts.map +1 -0
  74. package/dist/random.js +35 -0
  75. package/dist/random_alea.d.ts +23 -0
  76. package/dist/random_alea.d.ts.map +1 -0
  77. package/dist/random_alea.js +95 -0
  78. package/dist/regexp.d.ts +12 -0
  79. package/dist/regexp.d.ts.map +1 -0
  80. package/dist/regexp.js +16 -0
  81. package/dist/result.d.ts +64 -0
  82. package/dist/result.d.ts.map +1 -0
  83. package/dist/result.js +48 -0
  84. package/dist/source_json.d.ts +375 -0
  85. package/dist/source_json.d.ts.map +1 -0
  86. package/dist/source_json.js +189 -0
  87. package/dist/string.d.ts +51 -0
  88. package/dist/string.d.ts.map +1 -0
  89. package/dist/string.js +92 -0
  90. package/dist/throttle.d.ts +26 -0
  91. package/dist/throttle.d.ts.map +1 -0
  92. package/dist/throttle.js +53 -0
  93. package/dist/timings.d.ts +33 -0
  94. package/dist/timings.d.ts.map +1 -0
  95. package/dist/timings.js +75 -0
  96. package/dist/types.d.ts +77 -0
  97. package/dist/types.d.ts.map +1 -0
  98. package/dist/types.js +10 -0
  99. package/dist/url.d.ts +10 -0
  100. package/dist/url.d.ts.map +1 -0
  101. package/dist/url.js +8 -0
  102. package/package.json +125 -0
  103. package/src/lib/array.ts +30 -0
  104. package/src/lib/async.ts +182 -0
  105. package/src/lib/colors.ts +132 -0
  106. package/src/lib/counter.ts +11 -0
  107. package/src/lib/deep_equal.ts +155 -0
  108. package/src/lib/dom.ts +108 -0
  109. package/src/lib/error.ts +22 -0
  110. package/src/lib/fetch.ts +231 -0
  111. package/src/lib/fs.ts +128 -0
  112. package/src/lib/function.ts +32 -0
  113. package/src/lib/git.ts +390 -0
  114. package/src/lib/id.ts +30 -0
  115. package/src/lib/iterator.ts +8 -0
  116. package/src/lib/json.ts +61 -0
  117. package/src/lib/library_json.ts +122 -0
  118. package/src/lib/log.ts +469 -0
  119. package/src/lib/map.ts +18 -0
  120. package/src/lib/maths.ts +91 -0
  121. package/src/lib/object.ts +110 -0
  122. package/src/lib/package_json.ts +135 -0
  123. package/src/lib/path.ts +137 -0
  124. package/src/lib/print.ts +111 -0
  125. package/src/lib/process.ts +207 -0
  126. package/src/lib/random.ts +48 -0
  127. package/src/lib/random_alea.ts +107 -0
  128. package/src/lib/regexp.ts +17 -0
  129. package/src/lib/result.ts +67 -0
  130. package/src/lib/source_json.ts +209 -0
  131. package/src/lib/string.ts +99 -0
  132. package/src/lib/throttle.ts +70 -0
  133. package/src/lib/timings.ts +93 -0
  134. package/src/lib/types.ts +99 -0
  135. package/src/lib/url.ts +14 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/process.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,MAAM,oBAAoB,CAAC;AAK5B,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAIxC,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,OAAO;IACvB,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IAC9B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAID,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,KAAK,GAAI,GAAG,MAAM,UAAU,CAAC,OAAO,aAAa,CAAC,KAAG,OAAO,CAAC,WAAW,CACvD,CAAC;AAE/B,MAAM,WAAW,UAAU;IAC1B,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,GACrB,SAAS,MAAM,EACf,OAAM,aAAa,CAAC,MAAM,CAAM,EAChC,UAAU,YAAY,KACpB,OAAO,CAAC,UAAU,CAYpB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACzB,SAAS,MAAM,EACf,OAAM,aAAa,CAAC,MAAM,CAAM,EAChC,UAAU,YAAY,KACpB,cAUF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,OAAO,YAAY,KAAG,MACwC,CAAC;AAEnG;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,GAAG,CAAC,YAAY,CAAa,CAAC;AAEzD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAAI,OAAO,YAAY,KAAG,CAAC,MAAM,IAAI,CAWtE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,OAAO,GAAI,OAAO,YAAY,KAAG,OAAO,CAAC,WAAW,CAShE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW,QAAO,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CACQ,CAAC;AAElE;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,GACzC,iBAAiB,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,uBAAuB,KAAK,MAAM,GAAG,IAAI,EACtF,iBAAiB,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,uBAAuB,KAAK,MAAM,GAAG,IAAI,EACtF,eAAc,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,uBAAuB,KAAK,IACtD,KACd,IAYF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,WAAW,KAAG,MAKxD,CAAC;AAGF,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,yBAAyB,GACrC,SAAS,MAAM,EACf,OAAM,aAAa,CAAC,MAAM,CAAM,EAChC,UAAU,YAAY,KACpB,kBAuBF,CAAC"}
@@ -0,0 +1,148 @@
1
+ import { spawn as spawn_child_process, } from 'node:child_process';
2
+ import { styleText as st } from 'node:util';
3
+ import { Logger } from './log.js';
4
+ import { print_error, print_key_value } from './print.js';
5
+ const log = new Logger('process');
6
+ /**
7
+ * A convenient promise wrapper around `spawn_process`
8
+ * intended for commands that have an end, not long running-processes like watchers.
9
+ * Any more advanced usage should use `spawn_process` directly for access to the `child` process.
10
+ */
11
+ export const spawn = (...args) => spawn_process(...args).closed;
12
+ /**
13
+ * Similar to `spawn` but buffers and returns `stdout` and `stderr` as strings.
14
+ */
15
+ export const spawn_out = async (command, args = [], options) => {
16
+ const { child, closed } = spawn_process(command, args, { ...options, stdio: 'pipe' });
17
+ let stdout = null;
18
+ child.stdout.on('data', (data) => {
19
+ stdout = (stdout ?? '') + data.toString();
20
+ });
21
+ let stderr = null;
22
+ child.stderr.on('data', (data) => {
23
+ stderr = (stderr ?? '') + data.toString();
24
+ });
25
+ const result = await closed;
26
+ return { result, stdout, stderr };
27
+ };
28
+ /**
29
+ * Wraps the normal Node `childProcess.spawn` with graceful child shutdown behavior.
30
+ * Also returns a convenient `closed` promise.
31
+ * If you only need `closed`, prefer the shorthand function `spawn`.
32
+ * @mutates global_spawn calls `register_global_spawn()` which adds to the module-level Set
33
+ */
34
+ export const spawn_process = (command, args = [], options) => {
35
+ let resolve;
36
+ const closed = new Promise((r) => (resolve = r));
37
+ const child = spawn_child_process(command, args, { stdio: 'inherit', ...options });
38
+ const unregister = register_global_spawn(child);
39
+ child.once('close', (code, signal) => {
40
+ unregister();
41
+ resolve(code ? { ok: false, child, code, signal } : { ok: true, child, code, signal });
42
+ });
43
+ return { closed, child };
44
+ };
45
+ export const print_child_process = (child) => `${st('gray', 'pid(')}${child.pid}${st('gray', ')')} ← ${st('green', child.spawnargs.join(' '))}`;
46
+ /**
47
+ * We register spawned processes gloabally so we can gracefully exit child processes.
48
+ * Otherwise, errors can cause zombie processes, sometimes blocking ports even!
49
+ */
50
+ export const global_spawn = new Set();
51
+ /**
52
+ * Returns a function that unregisters the `child`.
53
+ * @param child the child process to register
54
+ * @returns cleanup function that removes the child from `global_spawn`
55
+ * @mutates global_spawn adds child to the module-level Set, and the returned function removes it
56
+ */
57
+ export const register_global_spawn = (child) => {
58
+ if (global_spawn.has(child)) {
59
+ log.error(st('red', 'already registered global spawn:'), print_child_process(child));
60
+ }
61
+ global_spawn.add(child);
62
+ return () => {
63
+ if (!global_spawn.has(child)) {
64
+ log.error(st('red', 'spawn not registered:'), print_child_process(child));
65
+ }
66
+ global_spawn.delete(child);
67
+ };
68
+ };
69
+ /**
70
+ * Kills a child process and returns a `SpawnResult`.
71
+ */
72
+ export const despawn = (child) => {
73
+ let resolve;
74
+ const closed = new Promise((r) => (resolve = r));
75
+ log.debug('despawning', print_child_process(child));
76
+ child.once('close', (code, signal) => {
77
+ resolve(code ? { ok: false, child, code, signal } : { ok: true, child, code, signal });
78
+ });
79
+ child.kill();
80
+ return closed;
81
+ };
82
+ /**
83
+ * Kills all globally registered child processes.
84
+ * @mutates global_spawn indirectly removes processes through `despawn()` calls
85
+ */
86
+ export const despawn_all = () => Promise.all(Array.from(global_spawn, (child) => despawn(child)));
87
+ /**
88
+ * Attaches the `'uncoughtException'` event to despawn all processes,
89
+ * and enables custom error logging with `to_error_label`.
90
+ * @param to_error_label - Customize the error label or return `null` for the default `origin`.
91
+ * @param map_error_text - Customize the error text. Return `''` to silence, or `null` for the default `print_error(err)`.
92
+ */
93
+ export const attach_process_error_handlers = (to_error_label, map_error_text, handle_error = () => process.exit(1)) => {
94
+ process.on('uncaughtException', async (err, origin) => {
95
+ const label = to_error_label?.(err, origin) ?? origin;
96
+ if (label) {
97
+ const error_text = map_error_text?.(err, origin) ?? print_error(err);
98
+ if (error_text) {
99
+ new Logger(label).error(error_text);
100
+ }
101
+ }
102
+ await despawn_all();
103
+ handle_error(err, origin);
104
+ });
105
+ };
106
+ /**
107
+ * Formats a `SpawnResult` for printing.
108
+ */
109
+ export const print_spawn_result = (result) => {
110
+ if (result.ok)
111
+ return 'ok';
112
+ let text = result.code === null ? '' : print_key_value('code', result.code);
113
+ if (result.signal !== null)
114
+ text += (text ? ' ' : '') + print_key_value('signal', result.signal);
115
+ return text;
116
+ };
117
+ /**
118
+ * Like `spawn_process` but with `restart` and `kill`,
119
+ * handling many concurrent `restart` calls gracefully.
120
+ */
121
+ export const spawn_restartable_process = (command, args = [], options) => {
122
+ let spawned = null;
123
+ let restarting = null;
124
+ const close = async () => {
125
+ if (!spawned)
126
+ return;
127
+ restarting = spawned.closed;
128
+ spawned.child.kill();
129
+ spawned = null;
130
+ await restarting;
131
+ restarting = null;
132
+ };
133
+ const restart = async () => {
134
+ if (restarting)
135
+ return restarting;
136
+ if (spawned)
137
+ await close();
138
+ spawned = spawn_process(command, args, { stdio: 'inherit', ...options });
139
+ };
140
+ const kill = async () => {
141
+ if (restarting)
142
+ await restarting;
143
+ await close();
144
+ };
145
+ // Start immediately -- it sychronously starts the process so there's no need to await.
146
+ void restart();
147
+ return { restart, kill };
148
+ };
@@ -0,0 +1,25 @@
1
+ import type { ArrayElement } from './types.js';
2
+ /**
3
+ * Generates a random `number` between `min` and `max`.
4
+ */
5
+ export declare const random_float: (min: number, max: number, random?: () => number) => number;
6
+ /**
7
+ * Returns a random integer between `min` and `max` inclusive.
8
+ * Node's `randomInt` is similar but exclusive of the max value, and makes `min` optional -
9
+ * https://nodejs.org/docs/latest-v20.x/api/crypto.html#cryptorandomintmin-max-callback
10
+ */
11
+ export declare const random_int: (min: number, max: number, random?: () => number) => number;
12
+ /**
13
+ * Generates a random `boolean`.
14
+ */
15
+ export declare const random_boolean: (random?: () => number) => boolean;
16
+ /**
17
+ * Selects a random item from an array.
18
+ */
19
+ export declare const random_item: <T extends ReadonlyArray<any>>(arr: T, random?: () => number) => ArrayElement<T>;
20
+ /**
21
+ * Mutates `array` with random ordering.
22
+ * @mutates array randomly reorders elements in place using Fisher-Yates shuffle
23
+ */
24
+ export declare const shuffle: <T extends Array<any>>(array: T, random?: typeof random_int) => T;
25
+ //# sourceMappingURL=random.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/random.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,YAAY,CAAC;AAE7C;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,qBAAoB,KAAG,MACjD,CAAC;AAE9B;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,qBAAoB,KAAG,MAC/B,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,qBAAoB,KAAG,OAAyB,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,aAAa,CAAC,GAAG,CAAC,EACvD,KAAK,CAAC,EACN,qBAAoB,KAClB,YAAY,CAAC,CAAC,CAA+C,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,OAAO,UAAU,KAAK,CAcrF,CAAC"}
package/dist/random.js ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Generates a random `number` between `min` and `max`.
3
+ */
4
+ export const random_float = (min, max, random = Math.random) => random() * (max - min) + min;
5
+ /**
6
+ * Returns a random integer between `min` and `max` inclusive.
7
+ * Node's `randomInt` is similar but exclusive of the max value, and makes `min` optional -
8
+ * https://nodejs.org/docs/latest-v20.x/api/crypto.html#cryptorandomintmin-max-callback
9
+ */
10
+ export const random_int = (min, max, random = Math.random) => Math.floor(random() * (max - min + 1)) + min;
11
+ /**
12
+ * Generates a random `boolean`.
13
+ */
14
+ export const random_boolean = (random = Math.random) => random() > 0.5;
15
+ /**
16
+ * Selects a random item from an array.
17
+ */
18
+ export const random_item = (arr, random = Math.random) => arr[random_int(0, arr.length - 1, random)];
19
+ /**
20
+ * Mutates `array` with random ordering.
21
+ * @mutates array randomly reorders elements in place using Fisher-Yates shuffle
22
+ */
23
+ export const shuffle = (array, random = random_int) => {
24
+ const { length } = array;
25
+ const max = length - 1;
26
+ for (let i = 0; i < length; i++) {
27
+ const index = random(0, max);
28
+ if (i === index)
29
+ continue;
30
+ const item = array[index];
31
+ array[index] = array[i];
32
+ array[i] = item;
33
+ }
34
+ return array;
35
+ };
@@ -0,0 +1,23 @@
1
+ export interface Alea {
2
+ (): number;
3
+ uint32: () => number;
4
+ fract53: () => number;
5
+ version: string;
6
+ seeds: Array<unknown>;
7
+ }
8
+ /**
9
+ * Seeded pseudo-random number generator.
10
+ * DO NOT USE when security matters, use webcrypto APIs instead.
11
+ *
12
+ * @see http://baagoe.com/en/RandomMusings/javascript/
13
+ * @see https://github.com/nquinlan/better-random-numbers-for-javascript-mirror
14
+ */
15
+ export declare const create_random_alea: (...seed: Array<unknown>) => Alea;
16
+ type Mash = (data: any) => number;
17
+ /**
18
+ * @source http://baagoe.com/en/RandomMusings/javascript/
19
+ * @copyright Johannes Baagøe <baagoe@baagoe.com>, 2010
20
+ */
21
+ export declare const masher: () => Mash;
22
+ export {};
23
+ //# sourceMappingURL=random_alea.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random_alea.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/random_alea.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,IAAI;IACpB,IAAI,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACtB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,KAAG,IAqC5D,CAAC;AAEF,KAAK,IAAI,GAAG,CAAC,IAAI,EAAE,GAAG,KAAK,MAAM,CAAC;AAElC;;;GAGG;AACH,eAAO,MAAM,MAAM,QAAO,IAgBzB,CAAC"}
@@ -0,0 +1,95 @@
1
+ /*
2
+
3
+ DO NOT USE when security matters, use webcrypto APIs instead.
4
+ This is the Alea pseudo-random number generator by Johannes Baagøe.
5
+
6
+ From http://baagoe.com/en/RandomMusings/javascript/
7
+ via https://github.com/nquinlan/better-random-numbers-for-javascript-mirror
8
+
9
+ Copyright (C) 2010 by Johannes Baagøe <baagoe@baagoe.org>
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in
19
+ all copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
+ THE SOFTWARE.
28
+
29
+ */
30
+ /**
31
+ * Seeded pseudo-random number generator.
32
+ * DO NOT USE when security matters, use webcrypto APIs instead.
33
+ *
34
+ * @see http://baagoe.com/en/RandomMusings/javascript/
35
+ * @see https://github.com/nquinlan/better-random-numbers-for-javascript-mirror
36
+ */
37
+ export const create_random_alea = (...seed) => {
38
+ let s0 = 0;
39
+ let s1 = 0;
40
+ let s2 = 0;
41
+ let c = 1;
42
+ const seeds = seed.length ? seed : [Date.now()];
43
+ let mash = masher();
44
+ s0 = mash(' ');
45
+ s1 = mash(' ');
46
+ s2 = mash(' ');
47
+ for (const s of seeds) {
48
+ s0 -= mash(s);
49
+ if (s0 < 0)
50
+ s0 += 1;
51
+ s1 -= mash(s);
52
+ if (s1 < 0)
53
+ s1 += 1;
54
+ s2 -= mash(s);
55
+ if (s2 < 0)
56
+ s2 += 1;
57
+ }
58
+ mash = null;
59
+ const random = () => {
60
+ const t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
61
+ s0 = s1;
62
+ s1 = s2;
63
+ return (s2 = t - (c = t | 0));
64
+ };
65
+ random.uint32 = () => {
66
+ return random() * 0x100000000; // 2^32
67
+ };
68
+ random.fract53 = () => {
69
+ return random() + ((random() * 0x200000) | 0) * 1.1102230246251565e-16; // 2^-53
70
+ };
71
+ random.version = 'Alea 0.9';
72
+ random.seeds = seeds;
73
+ return random;
74
+ };
75
+ /**
76
+ * @source http://baagoe.com/en/RandomMusings/javascript/
77
+ * @copyright Johannes Baagøe <baagoe@baagoe.com>, 2010
78
+ */
79
+ export const masher = () => {
80
+ let n = 0xefc8249d;
81
+ return (data) => {
82
+ const d = data + '';
83
+ for (let i = 0; i < d.length; i++) {
84
+ n += d.charCodeAt(i);
85
+ let h = 0.02519603282416938 * n;
86
+ n = h >>> 0;
87
+ h -= n;
88
+ h *= n;
89
+ n = h >>> 0;
90
+ h -= n;
91
+ n += h * 0x100000000; // 2^32
92
+ }
93
+ return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
94
+ };
95
+ };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Escapes a string for literal matching in a RegExp.
3
+ * @source https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/RegularExpressions
4
+ */
5
+ export declare const escape_regexp: (str: string) => string;
6
+ /**
7
+ * Reset a RegExp's lastIndex to 0 for global and sticky patterns.
8
+ * Ensures consistent behavior by clearing state that affects subsequent matches.
9
+ * @mutates regexp sets lastIndex to 0 if regexp is global or sticky
10
+ */
11
+ export declare const reset_regexp: <T extends RegExp>(regexp: T) => T;
12
+ //# sourceMappingURL=regexp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regexp.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/regexp.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,MAAoD,CAAC;AAEjG;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,MAAM,EAAE,QAAQ,CAAC,KAAG,CAK1D,CAAC"}
package/dist/regexp.js ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Escapes a string for literal matching in a RegExp.
3
+ * @source https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/RegularExpressions
4
+ */
5
+ export const escape_regexp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
6
+ /**
7
+ * Reset a RegExp's lastIndex to 0 for global and sticky patterns.
8
+ * Ensures consistent behavior by clearing state that affects subsequent matches.
9
+ * @mutates regexp sets lastIndex to 0 if regexp is global or sticky
10
+ */
11
+ export const reset_regexp = (regexp) => {
12
+ if (regexp.global || regexp.sticky) {
13
+ regexp.lastIndex = 0;
14
+ }
15
+ return regexp;
16
+ };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * An alternative pattern to throwing and catching errors.
3
+ * Uses the type system to strongly type error return values when desired.
4
+ * Catching errors is then reserved for unexpected situations.
5
+ */
6
+ export type Result<TValue = object, TError = object> = ({
7
+ ok: true;
8
+ } & TValue) | ({
9
+ ok: false;
10
+ } & TError);
11
+ /**
12
+ * Frozen object representing a successful result.
13
+ */
14
+ export declare const OK: Readonly<{
15
+ readonly ok: true;
16
+ }>;
17
+ /**
18
+ * Frozen object representing a failed result.
19
+ */
20
+ export declare const NOT_OK: Readonly<{
21
+ readonly ok: false;
22
+ }>;
23
+ /**
24
+ * A helper that says,
25
+ * "hey I know this is wrapped in a `Result`, but I expect it to be `ok`,
26
+ * so if it's not, I understand it will throw an error that wraps the result".
27
+ * @param result Some `Result` object.
28
+ * @param message Optional custom error message.
29
+ * @returns The wrapped value.
30
+ */
31
+ export declare const unwrap: <TValue extends {
32
+ value?: unknown;
33
+ }, TError extends {
34
+ message?: string;
35
+ }>(result: Result<TValue, TError>, message?: string) => TValue["value"];
36
+ /**
37
+ * A custom error class that's thrown by `unwrap`.
38
+ * Wraps a failed `Result` with an optional message,
39
+ * and also accepts an optional message that overrides the result's.
40
+ * Useful for generic handling of unwrapped results
41
+ * to forward custom messages and other failed result data.
42
+ */
43
+ export declare class ResultError extends Error {
44
+ static DEFAULT_MESSAGE: string;
45
+ readonly result: {
46
+ ok: false;
47
+ message?: string;
48
+ };
49
+ constructor(result: {
50
+ ok: false;
51
+ message?: string;
52
+ }, message?: string, options?: ErrorOptions);
53
+ }
54
+ /**
55
+ * A helper that does the opposite of `unwrap`, throwing if the `Result` is ok.
56
+ * Note that while `unwrap` returns the wrapped `value`, `unwrap_error` returns the entire result.
57
+ * @param result Some `Result` object.
58
+ * @param message Optional custom error message.
59
+ * @returns The type-narrowed result.
60
+ */
61
+ export declare const unwrap_error: <TError extends object>(result: Result<object, TError>, message?: string) => {
62
+ ok: false;
63
+ } & TError;
64
+ //# sourceMappingURL=result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/result.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,GAAG,MAAM,IAChD,CAAC;IAAC,EAAE,EAAE,IAAI,CAAA;CAAC,GAAG,MAAM,CAAC,GACrB,CAAC;IAAC,EAAE,EAAE,KAAK,CAAA;CAAC,GAAG,MAAM,CAAC,CAAC;AAE1B;;GAEG;AACH,eAAO,MAAM,EAAE;;EAAqC,CAAC;AAErD;;GAEG;AACH,eAAO,MAAM,MAAM;;EAAsC,CAAC;AAE1D;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,GAAI,MAAM,SAAS;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAC,EAAE,MAAM,SAAS;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAC,EACzF,QAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,UAAU,MAAM,KACd,MAAM,CAAC,OAAO,CAGhB,CAAC;AAEF;;;;;;GAMG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACrC,MAAM,CAAC,eAAe,SAAmB;IAEzC,QAAQ,CAAC,MAAM,EAAE;QAAC,EAAE,EAAE,KAAK,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC;gBAEnC,MAAM,EAAE;QAAC,EAAE,EAAE,KAAK,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAI3F;AAED;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,MAAM,EACjD,QAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,gBAAyC,KACvC;IAAC,EAAE,EAAE,KAAK,CAAA;CAAC,GAAG,MAGhB,CAAC"}
package/dist/result.js ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Frozen object representing a successful result.
3
+ */
4
+ export const OK = Object.freeze({ ok: true });
5
+ /**
6
+ * Frozen object representing a failed result.
7
+ */
8
+ export const NOT_OK = Object.freeze({ ok: false });
9
+ /**
10
+ * A helper that says,
11
+ * "hey I know this is wrapped in a `Result`, but I expect it to be `ok`,
12
+ * so if it's not, I understand it will throw an error that wraps the result".
13
+ * @param result Some `Result` object.
14
+ * @param message Optional custom error message.
15
+ * @returns The wrapped value.
16
+ */
17
+ export const unwrap = (result, message) => {
18
+ if (!result.ok)
19
+ throw new ResultError(result, message);
20
+ return result.value;
21
+ };
22
+ /**
23
+ * A custom error class that's thrown by `unwrap`.
24
+ * Wraps a failed `Result` with an optional message,
25
+ * and also accepts an optional message that overrides the result's.
26
+ * Useful for generic handling of unwrapped results
27
+ * to forward custom messages and other failed result data.
28
+ */
29
+ export class ResultError extends Error {
30
+ static DEFAULT_MESSAGE = 'unknown error';
31
+ result;
32
+ constructor(result, message, options) {
33
+ super(message ?? result.message ?? ResultError.DEFAULT_MESSAGE, options);
34
+ this.result = result;
35
+ }
36
+ }
37
+ /**
38
+ * A helper that does the opposite of `unwrap`, throwing if the `Result` is ok.
39
+ * Note that while `unwrap` returns the wrapped `value`, `unwrap_error` returns the entire result.
40
+ * @param result Some `Result` object.
41
+ * @param message Optional custom error message.
42
+ * @returns The type-narrowed result.
43
+ */
44
+ export const unwrap_error = (result, message = 'Failed to unwrap result error') => {
45
+ if (result.ok)
46
+ throw Error(message);
47
+ return result;
48
+ };