@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/root-walk.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { FsSafeError } from "./errors.js";
|
|
3
3
|
import { resolveRootPath } from "./root-path.js";
|
|
4
|
+
import { createSuppressedError } from "./suppressed-error.js";
|
|
4
5
|
function validateBudget(name, value) {
|
|
5
6
|
if (value === undefined)
|
|
6
7
|
return Number.POSITIVE_INFINITY;
|
|
@@ -25,6 +26,9 @@ export async function* walkRoot(root, relativePath, options) {
|
|
|
25
26
|
if (!["skip", "follow-within-root"].includes(options.symlinkPolicy)) {
|
|
26
27
|
throw new TypeError(`invalid root walk symlink policy: ${String(options.symlinkPolicy)}`);
|
|
27
28
|
}
|
|
29
|
+
if (options.order !== undefined && !["sorted", "filesystem"].includes(options.order)) {
|
|
30
|
+
throw new TypeError(`invalid root walk order: ${String(options.order)}`);
|
|
31
|
+
}
|
|
28
32
|
if (options.limitBehavior !== undefined &&
|
|
29
33
|
!["truncate", "throw"].includes(options.limitBehavior)) {
|
|
30
34
|
throw new TypeError(`invalid root walk limit behavior: ${String(options.limitBehavior)}`);
|
|
@@ -38,6 +42,12 @@ export async function* walkRoot(root, relativePath, options) {
|
|
|
38
42
|
const visitedDirectories = new Set();
|
|
39
43
|
let examined = 0;
|
|
40
44
|
let truncated = false;
|
|
45
|
+
const admitEntry = () => {
|
|
46
|
+
if (examined >= maxEntries)
|
|
47
|
+
return false;
|
|
48
|
+
examined += 1;
|
|
49
|
+
return true;
|
|
50
|
+
};
|
|
41
51
|
const onLimit = (atPath) => {
|
|
42
52
|
if ((options.limitBehavior ?? "truncate") === "throw") {
|
|
43
53
|
throw new FsSafeError("too-large", `root walk budget exceeded at ${atPath || "."}`);
|
|
@@ -45,9 +55,15 @@ export async function* walkRoot(root, relativePath, options) {
|
|
|
45
55
|
truncated = true;
|
|
46
56
|
return limitEntry(atPath);
|
|
47
57
|
};
|
|
58
|
+
const onDirectoryError = (directory, error) => {
|
|
59
|
+
// Rethrow cancellation with any disposal failure already attached.
|
|
60
|
+
if (options.signal?.aborted || (options.onDirectoryError ?? "throw") === "throw")
|
|
61
|
+
throw error;
|
|
62
|
+
return { relativePath: directory, kind: "directory-error", size: 0, error };
|
|
63
|
+
};
|
|
48
64
|
async function* visit(directory, depth) {
|
|
49
65
|
options.signal?.throwIfAborted();
|
|
50
|
-
let
|
|
66
|
+
let listing;
|
|
51
67
|
try {
|
|
52
68
|
const resolvedDirectory = await resolveRootPath({
|
|
53
69
|
absolutePath: path.resolve(root.rootReal, directory),
|
|
@@ -67,66 +83,99 @@ export async function* walkRoot(root, relativePath, options) {
|
|
|
67
83
|
.relative(root.rootReal, resolvedDirectory.canonicalPath)
|
|
68
84
|
.split(path.sep)
|
|
69
85
|
.join(path.posix.sep);
|
|
70
|
-
|
|
86
|
+
listing = await root.list(listingDirectory, {
|
|
87
|
+
order: options.order ?? "sorted",
|
|
88
|
+
signal: options.signal,
|
|
89
|
+
snapshot: maxEntries === Number.POSITIVE_INFINITY,
|
|
90
|
+
admitEntry,
|
|
91
|
+
});
|
|
71
92
|
}
|
|
72
93
|
catch (error) {
|
|
73
|
-
|
|
74
|
-
options.signal?.throwIfAborted();
|
|
75
|
-
if ((options.onDirectoryError ?? "throw") === "throw")
|
|
76
|
-
throw error;
|
|
77
|
-
yield { relativePath: directory, kind: "directory-error", size: 0, error };
|
|
94
|
+
yield onDirectoryError(directory, error);
|
|
78
95
|
return;
|
|
79
96
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (
|
|
97
|
+
// A thrown undefined still needs to be retained if closing also fails.
|
|
98
|
+
let failed = false;
|
|
99
|
+
let operationError;
|
|
100
|
+
try {
|
|
101
|
+
while (true) {
|
|
102
|
+
let next;
|
|
103
|
+
try {
|
|
104
|
+
next = await listing.next();
|
|
105
|
+
options.signal?.throwIfAborted();
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
yield onDirectoryError(directory, error);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (next === undefined)
|
|
112
|
+
return;
|
|
113
|
+
const name = next.kind === "entry" ? next.entry.name : next.name;
|
|
114
|
+
const child = directory
|
|
115
|
+
? path.posix.join(directory.split(path.sep).join(path.posix.sep), name)
|
|
116
|
+
: name;
|
|
117
|
+
if (next.kind === "limit") {
|
|
118
|
+
yield onLimit(child);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const entry = next.entry;
|
|
122
|
+
let kind = entryKind(entry);
|
|
123
|
+
let size = entry.size;
|
|
124
|
+
if (kind === "symlink") {
|
|
125
|
+
if (options.symlinkPolicy === "skip") {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const resolved = await resolveRootPath({
|
|
129
|
+
absolutePath: path.resolve(root.rootReal, child),
|
|
130
|
+
rootPath: root.rootReal,
|
|
131
|
+
rootCanonicalPath: root.rootReal,
|
|
132
|
+
boundaryLabel: "root walk",
|
|
133
|
+
});
|
|
134
|
+
if (!resolved.exists) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const target = await root.stat(path.relative(root.rootReal, resolved.canonicalPath));
|
|
138
|
+
kind = target.isDirectory ? "directory" : target.isFile ? "file" : "other";
|
|
139
|
+
size = target.size;
|
|
140
|
+
}
|
|
141
|
+
const walkEntry = { relativePath: child, kind, size };
|
|
142
|
+
const filterResult = options.entryFilter?.(walkEntry) ?? "include";
|
|
143
|
+
if (!["include", "skip", "skip-subtree"].includes(filterResult)) {
|
|
144
|
+
throw new TypeError(`invalid root walk entryFilter result: ${String(filterResult)}`);
|
|
145
|
+
}
|
|
146
|
+
if (filterResult === "include") {
|
|
147
|
+
yield walkEntry;
|
|
148
|
+
}
|
|
149
|
+
if (kind !== "directory") {
|
|
95
150
|
continue;
|
|
96
151
|
}
|
|
97
|
-
|
|
98
|
-
absolutePath: path.resolve(root.rootReal, child),
|
|
99
|
-
rootPath: root.rootReal,
|
|
100
|
-
rootCanonicalPath: root.rootReal,
|
|
101
|
-
boundaryLabel: "root walk",
|
|
102
|
-
});
|
|
103
|
-
if (!resolved.exists) {
|
|
152
|
+
if (filterResult === "skip-subtree") {
|
|
104
153
|
continue;
|
|
105
154
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
if (filterResult === "include") {
|
|
115
|
-
yield walkEntry;
|
|
116
|
-
}
|
|
117
|
-
if (kind !== "directory") {
|
|
118
|
-
continue;
|
|
155
|
+
if (depth >= maxDepth) {
|
|
156
|
+
yield onLimit(child);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
yield* visit(child, depth + 1);
|
|
160
|
+
if (truncated)
|
|
161
|
+
return;
|
|
119
162
|
}
|
|
120
|
-
|
|
121
|
-
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
failed = true;
|
|
166
|
+
operationError = error;
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
try {
|
|
171
|
+
await listing[Symbol.asyncDispose]();
|
|
122
172
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
173
|
+
catch (closeError) {
|
|
174
|
+
if (failed) {
|
|
175
|
+
throw createSuppressedError(closeError, operationError, "directory walk and close both failed");
|
|
176
|
+
}
|
|
177
|
+
throw closeError;
|
|
126
178
|
}
|
|
127
|
-
yield* visit(child, depth + 1);
|
|
128
|
-
if (truncated)
|
|
129
|
-
return;
|
|
130
179
|
}
|
|
131
180
|
}
|
|
132
181
|
yield* visit(relativePath, 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-write-mode.d.ts","sourceRoot":"","sources":["../src/root-write-mode.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"root-write-mode.d.ts","sourceRoot":"","sources":["../src/root-write-mode.ts"],"names":[],"mappings":"AASA,wBAAsB,sBAAsB,CAAC,MAAM,EAAE;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsClB"}
|
package/dist/root-write-mode.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import fsSync from "node:fs";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import { FsSafeError } from "./errors.js";
|
|
4
|
-
import { sameFileIdentity } from "./file-identity.js";
|
|
5
4
|
import { isNotFoundPathError, isPathInside } from "./path.js";
|
|
6
5
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
7
6
|
import { hardlinkedPathNotAllowedError, outsideWorkspaceError } from "./root-errors.js";
|
|
@@ -23,9 +22,7 @@ export async function inheritWriteTargetMode(params) {
|
|
|
23
22
|
const handle = await fs.open(params.targetPath, resolveReadOpenFlags());
|
|
24
23
|
try {
|
|
25
24
|
// Bind admission to the inode whose metadata is inherited.
|
|
26
|
-
|
|
27
|
-
throw new FsSafeError("path-mismatch", "write target changed during mode inheritance");
|
|
28
|
-
}
|
|
25
|
+
await inspectFileIdentity(() => fsSync.fstatSync(handle.fd, { bigint: true }), existing);
|
|
29
26
|
}
|
|
30
27
|
finally {
|
|
31
28
|
await handle.close().catch(() => undefined);
|
package/dist/root.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export { DEFAULT_ROOT_MAX_BYTES, openLocalFileSafely, readLocalFileSafely, resolveOpenedFileRealPathForHandle, 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 SymlinkPolicy, type WritableOpenMode, type WritableOpenResult, } from "./root-impl.js";
|
|
1
|
+
export { DEFAULT_ROOT_MAX_BYTES, openLocalFileSafely, readLocalFileSafely, resolveOpenedFileRealPathForHandle, root, type DenyMutationPolicy, type HardlinkPolicy, type MutationSymlinkPolicy, type RenameIdentityPolicy, type OpenResult, type ReadResult, type Root, type RootAppendOptions, type RootCopyOptions, type RootCopySource, 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 SymlinkPolicy, type WritableOpenMode, type WritableOpenResult, } from "./root-impl.js";
|
|
2
|
+
export type { RootCopyPublicationReceipt } from "./copy-publication.js";
|
|
3
|
+
export type { CopyCloneMode } from "./copy-policy.js";
|
|
2
4
|
export type { ContainmentGuarantee } from "./containment.js";
|
|
3
5
|
export type { RootWalkDataEntry, RootWalkDataEntryKind, RootWalkDirectoryErrorBehavior, RootWalkEntry, RootWalkEntryFilter, RootWalkEntryFilterResult, RootWalkEntryKind, RootWalkLimitBehavior, RootWalkOptions, RootWalkSymlinkPolicy, } from "./root-walk.js";
|
|
4
6
|
//# sourceMappingURL=root.d.ts.map
|
package/dist/root.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../src/root.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,kCAAkC,EAClC,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,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,YAAY,EACV,iBAAiB,EACjB,qBAAqB,EACrB,8BAA8B,EAC9B,aAAa,EACb,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,qBAAqB,GACtB,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../src/root.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,kCAAkC,EAClC,IAAI,EACJ,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,IAAI,EACT,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,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,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACxE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,YAAY,EACV,iBAAiB,EACjB,qBAAqB,EACrB,8BAA8B,EAC9B,aAAa,EACb,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,qBAAqB,GACtB,MAAM,gBAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secure-file.d.ts","sourceRoot":"","sources":["../src/secure-file.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAa7C,OAAO,EAOL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC5B,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"secure-file.d.ts","sourceRoot":"","sources":["../src/secure-file.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAa7C,OAAO,EAOL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC5B,MAAM,kBAAkB,CAAC;AAI1B,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,sBAAsB,CAAC;IAC/B,WAAW,CAAC,EAAE,2BAA2B,CAAC;IAC1C,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,EAAE,CAAC,EAAE,mBAAmB,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,sBAAsB,CAAC;AAE7D,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;IACZ,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B,CAAC;AAmMF,wBAAsB,cAAc,CAClC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAe/B"}
|
package/dist/secure-file.js
CHANGED
|
@@ -11,6 +11,7 @@ import { formatPermissionErrorDetail } from "./permission-exec.js";
|
|
|
11
11
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
12
12
|
import { inspectPathPermissions, isGroupReadable, isGroupWritable, isWorldReadable, isWorldWritable, modeBits, } from "./permissions.js";
|
|
13
13
|
import { inspectFileIdentity } from "./strict-file-identity.js";
|
|
14
|
+
import { scheduleTimeout } from "./timing.js";
|
|
14
15
|
function isAbsolutePathname(value) {
|
|
15
16
|
return (path.isAbsolute(value) ||
|
|
16
17
|
(process.platform === "win32" &&
|
|
@@ -160,12 +161,12 @@ async function readHandleWithTimeout(handle, timeoutMs, maxBytes) {
|
|
|
160
161
|
if (timeoutMs === undefined || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
161
162
|
return await read();
|
|
162
163
|
}
|
|
163
|
-
let
|
|
164
|
+
let cancelTimeout;
|
|
164
165
|
try {
|
|
165
166
|
return await Promise.race([
|
|
166
167
|
read(),
|
|
167
168
|
new Promise((_resolve, reject) => {
|
|
168
|
-
|
|
169
|
+
cancelTimeout = scheduleTimeout(() => {
|
|
169
170
|
void handle.close().catch(() => undefined);
|
|
170
171
|
reject(new FsSafeError("timeout", `secure file read timed out after ${timeoutMs}ms`));
|
|
171
172
|
}, timeoutMs);
|
|
@@ -173,8 +174,7 @@ async function readHandleWithTimeout(handle, timeoutMs, maxBytes) {
|
|
|
173
174
|
]);
|
|
174
175
|
}
|
|
175
176
|
finally {
|
|
176
|
-
|
|
177
|
-
clearTimeout(timeout);
|
|
177
|
+
cancelTimeout?.();
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
export async function readSecureFile(options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidecar-lock-acquire.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-acquire.ts"],"names":[],"mappings":"AAQA,OAAO,EAA6B,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAS3C,OAAO,EAWL,KAAK,mBAAmB,EACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"sidecar-lock-acquire.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-acquire.ts"],"names":[],"mappings":"AAQA,OAAO,EAA6B,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAS3C,OAAO,EAWL,KAAK,mBAAmB,EACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAI5F,KAAK,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC;AAEvF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,cAAc,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;CAClC,CAAC;AAEF,KAAK,6BAA6B,GAAG;IACnC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACnC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,2BAA2B,IAAI,IAAI,CAAC;IACpC,iBAAiB,CAAC,oBAAoB,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,iBAAiB,CAAC;IAC1F,eAAe,CACb,oBAAoB,EAAE,MAAM,EAC5B,IAAI,EAAE,eAAe,EACrB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC5B,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB,CAAC;AAqBF,wBAAsB,kBAAkB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/E,OAAO,EAAE,yBAAyB,CAAC,QAAQ,CAAC,EAC5C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,iBAAiB,CAAC,CAqT5B"}
|
|
@@ -10,6 +10,7 @@ import { createNativeExclusiveFile } from "./native-operations.js";
|
|
|
10
10
|
import { computeSidecarLockDelayMs, defaultSidecarLockShouldReclaim, isTransientLockFileDenial, maxTransientLockDenials, validateSidecarLockRetryOptions, validateSidecarLockTimeoutMs, } from "./sidecar-lock-policy.js";
|
|
11
11
|
import { readSidecarLockRawSnapshot, parseSidecarLockSnapshot, relativeSidecarLockPath, releaseSidecarReclaimGuard, removeSidecarLockIfUnchanged, removeStaleSidecarLockIfAllowed, serializeSidecarLockPayload, sidecarLockSnapshotStillPresent, sidecarReclaimGuardExists, tryAcquireSidecarReclaimGuard, } from "./sidecar-lock-reclaim.js";
|
|
12
12
|
import { createSuppressedError } from "./suppressed-error.js";
|
|
13
|
+
import { sleep } from "./timing.js";
|
|
13
14
|
async function resolveNormalizedTargetPath(targetPath, lockRoot) {
|
|
14
15
|
const resolved = path.resolve(targetPath);
|
|
15
16
|
const dir = path.dirname(resolved);
|
|
@@ -86,7 +87,7 @@ export async function acquireSidecarLock(options, context) {
|
|
|
86
87
|
: Math.max(0, options.timeoutMs - elapsed);
|
|
87
88
|
const delay = Math.min(computeSidecarLockDelayMs(retry, attempt), remaining);
|
|
88
89
|
attempt += 1;
|
|
89
|
-
await
|
|
90
|
+
await sleep(delay);
|
|
90
91
|
};
|
|
91
92
|
// Waiting can fail on the caller's own retry or deadline limits. Classifying
|
|
92
93
|
// a denial as contention must not cost them the original diagnosis, so hand
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidecar-lock-policy.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAQvE,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,uBAAuB,GAAG,IAAI,CAkBpF;AAED,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAGhF;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,uBAAuB,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"sidecar-lock-policy.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAQvE,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,uBAAuB,GAAG,IAAI,CAkBpF;AAED,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAGhF;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,uBAAuB,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAUjG;AASD,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAEzC,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGnF;AAED,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAU7E;AAED,wBAAsB,+BAA+B,CAAC,MAAM,EAAE;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,OAAO,CAAC,CAQnB"}
|
|
@@ -32,7 +32,9 @@ export function computeSidecarLockDelayMs(retry, attempt) {
|
|
|
32
32
|
const minTimeout = retry.minTimeout ?? 50;
|
|
33
33
|
const maxTimeout = retry.maxTimeout ?? 1000;
|
|
34
34
|
const factor = retry.factor ?? 1;
|
|
35
|
-
|
|
35
|
+
// Zero times an overflowing power is NaN, which makes Atomics.wait unbounded.
|
|
36
|
+
const scaled = minTimeout === 0 ? 0 : minTimeout * factor ** attempt;
|
|
37
|
+
const base = Math.min(maxTimeout, Math.max(minTimeout, scaled));
|
|
36
38
|
const jitter = retry.randomize ? 1 + Math.random() : 1;
|
|
37
39
|
return Math.min(maxTimeout, Math.round(base * jitter));
|
|
38
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"temp-cleanup.d.ts","sourceRoot":"","sources":["../src/temp-cleanup.ts"],"names":[],"mappings":"AACA,OAAO,EAA8B,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEvF,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,CAAC;AAEvD,MAAM,MAAM,oBAAoB,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG;IAChD,WAAW,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAC/C,CAAC;
|
|
1
|
+
{"version":3,"file":"temp-cleanup.d.ts","sourceRoot":"","sources":["../src/temp-cleanup.ts"],"names":[],"mappings":"AACA,OAAO,EAA8B,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEvF,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,CAAC;AAEvD,MAAM,MAAM,oBAAoB,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG;IAChD,WAAW,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAC/C,CAAC;AAmDF,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IACR,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;CAC7B,GACA,oBAAoB,CA2BtB;AAED,wBAAgB,mCAAmC,IAAI,IAAI,CAE1D;AAED,wBAAgB,kCAAkC,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAUzE"}
|
package/dist/temp-cleanup.js
CHANGED
|
@@ -11,8 +11,9 @@ function pathStillMatchesReceipt(entry) {
|
|
|
11
11
|
return (!entry.singleLinkFile || (current.isFile() && current.nlink === 1n)) &&
|
|
12
12
|
sameFileIdentityForCleanup(current, entry.identity);
|
|
13
13
|
}
|
|
14
|
-
catch
|
|
15
|
-
|
|
14
|
+
catch {
|
|
15
|
+
// A missing pathname grants no authority over an entry created after this lookup.
|
|
16
|
+
return false;
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
function removeRegisteredPathSync(entry) {
|
package/dist/timing.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare function scheduleTimeout(callback: () => void, ms: number): () => void;
|
|
1
2
|
export declare function sleep(ms: number): Promise<void>;
|
|
2
3
|
export declare function sleepSync(ms: number): void;
|
|
3
4
|
export declare function withTimeout<T>(promise: Promise<T>, timeoutMs: number, labelOrOptions?: string | {
|
package/dist/timing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../src/timing.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../src/timing.ts"],"names":[],"mappings":"AAEA,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,IAAI,CAgB5E;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAK1C;AAED,wBAAsB,WAAW,CAAC,CAAC,EACjC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,cAAc,GAAE,MAAM,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,KAAK,CAAA;CAErF,GACA,OAAO,CAAC,CAAC,CAAC,CA2BZ"}
|
package/dist/timing.js
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
|
+
const MAX_TIMER_DELAY_MS = 2 ** 31 - 1;
|
|
2
|
+
export function scheduleTimeout(callback, ms) {
|
|
3
|
+
let timer;
|
|
4
|
+
if (Number.isFinite(ms) && ms > MAX_TIMER_DELAY_MS) {
|
|
5
|
+
const startedAt = performance.now();
|
|
6
|
+
const tick = () => {
|
|
7
|
+
const remaining = ms - (performance.now() - startedAt);
|
|
8
|
+
if (remaining <= 0)
|
|
9
|
+
callback();
|
|
10
|
+
else
|
|
11
|
+
timer = setTimeout(tick, Math.min(remaining, MAX_TIMER_DELAY_MS));
|
|
12
|
+
};
|
|
13
|
+
// Node clamps overflowing delays to 1 ms. Rearm bounded timers against a
|
|
14
|
+
// monotonic clock so clock changes and event-loop stalls cannot shorten them.
|
|
15
|
+
timer = setTimeout(tick, MAX_TIMER_DELAY_MS);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
timer = setTimeout(callback, ms);
|
|
19
|
+
}
|
|
20
|
+
return () => clearTimeout(timer);
|
|
21
|
+
}
|
|
1
22
|
export function sleep(ms) {
|
|
2
|
-
return new Promise((resolve) =>
|
|
23
|
+
return new Promise((resolve) => { scheduleTimeout(resolve, ms); });
|
|
3
24
|
}
|
|
4
25
|
export function sleepSync(ms) {
|
|
5
26
|
if (ms <= 0) {
|
|
@@ -16,12 +37,12 @@ export async function withTimeout(promise, timeoutMs, labelOrOptions = {
|
|
|
16
37
|
const options = typeof labelOrOptions === "string" ? { label: labelOrOptions } : labelOrOptions;
|
|
17
38
|
const createError = options.createError ??
|
|
18
39
|
(() => new Error(options.message ?? `${options.label ?? "operation"} timed out after ${timeoutMs}ms`));
|
|
19
|
-
let
|
|
40
|
+
let cancelTimeout;
|
|
20
41
|
try {
|
|
21
42
|
return await Promise.race([
|
|
22
43
|
promise,
|
|
23
44
|
new Promise((_, reject) => {
|
|
24
|
-
|
|
45
|
+
cancelTimeout = scheduleTimeout(() => {
|
|
25
46
|
try {
|
|
26
47
|
reject(createError());
|
|
27
48
|
}
|
|
@@ -33,8 +54,6 @@ export async function withTimeout(promise, timeoutMs, labelOrOptions = {
|
|
|
33
54
|
]);
|
|
34
55
|
}
|
|
35
56
|
finally {
|
|
36
|
-
|
|
37
|
-
clearTimeout(timeoutId);
|
|
38
|
-
}
|
|
57
|
+
cancelTimeout?.();
|
|
39
58
|
}
|
|
40
59
|
}
|
package/dist/trash.js
CHANGED
|
@@ -18,7 +18,7 @@ function isTrashDestinationCollision(error) {
|
|
|
18
18
|
return Boolean(code && TRASH_DESTINATION_COLLISION_CODES.has(code));
|
|
19
19
|
}
|
|
20
20
|
function isSameOrChildPath(candidate, parent) {
|
|
21
|
-
return candidate === parent || candidate.startsWith(`${parent}${path.sep}`);
|
|
21
|
+
return candidate === parent || candidate.startsWith(parent.endsWith(path.sep) ? parent : `${parent}${path.sep}`);
|
|
22
22
|
}
|
|
23
23
|
function resolveAllowedTrashRoots(allowedRoots) {
|
|
24
24
|
const roots = [...(allowedRoots ?? [os.homedir(), os.tmpdir()])].flatMap((root) => {
|
|
@@ -107,7 +107,7 @@ function resolveContainedPath(root, leaf) {
|
|
|
107
107
|
return resolvedPath;
|
|
108
108
|
}
|
|
109
109
|
function reserveTrashDestination(trashDir, base, timestamp) {
|
|
110
|
-
const containerPrefix = resolveContainedPath(trashDir,
|
|
110
|
+
const containerPrefix = resolveContainedPath(trashDir, `.fs-safe-trash-${timestamp}-`);
|
|
111
111
|
const container = fs.mkdtempSync(containerPrefix);
|
|
112
112
|
const resolvedContainer = path.resolve(container);
|
|
113
113
|
const resolvedTrashDir = path.resolve(trashDir);
|
package/dist/walk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../src/walk.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;AAI7B,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AACvE,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE9D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC;IACjD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IAGnB,UAAU,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACrC,CAAC;AAEF,KAAK,+BAA+B,GAAG,mBAAmB,GAAG;IAC3D,UAAU,EAAE,oBAAoB,EAAE,CAAC;CACpC,CAAC;
|
|
1
|
+
{"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../src/walk.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;AAI7B,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AACvE,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE9D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC;IACjD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IAGnB,UAAU,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACrC,CAAC;AAEF,KAAK,+BAA+B,GAAG,mBAAmB,GAAG;IAC3D,UAAU,EAAE,oBAAoB,EAAE,CAAC;CACpC,CAAC;AAgFF,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,oBAAyB,GACjC,+BAA+B,CAyDjC;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,+BAA+B,CAAC,CAyD1C"}
|
package/dist/walk.js
CHANGED
|
@@ -27,7 +27,7 @@ function shouldStop(result, options) {
|
|
|
27
27
|
return options.maxEntries !== undefined && result.scannedEntryCount >= Math.max(0, options.maxEntries);
|
|
28
28
|
}
|
|
29
29
|
function buildEntry(params) {
|
|
30
|
-
const fullPath =
|
|
30
|
+
const fullPath = params.fullPath;
|
|
31
31
|
const relativePath = path.relative(params.rootDir, fullPath) || params.dirent.name;
|
|
32
32
|
return {
|
|
33
33
|
name: params.dirent.name,
|
|
@@ -47,27 +47,7 @@ function recordFailedDir(result, root, dir, depth, error) {
|
|
|
47
47
|
error,
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
|
-
function
|
|
51
|
-
const kind = kindForDirent(dirent);
|
|
52
|
-
if (kind !== "symlink")
|
|
53
|
-
return kind;
|
|
54
|
-
if (symlinks === "skip")
|
|
55
|
-
return null;
|
|
56
|
-
if (symlinks === "include")
|
|
57
|
-
return "symlink";
|
|
58
|
-
try {
|
|
59
|
-
const stat = fsSync.statSync(fullPath);
|
|
60
|
-
if (stat.isDirectory())
|
|
61
|
-
return "directory";
|
|
62
|
-
if (stat.isFile())
|
|
63
|
-
return "file";
|
|
64
|
-
}
|
|
65
|
-
catch {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
return "other";
|
|
69
|
-
}
|
|
70
|
-
async function resolveAsyncKind(fullPath, dirent, symlinks) {
|
|
50
|
+
function resolveKind(fullPath, dirent, symlinks) {
|
|
71
51
|
const kind = kindForDirent(dirent);
|
|
72
52
|
if (kind !== "symlink")
|
|
73
53
|
return kind;
|
|
@@ -127,10 +107,10 @@ export function walkDirectorySync(rootDir, options = {}) {
|
|
|
127
107
|
}
|
|
128
108
|
result.scannedEntryCount += 1;
|
|
129
109
|
const fullPath = path.join(dir, dirent.name);
|
|
130
|
-
const kind =
|
|
110
|
+
const kind = resolveKind(fullPath, dirent, symlinks);
|
|
131
111
|
if (!kind)
|
|
132
112
|
continue;
|
|
133
|
-
const entry = buildEntry({ rootDir: root,
|
|
113
|
+
const entry = buildEntry({ rootDir: root, fullPath, dirent, depth, kind });
|
|
134
114
|
if (options.include?.(entry) ?? true) {
|
|
135
115
|
result.entries.push(entry);
|
|
136
116
|
}
|
|
@@ -186,10 +166,10 @@ export async function walkDirectory(rootDir, options = {}) {
|
|
|
186
166
|
}
|
|
187
167
|
result.scannedEntryCount += 1;
|
|
188
168
|
const fullPath = path.join(dir, dirent.name);
|
|
189
|
-
const kind =
|
|
169
|
+
const kind = resolveKind(fullPath, dirent, symlinks);
|
|
190
170
|
if (!kind)
|
|
191
171
|
continue;
|
|
192
|
-
const entry = buildEntry({ rootDir: root,
|
|
172
|
+
const entry = buildEntry({ rootDir: root, fullPath, dirent, depth, kind });
|
|
193
173
|
if (options.include?.(entry) ?? true) {
|
|
194
174
|
result.entries.push(entry);
|
|
195
175
|
}
|
package/dist/windows-owner.d.ts
CHANGED
|
@@ -6,24 +6,21 @@ export type WindowsOwnerExec = (command: string, args: string[]) => Promise<{
|
|
|
6
6
|
export type WindowsOwnerSummary = {
|
|
7
7
|
sid?: string;
|
|
8
8
|
currentUserSid?: string;
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
daclPresent?: boolean;
|
|
10
|
+
aces?: WindowsOwnerAce[];
|
|
11
|
+
aclError?: string;
|
|
11
12
|
remote?: boolean;
|
|
12
13
|
trusted?: boolean;
|
|
13
14
|
error?: string;
|
|
14
15
|
errorDetail?: PermissionCommandFailure;
|
|
15
16
|
errorCause?: unknown;
|
|
16
17
|
};
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
export declare function resolveWindowsCurrentUserSid(params: {
|
|
24
|
-
env?: NodeJS.ProcessEnv;
|
|
25
|
-
exec: WindowsOwnerExec;
|
|
26
|
-
}): Promise<string | null>;
|
|
18
|
+
export type WindowsOwnerAce = {
|
|
19
|
+
sid: string;
|
|
20
|
+
mask: number;
|
|
21
|
+
deny: boolean;
|
|
22
|
+
inheritOnly: boolean;
|
|
23
|
+
};
|
|
27
24
|
export declare function inspectWindowsOwner(params: {
|
|
28
25
|
targetPath: string;
|
|
29
26
|
env?: NodeJS.ProcessEnv;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"windows-owner.d.ts","sourceRoot":"","sources":["../src/windows-owner.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,sBAAsB,CAAC;AAG9B,MAAM,MAAM,gBAAgB,GAAG,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,KACX,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEjD,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,
|
|
1
|
+
{"version":3,"file":"windows-owner.d.ts","sourceRoot":"","sources":["../src/windows-owner.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,sBAAsB,CAAC;AAG9B,MAAM,MAAM,gBAAgB,GAAG,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,KACX,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEjD,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,eAAe,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,wBAAwB,CAAC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAqDF,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,IAAI,EAAE,gBAAgB,CAAC;CACxB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA+C/B"}
|