instrumentality 0.0.3 → 0.0.4
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 +2 -2
- package/dist/base.d.ts +30 -47
- package/dist/base.d.ts.map +1 -1
- package/dist/base.js +29 -44
- package/dist/dom.d.ts +19 -28
- package/dist/dom.d.ts.map +1 -1
- package/dist/dom.js +26 -41
- package/dist/road.d.ts +218 -178
- package/dist/road.d.ts.map +1 -1
- package/dist/road.js +448 -472
- package/package.json +1 -1
- package/src/base.ts +33 -50
- package/src/dom.ts +29 -44
- package/src/road.ts +500 -525
package/package.json
CHANGED
package/src/base.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Subclass of {@link Error} that represents an error thrown from this library, providing a specific name for easier identification.
|
|
3
|
-
*/
|
|
1
|
+
/** Subclass of {@link Error} that represents an error thrown from this library, providing a specific name for easier identification. */
|
|
4
2
|
export class InsErr extends Error { override name = "Instrumentality-Error" }
|
|
5
3
|
|
|
6
4
|
|
|
@@ -11,22 +9,23 @@ export class InsErr extends Error { override name = "Instrumentality-Error" }
|
|
|
11
9
|
*
|
|
12
10
|
* @param fn_ - The function to be retried.
|
|
13
11
|
* @param maxAttempts_ - The maximum number of attempts to execute the function.
|
|
14
|
-
* @param
|
|
12
|
+
* @param cbErr_ - An optional callback function to be executed after each failed attempt.
|
|
15
13
|
* @param abs_ - An optional AbortSignal to abort the retry process.
|
|
16
|
-
* @returns The result of
|
|
17
|
-
* @throws If the maximum
|
|
14
|
+
* @returns The result of {@link fn_} if it succeeds within the allowed attempts.
|
|
15
|
+
* @throws {unknown} If {@link fn_} fails after the maximum attempts, the last error thrown by {@link fn_} is re-thrown.
|
|
16
|
+
* @throws {InsErr} If the maximum attempts is less than 1 or if the operation is aborted.
|
|
18
17
|
*/
|
|
19
|
-
export async function retry<T>(fn_: () => T, maxAttempts_: number,
|
|
18
|
+
export async function retry<T>(fn_: () => T, maxAttempts_: number, cbErr_?: () => unknown, abs_?: AbortSignal): Promise<T> {
|
|
20
19
|
while (--maxAttempts_ >= 0 && !(abs_?.aborted ?? false))
|
|
21
20
|
try {
|
|
22
21
|
return await fn_()
|
|
23
22
|
} catch (err: unknown) {
|
|
24
|
-
if (maxAttempts_
|
|
23
|
+
if (maxAttempts_ <= 0)
|
|
25
24
|
throw err
|
|
26
|
-
await
|
|
25
|
+
await cbErr_?.()
|
|
27
26
|
}
|
|
28
27
|
if (maxAttempts_ < 0)
|
|
29
|
-
throw new InsErr("Max attempts
|
|
28
|
+
throw new InsErr("Max attempts must be at least 1")
|
|
30
29
|
else
|
|
31
30
|
throw new InsErr("Operation aborted")
|
|
32
31
|
}
|
|
@@ -34,11 +33,11 @@ export async function retry<T>(fn_: () => T, maxAttempts_: number, _cbErr?: () =
|
|
|
34
33
|
|
|
35
34
|
|
|
36
35
|
/**
|
|
37
|
-
* Asynchronously
|
|
36
|
+
* Asynchronously sleep.
|
|
38
37
|
*
|
|
39
38
|
* @param ms_ - The number of milliseconds to sleep.
|
|
40
39
|
* @param abs_ - An optional AbortSignal to abort the sleep.
|
|
41
|
-
* @
|
|
40
|
+
* @throws {InsErr} If the sleep is aborted before or during the wait.
|
|
42
41
|
*/
|
|
43
42
|
export async function sleep(ms_: number, abs_?: AbortSignal): Promise<void> {
|
|
44
43
|
if (abs_?.aborted)
|
|
@@ -61,7 +60,7 @@ export async function sleep(ms_: number, abs_?: AbortSignal): Promise<void> {
|
|
|
61
60
|
|
|
62
61
|
|
|
63
62
|
/**
|
|
64
|
-
*
|
|
63
|
+
* Build a tuple of a specified length.
|
|
65
64
|
*
|
|
66
65
|
* @template N - The desired length of the tuple.
|
|
67
66
|
* @template T - The tuple being built (used for recursion).
|
|
@@ -71,7 +70,7 @@ type BuildTuple<N extends number, T extends number[] = []> =
|
|
|
71
70
|
|
|
72
71
|
|
|
73
72
|
/**
|
|
74
|
-
*
|
|
73
|
+
* Add two number types together.
|
|
75
74
|
*
|
|
76
75
|
* @template A - The first number type.
|
|
77
76
|
* @template B - The second number type.
|
|
@@ -81,7 +80,7 @@ export type Add<A extends number, B extends number> =
|
|
|
81
80
|
|
|
82
81
|
|
|
83
82
|
/**
|
|
84
|
-
*
|
|
83
|
+
* Enumerate numbers from 0 to N-1 as a union type.
|
|
85
84
|
*
|
|
86
85
|
* @template N - The upper limit (exclusive) for the enumeration.
|
|
87
86
|
* @template A - The accumulator array used for recursion.
|
|
@@ -92,31 +91,28 @@ A['length'] extends N ? A[number] : Enumerate<N, [...A, A['length']]>
|
|
|
92
91
|
|
|
93
92
|
|
|
94
93
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
* The class starts a timer upon instantiation and provides properties to access the elapsed time in different units (milliseconds, seconds, minutes, etc.).
|
|
98
|
-
* The `round` method can be called to record the current elapsed time and restart the timer.
|
|
94
|
+
* Wrapper around {@link performance.now}
|
|
99
95
|
*
|
|
100
96
|
* @property {@link rounds} - An array that stores the recorded elapsed times from each round.
|
|
101
97
|
* @property {@link timer} - The initial timestamp when the benchmark was created or last reset.
|
|
102
98
|
* @method {@link round} - Records the current elapsed time and restarts the timer.
|
|
103
99
|
* @method {@link reset} - Resets the benchmark timer to the current time and clears recorded rounds.
|
|
104
|
-
* @accessor {@link y}
|
|
105
|
-
* @accessor {@link mn}
|
|
106
|
-
* @accessor {@link w}
|
|
107
|
-
* @accessor {@link d}
|
|
108
|
-
* @accessor {@link h}
|
|
109
|
-
* @accessor {@link m}
|
|
110
|
-
* @accessor {@link s}
|
|
111
|
-
* @accessor {@link ms}
|
|
112
|
-
* @accessor {@link μs}
|
|
113
|
-
* @accessor {@link ns}
|
|
114
|
-
* @accessor {@link ps}
|
|
100
|
+
* @accessor {@link y} (years)
|
|
101
|
+
* @accessor {@link mn} (months)
|
|
102
|
+
* @accessor {@link w} (weeks)
|
|
103
|
+
* @accessor {@link d} (days)
|
|
104
|
+
* @accessor {@link h} (hours)
|
|
105
|
+
* @accessor {@link m} (minutes)
|
|
106
|
+
* @accessor {@link s} (seconds)
|
|
107
|
+
* @accessor {@link ms} (milliseconds)
|
|
108
|
+
* @accessor {@link μs} (microseconds)
|
|
109
|
+
* @accessor {@link ns} (nanoseconds)
|
|
110
|
+
* @accessor {@link ps} (picoseconds)
|
|
115
111
|
*/
|
|
116
112
|
export class Benchmark {
|
|
117
|
-
/** An array that stores the recorded elapsed times from each round. */
|
|
113
|
+
/** An array that stores the recorded elapsed times from each round (relative to the previous). */
|
|
118
114
|
rounds: number[] = []
|
|
119
|
-
/**
|
|
115
|
+
/** The initial timestamp when the benchmark was created or last reset. */
|
|
120
116
|
timer = performance.now()
|
|
121
117
|
/** Records the current elapsed time and restarts the timer. */
|
|
122
118
|
round() { this.rounds.push(this.ms); this.timer = performance.now() }
|
|
@@ -149,9 +145,7 @@ export { Benchmark as Bench, Benchmark as Timer, Benchmark as Stopwatch }
|
|
|
149
145
|
|
|
150
146
|
|
|
151
147
|
|
|
152
|
-
/**
|
|
153
|
-
* Helper type that represents a view of a Uint8Array, exposing only view methods and properties, along with a readonly index signature for accessing elements.
|
|
154
|
-
*/
|
|
148
|
+
/** Compiler sugar to hide mutating methods/properties for read-only operations (no runtime effect). */
|
|
155
149
|
export type Uint8ArrayView = Pick<Uint8Array,
|
|
156
150
|
| "at"
|
|
157
151
|
| "includes"
|
|
@@ -202,22 +196,13 @@ export const BASE122_SHORT = 0b111 as const
|
|
|
202
196
|
|
|
203
197
|
|
|
204
198
|
/**
|
|
205
|
-
* Encodes indexed data into a base-122 representation
|
|
206
|
-
* The encoding process packs 7 bits of data into each character, and uses a two-byte sequence for reserved characters to ensure that the output string remains valid.
|
|
199
|
+
* Encodes indexed data into a base-122 representation.
|
|
207
200
|
*
|
|
208
|
-
* @remarks The high density of base-122 comes with the trade-off of not being able to use the output string in certain contexts, such as URLs or file names.
|
|
209
201
|
* @param data_ - An array-like object containing the data to be encoded.
|
|
210
202
|
* @returns A string representing the base-122 encoded data.
|
|
211
|
-
* @throws If somehow malformed UTF-8 data is generated, the TextDecoder will throw an error (shouldn't happen if the input is valid).
|
|
212
|
-
* @
|
|
213
|
-
* @see {@link
|
|
214
|
-
* @example
|
|
215
|
-
* // (pseudo-code)
|
|
216
|
-
* // build script
|
|
217
|
-
* appendFile(".html", `<script type="text/plain">${encode122(compress(readFile(".jpg")))}</script>`)
|
|
218
|
-
*
|
|
219
|
-
* // HTML
|
|
220
|
-
* <script type="text/plain">!!pƋƸ²VӦnKZ6w)jpA</script> // embedd data into HTML without it being interpreted as HTML or JS
|
|
203
|
+
* @throws If somehow malformed UTF-8 data is generated, the {@link TextDecoder} will throw an error (shouldn't happen if the input is valid).
|
|
204
|
+
* @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.
|
|
205
|
+
* @see {@link TextDecoder} how the output string is generated from the byte array (this step is necessary for accurate translation to a string).
|
|
221
206
|
*/
|
|
222
207
|
export function encode122(data_: ArrayLike<number>): string {
|
|
223
208
|
const out: number[] = []
|
|
@@ -259,12 +244,10 @@ export function encode122(data_: ArrayLike<number>): string {
|
|
|
259
244
|
|
|
260
245
|
/**
|
|
261
246
|
* Decodes a base-122 encoded string back into its original byte representation.
|
|
262
|
-
* The decoding process reverses the encoding, extracting 7 bits of data from each character and handling two-byte sequences for illegal characters.
|
|
263
247
|
*
|
|
264
248
|
* @param base122_ - The base-122 encoded string to decode.
|
|
265
249
|
* @returns A Uint8Array containing the original byte data.
|
|
266
250
|
* @throws If an invalid base-122 illegal index is encountered during decoding (shouldn't happen if the input was generated by {@link encode122}).
|
|
267
|
-
* @see {@link encode122} for encoding data into base-122.
|
|
268
251
|
*/
|
|
269
252
|
export function decode122(base122_: string) {
|
|
270
253
|
const out: number[] = []
|
package/src/dom.ts
CHANGED
|
@@ -1,82 +1,67 @@
|
|
|
1
1
|
import * as bs from "./base.ts"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/** Subclass of {@link bs.InsErr} that represents an error thrown from this specific module of the library */
|
|
5
6
|
export class DomErr extends bs.InsErr { override name = "Instrumentality-DOM-Error" }
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* @returns A Promise that resolves when the DOM is ready.
|
|
11
|
+
* Resolves on `DOMContentLoaded` or immediately if the document is already ready.
|
|
13
12
|
*/
|
|
14
13
|
export async function onceReady(): Promise<void> {
|
|
15
14
|
if (document.readyState === "complete" || document.readyState === "interactive")
|
|
16
|
-
return
|
|
15
|
+
return
|
|
17
16
|
return new Promise(r => document.addEventListener("DOMContentLoaded", () => r(), { once: true }))
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
|
-
*
|
|
22
|
+
* Typed accessor for {@link document.getElementById}
|
|
24
23
|
*
|
|
25
|
-
* @param id_ - The ID of the
|
|
26
|
-
* @param
|
|
27
|
-
* @returns The
|
|
28
|
-
* @throws Will throw an error if the element is not found or does not match the expected type.
|
|
24
|
+
* @param id_ - The ID of the element to retrieve.
|
|
25
|
+
* @param type_ - Expected type, defaults to {@link HTMLElement}.
|
|
26
|
+
* @returns The corresponding element if found and of the expected type, otherwise `null`.
|
|
29
27
|
*/
|
|
30
|
-
export function byId<T extends HTMLElement>(id_: string,
|
|
28
|
+
export function byId<T extends HTMLElement>(id_: string, type_: new () => T): T | null {
|
|
31
29
|
const element = document.getElementById(id_)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return element as T
|
|
30
|
+
if (element instanceof type_)
|
|
31
|
+
return element
|
|
32
|
+
return null
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
|
|
39
36
|
/**
|
|
40
|
-
*
|
|
37
|
+
* Typed accessor for {@link document.getElementsByClassName}
|
|
41
38
|
*
|
|
42
39
|
* @param className_ - The class name of the elements to retrieve.
|
|
43
|
-
* @param
|
|
44
|
-
* @returns
|
|
45
|
-
* @throws Will throw an error if any element does not match the expected type.
|
|
40
|
+
* @param type_ - An optional constructor function for the expected element type.
|
|
41
|
+
* @returns All elements with the specified class name and type.
|
|
46
42
|
*/
|
|
47
|
-
export function byClass<T extends HTMLElement>(className_: string,
|
|
48
|
-
return
|
|
49
|
-
const typeCtor = elementType_ ?? HTMLElement
|
|
50
|
-
if (!(element instanceof typeCtor))
|
|
51
|
-
throw new DomErr(`Type missmatch: Element at index ${index} with class '${className_}' is not of type ${typeCtor.name}`)
|
|
52
|
-
return element as T
|
|
53
|
-
})
|
|
43
|
+
export function byClass<T extends HTMLElement>(className_: string, type_: new () => T): T[] {
|
|
44
|
+
return [...document.getElementsByClassName(className_)].filter((el): el is T => el instanceof type_)
|
|
54
45
|
}
|
|
55
46
|
|
|
56
47
|
|
|
57
48
|
/**
|
|
58
|
-
*
|
|
49
|
+
* Typed accessor for {@link document.getElementsByTagName}
|
|
59
50
|
*
|
|
60
|
-
* @param
|
|
51
|
+
* @param tag_ - The HTML tag name of the elements to retrieve.
|
|
52
|
+
* @returns An array of {@link HTMLElement}s with the specified tag name.
|
|
61
53
|
*/
|
|
62
|
-
export function byTag<K extends keyof HTMLElementTagNameMap>(
|
|
63
|
-
return
|
|
54
|
+
export function byTag<K extends keyof HTMLElementTagNameMap>(tag_: K): HTMLElementTagNameMap[K][] {
|
|
55
|
+
return [...document.getElementsByTagName(tag_)]
|
|
64
56
|
}
|
|
65
57
|
|
|
66
58
|
|
|
67
59
|
|
|
68
|
-
/**
|
|
69
|
-
* Regular expression to match cookie name-value pairs in a cookie string.
|
|
70
|
-
*/
|
|
71
|
-
export const COOKIE_PAIR_REGEX = /(?:^|; )([^=;]+)=([^;]*)/g
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
60
|
/**
|
|
76
61
|
* Sets a cookie with the specified name, data, and optional path.
|
|
77
62
|
*
|
|
78
63
|
* @param name_ - The name of the cookie.
|
|
79
|
-
* @param data_ - The data to be stored in the cookie
|
|
64
|
+
* @param data_ - The data to be stored in the cookie.
|
|
80
65
|
* @param path_ - An optional path for the cookie; defaults to {@link DEFAULT_PATH}.
|
|
81
66
|
*/
|
|
82
67
|
export function setCookie(name_: string, data_: {
|
|
@@ -97,9 +82,9 @@ export function setCookie(name_: string, data_: {
|
|
|
97
82
|
}
|
|
98
83
|
|
|
99
84
|
/**
|
|
100
|
-
* Expires a cookie
|
|
85
|
+
* Expires a cookie immediately.
|
|
101
86
|
*
|
|
102
|
-
* @param name_ - The name of the cookie
|
|
87
|
+
* @param name_ - The name of the cookie.
|
|
103
88
|
* @param path_ - An optional path for the cookie; defaults to {@link DEFAULT_PATH}.
|
|
104
89
|
*/
|
|
105
90
|
export function expireCookie(name_: string, path_ = '/'): void {
|
|
@@ -107,13 +92,13 @@ export function expireCookie(name_: string, path_ = '/'): void {
|
|
|
107
92
|
}
|
|
108
93
|
|
|
109
94
|
/**
|
|
110
|
-
* Lists all cookies as a record of
|
|
95
|
+
* Lists all cookies as a record of key-value pairs.
|
|
111
96
|
*
|
|
112
97
|
* @returns A record where each key is a cookie name and each value is the corresponding cookie value.
|
|
113
98
|
*/
|
|
114
99
|
export function cookies(): Record<string, unknown> {
|
|
115
100
|
const cookies: Record<string, unknown> = {}
|
|
116
|
-
const matches = document.cookie.matchAll(
|
|
101
|
+
const matches = document.cookie.matchAll(/(?:^|; )([^=;]+)=([^;]*)/g)
|
|
117
102
|
for (const match of matches)
|
|
118
103
|
cookies[decodeURIComponent(match[1] ?? "")] = JSON.parse(decodeURIComponent(match[2] ?? ""))
|
|
119
104
|
return cookies
|