@openclaw/fs-safe 0.2.6 → 0.3.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +21 -7
  3. package/dist/archive-deadline.d.ts +9 -0
  4. package/dist/archive-deadline.d.ts.map +1 -0
  5. package/dist/archive-deadline.js +67 -0
  6. package/dist/archive-file-io.d.ts +9 -0
  7. package/dist/archive-file-io.d.ts.map +1 -0
  8. package/dist/archive-file-io.js +11 -0
  9. package/dist/archive-staging.d.ts.map +1 -1
  10. package/dist/archive-staging.js +43 -3
  11. package/dist/archive.d.ts.map +1 -1
  12. package/dist/archive.js +213 -105
  13. package/dist/deny-mutations.d.ts +11 -0
  14. package/dist/deny-mutations.d.ts.map +1 -0
  15. package/dist/deny-mutations.js +102 -0
  16. package/dist/errors.d.ts +1 -1
  17. package/dist/errors.d.ts.map +1 -1
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/json-durable-queue.d.ts.map +1 -1
  21. package/dist/json-durable-queue.js +5 -0
  22. package/dist/json.d.ts.map +1 -1
  23. package/dist/json.js +51 -4
  24. package/dist/opened-realpath.d.ts +3 -0
  25. package/dist/opened-realpath.d.ts.map +1 -0
  26. package/dist/opened-realpath.js +79 -0
  27. package/dist/output.d.ts.map +1 -1
  28. package/dist/output.js +1 -0
  29. package/dist/pinned-write.js +3 -9
  30. package/dist/read-opened-file.d.ts +18 -0
  31. package/dist/read-opened-file.d.ts.map +1 -0
  32. package/dist/read-opened-file.js +15 -0
  33. package/dist/regular-file.d.ts.map +1 -1
  34. package/dist/regular-file.js +23 -3
  35. package/dist/root-impl.d.ts +18 -15
  36. package/dist/root-impl.d.ts.map +1 -1
  37. package/dist/root-impl.js +60 -100
  38. package/dist/root-paths.d.ts.map +1 -1
  39. package/dist/root-paths.js +16 -5
  40. package/dist/root.d.ts +1 -1
  41. package/dist/root.d.ts.map +1 -1
  42. package/dist/secret-file.d.ts +1 -0
  43. package/dist/secret-file.d.ts.map +1 -1
  44. package/dist/secret-file.js +23 -3
  45. package/dist/sidecar-lock.d.ts.map +1 -1
  46. package/dist/sidecar-lock.js +9 -3
  47. package/dist/symlink-parents.js +2 -2
  48. package/docs/errors.md +2 -0
  49. package/docs/python-helper.md +3 -3
  50. package/docs/root.md +19 -9
  51. package/docs/secret-file.md +3 -2
  52. package/docs/security-model.md +4 -0
  53. package/docs/timing.md +1 -1
  54. package/docs/types.md +21 -9
  55. package/docs/writing.md +19 -1
  56. package/package.json +1 -1
package/dist/json.js CHANGED
@@ -1,10 +1,49 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import fsSync from "node:fs";
3
3
  import path from "node:path";
4
+ import { FsSafeError } from "./errors.js";
4
5
  import { stringifyJsonDocument } from "./json-stringify.js";
5
- import { readRegularFile, readRegularFileSync } from "./regular-file.js";
6
+ import { readRegularFile, readRegularFileSync, statRegularFile } from "./regular-file.js";
6
7
  import { openRootFileSync } from "./root-file.js";
7
8
  import { writeTextAtomic } from "./text-atomic.js";
