instrumentality 0.0.7 → 0.0.9
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.
- package/README.md +3 -5
- package/dist/base.d.ts +11 -12
- package/dist/base.d.ts.map +1 -1
- package/dist/base.js +23 -39
- package/dist/dom.d.ts +1 -6
- package/dist/dom.d.ts.map +1 -1
- package/dist/dom.js +1 -6
- package/dist/road.d.ts +121 -103
- package/dist/road.d.ts.map +1 -1
- package/dist/road.js +401 -388
- package/package.json +5 -3
- package/src/base.ts +22 -43
- package/src/dom.ts +1 -10
- package/src/road.ts +352 -426
package/package.json
CHANGED
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
"url": "https://github.com/clerkburk/instrumentality.git"
|
|
6
6
|
},
|
|
7
7
|
"type": "module",
|
|
8
|
-
"version": "0.0.
|
|
8
|
+
"version": "0.0.9",
|
|
9
9
|
"main": "./dist/base.js",
|
|
10
10
|
"types": "./dist/base.d.ts",
|
|
11
11
|
"devDependencies": {
|
|
12
12
|
"@types/node": "^26.1.1",
|
|
13
|
-
"
|
|
13
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
14
|
+
"typescript": "^7.0.2",
|
|
15
|
+
"vitest": "^4.1.11"
|
|
14
16
|
},
|
|
15
17
|
"exports": {
|
|
16
18
|
".": {
|
|
@@ -36,6 +38,6 @@
|
|
|
36
38
|
"prepublishOnly": "npm run build",
|
|
37
39
|
"prepare": "npm run build",
|
|
38
40
|
"test": "vitest run",
|
|
39
|
-
"test:watch": "vitest"
|
|
41
|
+
"test:watch": "vitest watch"
|
|
40
42
|
}
|
|
41
43
|
}
|
package/src/base.ts
CHANGED
|
@@ -1,61 +1,41 @@
|
|
|
1
1
|
/** Subclass of {@link Error} that represents an error thrown from this library, providing a specific name for easier identification. */
|
|
2
|
-
export class
|
|
3
|
-
|
|
2
|
+
export class Err extends Error { override name = "Instrumentality-Error" }
|
|
3
|
+
export { Err as InsErr }
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Retries a function multiple times
|
|
8
|
+
* Retries a function multiple times until it succeeds or the maximum number of attempts is reached, or the error callback indicates to stop.
|
|
9
9
|
*
|
|
10
10
|
* @param fn_ - The function to be retried.
|
|
11
11
|
* @param maxAttempts_ - The maximum number of attempts to execute the function.
|
|
12
|
-
* @param cbErr_ - An optional callback function to
|
|
13
|
-
* @param abs_ - An optional AbortSignal to abort the retry process.
|
|
12
|
+
* @param cbErr_ - An optional callback function that is invoked when an error occurs. It receives the error and the remaining number of attempts as arguments and should return `true` to continue retrying or `false` to stop.
|
|
14
13
|
* @returns The result of {@link fn_} if it succeeds within the allowed attempts.
|
|
15
|
-
* @throws
|
|
16
|
-
* @throws
|
|
14
|
+
* @throws the last error thrown by {@link fn_} if it fails after the maximum attempts or if the error callback indicates to stop.
|
|
15
|
+
* @throws If {@link cbErr_} throws or returns a rejected promise, the error is propagated immediately.
|
|
16
|
+
* @throws {InsErr} If {@link maxAttempts_} isn't a positive integer.
|
|
17
17
|
*/
|
|
18
|
-
export async function retry<T>(fn_: () => T
|
|
19
|
-
|
|
18
|
+
export async function retry<T>(fn_: () => T | PromiseLike<T>, maxAttempts_: number, cbErr_?: (err: unknown, remainingAttempts: number) => boolean | PromiseLike<boolean>): Promise<T> {
|
|
19
|
+
if (!Number.isInteger(maxAttempts_) || maxAttempts_ < 1)
|
|
20
|
+
throw new Err("Max attempts isn't a positive integer")
|
|
21
|
+
while (true)
|
|
20
22
|
try {
|
|
21
23
|
return await fn_()
|
|
22
24
|
} catch (err: unknown) {
|
|
23
|
-
if (maxAttempts_ <= 0)
|
|
25
|
+
if (--maxAttempts_ <= 0 || (cbErr_ && !(await cbErr_(err, maxAttempts_))))
|
|
24
26
|
throw err
|
|
25
|
-
await cbErr_?.()
|
|
26
27
|
}
|
|
27
|
-
if (maxAttempts_ < 0)
|
|
28
|
-
throw new InsErr("Max attempts must be at least 1")
|
|
29
|
-
else
|
|
30
|
-
throw new InsErr("Operation aborted")
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
|
|
34
31
|
|
|
35
32
|
/**
|
|
36
|
-
*
|
|
33
|
+
* Alias for `setTimeout`.
|
|
37
34
|
*
|
|
38
35
|
* @param ms_ - The number of milliseconds to sleep.
|
|
39
|
-
* @
|
|
40
|
-
* @throws {InsErr} If the sleep is aborted before or during the wait.
|
|
36
|
+
* @remarks The delay is a minimum, not an exact duration. The actual elapsed time also includes timer scheduling, event-loop latency, and promise-continuation overhead, so it may exceed {@link ms_}, especially for short delays.
|
|
41
37
|
*/
|
|
42
|
-
export
|
|
43
|
-
if (abs_?.aborted)
|
|
44
|
-
return Promise.reject(new InsErr("Sleep aborted before start"))
|
|
45
|
-
return new Promise((resolve, reject) => {
|
|
46
|
-
const timeout = setTimeout(() => {
|
|
47
|
-
abs_?.removeEventListener("abort", onAbort)
|
|
48
|
-
resolve()
|
|
49
|
-
}, ms_)
|
|
50
|
-
|
|
51
|
-
function onAbort() {
|
|
52
|
-
clearTimeout(timeout)
|
|
53
|
-
abs_?.removeEventListener("abort", onAbort)
|
|
54
|
-
reject(new InsErr("Sleep aborted during wait"))
|
|
55
|
-
}
|
|
56
|
-
abs_?.addEventListener("abort", onAbort, { once: true })
|
|
57
|
-
})
|
|
58
|
-
}
|
|
38
|
+
export function sleep(ms_: number): Promise<void> { return new Promise<void>(r => setTimeout(r, ms_)) }
|
|
59
39
|
|
|
60
40
|
|
|
61
41
|
|
|
@@ -202,12 +182,12 @@ export const BASE122_SHORT = 0b111 as const
|
|
|
202
182
|
*
|
|
203
183
|
* @param data_ - An array-like object containing the data to be encoded.
|
|
204
184
|
* @returns A string representing the base-122 encoded data.
|
|
205
|
-
* @throws If somehow malformed UTF-8 data is generated, the {@link TextDecoder} will throw an error (shouldn't happen if the input is valid).
|
|
206
185
|
* @remarks The high density might not be suitable for all use cases, especially if the medium used to transmit the data has limitations on character sets or encoding.
|
|
207
186
|
* @see {@link TextDecoder} how the output string is generated from the byte array (this step is necessary for accurate translation to a string).
|
|
208
187
|
*/
|
|
209
188
|
export function encode122(data_: ArrayLike<number>): string {
|
|
210
|
-
const out
|
|
189
|
+
const out = new Uint8Array(2 * Math.ceil(data_.length * 8 / 7))
|
|
190
|
+
let outIndex = 0
|
|
211
191
|
let byteIndex = 0
|
|
212
192
|
let bitIndex = 0
|
|
213
193
|
|
|
@@ -230,17 +210,16 @@ export function encode122(data_: ArrayLike<number>): string {
|
|
|
230
210
|
for (let value = next7(); value !== undefined; value = next7()) {
|
|
231
211
|
const illegalIndex = BASE122_ILLEGAL_INDEX[value]
|
|
232
212
|
if (illegalIndex === undefined)
|
|
233
|
-
out
|
|
213
|
+
out[outIndex++] = value
|
|
234
214
|
else {
|
|
235
215
|
const next = next7()
|
|
236
216
|
const payload = next ?? value
|
|
237
|
-
out
|
|
217
|
+
out[outIndex++] =
|
|
238
218
|
0b11000010 | ((next === undefined ? BASE122_SHORT : illegalIndex) << 2) | (payload >>> 6),
|
|
239
|
-
|
|
240
|
-
)
|
|
219
|
+
out[outIndex++] = 0b10000000 | (payload & 0b00111111)
|
|
241
220
|
}
|
|
242
221
|
}
|
|
243
|
-
return new TextDecoder("utf-8", { fatal: true }).decode(
|
|
222
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(out.subarray(0, outIndex))
|
|
244
223
|
}
|
|
245
224
|
|
|
246
225
|
|
|
@@ -278,7 +257,7 @@ export function decode122(base122_: string) {
|
|
|
278
257
|
if (illegalIndex < BASE122_ILLEGAL.length)
|
|
279
258
|
push7(BASE122_ILLEGAL[illegalIndex]!)
|
|
280
259
|
else if (illegalIndex !== BASE122_SHORT)
|
|
281
|
-
throw new
|
|
260
|
+
throw new Err(`Invalid base-122 illegal index ${illegalIndex} at position ${i}`)
|
|
282
261
|
push7(code & 0b01111111)
|
|
283
262
|
}
|
|
284
263
|
|
package/src/dom.ts
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
import * as bs from "./base.ts"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
/** Subclass of {@link bs.InsErr} that represents an error thrown from this specific module of the library */
|
|
6
|
-
export class DomErr extends bs.InsErr { override name = "Instrumentality-DOM-Error" }
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
1
|
/**
|
|
11
2
|
* Resolves on `DOMContentLoaded` or immediately if the document is already ready.
|
|
12
3
|
*/
|
|
@@ -37,7 +28,7 @@ export function byId<T extends HTMLElement>(id_: string, type_: new () => T): T
|
|
|
37
28
|
* Typed accessor for {@link document.getElementsByClassName}
|
|
38
29
|
*
|
|
39
30
|
* @param className_ - The class name of the elements to retrieve.
|
|
40
|
-
* @param type_ -
|
|
31
|
+
* @param type_ - The constructor function for the expected element type.
|
|
41
32
|
* @returns All elements with the specified class name and type.
|
|
42
33
|
*/
|
|
43
34
|
export function byClass<T extends HTMLElement>(className_: string, type_: new () => T): T[] {
|