@openclaw/fs-safe 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -0
- package/README.md +17 -0
- package/dist/advanced.d.ts +1 -0
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +1 -0
- package/dist/archive-crc32.d.ts.map +1 -1
- package/dist/archive-crc32.js +6 -1
- package/dist/archive-deadline.d.ts.map +1 -1
- package/dist/archive-deadline.js +3 -4
- package/dist/archive-gzip-tail.d.ts +2 -0
- package/dist/archive-gzip-tail.d.ts.map +1 -1
- package/dist/archive-gzip-tail.js +20 -3
- package/dist/archive-merge.js +1 -1
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +3 -2
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +67 -66
- package/dist/archive-tar-stream.d.ts +11 -4
- package/dist/archive-tar-stream.d.ts.map +1 -1
- package/dist/archive-tar-stream.js +20 -8
- package/dist/archive-tar-wasm.d.ts.map +1 -1
- package/dist/archive-tar-wasm.js +2 -1
- package/dist/bounded-read.d.ts +7 -0
- package/dist/bounded-read.d.ts.map +1 -1
- package/dist/bounded-read.js +73 -43
- package/dist/clone-metadata.d.ts +19 -0
- package/dist/clone-metadata.d.ts.map +1 -0
- package/dist/clone-metadata.js +32 -0
- package/dist/copy-file-input.d.ts +23 -0
- package/dist/copy-file-input.d.ts.map +1 -0
- package/dist/copy-file-input.js +91 -0
- package/dist/copy-policy.d.ts +3 -0
- package/dist/copy-policy.d.ts.map +1 -0
- package/dist/copy-policy.js +8 -0
- package/dist/copy-publication.d.ts +10 -1
- package/dist/copy-publication.d.ts.map +1 -1
- package/dist/copy-publication.js +27 -0
- package/dist/copy-tree-portable.d.ts +9 -0
- package/dist/copy-tree-portable.d.ts.map +1 -0
- package/dist/copy-tree-portable.js +191 -0
- package/dist/copy.d.ts +16 -0
- package/dist/copy.d.ts.map +1 -0
- package/dist/copy.js +123 -0
- package/dist/durability.d.ts +1 -1
- package/dist/durability.d.ts.map +1 -1
- package/dist/error-detail.d.ts.map +1 -1
- package/dist/error-detail.js +4 -1
- package/dist/file-hash.d.ts +6 -2
- package/dist/file-hash.d.ts.map +1 -1
- package/dist/file-hash.js +44 -8
- package/dist/filename.d.ts.map +1 -1
- package/dist/filename.js +2 -12
- package/dist/guarded-mkdir.d.ts +1 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +1 -0
- package/dist/guarded-mutation.d.ts +2 -0
- package/dist/guarded-mutation.d.ts.map +1 -1
- package/dist/guarded-mutation.js +8 -4
- package/dist/home-dir.d.ts.map +1 -1
- package/dist/home-dir.js +9 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/install-path.d.ts.map +1 -1
- package/dist/install-path.js +2 -6
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +13 -14
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +22 -24
- package/dist/move-path-stage.d.ts +8 -0
- package/dist/move-path-stage.d.ts.map +1 -0
- package/dist/move-path-stage.js +55 -0
- package/dist/move-path.d.ts.map +1 -1
- package/dist/move-path.js +26 -31
- package/dist/mutation-authority.d.ts +8 -0
- package/dist/mutation-authority.d.ts.map +1 -0
- package/dist/mutation-authority.js +36 -0
- package/dist/native-binding.d.ts +24 -1
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-operations.d.ts +1 -1
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +11 -5
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +18 -7
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +1 -0
- package/dist/native-staged-file.d.ts +3 -3
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +35 -8
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +3 -1
- package/dist/permissions-windows.d.ts.map +1 -1
- package/dist/permissions-windows.js +38 -48
- package/dist/pinned-operation.js +1 -1
- package/dist/pinned-write.d.ts +5 -1
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +50 -30
- package/dist/positional-read.d.ts +9 -0
- package/dist/positional-read.d.ts.map +1 -0
- package/dist/positional-read.js +36 -0
- package/dist/publish-copy-stage.d.ts +13 -0
- package/dist/publish-copy-stage.d.ts.map +1 -0
- package/dist/publish-copy-stage.js +47 -0
- package/dist/publish-file.d.ts.map +1 -1
- package/dist/publish-file.js +6 -5
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +6 -2
- package/dist/root-context.d.ts +3 -0
- package/dist/root-context.d.ts.map +1 -1
- package/dist/root-context.js +51 -26
- package/dist/root-directory-list.d.ts +24 -0
- package/dist/root-directory-list.d.ts.map +1 -0
- package/dist/root-directory-list.js +201 -0
- package/dist/root-errors.d.ts +1 -0
- package/dist/root-errors.d.ts.map +1 -1
- package/dist/root-errors.js +3 -0
- package/dist/root-file.d.ts +2 -0
- package/dist/root-file.d.ts.map +1 -1
- package/dist/root-file.js +12 -4
- package/dist/root-impl.d.ts +6 -50
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +330 -210
- package/dist/root-options.d.ts +66 -0
- package/dist/root-options.d.ts.map +1 -0
- package/dist/root-options.js +18 -0
- package/dist/root-path-existing.d.ts +5 -0
- package/dist/root-path-existing.d.ts.map +1 -1
- package/dist/root-path-existing.js +56 -1
- package/dist/root-path.d.ts +1 -0
- package/dist/root-path.d.ts.map +1 -1
- package/dist/root-path.js +74 -162
- package/dist/root-symlink-policy.d.ts +13 -0
- package/dist/root-symlink-policy.d.ts.map +1 -0
- package/dist/root-symlink-policy.js +34 -0
- package/dist/root-walk.d.ts +5 -4
- package/dist/root-walk.d.ts.map +1 -1
- package/dist/root-walk.js +99 -50
- package/dist/root-write-mode.d.ts.map +1 -1
- package/dist/root-write-mode.js +1 -4
- package/dist/root.d.ts +3 -1
- package/dist/root.d.ts.map +1 -1
- package/dist/secure-file.d.ts.map +1 -1
- package/dist/secure-file.js +4 -4
- package/dist/sidecar-lock-acquire.d.ts.map +1 -1
- package/dist/sidecar-lock-acquire.js +2 -1
- package/dist/sidecar-lock-policy.d.ts.map +1 -1
- package/dist/sidecar-lock-policy.js +3 -1
- package/dist/temp-cleanup.d.ts.map +1 -1
- package/dist/temp-cleanup.js +3 -2
- package/dist/timing.d.ts +1 -0
- package/dist/timing.d.ts.map +1 -1
- package/dist/timing.js +25 -6
- package/dist/trash.js +2 -2
- package/dist/walk.d.ts.map +1 -1
- package/dist/walk.js +6 -26
- package/dist/windows-owner.d.ts +9 -12
- package/dist/windows-owner.d.ts.map +1 -1
- package/dist/windows-owner.js +24 -58
- package/dist/write-file-handle.d.ts +6 -0
- package/dist/write-file-handle.d.ts.map +1 -0
- package/dist/write-file-handle.js +25 -0
- package/docs/advanced.md +18 -4
- package/docs/archive.md +22 -7
- package/docs/atomic.md +7 -0
- package/docs/contributing.md +7 -0
- package/docs/copy.md +86 -0
- package/docs/durability.md +17 -2
- package/docs/errors.md +1 -1
- package/docs/local-roots.md +8 -1
- package/docs/native.md +14 -1
- package/docs/permissions.md +20 -10
- package/docs/positional-read.md +63 -0
- package/docs/root.md +166 -4
- package/docs/security-model.md +14 -0
- package/docs/timing.md +2 -0
- package/docs/types.md +18 -11
- package/docs/walk.md +54 -5
- package/docs/writing.md +20 -2
- package/package.json +13 -8
package/dist/copy.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type CopyCloneMode } from "./copy-policy.js";
|
|
2
|
+
export { readCloneFileMetadata, type CloneFileMetadata } from "./clone-metadata.js";
|
|
3
|
+
export type { CopyCloneMode } from "./copy-policy.js";
|
|
4
|
+
export type TreeCloneBackend = "apfs" | "btrfs" | "refs" | "xfs";
|
|
5
|
+
export type CopyTreeOptions = {
|
|
6
|
+
clone?: CopyCloneMode;
|
|
7
|
+
signal?: AbortSignal;
|
|
8
|
+
concurrency?: number;
|
|
9
|
+
};
|
|
10
|
+
/** Inspect an existing real directory without creating probe files. */
|
|
11
|
+
export declare function probeTreeClone(parentPath: string): TreeCloneBackend | undefined;
|
|
12
|
+
/** Create an empty clone source: a Btrfs subvolume or an ordinary supported directory. */
|
|
13
|
+
export declare function createCloneSource(destination: string, options?: Pick<CopyTreeOptions, "signal">): Promise<void>;
|
|
14
|
+
/** Copy an immutable, caller-owned tree, preferring native cloning unless configured otherwise. */
|
|
15
|
+
export declare function copyTree(source: string, destination: string, options?: CopyTreeOptions): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=copy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../src/copy.ts"],"names":[],"mappings":"AAGA,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAK5E,OAAO,EAAE,qBAAqB,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACpF,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;AACjE,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAS/E;AAED,0FAA0F;AAC1F,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAM,GAC5C,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,mGAAmG;AACnG,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAIf"}
|
package/dist/copy.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { assertAbsolutePathInput } from "./absolute-path.js";
|
|
4
|
+
import { resolveCopyCloneMode } from "./copy-policy.js";
|
|
5
|
+
import { copyOwnedTree } from "./copy-tree-portable.js";
|
|
6
|
+
import { FsSafeError } from "./errors.js";
|
|
7
|
+
import { getNativeBinding, requireNativeBinding } from "./native.js";
|
|
8
|
+
import { assertStagedDirectoryCurrent, openStagedDirectory } from "./staged-directory.js";
|
|
9
|
+
export { readCloneFileMetadata } from "./clone-metadata.js";
|
|
10
|
+
/** Inspect an existing real directory without creating probe files. */
|
|
11
|
+
export function probeTreeClone(parentPath) {
|
|
12
|
+
const native = getNativeBinding();
|
|
13
|
+
if (!native)
|
|
14
|
+
return undefined;
|
|
15
|
+
const parent = openStagedDirectory(assertAbsolutePathInput(parentPath));
|
|
16
|
+
try {
|
|
17
|
+
return native.probeTreeClone(parent.fd) ?? undefined;
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
fs.closeSync(parent.fd);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Create an empty clone source: a Btrfs subvolume or an ordinary supported directory. */
|
|
24
|
+
export async function createCloneSource(destination, options = {}) {
|
|
25
|
+
await materializeTree(undefined, destination, options, "always");
|
|
26
|
+
}
|
|
27
|
+
/** Copy an immutable, caller-owned tree, preferring native cloning unless configured otherwise. */
|
|
28
|
+
export async function copyTree(source, destination, options = {}) {
|
|
29
|
+
options.signal?.throwIfAborted();
|
|
30
|
+
const policy = resolveCopyCloneMode(options.clone, "auto");
|
|
31
|
+
await materializeTree(source, destination, options, policy);
|
|
32
|
+
}
|
|
33
|
+
function cloneUnavailable(error) {
|
|
34
|
+
if (error instanceof FsSafeError && error.code === "unsupported-platform")
|
|
35
|
+
return true;
|
|
36
|
+
if (!(error instanceof Error) || !("code" in error))
|
|
37
|
+
return false;
|
|
38
|
+
// ENOTSUP also describes unsupported contents (for example named streams).
|
|
39
|
+
// Only capability failures may select a byte copy, never lossy source errors.
|
|
40
|
+
return error.code === "CLONE_UNAVAILABLE" || error.code === "EXDEV" || error.code === "ENOSYS";
|
|
41
|
+
}
|
|
42
|
+
async function materializeTree(source, destination, options, policy) {
|
|
43
|
+
options.signal?.throwIfAborted();
|
|
44
|
+
const concurrency = options.concurrency ?? 16;
|
|
45
|
+
if (!Number.isInteger(concurrency) || concurrency < 1 || concurrency > 32) {
|
|
46
|
+
throw new FsSafeError("invalid-path", "clone concurrency must be an integer between 1 and 32");
|
|
47
|
+
}
|
|
48
|
+
const native = policy === "always"
|
|
49
|
+
? requireNativeBinding()
|
|
50
|
+
: policy === "auto"
|
|
51
|
+
? getNativeBinding()
|
|
52
|
+
: undefined;
|
|
53
|
+
const target = assertAbsolutePathInput(destination);
|
|
54
|
+
const name = path.basename(target);
|
|
55
|
+
if (!name)
|
|
56
|
+
throw new FsSafeError("invalid-path", "clone destination must name a child directory");
|
|
57
|
+
const parent = openStagedDirectory(path.dirname(target));
|
|
58
|
+
let original;
|
|
59
|
+
try {
|
|
60
|
+
const supported = native?.probeTreeClone(parent.fd);
|
|
61
|
+
if (!supported && policy === "always") {
|
|
62
|
+
throw new FsSafeError("unsupported-platform", "destination filesystem does not support tree cloning");
|
|
63
|
+
}
|
|
64
|
+
if (source !== undefined) {
|
|
65
|
+
original = openStagedDirectory(assertAbsolutePathInput(source));
|
|
66
|
+
const relative = path.relative(original.receipt.realPath, path.join(parent.receipt.realPath, name));
|
|
67
|
+
if (relative === "" ||
|
|
68
|
+
(!path.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path.sep}`))) {
|
|
69
|
+
throw new FsSafeError("invalid-path", "clone destination must be outside the source tree");
|
|
70
|
+
}
|
|
71
|
+
assertStagedDirectoryCurrent(original.receipt);
|
|
72
|
+
}
|
|
73
|
+
assertStagedDirectoryCurrent(parent.receipt);
|
|
74
|
+
options.signal?.throwIfAborted();
|
|
75
|
+
let cloned = false;
|
|
76
|
+
// napi-rs uses the supplied signal's onabort property. Give it a private
|
|
77
|
+
// signal so caller handlers and other admitted native operations stay intact.
|
|
78
|
+
const cancellation = options.signal && supported ? new AbortController() : undefined;
|
|
79
|
+
const abort = () => cancellation?.abort();
|
|
80
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
81
|
+
try {
|
|
82
|
+
if (native && supported) {
|
|
83
|
+
await native.cloneTree(original?.fd ?? null, parent.fd, name, concurrency, cancellation?.signal);
|
|
84
|
+
cloned = true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
options.signal?.throwIfAborted();
|
|
89
|
+
if (policy !== "auto" || !cloneUnavailable(error)) {
|
|
90
|
+
if (error instanceof Error && "code" in error && error.code === "CLONE_UNAVAILABLE") {
|
|
91
|
+
throw new FsSafeError("unsupported-platform", error.message, { cause: error });
|
|
92
|
+
}
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
options.signal?.removeEventListener("abort", abort);
|
|
98
|
+
}
|
|
99
|
+
options.signal?.throwIfAborted();
|
|
100
|
+
assertStagedDirectoryCurrent(parent.receipt);
|
|
101
|
+
if (original)
|
|
102
|
+
assertStagedDirectoryCurrent(original.receipt);
|
|
103
|
+
if (!cloned && original) {
|
|
104
|
+
await copyOwnedTree(original, target, {
|
|
105
|
+
signal: options.signal,
|
|
106
|
+
concurrency: options.concurrency ?? (process.platform === "win32" ? 4 : 1),
|
|
107
|
+
copyFileContents: process.platform === "win32" ? native?.copyFileContents : undefined,
|
|
108
|
+
});
|
|
109
|
+
options.signal?.throwIfAborted();
|
|
110
|
+
assertStagedDirectoryCurrent(parent.receipt);
|
|
111
|
+
assertStagedDirectoryCurrent(original.receipt);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
try {
|
|
116
|
+
if (original)
|
|
117
|
+
fs.closeSync(original.fd);
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
fs.closeSync(parent.fd);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
package/dist/durability.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { ensureDurableDirectory, pinDirectory, syncDirectory, syncDirectoryBestEffort, syncDirectoryBestEffortSync, syncDirectorySync, type DirectoryReceipt, type DirectorySyncOutcome, type DurableDirectoryReceipt, type EnsureDurableDirectoryOptions, type PinnedDirectory, } from "./directory-durability.js";
|
|
2
2
|
export { isHardlinkFallbackError, publishFileExclusive, type PublishFileExclusiveResult, type PublishFileExclusiveStrategy, type PublishFileExclusiveCleanup, type PublishFileExclusiveDirectorySyncFailure, type PublishFileExclusiveFailureDetails, type PublishFileExclusiveFailurePhase, type PublishFileExclusiveSyncFailurePolicy, } from "./publish-file.js";
|
|
3
|
-
export { sha256File, type Sha256FileInput, type Sha256FileResult, } from "./file-hash.js";
|
|
3
|
+
export { sha256File, type Sha256FileInput, type Sha256FileOptions, type Sha256FileResult, } from "./file-hash.js";
|
|
4
4
|
//# sourceMappingURL=durability.d.ts.map
|
package/dist/durability.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durability.d.ts","sourceRoot":"","sources":["../src/durability.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,aAAa,EACb,uBAAuB,EACvB,2BAA2B,EAC3B,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,6BAA6B,EAClC,KAAK,eAAe,GACrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EAChC,KAAK,wCAAwC,EAC7C,KAAK,kCAAkC,EACvC,KAAK,gCAAgC,EACrC,KAAK,qCAAqC,GAC3C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"durability.d.ts","sourceRoot":"","sources":["../src/durability.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,aAAa,EACb,uBAAuB,EACvB,2BAA2B,EAC3B,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,6BAA6B,EAClC,KAAK,eAAe,GACrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EAChC,KAAK,wCAAwC,EAC7C,KAAK,kCAAkC,EACvC,KAAK,gCAAgC,EACrC,KAAK,qCAAqC,GAC3C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-detail.d.ts","sourceRoot":"","sources":["../src/error-detail.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"error-detail.d.ts","sourceRoot":"","sources":["../src/error-detail.ts"],"names":[],"mappings":"AAMA,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIvD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM/C"}
|
package/dist/error-detail.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import os from "node:os";
|
|
2
|
+
import path from "node:path";
|
|
2
3
|
const UNSAFE_ERROR_DETAIL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f\u2028\u2029]/gu;
|
|
3
4
|
export function formatErrorDetail(value) {
|
|
4
5
|
return value.replace(UNSAFE_ERROR_DETAIL_CHARACTERS, (character) => `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`);
|
|
5
6
|
}
|
|
6
7
|
export function shortPath(value) {
|
|
7
8
|
const home = os.homedir();
|
|
8
|
-
const
|
|
9
|
+
const prefix = home.endsWith(path.sep) ? home : `${home}${path.sep}`;
|
|
10
|
+
const shortened = value === home ? "~"
|
|
11
|
+
: value.startsWith(prefix) ? `~${path.sep}${value.slice(prefix.length)}` : value;
|
|
9
12
|
return formatErrorDetail(shortened);
|
|
10
13
|
}
|
package/dist/file-hash.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import type { FileHandle } from "node:fs/promises";
|
|
2
2
|
import { type NativeBinding } from "./native.js";
|
|
3
3
|
export type Sha256FileInput = string | FileHandle;
|
|
4
|
+
export type Sha256FileOptions = {
|
|
5
|
+
maxBytes?: number;
|
|
6
|
+
signal?: AbortSignal;
|
|
7
|
+
};
|
|
4
8
|
export type Sha256FileResult = {
|
|
5
9
|
bytes: number;
|
|
6
10
|
digest: string;
|
|
7
11
|
};
|
|
8
|
-
export declare function hashFileHandle(handle: FileHandle, native?: NativeBinding | undefined): Promise<Sha256FileResult>;
|
|
9
|
-
export declare function sha256File(input: Sha256FileInput): Promise<Sha256FileResult>;
|
|
12
|
+
export declare function hashFileHandle(handle: FileHandle, native?: NativeBinding | undefined, { maxBytes, signal }?: Sha256FileOptions): Promise<Sha256FileResult>;
|
|
13
|
+
export declare function sha256File(input: Sha256FileInput, options?: Sha256FileOptions): Promise<Sha256FileResult>;
|
|
10
14
|
//# sourceMappingURL=file-hash.d.ts.map
|
package/dist/file-hash.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-hash.d.ts","sourceRoot":"","sources":["../src/file-hash.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"file-hash.d.ts","sourceRoot":"","sources":["../src/file-hash.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAInE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,CAAC;AAElD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,EAClB,MAAM,GAAE,aAAa,GAAG,SAA8B,EACtD,EAAE,QAAmB,EAAE,MAAM,EAAE,GAAE,iBAAsB,GACtD,OAAO,CAAC,gBAAgB,CAAC,CAoD3B;AAoDD,wBAAsB,UAAU,CAC9B,KAAK,EAAE,eAAe,EACtB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAM3B"}
|
package/dist/file-hash.js
CHANGED
|
@@ -1,23 +1,53 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import fsSync from "node:fs";
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
|
+
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
4
5
|
import { FsSafeError } from "./errors.js";
|
|
5
6
|
import { getNativeBinding } from "./native.js";
|
|
6
7
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
7
8
|
import { inspectFileIdentity } from "./strict-file-identity.js";
|
|
8
|
-
export async function hashFileHandle(handle, native = getNativeBinding()) {
|
|
9
|
+
export async function hashFileHandle(handle, native = getNativeBinding(), { maxBytes = Infinity, signal } = {}) {
|
|
10
|
+
signal?.throwIfAborted();
|
|
9
11
|
const stat = fsSync.fstatSync(handle.fd);
|
|
10
12
|
if (!stat.isFile()) {
|
|
11
13
|
throw new FsSafeError("not-file", "SHA-256 input is not a regular file");
|
|
12
14
|
}
|
|
15
|
+
if (stat.size > maxBytes) {
|
|
16
|
+
throw new FsSafeError("too-large", `SHA-256 input exceeds ${maxBytes} bytes`);
|
|
17
|
+
}
|
|
13
18
|
if (native) {
|
|
14
|
-
|
|
19
|
+
// A completed N-API task can mask later aborts on the same signal.
|
|
20
|
+
const nativeSignal = signal ? AbortSignal.any([signal]) : undefined;
|
|
21
|
+
try {
|
|
22
|
+
const result = await native.sha256File(handle.fd, Number.isFinite(maxBytes) ? maxBytes : undefined, nativeSignal);
|
|
23
|
+
signal?.throwIfAborted();
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
// N-API settles only after compute stops; never race descriptor cleanup.
|
|
28
|
+
signal?.throwIfAborted();
|
|
29
|
+
if (error?.code === "too-large") {
|
|
30
|
+
throw new FsSafeError("too-large", `SHA-256 input exceeds ${maxBytes} bytes`, { cause: error });
|
|
31
|
+
}
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
// Node retains composite signals while N-API's abort listener is attached.
|
|
36
|
+
if (nativeSignal)
|
|
37
|
+
nativeSignal.onabort = null;
|
|
38
|
+
}
|
|
15
39
|
}
|
|
16
40
|
const hash = createHash("sha256");
|
|
17
|
-
const buffer = Buffer.allocUnsafe(64 * 1024);
|
|
41
|
+
const buffer = Buffer.allocUnsafe(Math.min(256 * 1024, Math.max(64 * 1024, stat.size)));
|
|
18
42
|
let position = 0;
|
|
19
43
|
while (true) {
|
|
20
|
-
|
|
44
|
+
signal?.throwIfAborted();
|
|
45
|
+
const length = Math.min(buffer.length, maxBytes - position + 1);
|
|
46
|
+
const { bytesRead } = await handle.read(buffer, 0, length, position);
|
|
47
|
+
signal?.throwIfAborted();
|
|
48
|
+
if (bytesRead > maxBytes - position) {
|
|
49
|
+
throw new FsSafeError("too-large", `SHA-256 input exceeds ${maxBytes} bytes`);
|
|
50
|
+
}
|
|
21
51
|
if (bytesRead === 0) {
|
|
22
52
|
return { bytes: position, digest: hash.digest("hex") };
|
|
23
53
|
}
|
|
@@ -25,7 +55,7 @@ export async function hashFileHandle(handle, native = getNativeBinding()) {
|
|
|
25
55
|
position += bytesRead;
|
|
26
56
|
}
|
|
27
57
|
}
|
|
28
|
-
async function hashPath(filePath) {
|
|
58
|
+
async function hashPath(filePath, options) {
|
|
29
59
|
const before = await inspectFileIdentity(async () => {
|
|
30
60
|
const stat = fsSync.lstatSync(filePath, { bigint: true });
|
|
31
61
|
if (stat.isSymbolicLink()) {
|
|
@@ -38,6 +68,7 @@ async function hashPath(filePath) {
|
|
|
38
68
|
});
|
|
39
69
|
let handle;
|
|
40
70
|
try {
|
|
71
|
+
options.signal?.throwIfAborted();
|
|
41
72
|
handle = await fs.open(filePath, resolveReadOpenFlags());
|
|
42
73
|
}
|
|
43
74
|
catch (error) {
|
|
@@ -49,6 +80,7 @@ async function hashPath(filePath) {
|
|
|
49
80
|
throw error;
|
|
50
81
|
}
|
|
51
82
|
try {
|
|
83
|
+
options.signal?.throwIfAborted();
|
|
52
84
|
const opened = await inspectFileIdentity(async () => {
|
|
53
85
|
const stat = fsSync.fstatSync(handle.fd, { bigint: true });
|
|
54
86
|
if (!stat.isFile()) {
|
|
@@ -63,12 +95,16 @@ async function hashPath(filePath) {
|
|
|
63
95
|
}
|
|
64
96
|
return stat;
|
|
65
97
|
}, opened);
|
|
66
|
-
return await hashFileHandle(handle);
|
|
98
|
+
return await hashFileHandle(handle, getNativeBinding(), options);
|
|
67
99
|
}
|
|
68
100
|
finally {
|
|
69
101
|
await handle.close().catch(() => undefined);
|
|
70
102
|
}
|
|
71
103
|
}
|
|
72
|
-
export async function sha256File(input) {
|
|
73
|
-
|
|
104
|
+
export async function sha256File(input, options = {}) {
|
|
105
|
+
options.signal?.throwIfAborted();
|
|
106
|
+
const normalized = { maxBytes: normalizeMaxBytes(options.maxBytes), signal: options.signal };
|
|
107
|
+
return typeof input === "string"
|
|
108
|
+
? await hashPath(input, normalized)
|
|
109
|
+
: await hashFileHandle(input, getNativeBinding(), normalized);
|
|
74
110
|
}
|
package/dist/filename.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filename.d.ts","sourceRoot":"","sources":["../src/filename.ts"],"names":[],"mappings":"AAqCA,yFAAyF;AACzF,wBAAgB,8BAA8B,CAAC,MAAM,EAAE;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,MAAM,CA8BT;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"filename.d.ts","sourceRoot":"","sources":["../src/filename.ts"],"names":[],"mappings":"AAqCA,yFAAyF;AACzF,wBAAgB,8BAA8B,CAAC,MAAM,EAAE;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,MAAM,CA8BT;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAoBxF"}
|
package/dist/filename.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { WINDOWS_RESERVED_DEVICE_NAMES } from "./device-path.js";
|
|
3
|
-
const
|
|
3
|
+
const INVALID_FILE_NAME_CHARACTERS = /[\u0000-\u001f\u007f-\u009f<>:"/\\|?*]/g;
|
|
4
4
|
function trimWindowsIgnoredSuffix(value) {
|
|
5
5
|
let end = value.length;
|
|
6
6
|
while (end > 0) {
|
|
@@ -65,17 +65,7 @@ export function sanitizeUntrustedFileName(fileName, fallbackName) {
|
|
|
65
65
|
}
|
|
66
66
|
let base = path.posix.basename(trimmed);
|
|
67
67
|
base = path.win32.basename(base);
|
|
68
|
-
|
|
69
|
-
for (let i = 0; i < base.length; i++) {
|
|
70
|
-
const code = base.charCodeAt(i);
|
|
71
|
-
if (code < 0x20 ||
|
|
72
|
-
(code >= 0x7f && code <= 0x9f) ||
|
|
73
|
-
WINDOWS_INVALID_FILE_NAME_CHARACTERS.has(base[i])) {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
cleaned += base[i];
|
|
77
|
-
}
|
|
78
|
-
base = cleaned.trim();
|
|
68
|
+
base = base.replace(INVALID_FILE_NAME_CHARACTERS, "").trim();
|
|
79
69
|
if (!base || base === "." || base === "..") {
|
|
80
70
|
return fallbackName;
|
|
81
71
|
}
|
package/dist/guarded-mkdir.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare function mkdirPathComponentsWithGuards(params: {
|
|
|
8
8
|
rootReal: string;
|
|
9
9
|
targetPath: string;
|
|
10
10
|
beforeComponent?: (componentPath: string) => Promise<void> | void;
|
|
11
|
+
assertBeforeMutation?: () => void;
|
|
11
12
|
mode?: number;
|
|
12
13
|
rejectSymlinks?: boolean;
|
|
13
14
|
}): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guarded-mkdir.d.ts","sourceRoot":"","sources":["../src/guarded-mkdir.ts"],"names":[],"mappings":"AA0BA;;;;;GAKG;AACH,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"guarded-mkdir.d.ts","sourceRoot":"","sources":["../src/guarded-mkdir.ts"],"names":[],"mappings":"AA0BA;;;;;GAKG;AACH,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClE,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,CAAC,CAwDlB"}
|
package/dist/guarded-mkdir.js
CHANGED
|
@@ -42,6 +42,7 @@ export async function mkdirPathComponentsWithGuards(params) {
|
|
|
42
42
|
const parentGuard = await createAsyncDirectoryGuard(current);
|
|
43
43
|
await assertAsyncDirectoryGuard(parentGuard);
|
|
44
44
|
await params.beforeComponent?.(next);
|
|
45
|
+
params.assertBeforeMutation?.();
|
|
45
46
|
try {
|
|
46
47
|
await fs.mkdir(next, { mode: params.mode });
|
|
47
48
|
}
|
|
@@ -24,12 +24,14 @@ export declare function guardedRenameSync(params: {
|
|
|
24
24
|
}): void;
|
|
25
25
|
export declare function guardedRm(params: {
|
|
26
26
|
target: string;
|
|
27
|
+
assertBeforeMutation?: () => void;
|
|
27
28
|
recursive?: boolean;
|
|
28
29
|
force?: boolean;
|
|
29
30
|
verifyAfter?: boolean;
|
|
30
31
|
}): Promise<void>;
|
|
31
32
|
export declare function guardedRmSync(params: {
|
|
32
33
|
target: string;
|
|
34
|
+
assertBeforeMutation?: () => void;
|
|
33
35
|
recursive?: boolean;
|
|
34
36
|
force?: boolean;
|
|
35
37
|
verifyAfter?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guarded-mutation.d.ts","sourceRoot":"","sources":["../src/guarded-mutation.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAGnD,OAAO,EAOL,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACxB,MAAM,sBAAsB,CAAC;AAE9B,wBAAsB,wBAAwB,CAAC,CAAC,EAC9C,MAAM,EAAE,SAAS,sBAAsB,EAAE,EACzC,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACxB,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACrE,GACL,OAAO,CAAC,CAAC,CAAC,CAyBZ;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EACvC,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,MAAM,EAAE,MAAM,CAAC,EACf,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,CAAC,CAWH;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE;IAC1C,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC;IACzE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,IAAI,CAUP;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"guarded-mutation.d.ts","sourceRoot":"","sources":["../src/guarded-mutation.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAGnD,OAAO,EAOL,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACxB,MAAM,sBAAsB,CAAC;AAE9B,wBAAsB,wBAAwB,CAAC,CAAC,EAC9C,MAAM,EAAE,SAAS,sBAAsB,EAAE,EACzC,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACxB,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACrE,GACL,OAAO,CAAC,CAAC,CAAC,CAyBZ;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EACvC,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,MAAM,EAAE,MAAM,CAAC,EACf,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,CAAC,CAWH;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE;IAC1C,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC;IACzE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,IAAI,CAUP;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAahB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,IAAI,CAaP"}
|
package/dist/guarded-mutation.js
CHANGED
|
@@ -67,6 +67,7 @@ export function guardedRenameSync(params) {
|
|
|
67
67
|
export async function guardedRm(params) {
|
|
68
68
|
const guard = await createAsyncDirectoryGuard(path.dirname(params.target));
|
|
69
69
|
await withAsyncDirectoryGuards([guard], async () => {
|
|
70
|
+
params.assertBeforeMutation?.();
|
|
70
71
|
await fs.rm(params.target, {
|
|
71
72
|
...(params.recursive !== undefined ? { recursive: params.recursive } : {}),
|
|
72
73
|
...(params.force !== undefined ? { force: params.force } : {}),
|
|
@@ -75,8 +76,11 @@ export async function guardedRm(params) {
|
|
|
75
76
|
}
|
|
76
77
|
export function guardedRmSync(params) {
|
|
77
78
|
const guard = createSyncDirectoryGuard(path.dirname(params.target));
|
|
78
|
-
withSyncDirectoryGuards([guard], () =>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
withSyncDirectoryGuards([guard], () => {
|
|
80
|
+
params.assertBeforeMutation?.();
|
|
81
|
+
fsSync.rmSync(params.target, {
|
|
82
|
+
...(params.recursive !== undefined ? { recursive: params.recursive } : {}),
|
|
83
|
+
...(params.force !== undefined ? { force: params.force } : {}),
|
|
84
|
+
});
|
|
85
|
+
}, { verifyAfter: params.verifyAfter });
|
|
82
86
|
}
|
package/dist/home-dir.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"home-dir.d.ts","sourceRoot":"","sources":["../src/home-dir.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"home-dir.d.ts","sourceRoot":"","sources":["../src/home-dir.ts"],"names":[],"mappings":"AAoBA,wBAAgB,uBAAuB,CACrC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,OAAO,GAAE,MAAM,MAAmB,GACjC,MAAM,GAAG,SAAS,CAGpB;AAwCD,wBAAgB,sBAAsB,CACpC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,OAAO,GAAE,MAAM,MAAmB,GACjC,MAAM,CAER;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE;IACL,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC;CACxB,GACA,MAAM,CAYR;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE;IACL,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC;CACxB,GACA,MAAM,CAaR"}
|
package/dist/home-dir.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import os from "node:os";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { normalizeOptionalString } from "./string-coerce.js";
|
|
4
|
+
function hasHomePrefix(input) {
|
|
5
|
+
return input === "~" || input.startsWith("~/") ||
|
|
6
|
+
(path.sep === "\\" && input.startsWith("~\\"));
|
|
7
|
+
}
|
|
4
8
|
function normalize(value) {
|
|
5
9
|
const trimmed = normalizeOptionalString(value);
|
|
6
10
|
if (!trimmed) {
|
|
@@ -20,8 +24,7 @@ function resolveRawHomeDir(env, homedir) {
|
|
|
20
24
|
if (!explicitHome) {
|
|
21
25
|
return resolveRawOsHomeDir(env, homedir);
|
|
22
26
|
}
|
|
23
|
-
|
|
24
|
-
if (segments[0] !== "~") {
|
|
27
|
+
if (!hasHomePrefix(explicitHome)) {
|
|
25
28
|
return explicitHome;
|
|
26
29
|
}
|
|
27
30
|
// OPENCLAW_HOME starts with "~"; expand against the os home dir. Fall
|
|
@@ -56,8 +59,7 @@ export function resolveRequiredHomeDir(env = process.env, homedir = os.homedir)
|
|
|
56
59
|
return resolveEffectiveHomeDir(env, homedir) ?? path.resolve(process.cwd());
|
|
57
60
|
}
|
|
58
61
|
export function expandHomePrefix(input, opts) {
|
|
59
|
-
|
|
60
|
-
if (segments[0] !== "~") {
|
|
62
|
+
if (!hasHomePrefix(input)) {
|
|
61
63
|
return input;
|
|
62
64
|
}
|
|
63
65
|
const home = normalize(opts?.home) ??
|
|
@@ -65,14 +67,14 @@ export function expandHomePrefix(input, opts) {
|
|
|
65
67
|
if (!home) {
|
|
66
68
|
return input;
|
|
67
69
|
}
|
|
68
|
-
|
|
70
|
+
// Expand before normalizing so a following .. traverses the actual home.
|
|
71
|
+
return path.join(home, input.slice(2));
|
|
69
72
|
}
|
|
70
73
|
export function resolveHomeRelativePath(input, opts) {
|
|
71
74
|
if (!input) {
|
|
72
75
|
return input;
|
|
73
76
|
}
|
|
74
|
-
|
|
75
|
-
if (segments[0] !== "~") {
|
|
77
|
+
if (!hasHomePrefix(input)) {
|
|
76
78
|
return path.resolve(input);
|
|
77
79
|
}
|
|
78
80
|
const expanded = expandHomePrefix(input, {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { FsSafeError, categorizeFsSafeError, type FsSafeErrorCategory, type FsSafeErrorCode, type FsSafeErrorDetails, } from "./errors.js";
|
|
2
|
-
export { DEFAULT_ROOT_MAX_BYTES, root, type DenyMutationPolicy, type HardlinkPolicy, type RenameIdentityPolicy, type OpenResult, type ReadResult, type Root, type RootAppendOptions, type RootCopyOptions, type RootCreateJsonOptions, type RootCreateOptions, type RootDefaults, type RootMkdirOptions, type RootMoveOptions, type RootOpenOptions, type RootOpenWritableOptions, type RootOptions, type RootReadOptions, type RootRemoveOptions, type RootWriteJsonOptions, type RootWriteOptions, type RootWalkDataEntry, type RootWalkDataEntryKind, type RootWalkDirectoryErrorBehavior, type RootWalkEntry, type RootWalkEntryFilter, type RootWalkEntryFilterResult, type RootWalkEntryKind, type RootWalkLimitBehavior, type RootWalkOptions, type RootWalkSymlinkPolicy, type SymlinkPolicy, type WritableOpenMode, type WritableOpenResult, } from "./root.js";
|
|
2
|
+
export { DEFAULT_ROOT_MAX_BYTES, root, type DenyMutationPolicy, type HardlinkPolicy, type RenameIdentityPolicy, type OpenResult, type ReadResult, type Root, type RootAppendOptions, type RootCopyOptions, type RootCopySource, type RootCopyPublicationReceipt, type CopyCloneMode, type RootCreateJsonOptions, type RootCreateOptions, type RootDefaults, type RootMkdirOptions, type RootMoveOptions, type RootOpenOptions, type RootOpenWritableOptions, type RootOptions, type RootReadOptions, type RootRemoveOptions, type RootWriteJsonOptions, type RootWriteOptions, type RootWalkDataEntry, type RootWalkDataEntryKind, type RootWalkDirectoryErrorBehavior, type RootWalkEntry, type RootWalkEntryFilter, type RootWalkEntryFilterResult, type RootWalkEntryKind, type RootWalkLimitBehavior, type RootWalkOptions, type RootWalkSymlinkPolicy, type SymlinkPolicy, type MutationSymlinkPolicy, type WritableOpenMode, type WritableOpenResult, } from "./root.js";
|
|
3
3
|
export type { ContainmentGuarantee } from "./containment.js";
|
|
4
4
|
export { configureFsSafePython, configureFsSafeNative, getFsSafeNativeConfig, type FsSafePythonConfig, type FsSafeNativeConfig, type FsSafeNativeMode, } from "./native-config.js";
|
|
5
5
|
export { writeExternalFileWithinRoot, type ExternalFileWriteOptions, type ExternalFileWriteResult, } from "./output.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,IAAI,EACJ,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,IAAI,EACT,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,8BAA8B,EACnC,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,2BAA2B,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC7B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,IAAI,EACJ,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,IAAI,EACT,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,0BAA0B,EAC/B,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,8BAA8B,EACnC,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,2BAA2B,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC7B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-path.d.ts","sourceRoot":"","sources":["../src/install-path.ts"],"names":[],"mappings":"AAKA,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"install-path.d.ts","sourceRoot":"","sources":["../src/install-path.ts"],"names":[],"mappings":"AAKA,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB3D;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;CACtC,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAe5D;AAED,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkDhB"}
|
package/dist/install-path.js
CHANGED
|
@@ -19,12 +19,8 @@ export function safePathSegmentHashed(input) {
|
|
|
19
19
|
.replaceAll(/-+$/g, "");
|
|
20
20
|
const normalized = base.length > 0 ? base : "skill";
|
|
21
21
|
const safe = normalized === "." || normalized === ".." ? "skill" : normalized;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const prefix = safe.length > 50 ? safe.slice(0, 50) : safe;
|
|
25
|
-
return `${prefix}-${hash}`;
|
|
26
|
-
}
|
|
27
|
-
if (safe.length > 60) {
|
|
22
|
+
if (safe !== trimmed || safe.length > 60) {
|
|
23
|
+
const hash = createHash("sha256").update(trimmed).digest("hex").slice(0, 10);
|
|
28
24
|
return `${safe.slice(0, 50)}-${hash}`;
|
|
29
25
|
}
|
|
30
26
|
return safe;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-durable-queue.d.ts","sourceRoot":"","sources":["../src/json-durable-queue.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"json-durable-queue.d.ts","sourceRoot":"","sources":["../src/json-durable-queue.ts"],"names":[],"mappings":"AAoBA,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,0BAA0B,CAAC,CAAC,IAAI;IAC1C,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,2BAA2B,CAAC,CAAC,IAAI;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAOF,eAAO,MAAM,0CAA0C,QAAmB,CAAC;AAM3E,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED,wBAAsB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUpF;AAmBD,wBAAgB,iCAAiC,CAC/C,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,GACT,0BAA0B,CAO5B;AAED,wBAAsB,0BAA0B,CAAC,MAAM,EAAE;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhB;AAiLD,wBAAsB,0BAA0B,CAAC,MAAM,EAAE;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQhB;AAyDD,wBAAsB,yBAAyB,CAAC,CAAC,EAC/C,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,OAAO,CAAC,CAAC,CAAC,CASZ;AAED,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/F;AAED,wBAAsB,yBAAyB,CAAC,CAAC,EAAE,MAAM,EAAE;IACzD,KAAK,EAAE,0BAA0B,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAsBpB;AAED,wBAAsB,kCAAkC,CAAC,CAAC,EACxD,OAAO,EAAE,2BAA2B,CAAC,CAAC,CAAC,GACtC,OAAO,CAAC,CAAC,EAAE,CAAC,CA+Dd;AAED,wBAAsB,iCAAiC,CAAC,MAAM,EAAE;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,IAAI,CAAC,CAShB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs, {} from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
4
|
+
import { readBoundedAsync } from "./bounded-read.js";
|
|
4
5
|
import { syncDirectory } from "./directory-durability.js";
|
|
5
6
|
import { syncQueueDirectoryCreation } from "./json-durable-queue-directory.js";
|
|
6
7
|
import { getErrorCode, acknowledgeDurableQueueEntry, claimDurableQueueEntry, completeDeliveredQueueEntry, moveDurableQueueEntryToFailed, } from "./json-durable-queue-ownership.js";
|
|
@@ -253,20 +254,12 @@ async function readBoundedUtf8File(params) {
|
|
|
253
254
|
try {
|
|
254
255
|
const openedStat = await inspectQueueEntry(() => fs.fstatSync(handle.fd, { bigint: true }), params.maxBytes, initialStat);
|
|
255
256
|
await inspectQueueEntry(inspectPath, params.maxBytes, openedStat);
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
return Buffer.concat(chunks, total).toString("utf8");
|
|
263
|
-
}
|
|
264
|
-
total += bytesRead;
|
|
265
|
-
if (total > params.maxBytes) {
|
|
266
|
-
throw new Error(`queue entry exceeds ${params.maxBytes} bytes`);
|
|
267
|
-
}
|
|
268
|
-
chunks.push(Buffer.from(scratch.subarray(0, bytesRead)));
|
|
269
|
-
}
|
|
257
|
+
const bytes = await readBoundedAsync(params.maxBytes, async (buffer, length) => (await handle.read(buffer, 0, length, null)).bytesRead, {
|
|
258
|
+
initialSize: openedStat.size >= 0n && Number.isSafeInteger(Number(openedStat.size))
|
|
259
|
+
? Number(openedStat.size) : undefined,
|
|
260
|
+
createLimitError: () => new Error(`queue entry exceeds ${params.maxBytes} bytes`),
|
|
261
|
+
});
|
|
262
|
+
return bytes.toString("utf8");
|
|
270
263
|
}
|
|
271
264
|
finally {
|
|
272
265
|
await handle.close();
|
|
@@ -323,6 +316,12 @@ export async function loadPendingJsonDurableQueueEntries(options) {
|
|
|
323
316
|
for (const file of files) {
|
|
324
317
|
if (file.endsWith(".delivered")) {
|
|
325
318
|
const id = file.slice(0, -".delivered".length);
|
|
319
|
+
try {
|
|
320
|
+
assertSafeQueueEntryId(id);
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
326
325
|
await completeDeliveredQueueEntry(resolveJsonDurableQueueEntryPaths(options.queueDir, id));
|
|
327
326
|
}
|
|
328
327
|
else if (options.cleanupTmpMaxAgeMs !== undefined && file.endsWith(".tmp")) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-roots.d.ts","sourceRoot":"","sources":["../src/local-roots.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"local-roots.d.ts","sourceRoot":"","sources":["../src/local-roots.ts"],"names":[],"mappings":"AAOA,OAAO,EAAQ,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAE3F,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG;IAC9C,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oCAAoC,GAAG,sBAAsB,GAAG;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,sBAAsB,GAAG;IACnE,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B,CAAC;AAsDF,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,oCAAoC,GAC5C,oBAAoB,GAAG,IAAI,CAqC7B;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAiCtC"}
|