@vibe-agent-toolkit/utils 0.2.0-rc.11 → 0.2.0-rc.12
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 +111 -9
- package/dist/archive/archive.d.ts +129 -0
- package/dist/archive/archive.d.ts.map +1 -0
- package/dist/archive/archive.js +223 -0
- package/dist/archive/archive.js.map +1 -0
- package/dist/archive/entries.d.ts +132 -0
- package/dist/archive/entries.d.ts.map +1 -0
- package/dist/archive/entries.js +223 -0
- package/dist/archive/entries.js.map +1 -0
- package/dist/archive/limits.d.ts +39 -0
- package/dist/archive/limits.d.ts.map +1 -0
- package/dist/archive/limits.js +59 -0
- package/dist/archive/limits.js.map +1 -0
- package/dist/archive/records.d.ts +14 -0
- package/dist/archive/records.d.ts.map +1 -0
- package/dist/archive/records.js +3 -0
- package/dist/archive/records.js.map +1 -0
- package/dist/archive/tar-reader.d.ts +18 -0
- package/dist/archive/tar-reader.d.ts.map +1 -0
- package/dist/archive/tar-reader.js +173 -0
- package/dist/archive/tar-reader.js.map +1 -0
- package/dist/archive/zip-reader.d.ts +76 -0
- package/dist/archive/zip-reader.d.ts.map +1 -0
- package/dist/archive/zip-reader.js +376 -0
- package/dist/archive/zip-reader.js.map +1 -0
- package/dist/archive.d.ts +14 -0
- package/dist/archive.d.ts.map +1 -0
- package/dist/archive.js +12 -0
- package/dist/archive.js.map +1 -0
- package/dist/asset-reference.d.ts +17 -1
- package/dist/asset-reference.d.ts.map +1 -1
- package/dist/asset-reference.js +31 -7
- package/dist/asset-reference.js.map +1 -1
- package/dist/dirent-kind.d.ts +13 -40
- package/dist/dirent-kind.d.ts.map +1 -1
- package/dist/dirent-kind.js +21 -69
- package/dist/dirent-kind.js.map +1 -1
- package/dist/entrypoint.d.ts +2 -2
- package/dist/entrypoint.d.ts.map +1 -1
- package/dist/entrypoint.js +4 -3
- package/dist/entrypoint.js.map +1 -1
- package/dist/env-flag.d.ts +2 -0
- package/dist/env-flag.d.ts.map +1 -1
- package/dist/env-flag.js +2 -0
- package/dist/env-flag.js.map +1 -1
- package/dist/errors/confirmed-absent.d.ts +41 -0
- package/dist/errors/confirmed-absent.d.ts.map +1 -0
- package/dist/errors/confirmed-absent.js +43 -0
- package/dist/errors/confirmed-absent.js.map +1 -0
- package/dist/errors/errno-table.d.ts +177 -0
- package/dist/errors/errno-table.d.ts.map +1 -0
- package/dist/errors/errno-table.js +343 -0
- package/dist/errors/errno-table.js.map +1 -0
- package/dist/errors/fs-boundary.d.ts +36 -0
- package/dist/errors/fs-boundary.d.ts.map +1 -0
- package/dist/errors/fs-boundary.js +121 -0
- package/dist/errors/fs-boundary.js.map +1 -0
- package/dist/errors/fs-fault.d.ts +176 -0
- package/dist/errors/fs-fault.d.ts.map +1 -0
- package/dist/errors/fs-fault.js +215 -0
- package/dist/errors/fs-fault.js.map +1 -0
- package/dist/errors/git-errno.d.ts +13 -0
- package/dist/errors/git-errno.d.ts.map +1 -0
- package/dist/errors/git-errno.js +45 -0
- package/dist/errors/git-errno.js.map +1 -0
- package/dist/errors/path-present.d.ts +72 -0
- package/dist/errors/path-present.d.ts.map +1 -0
- package/dist/errors/path-present.js +110 -0
- package/dist/errors/path-present.js.map +1 -0
- package/dist/errors/rag-index-empty.d.ts +16 -0
- package/dist/errors/rag-index-empty.d.ts.map +1 -0
- package/dist/errors/rag-index-empty.js +16 -0
- package/dist/errors/rag-index-empty.js.map +1 -0
- package/dist/errors/suppressed-faults.d.ts +34 -0
- package/dist/errors/suppressed-faults.d.ts.map +1 -0
- package/dist/errors/suppressed-faults.js +66 -0
- package/dist/errors/suppressed-faults.js.map +1 -0
- package/dist/file-crawler.d.ts +13 -18
- package/dist/file-crawler.d.ts.map +1 -1
- package/dist/file-crawler.js +140 -24
- package/dist/file-crawler.js.map +1 -1
- package/dist/fs-utils.d.ts +75 -50
- package/dist/fs-utils.d.ts.map +1 -1
- package/dist/fs-utils.js +148 -158
- package/dist/fs-utils.js.map +1 -1
- package/dist/fs.d.ts +4 -4
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +4 -4
- package/dist/fs.js.map +1 -1
- package/dist/git-snapshot.d.ts +25 -17
- package/dist/git-snapshot.d.ts.map +1 -1
- package/dist/git-snapshot.js +65 -11
- package/dist/git-snapshot.js.map +1 -1
- package/dist/git-tracker.d.ts +11 -3
- package/dist/git-tracker.d.ts.map +1 -1
- package/dist/git-tracker.js +29 -6
- package/dist/git-tracker.js.map +1 -1
- package/dist/git-utils.d.ts.map +1 -1
- package/dist/git-utils.js +7 -35
- package/dist/git-utils.js.map +1 -1
- package/dist/git.d.ts +1 -1
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +1 -1
- package/dist/git.js.map +1 -1
- package/dist/gitignore-checker.d.ts.map +1 -1
- package/dist/gitignore-checker.js +5 -4
- package/dist/gitignore-checker.js.map +1 -1
- package/dist/in-order.d.ts +93 -0
- package/dist/in-order.d.ts.map +1 -0
- package/dist/in-order.js +165 -0
- package/dist/in-order.js.map +1 -0
- package/dist/index.d.ts +20 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -4
- package/dist/index.js.map +1 -1
- package/dist/kill-process-tree.d.ts +43 -0
- package/dist/kill-process-tree.d.ts.map +1 -0
- package/dist/kill-process-tree.js +48 -0
- package/dist/kill-process-tree.js.map +1 -0
- package/dist/link-following.d.ts +115 -0
- package/dist/link-following.d.ts.map +1 -0
- package/dist/link-following.js +283 -0
- package/dist/link-following.js.map +1 -0
- package/dist/listing-refusal.d.ts +44 -0
- package/dist/listing-refusal.d.ts.map +1 -1
- package/dist/listing-refusal.js +79 -2
- package/dist/listing-refusal.js.map +1 -1
- package/dist/name-fold.d.ts +25 -0
- package/dist/name-fold.d.ts.map +1 -0
- package/dist/name-fold.js +40 -0
- package/dist/name-fold.js.map +1 -0
- package/dist/path-containment.d.ts +3 -1
- package/dist/path-containment.d.ts.map +1 -1
- package/dist/path-containment.js +13 -7
- package/dist/path-containment.js.map +1 -1
- package/dist/path-utils.d.ts +14 -17
- package/dist/path-utils.d.ts.map +1 -1
- package/dist/path-utils.js +37 -55
- package/dist/path-utils.js.map +1 -1
- package/dist/process.d.ts +2 -0
- package/dist/process.d.ts.map +1 -1
- package/dist/process.js +2 -0
- package/dist/process.js.map +1 -1
- package/dist/project-utils.d.ts.map +1 -1
- package/dist/project-utils.js +8 -9
- package/dist/project-utils.js.map +1 -1
- package/dist/safe-exec.d.ts +6 -2
- package/dist/safe-exec.d.ts.map +1 -1
- package/dist/safe-exec.js +1 -1
- package/dist/safe-exec.js.map +1 -1
- package/dist/skill-targets.d.ts.map +1 -1
- package/dist/skill-targets.js +3 -1
- package/dist/skill-targets.js.map +1 -1
- package/dist/skill-test/spawn-claude.d.ts +0 -15
- package/dist/skill-test/spawn-claude.d.ts.map +1 -1
- package/dist/skill-test/spawn-claude.js +11 -50
- package/dist/skill-test/spawn-claude.js.map +1 -1
- package/dist/special-file.d.ts +18 -0
- package/dist/special-file.d.ts.map +1 -0
- package/dist/special-file.js +21 -0
- package/dist/special-file.js.map +1 -0
- package/dist/terminating-signals.d.ts +129 -0
- package/dist/terminating-signals.d.ts.map +1 -0
- package/dist/terminating-signals.js +210 -0
- package/dist/terminating-signals.js.map +1 -0
- package/dist/test-helpers.d.ts +9 -5
- package/dist/test-helpers.d.ts.map +1 -1
- package/dist/test-helpers.js +18 -21
- package/dist/test-helpers.js.map +1 -1
- package/dist/test-scratch-guard.d.ts +34 -0
- package/dist/test-scratch-guard.d.ts.map +1 -0
- package/dist/test-scratch-guard.js +45 -0
- package/dist/test-scratch-guard.js.map +1 -0
- package/dist/testing/archive-fixtures.d.ts +147 -0
- package/dist/testing/archive-fixtures.d.ts.map +1 -0
- package/dist/testing/archive-fixtures.js +449 -0
- package/dist/testing/archive-fixtures.js.map +1 -0
- package/dist/testing/executables.d.ts +6 -0
- package/dist/testing/executables.d.ts.map +1 -1
- package/dist/testing/executables.js +20 -9
- package/dist/testing/executables.js.map +1 -1
- package/dist/testing/fault-fs-preload.d.ts +16 -0
- package/dist/testing/fault-fs-preload.d.ts.map +1 -0
- package/dist/testing/fault-fs-preload.js +22 -0
- package/dist/testing/fault-fs-preload.js.map +1 -0
- package/dist/testing/fault-fs.d.ts +115 -0
- package/dist/testing/fault-fs.d.ts.map +1 -0
- package/dist/testing/fault-fs.js +411 -0
- package/dist/testing/fault-fs.js.map +1 -0
- package/dist/testing/fault-spec.d.ts +83 -0
- package/dist/testing/fault-spec.d.ts.map +1 -0
- package/dist/testing/fault-spec.js +132 -0
- package/dist/testing/fault-spec.js.map +1 -0
- package/dist/testing/hostile-tree.d.ts.map +1 -1
- package/dist/testing/hostile-tree.js +3 -4
- package/dist/testing/hostile-tree.js.map +1 -1
- package/dist/testing/platform-gates.d.ts +8 -0
- package/dist/testing/platform-gates.d.ts.map +1 -1
- package/dist/testing/platform-gates.js +24 -0
- package/dist/testing/platform-gates.js.map +1 -1
- package/dist/testing/temp-dir.d.ts +31 -0
- package/dist/testing/temp-dir.d.ts.map +1 -1
- package/dist/testing/temp-dir.js +63 -0
- package/dist/testing/temp-dir.js.map +1 -1
- package/dist/testing/tier-timeout.d.ts +34 -0
- package/dist/testing/tier-timeout.d.ts.map +1 -0
- package/dist/testing/tier-timeout.js +45 -0
- package/dist/testing/tier-timeout.js.map +1 -0
- package/dist/testing/tree-snapshot.d.ts +71 -0
- package/dist/testing/tree-snapshot.d.ts.map +1 -0
- package/dist/testing/tree-snapshot.js +163 -0
- package/dist/testing/tree-snapshot.js.map +1 -0
- package/dist/testing.d.ts +6 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +8 -1
- package/dist/testing.js.map +1 -1
- package/dist/text-file.d.ts +14 -1
- package/dist/text-file.d.ts.map +1 -1
- package/dist/text-file.js +41 -8
- package/dist/text-file.js.map +1 -1
- package/dist/timing-dump.d.ts.map +1 -1
- package/dist/timing-dump.js +2 -10
- package/dist/timing-dump.js.map +1 -1
- package/dist/tree-change/apply-decisions.d.ts +101 -0
- package/dist/tree-change/apply-decisions.d.ts.map +1 -0
- package/dist/tree-change/apply-decisions.js +139 -0
- package/dist/tree-change/apply-decisions.js.map +1 -0
- package/dist/tree-change/apply.d.ts +98 -0
- package/dist/tree-change/apply.d.ts.map +1 -0
- package/dist/tree-change/apply.js +364 -0
- package/dist/tree-change/apply.js.map +1 -0
- package/dist/tree-change/copy-decisions.d.ts +58 -0
- package/dist/tree-change/copy-decisions.d.ts.map +1 -0
- package/dist/tree-change/copy-decisions.js +66 -0
- package/dist/tree-change/copy-decisions.js.map +1 -0
- package/dist/tree-change/copy-tree.d.ts +125 -0
- package/dist/tree-change/copy-tree.d.ts.map +1 -0
- package/dist/tree-change/copy-tree.js +279 -0
- package/dist/tree-change/copy-tree.js.map +1 -0
- package/dist/tree-change/files.d.ts +167 -0
- package/dist/tree-change/files.d.ts.map +1 -0
- package/dist/tree-change/files.js +423 -0
- package/dist/tree-change/files.js.map +1 -0
- package/dist/tree-change/followed-walk.d.ts +54 -0
- package/dist/tree-change/followed-walk.d.ts.map +1 -0
- package/dist/tree-change/followed-walk.js +81 -0
- package/dist/tree-change/followed-walk.js.map +1 -0
- package/dist/tree-change/host-chain.d.ts +48 -0
- package/dist/tree-change/host-chain.d.ts.map +1 -0
- package/dist/tree-change/host-chain.js +85 -0
- package/dist/tree-change/host-chain.js.map +1 -0
- package/dist/tree-change/identity-compare.d.ts +61 -0
- package/dist/tree-change/identity-compare.d.ts.map +1 -0
- package/dist/tree-change/identity-compare.js +115 -0
- package/dist/tree-change/identity-compare.js.map +1 -0
- package/dist/tree-change/identity.d.ts +62 -0
- package/dist/tree-change/identity.d.ts.map +1 -0
- package/dist/tree-change/identity.js +152 -0
- package/dist/tree-change/identity.js.map +1 -0
- package/dist/tree-change/index.d.ts +24 -0
- package/dist/tree-change/index.d.ts.map +1 -0
- package/dist/tree-change/index.js +14 -0
- package/dist/tree-change/index.js.map +1 -0
- package/dist/tree-change/link-chain.d.ts +180 -0
- package/dist/tree-change/link-chain.d.ts.map +1 -0
- package/dist/tree-change/link-chain.js +377 -0
- package/dist/tree-change/link-chain.js.map +1 -0
- package/dist/tree-change/link-containment.d.ts +105 -0
- package/dist/tree-change/link-containment.d.ts.map +1 -0
- package/dist/tree-change/link-containment.js +196 -0
- package/dist/tree-change/link-containment.js.map +1 -0
- package/dist/tree-change/link-walk.d.ts +49 -0
- package/dist/tree-change/link-walk.d.ts.map +1 -0
- package/dist/tree-change/link-walk.js +69 -0
- package/dist/tree-change/link-walk.js.map +1 -0
- package/dist/tree-change/plan.d.ts +206 -0
- package/dist/tree-change/plan.d.ts.map +1 -0
- package/dist/tree-change/plan.js +320 -0
- package/dist/tree-change/plan.js.map +1 -0
- package/dist/tree-change/readable-tree.d.ts +44 -0
- package/dist/tree-change/readable-tree.d.ts.map +1 -0
- package/dist/tree-change/readable-tree.js +52 -0
- package/dist/tree-change/readable-tree.js.map +1 -0
- package/dist/tree-change/rollback-error.d.ts +29 -0
- package/dist/tree-change/rollback-error.d.ts.map +1 -0
- package/dist/tree-change/rollback-error.js +31 -0
- package/dist/tree-change/rollback-error.js.map +1 -0
- package/dist/tree-change/staging-names.d.ts +27 -0
- package/dist/tree-change/staging-names.d.ts.map +1 -0
- package/dist/tree-change/staging-names.js +40 -0
- package/dist/tree-change/staging-names.js.map +1 -0
- package/dist/tree-change/tree-walk.d.ts +81 -0
- package/dist/tree-change/tree-walk.d.ts.map +1 -0
- package/dist/tree-change/tree-walk.js +212 -0
- package/dist/tree-change/tree-walk.js.map +1 -0
- package/dist/win32-namespace.d.ts +24 -0
- package/dist/win32-namespace.d.ts.map +1 -0
- package/dist/win32-namespace.js +31 -0
- package/dist/win32-namespace.js.map +1 -0
- package/dist/yaml/surgical-yaml.d.ts +12 -3
- package/dist/yaml/surgical-yaml.d.ts.map +1 -1
- package/dist/yaml/surgical-yaml.js +16 -6
- package/dist/yaml/surgical-yaml.js.map +1 -1
- package/eslint/README.md +12 -4
- package/eslint/rules/fs-binding-scan.cjs +278 -0
- package/eslint/rules/no-adhoc-errno.cjs +364 -0
- package/eslint/rules/no-bare-symlink-in-tests.cjs +2 -3
- package/eslint/rules/no-blind-catch.cjs +1 -1
- package/eslint/rules/no-destructive-fs.cjs +359 -0
- package/eslint/rules/no-existssync.cjs +70 -0
- package/eslint/rules/no-fragile-entrypoint-guard.cjs +3 -2
- package/eslint/rules/no-link-following-fs.cjs +68 -0
- package/eslint/rules/no-literal-process-exit.cjs +3 -16
- package/eslint/rules/no-literal-test-timeout.cjs +214 -0
- package/eslint/rules/no-raw-signal-listener.cjs +224 -0
- package/eslint/rules/no-stdout-outside-writer.cjs +135 -0
- package/package.json +10 -2
- package/dist/errors/errno.d.ts +0 -51
- package/dist/errors/errno.d.ts.map +0 -1
- package/dist/errors/errno.js +0 -112
- package/dist/errors/errno.js.map +0 -1
- package/eslint/rules/no-fs-promises-cp.cjs +0 -43
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `snapshotTree` — a comparable, content-addressed picture of a directory tree.
|
|
3
|
+
*
|
|
4
|
+
* The fault matrix asks one question of every injected run: did the tree end
|
|
5
|
+
* byte-equal to BEFORE or to GOLDEN, never a third state? Answering it needs the
|
|
6
|
+
* trees as values: a map from relative path to what is there (kind, mode, content
|
|
7
|
+
* hash, link target), and a diff that names every difference in words.
|
|
8
|
+
*
|
|
9
|
+
* ## What it will not do
|
|
10
|
+
*
|
|
11
|
+
* - It never follows a link: a link is `{ kind: 'link', target }` and nothing under it is
|
|
12
|
+
* walked, so a snapshot cannot wander out of its root or loop.
|
|
13
|
+
* - It never opens a special file (FIFO, socket, device): `lstat` decides the kind first and
|
|
14
|
+
* only a regular file is opened, `O_NONBLOCK`, so a FIFO that slipped in between cannot hang it.
|
|
15
|
+
* - It never swallows an unreadable entry. A directory the OS refuses is a loud error naming
|
|
16
|
+
* it, because a gap in the picture would read as "unchanged".
|
|
17
|
+
*
|
|
18
|
+
* ⛔ Framework-free, like everything under `testing/`: no `vitest` import, so the `./testing`
|
|
19
|
+
* subpath keeps the empty third-party set its purity pin asserts.
|
|
20
|
+
*/
|
|
21
|
+
import { createHash } from 'node:crypto';
|
|
22
|
+
import { closeSync, constants, fstatSync, lstatSync, openSync, readdirSync, readFileSync, readlinkSync } from 'node:fs';
|
|
23
|
+
import { isPathAbsentError } from '../errors/errno-table.js';
|
|
24
|
+
import { safePath } from '../path-core.js';
|
|
25
|
+
import { decodeTextContent } from '../text-content.js';
|
|
26
|
+
const NON_BLOCKING = constants.O_NONBLOCK ?? 0;
|
|
27
|
+
const PERMISSION_BITS = 0o7777;
|
|
28
|
+
const ROOT_KEY = '.';
|
|
29
|
+
function unreadable(path, error) {
|
|
30
|
+
return new Error(`snapshotTree: cannot read ${path}: ${error.message}`, { cause: error });
|
|
31
|
+
}
|
|
32
|
+
/** The file's content as it is hashed: byte rewrites first, then (decoded once) text rewrites. */
|
|
33
|
+
function rewritten(content, key, rewrites) {
|
|
34
|
+
const applicable = rewrites.filter((rule) => rule.applies(key));
|
|
35
|
+
let bytes = content;
|
|
36
|
+
for (const rule of applicable)
|
|
37
|
+
if ('rewriteBytes' in rule)
|
|
38
|
+
bytes = rule.rewriteBytes(bytes);
|
|
39
|
+
const textRules = applicable.filter((rule) => 'rewrite' in rule);
|
|
40
|
+
return textRules.length === 0 ? bytes : textRules.reduce((text, rule) => rule.rewrite(text), decodeTextContent(bytes).text);
|
|
41
|
+
}
|
|
42
|
+
function hashFile(path, key, rewrites) {
|
|
43
|
+
let fd;
|
|
44
|
+
try {
|
|
45
|
+
fd = openSync(path, constants.O_RDONLY | NON_BLOCKING);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (isPathAbsentError(error))
|
|
49
|
+
return undefined;
|
|
50
|
+
throw unreadable(path, error);
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const stats = fstatSync(fd);
|
|
54
|
+
if (!stats.isFile())
|
|
55
|
+
return undefined;
|
|
56
|
+
return { mode: stats.mode & PERMISSION_BITS, sha256: createHash('sha256').update(rewritten(readFileSync(fd), key, rewrites)).digest('hex') };
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
throw unreadable(path, error);
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
closeSync(fd);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function linkTarget(path) {
|
|
66
|
+
try {
|
|
67
|
+
return readlinkSync(path);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
throw unreadable(path, error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** The entry at `path`, or undefined when it vanished between listing and looking. */
|
|
74
|
+
function entryAt(path, key, rewrites) {
|
|
75
|
+
let stats;
|
|
76
|
+
try {
|
|
77
|
+
stats = lstatSync(path);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
if (isPathAbsentError(error))
|
|
81
|
+
return undefined;
|
|
82
|
+
throw unreadable(path, error);
|
|
83
|
+
}
|
|
84
|
+
if (stats.isSymbolicLink())
|
|
85
|
+
return { kind: 'link', target: linkTarget(path) };
|
|
86
|
+
if (stats.isDirectory())
|
|
87
|
+
return { kind: 'dir', mode: stats.mode & PERMISSION_BITS };
|
|
88
|
+
if (!stats.isFile())
|
|
89
|
+
return { kind: 'special' };
|
|
90
|
+
const hashed = hashFile(path, key, rewrites);
|
|
91
|
+
return hashed === undefined ? { kind: 'special' } : { kind: 'file', ...hashed };
|
|
92
|
+
}
|
|
93
|
+
function walk(path, key, rewrites, out) {
|
|
94
|
+
const entry = entryAt(path, key, rewrites);
|
|
95
|
+
if (entry === undefined)
|
|
96
|
+
return;
|
|
97
|
+
out.set(key, entry);
|
|
98
|
+
if (entry.kind !== 'dir')
|
|
99
|
+
return;
|
|
100
|
+
let names;
|
|
101
|
+
try {
|
|
102
|
+
names = readdirSync(path);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
throw unreadable(path, error);
|
|
106
|
+
}
|
|
107
|
+
for (const name of names) {
|
|
108
|
+
walk(safePath.join(path, name), key === ROOT_KEY ? name : `${key}/${name}`, rewrites, out);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Snapshot the tree at `root`.
|
|
113
|
+
*
|
|
114
|
+
* @param root - A directory, a file or a link; absent yields the empty map
|
|
115
|
+
* @param options - Content rewrites applied before hashing; a key prefix for merging roots
|
|
116
|
+
* @returns Entries in walk order; compare with {@link diffSnapshots}
|
|
117
|
+
*/
|
|
118
|
+
export function snapshotTree(root, options = {}) {
|
|
119
|
+
const out = new Map();
|
|
120
|
+
walk(root, options.keyPrefix ?? ROOT_KEY, options.rewrites ?? [], out);
|
|
121
|
+
return out;
|
|
122
|
+
}
|
|
123
|
+
function describeEntry(entry) {
|
|
124
|
+
switch (entry.kind) {
|
|
125
|
+
case 'file': return `file mode ${entry.mode.toString(8)} sha256 ${entry.sha256.slice(0, 12)}`;
|
|
126
|
+
case 'dir': return `dir mode ${entry.mode.toString(8)}`;
|
|
127
|
+
case 'link': return `link -> ${entry.target}`;
|
|
128
|
+
case 'special': return 'special file';
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/** Everything an entry is compared by: what a diff line prints shows only the head of a file's hash. */
|
|
132
|
+
function stateOf(entry) {
|
|
133
|
+
return entry.kind === 'file' ? `${describeEntry(entry)} ${entry.sha256}` : describeEntry(entry);
|
|
134
|
+
}
|
|
135
|
+
function compareKeys(x, y) {
|
|
136
|
+
if (x === y)
|
|
137
|
+
return 0;
|
|
138
|
+
return x < y ? -1 : 1;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Every difference between two snapshots, in words: `+ key (…)` added, `- key (…)`
|
|
142
|
+
* removed, `~ key: … => …` changed. Sorted by key; empty means identical.
|
|
143
|
+
*/
|
|
144
|
+
export function diffSnapshots(a, b) {
|
|
145
|
+
const lines = [];
|
|
146
|
+
for (const [key, before] of a) {
|
|
147
|
+
const after = b.get(key);
|
|
148
|
+
if (after === undefined)
|
|
149
|
+
lines.push({ key, line: `- ${key} (${describeEntry(before)})` });
|
|
150
|
+
else if (stateOf(before) !== stateOf(after))
|
|
151
|
+
lines.push({ key, line: `~ ${key}: ${describeEntry(before)} => ${describeEntry(after)}` });
|
|
152
|
+
}
|
|
153
|
+
for (const [key, after] of b) {
|
|
154
|
+
if (!a.has(key))
|
|
155
|
+
lines.push({ key, line: `+ ${key} (${describeEntry(after)})` });
|
|
156
|
+
}
|
|
157
|
+
return lines.toSorted((x, y) => compareKeys(x.key, y.key)).map((item) => item.line);
|
|
158
|
+
}
|
|
159
|
+
/** The entries at `prefix` and under it (keys unchanged); a sibling sharing the spelling is not under it. */
|
|
160
|
+
export function subtree(s, prefix) {
|
|
161
|
+
return new Map([...s].filter(([key]) => key === prefix || key.startsWith(`${prefix}/`)));
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=tree-snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree-snapshot.js","sourceRoot":"","sources":["../../src/testing/tree-snapshot.ts"],"names":[],"mappings":"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"}
|
package/dist/testing.d.ts
CHANGED
|
@@ -21,10 +21,16 @@
|
|
|
21
21
|
import type { UnreadablePolicy } from './listing-refusal.js';
|
|
22
22
|
export * from './test-helpers.js';
|
|
23
23
|
export { __readCrawlTimingSnapshot, __setCrawlTimingForTest, __writeCrawlTimingDumpForTest, } from './crawl-timing.js';
|
|
24
|
+
export * from './testing/archive-fixtures.js';
|
|
24
25
|
export * from './testing/executables.js';
|
|
26
|
+
export * from './testing/fault-fs.js';
|
|
27
|
+
export { faultFsSpecOf, faultRuleOf, INJECTED_ERRNOS, injectedErrnoError } from './testing/fault-spec.js';
|
|
28
|
+
export type { FaultFsSpec, FaultRule, FaultSpec, FsApi, FsOpFamily, InjectedErrno } from './testing/fault-spec.js';
|
|
25
29
|
export * from './testing/hostile-tree.js';
|
|
26
30
|
export * from './testing/platform-gates.js';
|
|
27
31
|
export * from './testing/temp-dir.js';
|
|
32
|
+
export * from './testing/tier-timeout.js';
|
|
33
|
+
export * from './testing/tree-snapshot.js';
|
|
28
34
|
/** A planted fixture tree and the means to remove it. */
|
|
29
35
|
export interface TempCorpus {
|
|
30
36
|
/** Absolute path to the tree's root. */
|
package/dist/testing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAO7D,cAAc,mBAAmB,CAAC;AAIlC,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAG3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAO7D,cAAc,mBAAmB,CAAC;AAIlC,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAG3B,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AAGtC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC1G,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACnH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAE3C,yDAAyD;AACzD,MAAM,WAAW,UAAU;IACzB,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACvC,UAAU,CAMZ;AAED,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,2EAA2E;IAC3E,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,wDAAwD;IACxD,IAAI,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACvC,iBAAiB,CAyBnB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAEtE"}
|
package/dist/testing.js
CHANGED
|
@@ -31,10 +31,17 @@ export * from './test-helpers.js';
|
|
|
31
31
|
export { __readCrawlTimingSnapshot, __setCrawlTimingForTest, __writeCrawlTimingDumpForTest, } from './crawl-timing.js';
|
|
32
32
|
// The three fixture modules the sinks' suites share: the ONE temp-dir family,
|
|
33
33
|
// the host gates, and the hostile tree every sink is tested against.
|
|
34
|
+
export * from './testing/archive-fixtures.js';
|
|
34
35
|
export * from './testing/executables.js';
|
|
36
|
+
export * from './testing/fault-fs.js';
|
|
37
|
+
// By name: the harness's vocabulary, not its op table (`OPS`, `OpSpec`, `PathShape` are `fault-fs.ts`'s
|
|
38
|
+
// own wiring, and an `export *` here made them this subpath's API). Pinned by `module-subpaths.test.ts`.
|
|
39
|
+
export { faultFsSpecOf, faultRuleOf, INJECTED_ERRNOS, injectedErrnoError } from './testing/fault-spec.js';
|
|
35
40
|
export * from './testing/hostile-tree.js';
|
|
36
41
|
export * from './testing/platform-gates.js';
|
|
37
42
|
export * from './testing/temp-dir.js';
|
|
43
|
+
export * from './testing/tier-timeout.js';
|
|
44
|
+
export * from './testing/tree-snapshot.js';
|
|
38
45
|
/**
|
|
39
46
|
* Write a literal corpus into a fresh temp directory.
|
|
40
47
|
*
|
|
@@ -119,6 +126,6 @@ export function replantableCorpus(prefix, corpus) {
|
|
|
119
126
|
* @returns A `refuse` policy for `crawlDirectory` and the git listings
|
|
120
127
|
*/
|
|
121
128
|
export function refuseUnreadableFixture(root) {
|
|
122
|
-
return { refuse: { root, remedy: 'A test fixture must be listable in full; fix the fixture, not the walk.' } };
|
|
129
|
+
return { refuse: { root, remedy: 'A test fixture must be listable in full; fix the fixture, not the walk.', side: 'source' } };
|
|
123
130
|
}
|
|
124
131
|
//# sourceMappingURL=testing.js.map
|
package/dist/testing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG7D,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7D,6EAA6E;AAC7E,2EAA2E;AAC3E,+EAA+E;AAC/E,sEAAsE;AACtE,cAAc,mBAAmB,CAAC;AAClC,2EAA2E;AAC3E,8EAA8E;AAC9E,gEAAgE;AAChE,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,8EAA8E;AAC9E,qEAAqE;AACrE,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG7D,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7D,6EAA6E;AAC7E,2EAA2E;AAC3E,+EAA+E;AAC/E,sEAAsE;AACtE,cAAc,mBAAmB,CAAC;AAClC,2EAA2E;AAC3E,8EAA8E;AAC9E,gEAAgE;AAChE,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,8EAA8E;AAC9E,qEAAqE;AACrE,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,wGAAwG;AACxG,yGAAyG;AACzG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE1G,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAU3C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAc,EACd,MAAwC;IAExC,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IACpE,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACrD,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACjF,CAAC;AAYD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,MAAwC;IAExC,IAAI,OAA+B,CAAC;IACpC,OAAO;QACL,KAAK,EAAE,GAAG,EAAE;YACV,0EAA0E;YAC1E,uEAAuE;YACvE,wEAAwE;YACxE,wEAAwE;YACxE,iEAAiE;YACjE,OAAO,EAAE,OAAO,EAAE,CAAC;YACnB,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7C,CAAC;QACD,KAAK,EAAE,GAAG,EAAE;YACV,OAAO,EAAE,OAAO,EAAE,CAAC;YACnB,OAAO,GAAG,SAAS,CAAC;QACtB,CAAC;QACD,IAAI,EAAE,GAAG,EAAE;YACT,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CACb,sBAAsB,MAAM,iEAAiE,CAC9F,CAAC;YACJ,CAAC;YACD,OAAO,OAAO,CAAC,IAAI,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,yEAAyE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC;AACjI,CAAC"}
|
package/dist/text-file.d.ts
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* and the characters come from the same read. `readContentWithKey` in
|
|
20
20
|
* `@vibe-agent-toolkit/resources` is that caller and is shaped exactly that way.
|
|
21
21
|
*/
|
|
22
|
+
import { type FileHandle } from 'node:fs/promises';
|
|
22
23
|
import { type DecodedText } from './text-content.js';
|
|
23
24
|
/**
|
|
24
25
|
* Read a file and decode it through {@link decodeTextContent}.
|
|
@@ -59,6 +60,18 @@ export declare const MAX_DECODABLE_BYTES: number;
|
|
|
59
60
|
* @returns True when decoding it would exceed {@link MAX_DECODABLE_BYTES}
|
|
60
61
|
*/
|
|
61
62
|
export declare function exceedsDecodableLength(byteLength: number): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Open `filePath` for reading without ever blocking on it: a named pipe, socket
|
|
65
|
+
* or device is refused (`EFTYPE`) and its handle closed, so only a regular file
|
|
66
|
+
* (or a directory, which the read refuses itself) comes back. The open a caller
|
|
67
|
+
* uses to PROVE a source readable before copying it — a bare `open(path, 'r')`
|
|
68
|
+
* of a pipe waits for a writer forever.
|
|
69
|
+
*
|
|
70
|
+
* @param filePath - Path to open
|
|
71
|
+
* @returns The open handle; the caller closes it
|
|
72
|
+
* @throws an `EFTYPE` errno for a special file, and whatever `open` throws otherwise
|
|
73
|
+
*/
|
|
74
|
+
export declare function openForReading(filePath: string): Promise<FileHandle>;
|
|
62
75
|
/**
|
|
63
76
|
* Read a file's raw bytes for decoding — refusing, by `stat` and before reading
|
|
64
77
|
* a byte, one too large to decode at all.
|
|
@@ -78,7 +91,7 @@ export declare function exceedsDecodableLength(byteLength: number): boolean;
|
|
|
78
91
|
* @param filePath - Path to read
|
|
79
92
|
* @returns The file's bytes
|
|
80
93
|
* @throws {@link TextTooLargeError} when the file is past {@link MAX_DECODABLE_BYTES},
|
|
81
|
-
* and whatever `open`/`readFile` throw otherwise
|
|
94
|
+
* an `EFTYPE` errno when it is not a regular file, and whatever `open`/`readFile` throw otherwise
|
|
82
95
|
*/
|
|
83
96
|
export declare function readDecodableBytes(filePath: string): Promise<Buffer>;
|
|
84
97
|
//# sourceMappingURL=text-file.d.ts.map
|
package/dist/text-file.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-file.d.ts","sourceRoot":"","sources":["../src/text-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;
|
|
1
|
+
{"version":3,"file":"text-file.d.ts","sourceRoot":"","sources":["../src/text-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGzD,OAAO,EAAwC,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE3F;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAE5E;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAUjE;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAoC,CAAC;AAEvE;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAElE;AAoBD;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAS1E;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ1E"}
|
package/dist/text-file.js
CHANGED
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
* `@vibe-agent-toolkit/resources` is that caller and is shaped exactly that way.
|
|
21
21
|
*/
|
|
22
22
|
import { constants } from 'node:buffer';
|
|
23
|
-
import { closeSync, fstatSync, openSync, readFileSync } from 'node:fs';
|
|
23
|
+
import { closeSync, constants as fsConstants, fstatSync, openSync, readFileSync } from 'node:fs';
|
|
24
24
|
import { open } from 'node:fs/promises';
|
|
25
|
+
import { refuseSpecialFile } from './special-file.js';
|
|
25
26
|
import { decodeTextContent, TextTooLargeError } from './text-content.js';
|
|
26
27
|
/**
|
|
27
28
|
* Read a file and decode it through {@link decodeTextContent}.
|
|
@@ -48,9 +49,11 @@ export async function readTextContent(filePath) {
|
|
|
48
49
|
* @throws Whatever `readFileSync` throws, and {@link TextTooLargeError} as {@link readDecodableBytes} does
|
|
49
50
|
*/
|
|
50
51
|
export function readTextContentSync(filePath) {
|
|
51
|
-
const handle = openSync(filePath,
|
|
52
|
+
const handle = openSync(filePath, readWithoutBlocking());
|
|
52
53
|
try {
|
|
53
|
-
|
|
54
|
+
const stats = fstatSync(handle);
|
|
55
|
+
refuseSpecialFile(stats, filePath);
|
|
56
|
+
refuseUndecodableSize(stats.size);
|
|
54
57
|
return decodeTextContent(readFileSync(handle));
|
|
55
58
|
}
|
|
56
59
|
finally {
|
|
@@ -76,14 +79,44 @@ export function exceedsDecodableLength(byteLength) {
|
|
|
76
79
|
return byteLength > MAX_DECODABLE_BYTES;
|
|
77
80
|
}
|
|
78
81
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
+
* The flags to open for reading without waiting on a writer. Opening a named
|
|
83
|
+
* pipe blocks until one appears — a FIFO reached by a parse lane hung the whole
|
|
84
|
+
* run — and `O_NONBLOCK` returns at once so the handle's `fstat` can refuse it.
|
|
85
|
+
* It changes nothing for a regular file. Windows defines no `O_NONBLOCK` (and no
|
|
86
|
+
* FIFOs). Read at the call, not at import, so a test's partial `node:fs` mock
|
|
87
|
+
* that never reads a file does not have to supply `constants`.
|
|
82
88
|
*/
|
|
89
|
+
function readWithoutBlocking() {
|
|
90
|
+
const nonBlocking = fsConstants.O_NONBLOCK;
|
|
91
|
+
return fsConstants.O_RDONLY | (nonBlocking ?? 0);
|
|
92
|
+
}
|
|
93
|
+
/** Throw {@link TextTooLargeError} for a size no decode can hold. */
|
|
83
94
|
function refuseUndecodableSize(byteLength) {
|
|
84
95
|
if (exceedsDecodableLength(byteLength))
|
|
85
96
|
throw new TextTooLargeError(byteLength);
|
|
86
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Open `filePath` for reading without ever blocking on it: a named pipe, socket
|
|
100
|
+
* or device is refused (`EFTYPE`) and its handle closed, so only a regular file
|
|
101
|
+
* (or a directory, which the read refuses itself) comes back. The open a caller
|
|
102
|
+
* uses to PROVE a source readable before copying it — a bare `open(path, 'r')`
|
|
103
|
+
* of a pipe waits for a writer forever.
|
|
104
|
+
*
|
|
105
|
+
* @param filePath - Path to open
|
|
106
|
+
* @returns The open handle; the caller closes it
|
|
107
|
+
* @throws an `EFTYPE` errno for a special file, and whatever `open` throws otherwise
|
|
108
|
+
*/
|
|
109
|
+
export async function openForReading(filePath) {
|
|
110
|
+
const handle = await open(filePath, readWithoutBlocking());
|
|
111
|
+
try {
|
|
112
|
+
refuseSpecialFile(await handle.stat(), filePath);
|
|
113
|
+
return handle;
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
await handle.close();
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
87
120
|
/**
|
|
88
121
|
* Read a file's raw bytes for decoding — refusing, by `stat` and before reading
|
|
89
122
|
* a byte, one too large to decode at all.
|
|
@@ -103,10 +136,10 @@ function refuseUndecodableSize(byteLength) {
|
|
|
103
136
|
* @param filePath - Path to read
|
|
104
137
|
* @returns The file's bytes
|
|
105
138
|
* @throws {@link TextTooLargeError} when the file is past {@link MAX_DECODABLE_BYTES},
|
|
106
|
-
* and whatever `open`/`readFile` throw otherwise
|
|
139
|
+
* an `EFTYPE` errno when it is not a regular file, and whatever `open`/`readFile` throw otherwise
|
|
107
140
|
*/
|
|
108
141
|
export async function readDecodableBytes(filePath) {
|
|
109
|
-
const handle = await
|
|
142
|
+
const handle = await openForReading(filePath);
|
|
110
143
|
try {
|
|
111
144
|
refuseUndecodableSize((await handle.stat()).size);
|
|
112
145
|
return await handle.readFile();
|
package/dist/text-file.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-file.js","sourceRoot":"","sources":["../src/text-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"text-file.js","sourceRoot":"","sources":["../src/text-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,SAAS,IAAI,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACjG,OAAO,EAAE,IAAI,EAAmB,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAoB,MAAM,mBAAmB,CAAC;AAE3F;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB;IACpD,OAAO,iBAAiB,CAAC,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,EAAE,CAAC,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QAChC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACnC,qBAAqB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,OAAO,iBAAiB,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IACjD,CAAC;YAAS,CAAC;QACT,SAAS,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAW,SAAS,CAAC,iBAAiB,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,UAAkB;IACvD,OAAO,UAAU,GAAG,mBAAmB,CAAC;AAC1C,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,mBAAmB;IAC1B,MAAM,WAAW,GAAuB,WAAW,CAAC,UAAU,CAAC;IAC/D,OAAO,WAAW,CAAC,QAAQ,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,qEAAqE;AACrE,SAAS,qBAAqB,CAAC,UAAkB;IAC/C,IAAI,sBAAsB,CAAC,UAAU,CAAC;QAAE,MAAM,IAAI,iBAAiB,CAAC,UAAU,CAAC,CAAC;AAClF,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB;IACnD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAC3D,IAAI,CAAC;QACH,iBAAiB,CAAC,MAAM,MAAM,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;QACjD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAgB;IACvD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC;QACH,qBAAqB,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAClD,OAAO,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timing-dump.d.ts","sourceRoot":"","sources":["../src/timing-dump.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;
|
|
1
|
+
{"version":3,"file":"timing-dump.d.ts","sourceRoot":"","sources":["../src/timing-dump.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAQH;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;CACrB;AAQD;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,OAAO,CAAC;AA6BxC;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAE/E;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAG1F;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAM3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,IAAI,aAAa,CAOjD;AA+CD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,OAAO,GACnB,MAAM,GAAG,IAAI,CAoBf"}
|
package/dist/timing-dump.js
CHANGED
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
* itself is its accumulator shape, its dump body and the noun it is called by.
|
|
49
49
|
*/
|
|
50
50
|
import { writeFileSync } from 'node:fs';
|
|
51
|
+
import { isAlreadyExistsError } from './errors/errno-table.js';
|
|
51
52
|
import { safePath } from './path-core.js';
|
|
52
53
|
import { mkdirSyncReal } from './path-utils.js';
|
|
53
54
|
/** `process.cpuUsage()` reports microseconds; a dump reports milliseconds. */
|
|
@@ -152,15 +153,6 @@ function timingDumpCandidate(directory, stem, collision) {
|
|
|
152
153
|
const suffix = collision === 0 ? '' : `-${String(collision)}`;
|
|
153
154
|
return safePath.join(directory, `${stem}${suffix}.json`);
|
|
154
155
|
}
|
|
155
|
-
/**
|
|
156
|
-
* Whether a caught write failure means somebody else already holds the name.
|
|
157
|
-
*
|
|
158
|
-
* @param error - Whatever `writeFileSync` threw
|
|
159
|
-
* @returns `true` only for `EEXIST`, which is a lost race and not a fault
|
|
160
|
-
*/
|
|
161
|
-
function isNameAlreadyTaken(error) {
|
|
162
|
-
return error instanceof Error && 'code' in error && error.code === 'EEXIST';
|
|
163
|
-
}
|
|
164
156
|
/**
|
|
165
157
|
* Claim a name by creating it, and fill it in the same operation.
|
|
166
158
|
*
|
|
@@ -185,7 +177,7 @@ function claimTimingDump(directory, basename, contents) {
|
|
|
185
177
|
return { outcome: 'written', path: candidate };
|
|
186
178
|
}
|
|
187
179
|
catch (error) {
|
|
188
|
-
if (!
|
|
180
|
+
if (!isAlreadyExistsError(error))
|
|
189
181
|
return { outcome: 'failed', path: candidate, error };
|
|
190
182
|
}
|
|
191
183
|
}
|
package/dist/timing-dump.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timing-dump.js","sourceRoot":"","sources":["../src/timing-dump.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAoBhD,8EAA8E;AAC9E,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAEjC,uEAAuE;AACvE,MAAM,aAAa,GAAG,IAAI,CAAC;AAE3B;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAExC;;;;;;;;;GASG;AACH,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B,mFAAmF;AACnF,MAAM,cAAc,GAAG,wBAAwB,MAAM,CAAC,mBAAmB,CAAC,wCAAwC,CAAC;AAcnH;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAuB;IAC9D,OAAO,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;AACtD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY,EAAE,MAAc,EAAE,KAAc;IAClF,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,IAAI,oBAAoB,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY,EAAE,SAAiB;IACnE,IAAI,CAAC;QACH,aAAa,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uBAAuB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC/B,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,aAAa;QACxC,SAAS,EAAE,GAAG,CAAC,IAAI,GAAG,mBAAmB;QACzC,WAAW,EAAE,GAAG,CAAC,MAAM,GAAG,mBAAmB;KAC9C,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,mBAAmB,CAAC,SAAiB,EAAE,IAAY,EAAE,SAAiB;IAC7E,MAAM,MAAM,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;IAC9D,OAAO,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,GAAG,MAAM,OAAO,CAAC,CAAC;AAC3D,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"timing-dump.js","sourceRoot":"","sources":["../src/timing-dump.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The decisions of the apply half of the tree-change primitive, and of its file helpers, that touch
|
|
3
|
+
* no filesystem: each is handed what was read and answers what to do. `apply.ts` and `files.ts` are
|
|
4
|
+
* the halves that make the calls — and hold nothing else to decide.
|
|
5
|
+
*/
|
|
6
|
+
import { type FsFaultFacts } from '../errors/errno-table.js';
|
|
7
|
+
import { FsFaultError, type FsSide } from '../errors/fs-fault.js';
|
|
8
|
+
import { VatError } from '../errors/vat-error.js';
|
|
9
|
+
import type { EntryKind, PlannedChange } from './plan.js';
|
|
10
|
+
/** {@link tempDirRefusal}: a directory to dispose of that is not strictly under the temp directory — a defect in the caller. */
|
|
11
|
+
export declare const TEMP_DIR_OUTSIDE_TMPDIR_CODE = "TEMP_DIR_OUTSIDE_TMPDIR";
|
|
12
|
+
/** A replaced entry, parked once the new one was live, that could not be removed. */
|
|
13
|
+
export declare const TREE_CLEANUP_INCOMPLETE_CODE = "TREE_CLEANUP_INCOMPLETE";
|
|
14
|
+
/**
|
|
15
|
+
* Whether a `write` fill's failure is the DESTINATION's: a path the failing call acted on
|
|
16
|
+
* ({@link pathsActedOn} — the one reading of an errno's two paths, so never a symlink's target
|
|
17
|
+
* text) is under the staged tree, all the callback may write. Anything else, an input the
|
|
18
|
+
* callback read (a sibling of the destination included), is not: it is rethrown as it was, for
|
|
19
|
+
* the verb's boundary to classify.
|
|
20
|
+
*
|
|
21
|
+
* @param facts - The errno, the call and the paths the OS named
|
|
22
|
+
* @param sideOf - The side a path is on, with the staged tree as the only `destination`
|
|
23
|
+
*/
|
|
24
|
+
export declare function fillFaultIsDestinations(facts: FsFaultFacts, sideOf: (path: string) => FsSide | undefined): boolean;
|
|
25
|
+
/** What is at a destination when the apply reaches it. */
|
|
26
|
+
interface DestinationNow {
|
|
27
|
+
readonly kind: EntryKind;
|
|
28
|
+
/** Whether it is a directory holding nothing; read only when the plan took an empty directory as free. */
|
|
29
|
+
readonly emptyDirectory: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Whether a destination is no longer what the plan decided on — staging (a whole copy, a whole
|
|
33
|
+
* build) runs between the plan and the first rename, and anything can write there meanwhile:
|
|
34
|
+
* - another KIND of entry than the plan saw (nothing where it parks; something where it creates);
|
|
35
|
+
* - a directory a `must-be-free` change took because it was EMPTY, and now is not.
|
|
36
|
+
*
|
|
37
|
+
* @returns What changed, for the refusal's wording; `undefined` when it is as planned
|
|
38
|
+
*/
|
|
39
|
+
export declare function changedSincePlan(planned: PlannedChange, now: DestinationNow): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* The refusal of a destination that changed under the apply: the table's `occupied` destination
|
|
42
|
+
* fault (something appeared while the command wrote), naming it and what changed. The entry is
|
|
43
|
+
* left exactly as it was found.
|
|
44
|
+
*/
|
|
45
|
+
export declare function changedDestinationFault(planned: PlannedChange, what: string): FsFaultError;
|
|
46
|
+
/**
|
|
47
|
+
* What a finalize does with the parked entries it could not remove: a REMOVE's is thrown (removal
|
|
48
|
+
* was the job; the first one, with every other recorded beside it), a replace's is a warning — the
|
|
49
|
+
* new tree is live.
|
|
50
|
+
*
|
|
51
|
+
* @param refused - Each parked entry that would not go, with the op of its change
|
|
52
|
+
* @returns The index of the one to throw, or `undefined` when every one is a warning
|
|
53
|
+
*/
|
|
54
|
+
export declare function finalizeThrows(refused: ReadonlyArray<{
|
|
55
|
+
readonly op: PlannedChange['change']['op'];
|
|
56
|
+
}>): number | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Where the removal of the parents a create made goes next: `dir` is removed only while it is
|
|
59
|
+
* `top` (the first directory `mkdir` made) or under it, and the walk stops once `top` itself went.
|
|
60
|
+
*
|
|
61
|
+
* @param top - The first directory staging made, canonical
|
|
62
|
+
* @param dir - The directory about to be removed, canonical
|
|
63
|
+
* @returns `stop` (outside what staging made: never touched), `last` (it is `top`), or `continue` (go on to its parent)
|
|
64
|
+
*/
|
|
65
|
+
export declare function madeParentStep(top: string, dir: string): 'stop' | 'last' | 'continue';
|
|
66
|
+
/**
|
|
67
|
+
* The refusal of a file VAT writes into a tree it is building, where what was copied into that tree
|
|
68
|
+
* already holds an entry on the way — a file or a link at the file's own name, or a link (or a file)
|
|
69
|
+
* where one of its directories goes. Whatever is there came with the tree, so it is the SOURCE's
|
|
70
|
+
* layout (origin `content`), never something to write over or through.
|
|
71
|
+
*
|
|
72
|
+
* @param entry - The entry in the way, as a path
|
|
73
|
+
* @param writing - What VAT was writing, for the message: `VAT's marketplace marker`
|
|
74
|
+
* @param cause - The errno that reported it, when one did
|
|
75
|
+
*/
|
|
76
|
+
export declare function entryInTheWayFault(entry: string, writing: string, cause: unknown): FsFaultError;
|
|
77
|
+
/** A rename is tried this many times under win32 when the OS reports contention; the waits between are 50, 100, 200, 400, 800 ms. */
|
|
78
|
+
export declare const RENAME_TRIES = 6;
|
|
79
|
+
/**
|
|
80
|
+
* Whether a refused rename is tried again, and after how long: only under win32, only for
|
|
81
|
+
* contention (a scanner, an indexer, a handle still closing), and only while tries are left.
|
|
82
|
+
*
|
|
83
|
+
* @param platform - `process.platform`
|
|
84
|
+
* @param attempt - The 0-based try that just failed
|
|
85
|
+
* @param contention - Whether the errno is one a rename race raises there
|
|
86
|
+
* @returns The wait in milliseconds before the next try, or `undefined` when the refusal is final
|
|
87
|
+
*/
|
|
88
|
+
export declare function renameRetryDelay(platform: NodeJS.Platform, attempt: number, contention: boolean): number | undefined;
|
|
89
|
+
/**
|
|
90
|
+
* The refusal — a defect in the caller — of a directory to dispose of that is not strictly under
|
|
91
|
+
* the temp directory: the disposal makes a read-only tree writable before it deletes it, so a wrong
|
|
92
|
+
* argument (an empty string, a project directory) must be refused before anything is touched.
|
|
93
|
+
*
|
|
94
|
+
* @param dir - The directory handed to the disposal
|
|
95
|
+
* @param tmp - The temp directory
|
|
96
|
+
* @param containment - Where `dir` is against `tmp`, as `isUnderRoot` judged it
|
|
97
|
+
* @returns The error to throw, or `undefined` when `dir` may be disposed of
|
|
98
|
+
*/
|
|
99
|
+
export declare function tempDirRefusal(dir: string, tmp: string, containment: 'inside' | 'outside' | 'absent'): VatError | undefined;
|
|
100
|
+
export {};
|
|
101
|
+
//# sourceMappingURL=apply-decisions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-decisions.d.ts","sourceRoot":"","sources":["../../src/tree-change/apply-decisions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,YAAY,EAAgB,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGlD,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1D,gIAAgI;AAChI,eAAO,MAAM,4BAA4B,4BAA4B,CAAC;AAEtE,qFAAqF;AACrF,eAAO,MAAM,4BAA4B,4BAA4B,CAAC;AAEtE;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAAG,OAAO,CAElH;AAED,0DAA0D;AAC1D,UAAU,cAAc;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,0GAA0G;IAC1G,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAMhG;AAID;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAW1F;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,CAAC;IAAE,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,GAAG,MAAM,GAAG,SAAS,CAGzH;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAIrF;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,YAAY,CAU/F;AAED,qIAAqI;AACrI,eAAO,MAAM,YAAY,IAAI,CAAC;AAG9B;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAGpH;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAG3H"}
|