@openclaw/fs-safe 0.8.6 → 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 +93 -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-durability.d.ts +24 -0
- package/dist/archive-durability.d.ts.map +1 -0
- package/dist/archive-durability.js +180 -0
- 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 +22 -4
- package/dist/archive-input.js +4 -4
- package/dist/archive-kind.d.ts.map +1 -1
- package/dist/archive-kind.js +3 -2
- package/dist/archive-merge.d.ts +1 -0
- package/dist/archive-merge.d.ts.map +1 -1
- package/dist/archive-merge.js +42 -9
- package/dist/archive-native.d.ts +1 -0
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +4 -2
- package/dist/archive-options.d.ts +2 -0
- package/dist/archive-options.d.ts.map +1 -1
- package/dist/archive-parser.wasm +0 -0
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +72 -70
- package/dist/archive-staging.d.ts +1 -1
- package/dist/archive-staging.d.ts.map +1 -1
- package/dist/archive-staging.js +24 -19
- 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/archive.d.ts.map +1 -1
- package/dist/archive.js +9 -4
- 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 +15 -0
- package/dist/copy-publication.d.ts.map +1 -0
- package/dist/copy-publication.js +30 -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/directory-mode-node.d.ts.map +1 -1
- package/dist/directory-mode-node.js +4 -4
- 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 +49 -12
- package/dist/file-store-sync-write.d.ts +1 -0
- package/dist/file-store-sync-write.d.ts.map +1 -1
- package/dist/file-store-sync-write.js +9 -6
- package/dist/file-store.d.ts +4 -0
- package/dist/file-store.d.ts.map +1 -1
- package/dist/file-store.js +10 -1
- package/dist/filename.d.ts.map +1 -1
- package/dist/filename.js +2 -12
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +1 -2
- 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 +9 -5
- 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 +9 -13
- package/dist/json-document-store.d.ts +3 -0
- package/dist/json-document-store.d.ts.map +1 -1
- package/dist/json-document-store.js +1 -0
- package/dist/json-durable-queue-directory.js +3 -3
- package/dist/json-durable-queue-ownership.js +3 -2
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +31 -27
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +22 -24
- package/dist/move-path-cleanup.d.ts.map +1 -1
- package/dist/move-path-cleanup.js +4 -3
- 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 +55 -47
- 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/opened-file-failure.d.ts +1 -1
- package/dist/opened-file-failure.d.ts.map +1 -1
- package/dist/opened-file-failure.js +3 -2
- 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/permissions.js +3 -3
- 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/private-temp-workspace.d.ts.map +1 -1
- package/dist/private-temp-workspace.js +9 -3
- 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 +26 -25
- package/dist/replace-file-copy-fallback.d.ts.map +1 -1
- package/dist/replace-file-copy-fallback.js +30 -17
- package/dist/replace-file-copy-source.d.ts.map +1 -1
- package/dist/replace-file-copy-source.js +10 -5
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +6 -2
- package/dist/replace-file.d.ts.map +1 -1
- package/dist/replace-file.js +8 -3
- 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 +342 -208
- 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/secret-file.d.ts +1 -0
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +1 -0
- package/dist/secret-read-async.js +5 -5
- package/dist/secure-file.d.ts +1 -1
- package/dist/secure-file.d.ts.map +1 -1
- package/dist/secure-file.js +23 -13
- package/dist/sibling-staged-file.js +7 -7
- package/dist/sibling-temp.d.ts.map +1 -1
- package/dist/sibling-temp.js +16 -7
- package/dist/sidecar-lock-acquire.d.ts +1 -1
- package/dist/sidecar-lock-acquire.d.ts.map +1 -1
- package/dist/sidecar-lock-acquire.js +6 -4
- package/dist/sidecar-lock-policy.d.ts.map +1 -1
- package/dist/sidecar-lock-policy.js +5 -3
- package/dist/sidecar-lock-reclaim.d.ts.map +1 -1
- package/dist/sidecar-lock-reclaim.js +16 -4
- package/dist/sidecar-lock.d.ts.map +1 -1
- package/dist/sidecar-lock.js +2 -1
- package/dist/temp-cleanup.d.ts.map +1 -1
- package/dist/temp-cleanup.js +3 -2
- package/dist/temp-target.d.ts.map +1 -1
- package/dist/temp-target.js +9 -4
- 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 +7 -27
- 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/dist/write-open-flags.d.ts.map +1 -1
- package/dist/write-open-flags.js +1 -2
- package/docs/advanced.md +18 -4
- package/docs/archive.md +57 -9
- 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/file-store.md +48 -3
- package/docs/json-store.md +10 -0
- 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/reading.md +6 -0
- package/docs/root.md +168 -6
- package/docs/secret-file.md +6 -0
- package/docs/security-model.md +14 -0
- package/docs/sidecar-lock.md +2 -0
- package/docs/timing.md +2 -0
- package/docs/types.md +18 -11
- package/docs/walk.md +54 -5
- package/docs/writing.md +25 -5
- package/package.json +16 -11
package/dist/file-store.js
CHANGED
|
@@ -106,6 +106,7 @@ async function copyIntoRoot(params) {
|
|
|
106
106
|
});
|
|
107
107
|
await ensureParentInRoot(scopedRoot, relativePath, dirMode);
|
|
108
108
|
await scopedRoot.copyIn(relativePath, params.sourcePath, {
|
|
109
|
+
durable: params.durable,
|
|
109
110
|
maxBytes: params.maxBytes,
|
|
110
111
|
mkdir: false,
|
|
111
112
|
mode: params.mode ?? 0o600,
|
|
@@ -117,6 +118,7 @@ export function fileStore(options) {
|
|
|
117
118
|
const privateMode = options.private ?? false;
|
|
118
119
|
const dirMode = options.dirMode ?? 0o700;
|
|
119
120
|
const mode = options.mode ?? 0o600;
|
|
121
|
+
const durable = options.durable ?? true;
|
|
120
122
|
const maxBytes = normalizeMaxBytes(options.maxBytes);
|
|
121
123
|
async function openRoot() {
|
|
122
124
|
return await root(rootDir, { hardlinks: "reject", maxBytes });
|
|
@@ -132,6 +134,7 @@ export function fileStore(options) {
|
|
|
132
134
|
rootDir,
|
|
133
135
|
filePath: destination,
|
|
134
136
|
content,
|
|
137
|
+
durable: writeOptions?.durable ?? durable,
|
|
135
138
|
dirMode: writeOptions?.dirMode ?? dirMode,
|
|
136
139
|
mode: writeOptions?.mode ?? mode,
|
|
137
140
|
});
|
|
@@ -147,6 +150,7 @@ export function fileStore(options) {
|
|
|
147
150
|
await scopedRoot.write(safeRelativePath, content, {
|
|
148
151
|
mkdir: false,
|
|
149
152
|
mode: writeOptions?.mode ?? mode,
|
|
153
|
+
durable: writeOptions?.durable ?? durable,
|
|
150
154
|
});
|
|
151
155
|
return destination;
|
|
152
156
|
}
|
|
@@ -173,6 +177,7 @@ export function fileStore(options) {
|
|
|
173
177
|
rootDir,
|
|
174
178
|
filePath: destination,
|
|
175
179
|
content: Buffer.concat(chunks),
|
|
180
|
+
durable: writeOptions?.durable ?? durable,
|
|
176
181
|
dirMode: writeOptions?.dirMode ?? dirMode,
|
|
177
182
|
mode: writeOptions?.mode ?? mode,
|
|
178
183
|
});
|
|
@@ -188,6 +193,7 @@ export function fileStore(options) {
|
|
|
188
193
|
rootDir,
|
|
189
194
|
relativePath: safeRelativePath,
|
|
190
195
|
sourcePath: staged.path,
|
|
196
|
+
durable: writeOptions?.durable ?? durable,
|
|
191
197
|
maxBytes: limit,
|
|
192
198
|
mode: writeOptions?.mode ?? mode,
|
|
193
199
|
tempPrefix: writeOptions?.tempPrefix,
|
|
@@ -212,6 +218,7 @@ export function fileStore(options) {
|
|
|
212
218
|
rootDir,
|
|
213
219
|
relativePath,
|
|
214
220
|
sourcePath,
|
|
221
|
+
durable: writeOptions?.durable ?? durable,
|
|
215
222
|
dirMode: writeOptions?.dirMode ?? dirMode,
|
|
216
223
|
maxBytes: configuredLimit,
|
|
217
224
|
mode: writeOptions?.mode ?? mode,
|
|
@@ -283,7 +290,7 @@ export function fileStore(options) {
|
|
|
283
290
|
readRequired: async () => await (await openRoot()).readJson(assertRelativePath(relativePath)),
|
|
284
291
|
write: async (value, options) => {
|
|
285
292
|
const json = stringifyJsonDocument(value, null, 2);
|
|
286
|
-
await write(relativePath, options?.trailingNewline === false ? json : `${json}\n
|
|
293
|
+
await write(relativePath, options?.trailingNewline === false ? json : `${json}\n`, { durable: options?.durable });
|
|
287
294
|
},
|
|
288
295
|
}, jsonOptions);
|
|
289
296
|
},
|
|
@@ -297,6 +304,7 @@ export function fileStoreSync(options) {
|
|
|
297
304
|
const privateMode = options.private ?? false;
|
|
298
305
|
const dirMode = options.dirMode ?? 0o700;
|
|
299
306
|
const mode = options.mode ?? 0o600;
|
|
307
|
+
const durable = options.durable ?? true;
|
|
300
308
|
const maxBytes = normalizeMaxBytes(options.maxBytes);
|
|
301
309
|
function write(relativePath, data, writeOptions) {
|
|
302
310
|
const destination = resolveStorePath(rootDir, relativePath);
|
|
@@ -308,6 +316,7 @@ export function fileStoreSync(options) {
|
|
|
308
316
|
filePath: destination,
|
|
309
317
|
content,
|
|
310
318
|
privateMode,
|
|
319
|
+
durable: writeOptions?.durable ?? durable,
|
|
311
320
|
dirMode: writeOptions?.dirMode ?? dirMode,
|
|
312
321
|
mode: writeOptions?.mode ?? mode,
|
|
313
322
|
});
|
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/fs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOxD"}
|
package/dist/fs.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
-
import fsp from "node:fs/promises";
|
|
3
2
|
/**
|
|
4
3
|
* Returns true when `fs.stat()` can stat the path.
|
|
5
4
|
*
|
|
@@ -8,7 +7,7 @@ import fsp from "node:fs/promises";
|
|
|
8
7
|
*/
|
|
9
8
|
export async function pathExists(filePath) {
|
|
10
9
|
try {
|
|
11
|
-
|
|
10
|
+
fs.statSync(filePath);
|
|
12
11
|
return true;
|
|
13
12
|
}
|
|
14
13
|
catch {
|
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
|
@@ -49,7 +49,7 @@ export async function guardedRename(params) {
|
|
|
49
49
|
: await createAsyncDirectoryGuard(path.dirname(params.to));
|
|
50
50
|
await withAsyncDirectoryGuards([sourceGuard, targetGuard], async () => {
|
|
51
51
|
if (params.onSourceInspected) {
|
|
52
|
-
params.onSourceInspected(
|
|
52
|
+
params.onSourceInspected(fsSync.lstatSync(params.from, { bigint: true }));
|
|
53
53
|
}
|
|
54
54
|
// Authority must survive all awaited guards; do not yield before rename dispatch.
|
|
55
55
|
params.assertBeforeRename?.();
|
|
@@ -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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import
|
|
2
|
+
import fsSync from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { isPathInside } from "./path.js";
|
|
5
5
|
export function safeDirName(input) {
|
|
@@ -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;
|
|
@@ -49,9 +45,9 @@ export async function assertCanonicalPathWithinBase(params) {
|
|
|
49
45
|
if (!isPathInside(baseDir, candidatePath)) {
|
|
50
46
|
throw new Error(`Invalid path: must stay within ${params.boundaryLabel}`);
|
|
51
47
|
}
|
|
52
|
-
const baseLstat =
|
|
48
|
+
const baseLstat = fsSync.lstatSync(baseDir);
|
|
53
49
|
if (baseLstat.isSymbolicLink()) {
|
|
54
|
-
const baseStat =
|
|
50
|
+
const baseStat = fsSync.statSync(baseDir);
|
|
55
51
|
if (!baseStat.isDirectory()) {
|
|
56
52
|
throw new Error(`Invalid ${params.boundaryLabel}: base directory must resolve to a directory`);
|
|
57
53
|
}
|
|
@@ -59,15 +55,15 @@ export async function assertCanonicalPathWithinBase(params) {
|
|
|
59
55
|
else if (!baseLstat.isDirectory()) {
|
|
60
56
|
throw new Error(`Invalid ${params.boundaryLabel}: base directory must be a directory`);
|
|
61
57
|
}
|
|
62
|
-
const baseRealPath =
|
|
58
|
+
const baseRealPath = fsSync.realpathSync.native(baseDir);
|
|
63
59
|
const validateDirectory = async (dirPath) => {
|
|
64
60
|
const resolvedDirPath = path.resolve(dirPath);
|
|
65
|
-
const dirLstat =
|
|
61
|
+
const dirLstat = fsSync.lstatSync(dirPath);
|
|
66
62
|
if (dirLstat.isSymbolicLink()) {
|
|
67
63
|
if (resolvedDirPath !== baseDir) {
|
|
68
64
|
throw new Error(`Invalid path: must stay within ${params.boundaryLabel}`);
|
|
69
65
|
}
|
|
70
|
-
const dirStat =
|
|
66
|
+
const dirStat = fsSync.statSync(dirPath);
|
|
71
67
|
if (!dirStat.isDirectory()) {
|
|
72
68
|
throw new Error(`Invalid path: must stay within ${params.boundaryLabel}`);
|
|
73
69
|
}
|
|
@@ -75,7 +71,7 @@ export async function assertCanonicalPathWithinBase(params) {
|
|
|
75
71
|
else if (!dirLstat.isDirectory()) {
|
|
76
72
|
throw new Error(`Invalid path: must stay within ${params.boundaryLabel}`);
|
|
77
73
|
}
|
|
78
|
-
const dirRealPath =
|
|
74
|
+
const dirRealPath = fsSync.realpathSync.native(dirPath);
|
|
79
75
|
if (!isPathInside(baseRealPath, dirRealPath)) {
|
|
80
76
|
throw new Error(`Invalid path: must stay within ${params.boundaryLabel}`);
|
|
81
77
|
}
|
|
@@ -9,6 +9,8 @@ export type JsonStoreLockOptions = {
|
|
|
9
9
|
managerKey?: string;
|
|
10
10
|
};
|
|
11
11
|
export type JsonFileStoreOptions = {
|
|
12
|
+
/** Overrides the parent store's durability for every JSON mutation. */
|
|
13
|
+
durable?: boolean;
|
|
12
14
|
trailingNewline?: boolean;
|
|
13
15
|
lock?: boolean | JsonStoreLockOptions;
|
|
14
16
|
};
|
|
@@ -29,6 +31,7 @@ export type JsonStoreAdapter<T> = {
|
|
|
29
31
|
readRequired(): Promise<T>;
|
|
30
32
|
write(value: T, options?: {
|
|
31
33
|
trailingNewline?: boolean;
|
|
34
|
+
durable?: boolean;
|
|
32
35
|
}): Promise<void>;
|
|
33
36
|
};
|
|
34
37
|
export declare function createJsonStore<T>(adapter: JsonStoreAdapter<T>, options?: JsonFileStoreOptions): JsonStore<T>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-document-store.d.ts","sourceRoot":"","sources":["../src/json-document-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE3D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AASlE,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,GAAG,oBAAoB,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,IAAI,IAAI,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC/B,MAAM,CAAC,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAChC,YAAY,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,SAAS,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACpE,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACxE,CAAC;AAEF,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,YAAY,IAAI,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IACvC,YAAY,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"json-document-store.d.ts","sourceRoot":"","sources":["../src/json-document-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE3D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AASlE,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,GAAG,oBAAoB,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,IAAI,IAAI,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC/B,MAAM,CAAC,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAChC,YAAY,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,SAAS,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACpE,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACxE,CAAC;AAEF,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,YAAY,IAAI,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IACvC,YAAY,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5F,CAAC;AA2BF,wBAAgB,eAAe,CAAC,CAAC,EAC/B,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC5B,OAAO,GAAE,oBAAyB,GACjC,SAAS,CAAC,CAAC,CAAC,CAoFd"}
|
|
@@ -38,6 +38,7 @@ export function createJsonStore(adapter, options = {}) {
|
|
|
38
38
|
async function write(value) {
|
|
39
39
|
await adapter.write(value, {
|
|
40
40
|
trailingNewline: options.trailingNewline ?? true,
|
|
41
|
+
durable: options.durable,
|
|
41
42
|
});
|
|
42
43
|
}
|
|
43
44
|
async function withSerializedMutation(run) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import fsSync from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { syncDirectory } from "./directory-durability.js";
|
|
4
4
|
import { isPathRelativeEscape } from "./path.js";
|
|
5
5
|
export async function syncQueueDirectoryCreation(dir, validationBase) {
|
|
6
|
-
const baseReal =
|
|
7
|
-
const targetReal =
|
|
6
|
+
const baseReal = fsSync.realpathSync.native(validationBase);
|
|
7
|
+
const targetReal = fsSync.realpathSync.native(dir);
|
|
8
8
|
const relative = path.relative(baseReal, targetReal);
|
|
9
9
|
if (isPathRelativeEscape(relative)) {
|
|
10
10
|
throw new Error(`durable queue directory escapes validation base: ${dir}`);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { withSidecarLock } from "./sidecar-lock.js";
|
|
3
|
+
import fsSync, {} from "node:fs";
|
|
3
4
|
import fs from "node:fs/promises";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
import { syncDirectory } from "./directory-durability.js";
|
|
@@ -163,7 +164,7 @@ export function getErrorCode(error) {
|
|
|
163
164
|
}
|
|
164
165
|
async function lstatOrNull(filePath) {
|
|
165
166
|
try {
|
|
166
|
-
return
|
|
167
|
+
return fsSync.lstatSync(filePath, { bigint: true });
|
|
167
168
|
}
|
|
168
169
|
catch (error) {
|
|
169
170
|
if (getErrorCode(error) === "ENOENT")
|
|
@@ -205,7 +206,7 @@ async function ensureRetirementRoot(jsonPath) {
|
|
|
205
206
|
if (getErrorCode(error) !== "EEXIST")
|
|
206
207
|
throw error;
|
|
207
208
|
});
|
|
208
|
-
const root =
|
|
209
|
+
const root = fsSync.lstatSync(rootPath, { bigint: true });
|
|
209
210
|
assertDirectory(root, "queue retirement root");
|
|
210
211
|
await syncDirectory(parentPath);
|
|
211
212
|
return rootPath;
|
|
@@ -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";
|
|
@@ -18,7 +19,7 @@ export async function unlinkBestEffort(filePath) {
|
|
|
18
19
|
}
|
|
19
20
|
export async function jsonDurableQueueEntryExists(filePath) {
|
|
20
21
|
try {
|
|
21
|
-
const stat =
|
|
22
|
+
const stat = fs.lstatSync(filePath);
|
|
22
23
|
return stat.isFile();
|
|
23
24
|
}
|
|
24
25
|
catch (error) {
|
|
@@ -30,7 +31,7 @@ export async function jsonDurableQueueEntryExists(filePath) {
|
|
|
30
31
|
}
|
|
31
32
|
async function unlinkStaleTmpBestEffort(filePath, now, maxAgeMs) {
|
|
32
33
|
try {
|
|
33
|
-
const stat =
|
|
34
|
+
const stat = fs.statSync(filePath);
|
|
34
35
|
if (stat.isFile() && now - stat.mtimeMs >= maxAgeMs) {
|
|
35
36
|
await unlinkBestEffort(filePath);
|
|
36
37
|
}
|
|
@@ -113,22 +114,27 @@ async function isDarwinSystemAlias(dir, stat) {
|
|
|
113
114
|
if (resolved !== "/tmp" && resolved !== "/var") {
|
|
114
115
|
return false;
|
|
115
116
|
}
|
|
116
|
-
|
|
117
|
+
try {
|
|
118
|
+
return fs.realpathSync.native(resolved) === `/private${resolved}`;
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
117
123
|
}
|
|
118
124
|
async function assertNoSymlinkDirectorySegments(validationRoot, dir, allowMissing) {
|
|
119
125
|
let base = path.resolve(validationRoot.path);
|
|
120
126
|
let target = path.resolve(dir);
|
|
121
127
|
let current = base;
|
|
122
|
-
let baseStat =
|
|
128
|
+
let baseStat = fs.lstatSync(base);
|
|
123
129
|
if (baseStat.isSymbolicLink() && validationRoot.allowSymlinkBase) {
|
|
124
130
|
const relative = path.relative(base, target);
|
|
125
131
|
if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
126
132
|
throw new Error(`durable queue path is not a directory: ${dir}`);
|
|
127
133
|
}
|
|
128
|
-
base =
|
|
134
|
+
base = fs.realpathSync.native(base);
|
|
129
135
|
target = path.join(base, ...relative.split(path.sep).filter(Boolean));
|
|
130
136
|
current = base;
|
|
131
|
-
baseStat =
|
|
137
|
+
baseStat = fs.lstatSync(base);
|
|
132
138
|
}
|
|
133
139
|
if (baseStat.isSymbolicLink() || !baseStat.isDirectory()) {
|
|
134
140
|
throw new Error(`durable queue path is not a directory: ${dir}`);
|
|
@@ -142,7 +148,7 @@ async function assertNoSymlinkDirectorySegments(validationRoot, dir, allowMissin
|
|
|
142
148
|
current = path.join(current, segment);
|
|
143
149
|
let stat;
|
|
144
150
|
try {
|
|
145
|
-
stat =
|
|
151
|
+
stat = fs.lstatSync(current);
|
|
146
152
|
}
|
|
147
153
|
catch (error) {
|
|
148
154
|
if (allowMissing && error.code === "ENOENT") {
|
|
@@ -153,7 +159,7 @@ async function assertNoSymlinkDirectorySegments(validationRoot, dir, allowMissin
|
|
|
153
159
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
154
160
|
if (stat.isSymbolicLink() && validationRoot.allowSymlinkBase) {
|
|
155
161
|
if (await isDarwinSystemAlias(current, stat)) {
|
|
156
|
-
current =
|
|
162
|
+
current = fs.realpathSync.native(current);
|
|
157
163
|
continue;
|
|
158
164
|
}
|
|
159
165
|
}
|
|
@@ -172,7 +178,7 @@ async function chmodQueueDirectory(dir) {
|
|
|
172
178
|
let handle;
|
|
173
179
|
try {
|
|
174
180
|
handle = await fs.promises.open(dir, fs.constants.O_RDONLY | noFollow | directoryFlag);
|
|
175
|
-
const stat =
|
|
181
|
+
const stat = fs.fstatSync(handle.fd);
|
|
176
182
|
if (!stat.isDirectory()) {
|
|
177
183
|
throw new Error(`durable queue path is not a directory: ${dir}`);
|
|
178
184
|
}
|
|
@@ -193,7 +199,7 @@ async function chmodQueueDirectory(dir) {
|
|
|
193
199
|
}
|
|
194
200
|
}
|
|
195
201
|
}
|
|
196
|
-
const stat =
|
|
202
|
+
const stat = fs.lstatSync(dir);
|
|
197
203
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
198
204
|
throw new Error(`durable queue path is not a directory: ${dir}`);
|
|
199
205
|
}
|
|
@@ -218,7 +224,7 @@ async function inspectQueueEntry(inspect, maxBytes, expected) {
|
|
|
218
224
|
try {
|
|
219
225
|
return await inspectFileIdentity(async () => {
|
|
220
226
|
try {
|
|
221
|
-
const stat =
|
|
227
|
+
const stat = inspect();
|
|
222
228
|
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
223
229
|
throw new Error("queue entry is not a regular file");
|
|
224
230
|
}
|
|
@@ -242,26 +248,18 @@ async function inspectQueueEntry(inspect, maxBytes, expected) {
|
|
|
242
248
|
}
|
|
243
249
|
}
|
|
244
250
|
async function readBoundedUtf8File(params) {
|
|
245
|
-
const inspectPath = () => fs.
|
|
251
|
+
const inspectPath = () => fs.lstatSync(params.filePath, { bigint: true });
|
|
246
252
|
const initialStat = await inspectQueueEntry(inspectPath, params.maxBytes);
|
|
247
253
|
const handle = await fs.promises.open(params.filePath, resolveReadOpenFlags());
|
|
248
254
|
try {
|
|
249
|
-
const openedStat = await inspectQueueEntry(() => handle.
|
|
255
|
+
const openedStat = await inspectQueueEntry(() => fs.fstatSync(handle.fd, { bigint: true }), params.maxBytes, initialStat);
|
|
250
256
|
await inspectQueueEntry(inspectPath, params.maxBytes, openedStat);
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
return Buffer.concat(chunks, total).toString("utf8");
|
|
258
|
-
}
|
|
259
|
-
total += bytesRead;
|
|
260
|
-
if (total > params.maxBytes) {
|
|
261
|
-
throw new Error(`queue entry exceeds ${params.maxBytes} bytes`);
|
|
262
|
-
}
|
|
263
|
-
chunks.push(Buffer.from(scratch.subarray(0, bytesRead)));
|
|
264
|
-
}
|
|
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");
|
|
265
263
|
}
|
|
266
264
|
finally {
|
|
267
265
|
await handle.close();
|
|
@@ -318,6 +316,12 @@ export async function loadPendingJsonDurableQueueEntries(options) {
|
|
|
318
316
|
for (const file of files) {
|
|
319
317
|
if (file.endsWith(".delivered")) {
|
|
320
318
|
const id = file.slice(0, -".delivered".length);
|
|
319
|
+
try {
|
|
320
|
+
assertSafeQueueEntryId(id);
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
321
325
|
await completeDeliveredQueueEntry(resolveJsonDurableQueueEntryPaths(options.queueDir, id));
|
|
322
326
|
}
|
|
323
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"}
|