9
+ const READ_RETRY_MAX_ATTEMPTS = 5;
10
+ const READ_RETRY_BASE_DELAY_MS = 50;
11
+ function isRetryableReadError(err, options) {
12
+ if (err instanceof FsSafeError && err.code === "path-mismatch") {
13
+ return true;
14
+ }
15
+ if (options.retryOpenRaceErrors !== true) {
16
+ return false;
17
+ }
18
+ const code = getErrorCode(err);
19
+ return code === "ENOENT" || code === "EPERM";
20
+ }
21
+ function sleep(ms) {
22
+ return new Promise((resolve) => setTimeout(resolve, ms));
23
+ }
24
+ async function readRegularFileWithRetry(filePath, options = {}) {
25
+ let lastErr;
26
+ for (let attempt = 0; attempt < READ_RETRY_MAX_ATTEMPTS; attempt++) {
27
+ try {
28
+ return (await readRegularFile({ filePath })).buffer;
29
+ }
30
+ catch (err) {
31
+ lastErr = err;
32
+ if (!isRetryableReadError(err, options) || attempt === READ_RETRY_MAX_ATTEMPTS - 1) {
33
+ throw err;
34
+ }
35
+ await sleep(READ_RETRY_BASE_DELAY_MS * Math.pow(2, attempt));
36
+ }
37
+ }
38
+ throw lastErr;
39
+ }
40
+ async function readRegularFileIfExistsWithRetry(filePath) {
41
+ const initial = await statRegularFile(filePath);
42
+ if (initial.missing) {
43
+ return null;
44
+ }
45
+ return await readRegularFileWithRetry(filePath, { retryOpenRaceErrors: true });
46
+ }
8
47
  const JSON_FILE_MODE = 0o600;
9
48
  const JSON_DIR_MODE = 0o700;
10
49
  const SUPPORTS_SYNC_NOFOLLOW = process.platform !== "win32" && "O_NOFOLLOW" in fsSync.constants;
@@ -200,7 +239,11 @@ export function readRootJsonObjectSync(options) {
200
239
  }
