ranuts 0.2.0-alpha.1 → 0.3.0-alpha.1
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/CLAUDE.md +107 -16
- package/README.md +7 -5
- package/README.zh-CN.md +7 -5
- package/dist/chain-CTywmh_H.js +1 -0
- package/dist/{color-CRdlaDqQ.js → color-Dohr9BXX.js} +1 -1
- package/dist/enums-BAgbyGdH.js +1 -0
- package/dist/i18n-Cf5TtRb4.js +1 -0
- package/dist/index.d.ts +1 -5
- package/dist/index.js +1 -1
- package/dist/src/node/appendFile.d.ts +3 -3
- package/dist/src/node/fileInfo.d.ts +2 -2
- package/dist/src/node/index.js +1 -1
- package/dist/src/node/paresUrl.d.ts +1 -1
- package/dist/src/node/readFile.d.ts +3 -3
- package/dist/src/node/traverse.d.ts +2 -2
- package/dist/src/node/watchFile.d.ts +3 -3
- package/dist/src/node/writeFile.d.ts +3 -3
- package/dist/src/utils/async.d.ts +81 -0
- package/dist/src/utils/audioRecorder.d.ts +1 -1
- package/dist/src/utils/behavior.d.ts +12 -3
- package/dist/src/utils/bom.d.ts +68 -178
- package/dist/src/utils/bridge.d.ts +153 -0
- package/dist/src/utils/canvas.d.ts +54 -0
- package/dist/src/utils/chain.d.ts +80 -0
- package/dist/src/utils/color.d.ts +76 -4
- package/dist/src/utils/compose.d.ts +1 -1
- package/dist/src/utils/console.d.ts +19 -1
- package/dist/src/utils/debounce.d.ts +27 -5
- package/dist/src/utils/device.d.ts +31 -3
- package/dist/src/utils/dom.d.ts +5 -84
- package/dist/src/utils/error.d.ts +18 -1
- package/dist/src/utils/event.d.ts +61 -0
- package/dist/src/utils/file.d.ts +30 -0
- package/dist/src/utils/i18n/index.js +1 -0
- package/dist/src/utils/i18n.d.ts +69 -0
- package/dist/src/utils/idb.d.ts +178 -0
- package/dist/src/utils/img.d.ts +60 -4
- package/dist/src/utils/index.d.ts +48 -16
- package/dist/src/utils/index.js +1 -1
- package/dist/src/utils/lang.d.ts +69 -0
- package/dist/src/utils/localePath.d.ts +62 -0
- package/dist/src/utils/memoize.d.ts +53 -5
- package/dist/src/utils/monitor.d.ts +55 -26
- package/dist/src/utils/number.d.ts +46 -9
- package/dist/src/utils/obj.d.ts +56 -31
- package/dist/src/utils/prefetch.d.ts +81 -0
- package/dist/src/utils/queue.d.ts +53 -23
- package/dist/src/utils/report.d.ts +51 -3
- package/dist/src/utils/request.d.ts +26 -7
- package/dist/src/utils/script.d.ts +26 -4
- package/dist/src/utils/segment.d.ts +62 -0
- package/dist/src/utils/signal.d.ts +35 -3
- package/dist/src/utils/storage.d.ts +57 -0
- package/dist/src/utils/str.d.ts +112 -88
- package/dist/src/utils/style.d.ts +31 -0
- package/dist/src/utils/subscribe.d.ts +5 -5
- package/dist/src/utils/throttle.d.ts +26 -13
- package/dist/src/utils/time.d.ts +38 -6
- package/dist/src/utils/tween.d.ts +40 -0
- package/dist/src/utils/visual/application.d.ts +4 -4
- package/dist/src/utils/visual/enums.d.ts +4 -4
- package/dist/src/utils/visual/graphics/graphics.d.ts +25 -25
- package/dist/src/utils/visual/graphics/graphicsData.d.ts +1 -1
- package/dist/src/utils/visual/graphics/graphicsGeometry.d.ts +6 -6
- package/dist/src/utils/visual/index.js +1 -1
- package/dist/src/utils/visual/math/matrix.d.ts +8 -8
- package/dist/src/utils/visual/math/transform.d.ts +1 -1
- package/dist/src/utils/visual/render/batchRenderer.d.ts +20 -18
- package/dist/src/utils/visual/render/utils/batch/index.d.ts +13 -13
- package/dist/src/utils/visual/render/utils/float.d.ts +13 -13
- package/dist/src/utils/visual/render/utils/verticy.d.ts +3 -3
- package/dist/src/utils/visual/render/utils/webgl/initShader.d.ts +3 -2
- package/dist/src/utils/visual/render/utils/webgpu/shaders.d.ts +2 -2
- package/dist/src/utils/visual/render/webGPURenderer.d.ts +8 -8
- package/dist/src/utils/visual/vertex/container.d.ts +17 -16
- package/dist/src/utils/worker.d.ts +76 -0
- package/dist/src/utils/zip.d.ts +162 -0
- package/dist/src/vnode/index.d.ts +1 -1
- package/dist/src/vnode/index.js +1 -1
- package/dist/src/vnode/is.d.ts +4 -0
- package/dist/test/canvas.test.d.ts +1 -0
- package/dist/test/color.test.d.ts +1 -0
- package/dist/test/tween.test.d.ts +1 -0
- package/dist/test/utils/async.test.d.ts +1 -0
- package/dist/test/utils/file-read.test.d.ts +1 -0
- package/dist/test/utils/format.test.d.ts +1 -0
- package/dist/test/utils/idb.test.d.ts +1 -0
- package/dist/test/utils/instrumentation.test.d.ts +1 -0
- package/dist/test/utils/lang.test.d.ts +1 -0
- package/dist/test/utils/locale-path.test.d.ts +1 -0
- package/dist/test/utils/media-query.test.d.ts +1 -0
- package/dist/test/utils/number-parse.test.d.ts +1 -0
- package/dist/test/utils/prefetch.test.d.ts +1 -0
- package/dist/test/utils/query-storage.test.d.ts +1 -0
- package/dist/test/utils/queue.test.d.ts +1 -0
- package/dist/test/utils/report-config.test.d.ts +1 -0
- package/dist/test/utils/report-image.test.d.ts +1 -0
- package/dist/test/utils/segment.test.d.ts +1 -0
- package/dist/test/utils/signal-once.test.d.ts +1 -0
- package/dist/test/utils/single-flight.test.d.ts +1 -0
- package/dist/test/utils/timing.test.d.ts +1 -0
- package/dist/test/utils/worker-client.test.d.ts +1 -0
- package/dist/test/utils/zip.test.d.ts +1 -0
- package/dist/umd/index.umd.cjs +1 -1
- package/dist/umd/node/node.umd.cjs +1 -1
- package/dist/umd/utils/utils.umd.cjs +1 -1
- package/dist/utils-BDtXHcK8.js +1 -0
- package/docs/API.md +306 -147
- package/package.json +9 -6
- package/dist/src/vnode/chainDom.d.ts +0 -47
- package/dist/subscribe-CINWsor3.js +0 -1
- package/dist/utils-_OxsVZmz.js +0 -1
|
@@ -2,37 +2,66 @@ export interface Payload {
|
|
|
2
2
|
payload: Record<string, unknown>;
|
|
3
3
|
type?: string;
|
|
4
4
|
}
|
|
5
|
+
export interface MonitorOptions {
|
|
6
|
+
/** Telemetry endpoint. Required — without it nothing is sent. */
|
|
7
|
+
url: string;
|
|
8
|
+
/** Cookie holding the user id, included in every envelope */
|
|
9
|
+
userIdCookie?: string;
|
|
10
|
+
/** Minimum interval between beacons, ms. Default 300 */
|
|
11
|
+
throttleMs?: number;
|
|
12
|
+
/** Which channels to instrument. Everything except `console` is on by default. */
|
|
13
|
+
channels?: Partial<Record<MonitorChannel, boolean>>;
|
|
14
|
+
}
|
|
15
|
+
export type MonitorChannel = 'click' | 'error' | 'fetch' | 'xhr' | 'performance' | 'console';
|
|
16
|
+
/**
|
|
17
|
+
* @description: Front-end telemetry: page-load performance, clicks, errors, fetch/XHR traffic
|
|
18
|
+
* and (optionally) console output, all beaconed to one endpoint.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const monitor = new Monitor({ url: 'https://telemetry.example.com/collect' });
|
|
23
|
+
* const stop = monitor.start();
|
|
24
|
+
* monitor.log({ event: 'checkout' }); // manual event
|
|
25
|
+
* // on teardown (HMR, SPA route with a different config, tests)
|
|
26
|
+
* stop();
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
5
29
|
export declare class Monitor {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @description: 手动触发的上报
|
|
14
|
-
* @param {Record} payload
|
|
15
|
-
* @param {*} unknown
|
|
16
|
-
*/
|
|
17
|
-
log(payload: Record<string, unknown>): void;
|
|
18
|
-
/**
|
|
19
|
-
* @description: 点击上报
|
|
20
|
-
* @return {*}
|
|
21
|
-
*/
|
|
22
|
-
reportClick(): void;
|
|
23
|
-
reportXhr(): void;
|
|
30
|
+
private options;
|
|
31
|
+
private teardown;
|
|
32
|
+
private send;
|
|
33
|
+
constructor(options: MonitorOptions);
|
|
34
|
+
/** Whether instrumentation is currently installed */
|
|
35
|
+
get running(): boolean;
|
|
24
36
|
/**
|
|
25
|
-
* @description:
|
|
37
|
+
* @description: Install the configured channels. Idempotent — calling it twice does not
|
|
38
|
+
* double-instrument.
|
|
39
|
+
* @return {Function} stop — removes every listener and global patch
|
|
26
40
|
*/
|
|
27
|
-
|
|
41
|
+
start: () => (() => void);
|
|
42
|
+
/** @description: Remove every listener and restore every patched global */
|
|
43
|
+
stop: () => void;
|
|
28
44
|
/**
|
|
29
|
-
*
|
|
45
|
+
* Build one event. `createData()` is called **per event**, not once at install time — the
|
|
46
|
+
* old version captured it when the hook was registered, so every later click reported the
|
|
47
|
+
* URL and timestamp of page load rather than of the click.
|
|
30
48
|
*/
|
|
31
|
-
|
|
49
|
+
private event;
|
|
50
|
+
/** @description: Report a one-off event with the standard envelope */
|
|
51
|
+
log: (payload: Record<string, unknown>) => void;
|
|
52
|
+
/** @description: Page-load performance metrics; fires once, so it is not throttled */
|
|
53
|
+
reportPerformance: () => void;
|
|
54
|
+
/** @description: Click tracking */
|
|
55
|
+
reportClick: () => (() => void);
|
|
56
|
+
/** @description: Uncaught errors and unhandled rejections */
|
|
57
|
+
reportError: () => (() => void);
|
|
58
|
+
/** @description: fetch traffic */
|
|
59
|
+
reportFetch: () => (() => void);
|
|
60
|
+
/** @description: XMLHttpRequest traffic */
|
|
61
|
+
reportXhr: () => (() => void);
|
|
32
62
|
/**
|
|
33
|
-
* @description:
|
|
63
|
+
* @description: console output. Off by default — see `DEFAULT_CHANNELS`; a backend that
|
|
64
|
+
* logs to the console would loop.
|
|
34
65
|
*/
|
|
35
|
-
reportConsole()
|
|
36
|
-
init: () => void;
|
|
37
|
-
initialize(): void;
|
|
66
|
+
reportConsole: () => (() => void);
|
|
38
67
|
}
|
|
@@ -3,32 +3,32 @@ interface ComputeNumberResult {
|
|
|
3
3
|
next: (a: string, b: number) => ComputeNumberResult;
|
|
4
4
|
}
|
|
5
5
|
/**
|
|
6
|
-
* @description:
|
|
6
|
+
* @description: Convert a percentage string into a number
|
|
7
7
|
* @param {string} str
|
|
8
8
|
* @return {*}
|
|
9
9
|
*/
|
|
10
10
|
export declare const perToNum: (str?: string) => number;
|
|
11
11
|
/**
|
|
12
|
-
* @description:
|
|
12
|
+
* @description: Clamp a value between a minimum and a maximum
|
|
13
13
|
* @return {*}
|
|
14
14
|
*/
|
|
15
15
|
export declare const range: (num: number, min?: number, max?: number) => number;
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
* @param {number} a
|
|
19
|
-
* @param {"+"|"-"|"*"|"/"} type
|
|
20
|
-
* @param {number} b
|
|
17
|
+
* Arithmetic that works around floating-point precision.
|
|
18
|
+
* @param {number} a left operand
|
|
19
|
+
* @param {"+"|"-"|"*"|"/"} type operation
|
|
20
|
+
* @param {number} b right operand
|
|
21
21
|
* @example
|
|
22
22
|
* ```js
|
|
23
|
-
* //
|
|
23
|
+
* // chainable
|
|
24
24
|
* const res = computeNumber(1.3, "-", 1.2).next("+", 1.5).next("*", 2.3).next("/", 0.2).result;
|
|
25
25
|
* console.log(res);
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
28
|
export declare class Mathjs {
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
31
|
-
* @param {number} n
|
|
30
|
+
* Number of digits after the decimal point
|
|
31
|
+
* @param {number} n the number
|
|
32
32
|
*/
|
|
33
33
|
getDecimalLength: (n: number) => number;
|
|
34
34
|
amend: (n: number, precision?: number) => number;
|
|
@@ -42,4 +42,41 @@ export declare class Mathjs {
|
|
|
42
42
|
export declare function mathjs(a: number, type: string, b: number): ComputeNumberResult;
|
|
43
43
|
export declare const transformNumber: (value: string, locale?: string, precision?: number, fixed?: number) => string;
|
|
44
44
|
export declare const addNumSym: (value: string | number, flag?: string | number) => string;
|
|
45
|
+
/**
|
|
46
|
+
* @description: Chinese numerals to Arabic, covering 「十五」「二十三」「一百零三」「一千零一」「三万」.
|
|
47
|
+
* Simplified and traditional alike (万/萬); full-width digits are normalised first. Returns
|
|
48
|
+
* null when an unrecognised character is present.
|
|
49
|
+
* @param {string} value
|
|
50
|
+
* @return {number | null}
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* parseChineseNumber('二十三'); // 23
|
|
54
|
+
* parseChineseNumber('一百零三'); // 103
|
|
55
|
+
* parseChineseNumber('第三章'); // null — contains non-numeral characters, slice the number out first
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare const parseChineseNumber: (value: string) => number | null;
|
|
59
|
+
/**
|
|
60
|
+
* @description: Roman numerals to Arabic (either case, handling subtractive forms such as IV / IX). Returns null for invalid input.
|
|
61
|
+
* @param {string} value
|
|
62
|
+
* @return {number | null}
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* parseRomanNumber('XIV'); // 14
|
|
66
|
+
* parseRomanNumber('mcmxciv'); // 1994
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export declare const parseRomanNumber: (value: string) => number | null;
|
|
70
|
+
/**
|
|
71
|
+
* @description: English ordinals to numbers, tried in order: Arabic digits, number words
|
|
72
|
+
* (one–twenty), then Roman numerals. Returns null when none match.
|
|
73
|
+
* @param {string} value
|
|
74
|
+
* @return {number | null}
|
|
75
|
+
* @example
|
|
76
|
+
* ```ts
|
|
77
|
+
* parseEnglishNumber('Three'); // 3
|
|
78
|
+
* parseEnglishNumber('XII'); // 12
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export declare const parseEnglishNumber: (value: string) => number | null;
|
|
45
82
|
export {};
|
package/dist/src/utils/obj.d.ts
CHANGED
|
@@ -1,83 +1,108 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @description:
|
|
2
|
+
* @description: Serialise an object into a URL query string
|
|
3
3
|
* @param {*} data
|
|
4
4
|
* @return {*}
|
|
5
5
|
*/
|
|
6
6
|
export declare function querystring(data?: {}): string;
|
|
7
|
-
export declare const formatJson: (jsonObj: string, callback?: () => void) => string;
|
|
8
7
|
/**
|
|
9
|
-
* @description:
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* @description: Pretty-print JSON. Accepts an object or a JSON string (single quotes are
|
|
9
|
+
* tolerated and normalized to double quotes, which is common in hand-written config).
|
|
10
|
+
*
|
|
11
|
+
* This is `JSON.stringify(value, null, indent)` with lenient parsing in front. It replaces a
|
|
12
|
+
* ~90-line hand-rolled formatter that rebuilt the layout by regex-injecting newlines around
|
|
13
|
+
* every brace, bracket and comma, then tried to undo the damage inside string literals by
|
|
14
|
+
* counting quotes per line — which mis-handled escaped quotes, and treated a brace or comma
|
|
15
|
+
* inside a string value as structure. The platform serializer has none of those problems and
|
|
16
|
+
* is orders of magnitude faster.
|
|
17
|
+
*
|
|
18
|
+
* @param {string | object} value object, or a JSON string to reformat
|
|
19
|
+
* @param {Function} onError called with the parse/serialize error; the function returns `''`
|
|
20
|
+
* @param {number} indent spaces per level, default 4
|
|
21
|
+
* @return {string} formatted JSON, or `''` when the input could not be parsed
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* formatJson({ a: 1, b: [2, 3] });
|
|
25
|
+
* formatJson("{'a': 1}"); // single quotes tolerated
|
|
26
|
+
* formatJson('nope', (e) => log(e)); // '' + the error handed to the callback
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare const formatJson: (value: string | object, onError?: (error: Error) => void, indent?: number) => string;
|
|
30
|
+
/**
|
|
31
|
+
* @description: Return a new object without the properties whose values appear in `list` — typically used to drop empty strings and nulls
|
|
32
|
+
* @param {Object} obj source object
|
|
33
|
+
* @param {Array} list values to remove
|
|
12
34
|
* @return {Object}
|
|
13
35
|
*/
|
|
14
36
|
export declare const filterObj: (obj: Record<string, unknown>, list: Array<string>) => Record<string, unknown>;
|
|
15
37
|
type Obj = Record<string, any>;
|
|
16
38
|
/**
|
|
17
|
-
* @description:
|
|
39
|
+
* @description: Merge objects
|
|
18
40
|
* @param {Obj} a
|
|
19
41
|
* @param {Obj} b
|
|
20
42
|
* @return {*}
|
|
21
43
|
*/
|
|
22
44
|
export declare const merge: (a: Obj, b?: Obj) => Obj;
|
|
23
45
|
/**
|
|
24
|
-
*
|
|
46
|
+
* @description: Replace a property on an object, wrapping whatever was there before.
|
|
47
|
+
*
|
|
48
|
+
* Returns a **restore function**. Patching a global is a one-way door without it: tests cannot
|
|
49
|
+
* clean up after themselves, two instrumentation layers cannot be unwound in order, and a hot
|
|
50
|
+
* reload stacks wrapper on wrapper until the call is nested a dozen deep. Always keep the
|
|
51
|
+
* returned function and call it on teardown.
|
|
25
52
|
*
|
|
26
|
-
* @
|
|
27
|
-
* @param {
|
|
28
|
-
* @param {
|
|
29
|
-
* @param {
|
|
30
|
-
* @
|
|
53
|
+
* @param {any} source object to patch
|
|
54
|
+
* @param {string} name key to patch
|
|
55
|
+
* @param {Function} replacement receives the original value, returns the wrapper
|
|
56
|
+
* @param {boolean} isForced patch even when the key does not exist yet
|
|
57
|
+
* @return {Function} restore — puts the original value back; safe to call more than once
|
|
31
58
|
*/
|
|
32
|
-
export declare function replaceOld(source: any, name: string, replacement: (...args: unknown[]) => unknown, isForced?: boolean): void;
|
|
59
|
+
export declare function replaceOld(source: any, name: string, replacement: (...args: unknown[]) => unknown, isForced?: boolean): () => void;
|
|
33
60
|
/**
|
|
34
|
-
* @description:
|
|
61
|
+
* @description: Copy an exports object onto `obj`, then freeze it
|
|
35
62
|
* @param {Object} obj
|
|
36
63
|
* @param {Object} exports
|
|
37
64
|
* @return {Object}
|
|
38
65
|
*/
|
|
39
66
|
export declare const mergeExports: (obj: Record<string, string>, exports: Record<string, string>) => Record<string, string>;
|
|
40
67
|
/**
|
|
41
|
-
* @description:
|
|
68
|
+
* @description: Define a property on the global object
|
|
42
69
|
* @param {string} name
|
|
43
70
|
* @param {string} value
|
|
44
71
|
* @return {*}
|
|
45
72
|
*/
|
|
46
73
|
export declare const setAttributeByGlobal: (name: string, value: unknown) => void;
|
|
47
74
|
/**
|
|
48
|
-
*
|
|
49
|
-
* 实现类似 Lodash 的 isEqual 函数
|
|
75
|
+
* Deep-compare two values, in the manner of Lodash's isEqual.
|
|
50
76
|
*/
|
|
51
77
|
/**
|
|
52
|
-
*
|
|
53
|
-
* 处理特殊情况如 NaN, -0/+0
|
|
78
|
+
* Whether two primitives are the same value, handling the special cases NaN and -0/+0.
|
|
54
79
|
*/
|
|
55
80
|
export declare function sameValueZero(x: any, y: any): boolean;
|
|
56
81
|
/**
|
|
57
|
-
*
|
|
82
|
+
* Whether the value is object-like
|
|
58
83
|
*/
|
|
59
84
|
export declare function isObjectLike(value: any): boolean;
|
|
60
85
|
/**
|
|
61
|
-
*
|
|
86
|
+
* The object's internal [[Class]] tag
|
|
62
87
|
*/
|
|
63
88
|
export declare function getTag(value: any): string;
|
|
64
89
|
/**
|
|
65
|
-
*
|
|
90
|
+
* Whether the value is array-like
|
|
66
91
|
*/
|
|
67
92
|
export declare function isArrayLike(value: any): boolean;
|
|
68
93
|
/**
|
|
69
|
-
*
|
|
70
|
-
* @param value
|
|
71
|
-
* @param other
|
|
72
|
-
* @param seen
|
|
73
|
-
* @returns
|
|
94
|
+
* Deep-compare two values.
|
|
95
|
+
* @param value first value
|
|
96
|
+
* @param other second value
|
|
97
|
+
* @param seen objects already compared, so circular references terminate
|
|
98
|
+
* @returns whether the two are equal
|
|
74
99
|
*/
|
|
75
100
|
export declare function isEqual(value: any, other: any, seen?: Map<any, any>): boolean;
|
|
76
101
|
/**
|
|
77
|
-
*
|
|
78
|
-
* @param value
|
|
79
|
-
* @param cloneMap
|
|
80
|
-
* @returns
|
|
102
|
+
* Deep clone, covering the complex built-in types and circular references.
|
|
103
|
+
* @param value value to clone
|
|
104
|
+
* @param cloneMap objects already cloned, so circular references terminate
|
|
105
|
+
* @returns the cloned value
|
|
81
106
|
*/
|
|
82
107
|
export declare const cloneDeep: <T>(value: T, cloneMap?: WeakMap<object, any>) => T;
|
|
83
108
|
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background prefetching plus cache probing.
|
|
3
|
+
*
|
|
4
|
+
* The key fact: a same-origin GET that has been fetched once lands in the service worker's
|
|
5
|
+
* CacheStorage (assuming the SW is cache-first for same-origin GETs), and from then on any
|
|
6
|
+
* code requesting that URL hits the cache and works offline. So "warming up a large asset"
|
|
7
|
+
* needs no dedicated downloader — pulling the bytes into the cache is enough.
|
|
8
|
+
*
|
|
9
|
+
* But prefetching **spends the user's data on their behalf**, so it must be constrained:
|
|
10
|
+
* it should stay quiet under data-saver mode, on slow 2G, and whenever the user turned it off.
|
|
11
|
+
*/
|
|
12
|
+
export interface WhenIdleOptions {
|
|
13
|
+
/** Maximum wait for requestIdleCallback in milliseconds, defaults to 8000 */
|
|
14
|
+
timeout?: number;
|
|
15
|
+
/** Fallback delay in milliseconds when requestIdleCallback is unavailable, defaults to 2500 */
|
|
16
|
+
fallbackDelay?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* @description: Run a callback while the browser is idle, falling back to setTimeout where
|
|
20
|
+
* `requestIdleCallback` is missing (long absent in Safari).
|
|
21
|
+
* @param {Function} callback runs when idle
|
|
22
|
+
* @param {WhenIdleOptions} options
|
|
23
|
+
* @return {Function} cancel function; calling it after the callback ran is a no-op
|
|
24
|
+
*/
|
|
25
|
+
export declare const whenIdle: (callback: () => void, options?: WhenIdleOptions) => (() => void);
|
|
26
|
+
export interface NetworkAllowanceOptions {
|
|
27
|
+
/** localStorage switch: any value stored under this key means the user turned prefetching off */
|
|
28
|
+
optOutKey?: string;
|
|
29
|
+
/** effectiveType values treated as a "slow network", defaults to slow-2g / 2g */
|
|
30
|
+
slowTypes?: string[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* @description: Whether the current network and user settings allow proactively downloading
|
|
34
|
+
* a large asset. Returns false under data-saver (`saveData`), on a slow network, or when the
|
|
35
|
+
* user opted out. When the information is unavailable it **defaults to allowed** — the
|
|
36
|
+
* Network Information API does not exist in Safari/Firefox, and a missing reading must not
|
|
37
|
+
* disable prefetching everywhere.
|
|
38
|
+
* @param {NetworkAllowanceOptions} options
|
|
39
|
+
* @return {boolean}
|
|
40
|
+
*/
|
|
41
|
+
export declare const networkAllowsDownload: (options?: NetworkAllowanceOptions) => boolean;
|
|
42
|
+
/**
|
|
43
|
+
* @description: Whether a URL is already in CacheStorage. When probing a group of files,
|
|
44
|
+
* test the one that **finishes downloading last** (usually the largest), otherwise a
|
|
45
|
+
* half-finished download reads as fully cached.
|
|
46
|
+
* @param {string} url
|
|
47
|
+
* @return {Promise<boolean>}
|
|
48
|
+
*/
|
|
49
|
+
export declare const isUrlCached: (url: string) => Promise<boolean>;
|
|
50
|
+
/**
|
|
51
|
+
* @description: Pull a single URL into the cache; skipped when already cached. Failures are
|
|
52
|
+
* silent — a failed prefetch only means the later load performs a real download, it must not
|
|
53
|
+
* bubble up and interrupt the main flow.
|
|
54
|
+
* @param {string} url
|
|
55
|
+
* @return {Promise<void>}
|
|
56
|
+
*/
|
|
57
|
+
export declare const prefetchUrl: (url: string) => Promise<void>;
|
|
58
|
+
export interface PrefetchOptions {
|
|
59
|
+
/**
|
|
60
|
+
* Message type used to hand prefetching to the service worker. The SW keeps the work alive
|
|
61
|
+
* with `event.waitUntil`, so a download survives page navigation (very noticeable when the
|
|
62
|
+
* user moves around quickly); without a controlling SW it falls back to a main-thread fetch.
|
|
63
|
+
*/
|
|
64
|
+
serviceWorkerMessage?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* @description: Prefetch a group of URLs, **serially** — prefetching is background work, and
|
|
68
|
+
* saturating the bandwidth in parallel slows down the page the user is actually looking at.
|
|
69
|
+
* @param {string[]} urls
|
|
70
|
+
* @param {PrefetchOptions} options
|
|
71
|
+
* @return {Promise<void>}
|
|
72
|
+
*/
|
|
73
|
+
export declare const prefetchUrls: (urls: string[], options?: PrefetchOptions) => Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* @description: Prefetch a group of URLs while idle, subject to `networkAllowsDownload`.
|
|
76
|
+
* Non-blocking, returns immediately.
|
|
77
|
+
* @param {string[]} urls
|
|
78
|
+
* @param {object} options the idle-scheduling, network-allowance and SW-forwarding options combined
|
|
79
|
+
* @return {Function} cancel function (can only cancel a schedule that has not started)
|
|
80
|
+
*/
|
|
81
|
+
export declare const prefetchWhenIdle: (urls: string[], options?: WhenIdleOptions & NetworkAllowanceOptions & PrefetchOptions) => (() => void);
|
|
@@ -1,33 +1,63 @@
|
|
|
1
|
-
|
|
2
|
-
interface QuestQueueOptions {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
export type QueueTask<T = unknown> = () => Promise<T> | T;
|
|
2
|
+
export interface QuestQueueOptions {
|
|
3
|
+
/** Maximum concurrency; `<= 0` is treated as 1 */
|
|
4
|
+
simultaneous?: number;
|
|
5
5
|
}
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* @description: An async task queue with limited concurrency. At most `simultaneous` tasks
|
|
8
|
+
* run at once, the rest wait, and each completion pulls in the next. For batch uploads or
|
|
9
|
+
* batch requests — anything that must not be fired all at once.
|
|
10
|
+
*
|
|
11
|
+
* The queue is **FIFO**, and `add()` returns that task's own promise, so one failing task
|
|
12
|
+
* only rejects its own promise instead of taking the whole queue down. (The previous
|
|
13
|
+
* implementation popped LIFO, packed every task's result into a single shared promise, and
|
|
14
|
+
* `add` never started anything — `running` had to be called by hand.)
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const queue = new QuestQueue({ simultaneous: 3 });
|
|
19
|
+
* const results = await Promise.all(urls.map((url) => queue.add(() => fetch(url))));
|
|
20
|
+
* // or wait for the whole queue to drain (failures included):
|
|
21
|
+
* await queue.onIdle();
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
7
24
|
export declare class QuestQueue {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
25
|
+
/** Number of tasks currently running */
|
|
26
|
+
running: number;
|
|
27
|
+
/** Number of finished tasks (failures included) */
|
|
11
28
|
executed: number;
|
|
12
|
-
|
|
13
|
-
|
|
29
|
+
/** Maximum concurrency */
|
|
30
|
+
simultaneous: number;
|
|
31
|
+
private queue;
|
|
32
|
+
private idleWaiters;
|
|
33
|
+
constructor({ simultaneous }?: QuestQueueOptions);
|
|
34
|
+
/** Number of tasks waiting to run */
|
|
35
|
+
get pending(): number;
|
|
36
|
+
/** Whether the queue has drained (nothing queued, nothing running) */
|
|
37
|
+
get idle(): boolean;
|
|
14
38
|
/**
|
|
15
|
-
* @description:
|
|
16
|
-
*
|
|
17
|
-
* @
|
|
39
|
+
* @description: Enqueue an async task and get back its own result promise. Starts
|
|
40
|
+
* immediately when a slot is free.
|
|
41
|
+
* @param {QueueTask<T>} task nullary function returning a promise or a plain value
|
|
42
|
+
* @return {Promise<T>}
|
|
18
43
|
*/
|
|
19
|
-
add: (
|
|
44
|
+
add: <T = unknown>(task: QueueTask<T>) => Promise<T>;
|
|
20
45
|
/**
|
|
21
|
-
* @description:
|
|
22
|
-
*
|
|
23
|
-
*
|
|
46
|
+
* @description: Enqueue a batch with `Promise.allSettled` semantics: wait for all of them,
|
|
47
|
+
* report each outcome individually **in input order**, and never drop the remaining results
|
|
48
|
+
* because one failed.
|
|
49
|
+
* @param {QueueTask[]} tasks
|
|
50
|
+
* @return {Promise<PromiseSettledResult<T>[]>}
|
|
24
51
|
*/
|
|
25
|
-
|
|
52
|
+
allSettled: <T = unknown>(tasks: Array<QueueTask<T>>) => Promise<Array<PromiseSettledResult<T>>>;
|
|
26
53
|
/**
|
|
27
|
-
* @description:
|
|
28
|
-
* @
|
|
29
|
-
* @return {*}
|
|
54
|
+
* @description: Wait for the queue to drain. Resolves immediately when already empty.
|
|
55
|
+
* @return {Promise<void>}
|
|
30
56
|
*/
|
|
31
|
-
|
|
57
|
+
onIdle: () => Promise<void>;
|
|
58
|
+
/** @description: Drop every task that has not started (running ones are untouched); their promises reject */
|
|
59
|
+
clear: () => void;
|
|
60
|
+
/** Pull tasks off the head while slots are free; called again after each task to keep the loop going */
|
|
61
|
+
private next;
|
|
62
|
+
private settleIdle;
|
|
32
63
|
}
|
|
33
|
-
export {};
|
|
@@ -1,8 +1,56 @@
|
|
|
1
|
-
interface BeaconPayload {
|
|
1
|
+
export interface BeaconPayload {
|
|
2
|
+
/** Endpoint to send to. Falls back to whatever `setReportUrl` configured. */
|
|
2
3
|
url?: string;
|
|
3
4
|
type?: string;
|
|
4
5
|
payload: Record<string, unknown>;
|
|
5
6
|
}
|
|
6
|
-
export
|
|
7
|
+
export interface ReportConfig {
|
|
8
|
+
/** Default endpoint for every `report()` that does not pass its own `url` */
|
|
9
|
+
url?: string;
|
|
10
|
+
/** Cookie holding the current user id, included in `createData()`. Unset means no user id. */
|
|
11
|
+
userIdCookie?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* @description: Configure the default reporting endpoint (and optionally the cookie holding
|
|
15
|
+
* the user id). Call it once at startup so `report({ payload })` needs no `url`.
|
|
16
|
+
*
|
|
17
|
+
* There is deliberately no default. The previous version derived one from `getHost()`, which
|
|
18
|
+
* built a URL from a domain hard-coded to this repo's author — and a leftover edit had already
|
|
19
|
+
* degraded it to the literal `'//log.'`, so every report without an explicit `url` was posted
|
|
20
|
+
* to an unreachable host. A library cannot know where your telemetry belongs; it has to be told.
|
|
21
|
+
*
|
|
22
|
+
* @param {ReportConfig} next merged into the current configuration
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* setReportUrl({ url: 'https://telemetry.example.com/collect', userIdCookie: 'uid' });
|
|
26
|
+
* report({ payload: { event: 'page_view' } });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare const setReportUrl: (next: ReportConfig | string) => void;
|
|
30
|
+
/** @description: The currently configured reporting endpoint, or `''` when none was set */
|
|
31
|
+
export declare const getReportUrl: () => string;
|
|
32
|
+
/**
|
|
33
|
+
* @description: Send a telemetry beacon. Prefers `navigator.sendBeacon` (does not block
|
|
34
|
+
* unload, delivery is the browser's job) and falls back to a 1x1 image.
|
|
35
|
+
*
|
|
36
|
+
* The fallback is chosen by whether **sendBeacon itself is available and succeeded**, not by
|
|
37
|
+
* whether `navigator` exists — `navigator` exists in every browser, so testing that made the
|
|
38
|
+
* image fallback unreachable and silently dropped the report whenever sendBeacon was missing
|
|
39
|
+
* or returned false.
|
|
40
|
+
*
|
|
41
|
+
* @param {BeaconPayload} options
|
|
42
|
+
* @return {boolean} whether some transport accepted it
|
|
43
|
+
*/
|
|
44
|
+
export declare const report: ({ url, type, payload }: BeaconPayload) => boolean;
|
|
45
|
+
/**
|
|
46
|
+
* @description: Build the standard envelope that accompanies a report — page URL, referrer,
|
|
47
|
+
* viewport, user agent, a random event id and a timestamp. Merge your own fields on top.
|
|
48
|
+
*
|
|
49
|
+
* The user id comes from the cookie named by `setReportUrl({ userIdCookie })`; without that
|
|
50
|
+
* configuration no user id is included. (It used to read a cookie named after this repo's
|
|
51
|
+
* author's own deployment, which was never going to exist in anyone else's app.)
|
|
52
|
+
*
|
|
53
|
+
* @param {Record<string, unknown>} params extra fields, applied last
|
|
54
|
+
* @return {Record<string, unknown>} empty object under SSR
|
|
55
|
+
*/
|
|
7
56
|
export declare function createData(params?: Record<string, unknown>): Record<string, unknown>;
|
|
8
|
-
export {};
|
|
@@ -5,13 +5,32 @@ export interface Options {
|
|
|
5
5
|
errorHook: Hooks;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* @description: fetch
|
|
9
|
-
*
|
|
8
|
+
* @description: Instrument `window.fetch` so every request, response and failure reaches your
|
|
9
|
+
* hooks. The original behaviour is untouched: the response is passed through and errors are
|
|
10
|
+
* re-thrown.
|
|
11
|
+
*
|
|
12
|
+
* Returns a **restore function**. Without one, instrumenting a global is a one-way door — a
|
|
13
|
+
* hot reload stacks a new wrapper on the previous one, and a test can never give the page a
|
|
14
|
+
* clean `fetch` back.
|
|
15
|
+
*
|
|
16
|
+
* @param {Partial<Options>} options requestHook / responseHook / errorHook
|
|
17
|
+
* @return {Function} restore — puts the original `fetch` back
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const restore = handleFetchHook({ errorHook: (url, error) => report({ payload: { url } }) });
|
|
21
|
+
* // on teardown
|
|
22
|
+
* restore();
|
|
23
|
+
* ```
|
|
10
24
|
*/
|
|
11
|
-
export declare const handleFetchHook: (options?: Partial<Options>) => void;
|
|
25
|
+
export declare const handleFetchHook: (options?: Partial<Options>) => (() => void);
|
|
12
26
|
/**
|
|
13
|
-
* @description:
|
|
14
|
-
*
|
|
15
|
-
*
|
|
27
|
+
* @description: Instrument `XMLHttpRequest` (`open` / `send`) so requests, responses and
|
|
28
|
+
* failures reach your hooks. Patches the prototype, so it applies to every instance.
|
|
29
|
+
*
|
|
30
|
+
* Returns a **restore function** that undoes both patches. See `handleFetchHook` for why that
|
|
31
|
+
* matters.
|
|
32
|
+
*
|
|
33
|
+
* @param {Partial<Options>} options requestHook / responseHook / errorHook
|
|
34
|
+
* @return {Function} restore — puts the original `open` and `send` back
|
|
16
35
|
*/
|
|
17
|
-
export declare const handleXhrHook: (options?: Partial<Options>) => void;
|
|
36
|
+
export declare const handleXhrHook: (options?: Partial<Options>) => (() => void);
|
|
@@ -1,7 +1,29 @@
|
|
|
1
|
+
export interface LoadScriptOptions {
|
|
2
|
+
/** `'url'` loads via `src`; `'content'` inlines the script text directly */
|
|
3
|
+
type: 'url' | 'content';
|
|
4
|
+
/** The URL when type is `'url'`, the script body when it is `'content'` */
|
|
5
|
+
content: string;
|
|
6
|
+
}
|
|
1
7
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
8
|
+
* @description: Inject one script dynamically, de-duplicated by content.
|
|
9
|
+
*
|
|
10
|
+
* How this differs from `scriptOnLoad`: that one loads a batch of URLs at once (routing
|
|
11
|
+
* .css through a link tag), while this one handles a single script, supports an inline body,
|
|
12
|
+
* and **guarantees the same script is evaluated only once** — injecting a third-party SDK
|
|
13
|
+
* twice usually means its initialisation side effects ran twice.
|
|
14
|
+
*
|
|
15
|
+
* The de-duplication key is the md5 of `type + content`, so a URL and an identically named inline script cannot be confused.
|
|
16
|
+
*
|
|
17
|
+
* @param {LoadScriptOptions} options
|
|
18
|
+
* @return {Promise<{ success: boolean }>} rejects with `{ success: false, error }` on failure
|
|
19
|
+
*/
|
|
20
|
+
export declare const loadScript: ({ type, content }: LoadScriptOptions) => Promise<{
|
|
21
|
+
success: boolean;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Insert script/link tags dynamically
|
|
25
|
+
* @param {Array | String} url the script/link URLs to load
|
|
26
|
+
* @param {Element} append parent element to insert into, defaults to body
|
|
27
|
+
* @param {Function} callback fired once every script has loaded; the returned promise works too
|
|
6
28
|
*/
|
|
7
29
|
export declare const scriptOnLoad: (urls: string[], append?: HTMLElement, callback?: () => void) => Promise<void>;
|