201
240
  export async function tryReadJson(filePath) {
202
241
  try {
203
- const raw = (await readRegularFile({ filePath })).buffer.toString("utf8");
242
+ const buffer = await readRegularFileIfExistsWithRetry(filePath);
243
+ if (buffer === null) {
244
+ return null;
245
+ }
246
+ const raw = buffer.toString("utf8");
204
247
  return JSON.parse(raw);
205
248
  }
206
249
  catch {
@@ -210,7 +253,7 @@ export async function tryReadJson(filePath) {
210
253
  export async function readJson(filePath) {
211
254
  let raw;
212
255
  try {
213
- raw = (await readRegularFile({ filePath })).buffer.toString("utf8");
256
+ raw = (await readRegularFileWithRetry(filePath, { retryOpenRaceErrors: true })).toString("utf8");
214
257
  }
215
258
  catch (err) {
216
259
  throw new JsonFileReadError(filePath, "read", err);
@@ -225,7 +268,11 @@ export async function readJson(filePath) {
225
268
  export async function readJsonIfExists(filePath) {
226
269
  let raw;
227
270
  try {
228
- raw = (await readRegularFile({ filePath })).buffer.toString("utf8");
271
+ const buffer = await readRegularFileIfExistsWithRetry(filePath);
272
+ if (buffer === null) {
273
+ return null;
274
+ }
275
+ raw = buffer.toString("utf8");
229
276
  }
230
277
  catch (err) {
231
278
  if (getErrorCode(err) === "ENOENT") {
@@ -0,0 +1,3 @@
1
+ import type { FileHandle } from "node:fs/promises";
2
+ export declare function resolveOpenedFileRealPathForHandle(handle: FileHandle, ioPath: string): Promise<string>;
3
+ //# sourceMappingURL=opened-realpath.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opened-realpath.d.ts","sourceRoot":"","sources":["../src/opened-realpath.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAMnD,wBAAsB,kCAAkC,CACtD,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAoCjB"}
@@ -0,0 +1,79 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { FsSafeError } from "./errors.js";
4
+ import { sameFileIdentity } from "./file-identity.js";
5
+ import { isNotFoundPathError } from "./path.js";
6
+ export async function resolveOpenedFileRealPathForHandle(handle, ioPath) {
7
+ const handleStat = await handle.stat();
8
+ const fdCandidates = process.platform === "linux"
9
+ ? [`/proc/self/fd/${handle.fd}`, `/dev/fd/${handle.fd}`]
10
+ : process.platform === "win32"
11
+ ? []
12
+ : [`/dev/fd/${handle.fd}`];
13
+ for (const fdPath of fdCandidates) {
14
+ try {
15
+ const fdRealPath = await fs.realpath(fdPath);
16
+ const fdRealStat = await fs.stat(fdRealPath);
17
+ if (sameFileIdentity(handleStat, fdRealStat)) {
18
+ return fdRealPath;
19
+ }
20
+ }
21
+ catch {
22
+ // try next fd path
23
+ }
24
+ }
25
+ try {
26
+ const ioRealPath = await fs.realpath(ioPath);
27
+ const ioRealStat = await fs.stat(ioRealPath);
28
+ if (sameFileIdentity(handleStat, ioRealStat)) {
29
+ return ioRealPath;
30
+ }
31
+ }
32
+ catch (err) {
33
+ if (!isNotFoundPathError(err)) {
34
+ throw err;
35
+ }
36
+ }
37
+ const parentResolved = await resolveOpenedFileRealPathFromParent(handleStat, ioPath);
38
+ if (parentResolved) {
39
+ return parentResolved;
40
+ }
41
+ throw new FsSafeError("path-mismatch", "unable to resolve opened file path");
42
+ }
43
+ async function resolveOpenedFileRealPathFromParent(handleStat, ioPath) {
44
+ let parentReal;
45
+ try {
46
+ parentReal = await fs.realpath(path.dirname(ioPath));
47
+ }
48
+ catch (err) {
49
+ if (isNotFoundPathError(err)) {
50
+ return null;
51
+ }
52
+ throw err;
53
+ }
54
+ let entries;
55
+ try {
56
+ entries = await fs.readdir(parentReal);
57
+ }
58
+ catch (err) {
59
+ if (isNotFoundPathError(err)) {
60
+ return null;
61
+ }
62
+ throw err;
63
+ }
64
+ for (const entry of entries.toSorted()) {
65
+ const candidatePath = path.join(parentReal, entry);
66
+ try {
67
+ const candidateStat = await fs.lstat(candidatePath);
68
+ if (candidateStat.isFile() && sameFileIdentity(handleStat, candidateStat)) {
69
+ return await fs.realpath(candidatePath);
70
+ }
71
+ }
72
+ catch (err) {
73
+ if (!isNotFoundPathError(err)) {
74
+ throw err;
75
+ }
76
+ }
77
+ }
78
+ return null;
79
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,wBAAwB,CAAC,CAAC,GAAG,IAAI,IAAI;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,uBAAuB,CAAC,CAAC,GAAG,IAAI,IAAI;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,CAAC,CAAC;CACX,CAAC;AA6CF,wBAAsB,2BAA2B,CAAC,CAAC,GAAG,IAAI,EACxD,OAAO,EAAE,wBAAwB,CAAC,CAAC,CAAC,GACnC,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CA8BrC"}
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,wBAAwB,CAAC,CAAC,GAAG,IAAI,IAAI;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,uBAAuB,CAAC,CAAC,GAAG,IAAI,IAAI;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,CAAC,CAAC;CACX,CAAC;AA6CF,wBAAsB,2BAA2B,CAAC,CAAC,GAAG,IAAI,EACxD,OAAO,EAAE,wBAAwB,CAAC,CAAC,CAAC,GACnC,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CA+BrC"}
package/dist/output.js CHANGED
@@ -42,6 +42,7 @@ export async function writeExternalFileWithinRoot(options) {
42
42
  if (requestedTargetPath.length === 0) {
43
43
  throw new FsSafeError("invalid-path", "target path is required");
44
44
  }
45
+ assertFileTargetPath(requestedTargetPath);
45
46
  const targetPath = toRootPathInput({
46
47
  rootDir: targetRoot.rootDir,
47
48
  rootReal: targetRoot.rootReal,
@@ -67,7 +67,7 @@ export async function runPinnedWriteHelper(params) {
67
67
  relativeParentPath: params.relativeParentPath,
68
68
  });
69
69
  if (getFsSafePythonConfig().mode === "off") {
70
- return await runPinnedWriteFallbackOrThrow(params);
70
+ return await runPinnedWriteFallback(params);
71
71
  }
72
72
  if (params.input.kind === "stream") {
73
73
  try {
@@ -75,7 +75,7 @@ export async function runPinnedWriteHelper(params) {
75
75
  }
76
76
  catch (error) {
77
77
  if (canFallbackFromPythonError(error)) {
78
- return await runPinnedWriteFallbackOrThrow(params, error);
78
+ return await runPinnedWriteFallback(params);
79
79
  }
80
80
  throw error;
81
81
  }
@@ -99,7 +99,7 @@ export async function runPinnedWriteHelper(params) {
99
99
  }
100
100
  catch (error) {
101
101
  if (canFallbackFromPythonError(error)) {
102
- return await runPinnedWriteFallbackOrThrow(params, error);
102
+ return await runPinnedWriteFallback(params);
103
103
  }
104
104
  throw error;
105
105
  }
@@ -126,12 +126,6 @@ export async function runPinnedCopyHelper(params) {
126
126
  },
127
127
  });
128
128
  }
129
- async function runPinnedWriteFallbackOrThrow(params, cause) {
130
- if (process.platform !== "win32") {
131
- throw new FsSafeError("helper-unavailable", "Python helper is required for pinned writes on this platform", { cause });
132
- }
133
- return await runPinnedWriteFallback(params);
134
- }
135
129
  async function runPinnedWriteFallback(params) {
136
130
  const parentPath = params.relativeParentPath
137
131
  ? path.join(params.rootPath, ...params.relativeParentPath.split("/"))
@@ -0,0 +1,18 @@
1
+ import type { Stats } from "node:fs";
2
+ import type { FileHandle } from "node:fs/promises";
3
+ export type ReadResult = {
4
+ buffer: Buffer;
5
+ realPath: string;
6
+ stat: Stats;
7
+ };
8
+ type OpenedFile = {
9
+ handle: FileHandle;
10
+ realPath: string;
11
+ stat: Stats;
12
+ };
13
+ export declare function readOpenedFileSafely(params: {
14
+ opened: OpenedFile;
15
+ maxBytes?: number;
16
+ }): Promise<ReadResult>;
17
+ export {};
18
+ //# sourceMappingURL=read-opened-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-opened-file.d.ts","sourceRoot":"","sources":["../src/read-opened-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,UAAU,CAAC,CAmBtB"}
@@ -0,0 +1,15 @@
1
+ import { FsSafeError } from "./errors.js";
2
+ export async function readOpenedFileSafely(params) {
3
+ if (params.maxBytes !== undefined && params.opened.stat.size > params.maxBytes) {
4
+ throw new FsSafeError("too-large", `file exceeds limit of ${params.maxBytes} bytes (got ${params.opened.stat.size})`);
5
+ }
6
+ const buffer = await params.opened.handle.readFile();
7
+ if (params.maxBytes !== undefined && buffer.byteLength > params.maxBytes) {
8
+ throw new FsSafeError("too-large", `file exceeds limit of ${params.maxBytes} bytes (got ${buffer.byteLength})`);
9
+ }
10
+ return {
11
+ buffer,
12
+ realPath: params.opened.realPath,
13
+ stat: params.opened.stat,
14
+ };
15
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"regular-file.d.ts","sourceRoot":"","sources":["../src/regular-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,MAAM,MAAM,SAAS,CAAC;AAQ7B,MAAM,MAAM,qBAAqB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAExF,KAAK,8BAA8B,GAAG,IAAI,CACxC,OAAO,MAAM,CAAC,SAAS,EACvB,UAAU,GAAG,SAAS,GAAG,UAAU,CACpC,GACC,OAAO,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;AAEvD,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAEF,wBAAgB,6BAA6B,CAC3C,SAAS,GAAE,8BAAiD,GAC3D,MAAM,CAQR;AA2DD,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CActF;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,qBAAqB,CAc3E;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAgC3C;AA6CD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IACpF,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,KAAK,CAAC;CACb,CAoBA;AAmBD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDxF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI,CA2D7E"}
1
+ {"version":3,"file":"regular-file.d.ts","sourceRoot":"","sources":["../src/regular-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,MAAM,MAAM,SAAS,CAAC;AAS7B,MAAM,MAAM,qBAAqB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAExF,KAAK,8BAA8B,GAAG,IAAI,CACxC,OAAO,MAAM,CAAC,SAAS,EACvB,UAAU,GAAG,SAAS,GAAG,UAAU,CACpC,GACC,OAAO,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;AAEvD,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAEF,wBAAgB,6BAA6B,CAC3C,SAAS,GAAE,8BAAiD,GAC3D,MAAM,CAQR;AA2DD,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CActF;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,qBAAqB,CAc3E;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAiD3C;AA6CD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IACpF,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,KAAK,CAAC;CACb,CAoBA;AAmBD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDxF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI,CA2D7E"}
@@ -1,6 +1,7 @@
1
1
  import fsSync from "node:fs";
2
2
  import fs from "node:fs/promises";
3
3
  import path from "node:path";
4
+ import { FsSafeError } from "./errors.js";
4
5
  import { sameFileIdentity } from "./file-identity.js";
5
6
  import { isNotFoundPathError } from "./path.js";
6
7
  import { assertNoSymlinkParents, assertNoSymlinkParentsSync } from "./symlink-parents.js";
@@ -95,12 +96,31 @@ export async function readRegularFile(params) {
95
96
  if (params.maxBytes !== undefined && result.stat.size > params.maxBytes) {
96
97
  throw new Error(`File exceeds ${params.maxBytes} bytes: ${params.filePath}`);
97
98
  }
98
- const handle = await fs.open(params.filePath, resolveRegularFileReadFlags());
99
+ let handle;
100
+ try {
101
+ handle = await fs.open(params.filePath, resolveRegularFileReadFlags());
102
+ }
103
+ catch (err) {
104
+ if (isNotFoundPathError(err)) {
105
+ throw new FsSafeError("path-mismatch", `File changed during read: ${params.filePath}`);
106
+ }
107
+ throw err;
108
+ }
99
109
  try {
100
110
  const stat = await handle.stat();
111
+ let pathStat;
112
+ try {
113
+ pathStat = await fs.lstat(params.filePath);
114
+ }
115
+ catch (err) {
116
+ if (isNotFoundPathError(err)) {
117
+ throw new FsSafeError("path-mismatch", `File changed during read: ${params.filePath}`);
118
+ }
119
+ throw err;
120
+ }
101
121
  verifyStableReadTarget({
102
122
  filePath: params.filePath,
103
- pathStat: await fs.lstat(params.filePath),
123
+ pathStat,
104
124
  postOpenStat: stat,
105
125
  preOpenStat: result.stat,
106
126
  });
@@ -126,7 +146,7 @@ function verifyStableReadTarget(params) {
126
146
  }
127
147
  if (!sameFileIdentity(params.preOpenStat, params.postOpenStat) ||
128
148
  !sameFileIdentity(params.pathStat, params.postOpenStat)) {
129
- throw new Error(`File changed during read: ${params.filePath}`);
149
+ throw new FsSafeError("path-mismatch", `File changed during read: ${params.filePath}`);
130
150
  }
131
151
  }
132
152
  function readOpenedRegularFileSync(params) {
@@ -1,17 +1,17 @@
1
1
  import type { Stats } from "node:fs";
2
2
  import type { FileHandle } from "node:fs/promises";
3
+ import { type DenyMutationPolicy } from "./deny-mutations.js";
4
+ import { type ReadResult } from "./read-opened-file.js";
3
5
  import type { DirEntry, PathStat } from "./types.js";
6
+ export type { DenyMutationPolicy } from "./deny-mutations.js";
7
+ export { resolveOpenedFileRealPathForHandle } from "./opened-realpath.js";
8
+ export type { ReadResult } from "./read-opened-file.js";
4
9
  export type OpenResult = {
5
10
  handle: FileHandle;
6
11
  realPath: string;
7
12
  stat: Stats;
8
13
  [Symbol.asyncDispose](): Promise<void>;
9
14
  };
10
- export type ReadResult = {
11
- buffer: Buffer;
12
- realPath: string;
13
- stat: Stats;
14
- };
15
15
  export type RootOptions = {
16
16
  rootDir: string;
17
17
  defaults?: RootDefaults;
@@ -24,19 +24,20 @@ export type RootDefaults = {
24
24
  maxBytes?: number;
25
25
  mkdir?: boolean;
26
26
  mode?: number;
27
+ denyMutations?: DenyMutationPolicy;
27
28
  nonBlockingRead?: boolean;
28
29
  symlinks?: SymlinkPolicy;
29
30
  };
30
31
  export type RootReadOptions = Pick<RootDefaults, "hardlinks" | "maxBytes" | "nonBlockingRead" | "symlinks">;
31
32
  export type RootOpenOptions = Omit<RootReadOptions, "maxBytes">;
32
- export type RootWriteOptions = Pick<RootDefaults, "mkdir" | "mode"> & {
33
+ export type RootWriteOptions = Pick<RootDefaults, "denyMutations" | "mkdir" | "mode"> & {
33
34
  encoding?: BufferEncoding;
34
35
  overwrite?: boolean;
35
36
  };
36
- export type RootOpenWritableOptions = Pick<RootDefaults, "mkdir" | "mode"> & {
37
+ export type RootOpenWritableOptions = Pick<RootDefaults, "denyMutations" | "mkdir" | "mode"> & {
37
38
  writeMode?: WritableOpenMode;
38
39
  };
39
- export type RootCopyOptions = Pick<RootDefaults, "maxBytes" | "mkdir" | "mode"> & {
40
+ export type RootCopyOptions = Pick<RootDefaults, "denyMutations" | "maxBytes" | "mkdir" | "mode"> & {
40
41
  sourceHardlinks?: HardlinkPolicy;
41
42
  };
42
43
  export type RootWriteJsonOptions = RootWriteOptions & {
@@ -49,6 +50,11 @@ export type RootCreateJsonOptions = Omit<RootWriteJsonOptions, "overwrite">;
49
50
  export type RootAppendOptions = RootWriteOptions & {
50
51
  prependNewlineIfNeeded?: boolean;
51
52
  };
53
+ export type RootMoveOptions = Pick<RootDefaults, "denyMutations"> & {
54
+ overwrite?: boolean;
55
+ };
56
+ export type RootRemoveOptions = Pick<RootDefaults, "denyMutations">;
57
+ export type RootMkdirOptions = Pick<RootDefaults, "denyMutations">;
52
58
  export declare const DEFAULT_ROOT_MAX_BYTES: number;
53
59
  export interface Root {
54
60
  readonly rootDir: string;
@@ -69,9 +75,9 @@ export interface Root {
69
75
  reader(options?: RootReadOptions): (filePath: string) => Promise<Buffer>;
70
76
  openWritable(relativePath: string, options?: RootOpenWritableOptions): Promise<WritableOpenResult>;
71
77
  append(relativePath: string, data: string | Buffer, options?: RootAppendOptions): Promise<void>;
72
- remove(relativePath: string): Promise<void>;
73
- mkdir(relativePath: string): Promise<void>;
74
- ensureRoot(): Promise<void>;
78
+ remove(relativePath: string, options?: RootRemoveOptions): Promise<void>;
79
+ mkdir(relativePath: string, options?: RootMkdirOptions): Promise<void>;
80
+ ensureRoot(options?: RootMkdirOptions): Promise<void>;
75
81
  write(relativePath: string, data: string | Buffer, options?: RootWriteOptions): Promise<void>;
76
82
  create(relativePath: string, data: string | Buffer, options?: RootCreateOptions): Promise<void>;
77
83
  writeJson(relativePath: string, data: unknown, options?: RootWriteJsonOptions): Promise<void>;
@@ -85,9 +91,7 @@ export interface Root {
85
91
  list(relativePath: string, options: {
86
92
  withFileTypes: true;
87
93
  }): Promise<DirEntry[]>;
88
- move(fromRelative: string, toRelative: string, options?: {
89
- overwrite?: boolean;
90
- }): Promise<void>;
94
+ move(fromRelative: string, toRelative: string, options?: RootMoveOptions): Promise<void>;
91
95
  }
92
96
  export declare function root(rootDir: string, defaults?: RootDefaults): Promise<Root>;
93
97
  export declare function readLocalFileSafely(params: {
@@ -104,5 +108,4 @@ export type WritableOpenResult = {
104
108
  stat: Stats;
105
109
  [Symbol.asyncDispose](): Promise<void>;
106
110
  };
107
- export declare function resolveOpenedFileRealPathForHandle(handle: FileHandle, ioPath: string): Promise<string>;
108
111
  //# sourceMappingURL=root-impl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"root-impl.d.ts","sourceRoot":"","sources":["../src/root-impl.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"root-impl.d.ts","sourceRoot":"","sources":["../src/root-impl.ts"],"names":[],"mappings":"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"}