@openclaw/fs-safe 0.4.2 → 0.4.3

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.3 - 2026-07-18
4
+
5
+ ### Compatibility
6
+
7
+ - Restore the pre-0.4.2 `readRegularFile` and `readRegularFileSync` overflow error message while retaining allocation-bounded reads and the structured `too-large` error on the new low-level bounded-read primitives.
8
+
3
9
  ## 0.4.2 - 2026-07-18
4
10
 
5
11
  ### Features
@@ -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;AAW7B,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;AAWD,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,CAuD3C;AA+CD,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,CAwBA;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;AAW7B,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;AAsBD,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,CAyD3C;AAoDD,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,CAqBA;AAmBD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDxF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI,CA2D7E"}
@@ -20,6 +20,15 @@ function resolveRegularFileReadFlags() {
20
20
  ? fsSync.constants.O_NOFOLLOW
21
21
  : 0));
22
22
  }
23
+ function regularFileTooLargeError(filePath, maxBytes, cause) {
24
+ return new FsSafeError("too-large", `File exceeds ${maxBytes} bytes: ${filePath}`, { cause });
25
+ }
26
+ function translateBoundedReadOverflow(error, filePath, maxBytes) {
27
+ if (error instanceof FsSafeError && error.code === "too-large") {
28
+ throw regularFileTooLargeError(filePath, maxBytes, error);
29
+ }
30
+ throw error;
31
+ }
23
32
  export async function statRegularFile(filePath) {
24
33
  let stat;
25
34
  try {
@@ -59,7 +68,7 @@ export async function readRegularFile(params) {
59
68
  throw Object.assign(new Error(`File not found: ${params.filePath}`), { code: "ENOENT" });
60
69
  }
61
70
  if (params.maxBytes !== undefined && result.stat.size > params.maxBytes) {
62
- throw new FsSafeError("too-large", `file exceeds limit of ${params.maxBytes} bytes (got ${result.stat.size})`);
71
+ throw regularFileTooLargeError(params.filePath, params.maxBytes);
63
72
  }
64
73
  let handle;
65
74
  try {
@@ -90,13 +99,23 @@ export async function readRegularFile(params) {
90
99
  preOpenStat: result.stat,
91
100
  });
92
101
  if (params.maxBytes !== undefined && stat.size > params.maxBytes) {
93
- throw new FsSafeError("too-large", `file exceeds limit of ${params.maxBytes} bytes (got ${stat.size})`);
102
+ throw regularFileTooLargeError(params.filePath, params.maxBytes);
94
103
  }
95
104
  // With a byte cap, avoid readFile(): a raced file growth would allocate
96
105
  // the oversized content before the post-read check could reject it.
97
- const buffer = params.maxBytes === undefined
98
- ? await handle.readFile()
99
- : await readFileHandleBounded(handle, params.maxBytes);
106
+ let buffer;
107
+ try {
108
+ buffer =
109
+ params.maxBytes === undefined
110
+ ? await handle.readFile()
111
+ : await readFileHandleBounded(handle, params.maxBytes);
112
+ }
113
+ catch (error) {
114
+ if (params.maxBytes !== undefined) {
115
+ translateBoundedReadOverflow(error, params.filePath, params.maxBytes);
116
+ }
117
+ throw error;
118
+ }
100
119
  return { buffer, stat };
101
120
  }
102
121
  finally {
@@ -121,13 +140,23 @@ function readOpenedRegularFileSync(params) {
121
140
  preOpenStat: params.preOpenStat,
122
141
  });
123
142
  if (params.maxBytes !== undefined && stat.size > params.maxBytes) {
124
- throw new FsSafeError("too-large", `file exceeds limit of ${params.maxBytes} bytes (got ${stat.size})`);
143
+ throw regularFileTooLargeError(params.filePath, params.maxBytes);
125
144
  }
126
145
  // Keep capped sync reads incremental for the same reason as async reads:
127
146
  // readFileSync(fd) would buffer a raced oversized file before throwing.
128
- const buffer = params.maxBytes === undefined
129
- ? fsSync.readFileSync(params.fd)
130
- : readFileDescriptorBoundedSync(params.fd, params.maxBytes);
147
+ let buffer;
148
+ try {
149
+ buffer =
150
+ params.maxBytes === undefined
151
+ ? fsSync.readFileSync(params.fd)
152
+ : readFileDescriptorBoundedSync(params.fd, params.maxBytes);
153
+ }
154
+ catch (error) {
155
+ if (params.maxBytes !== undefined) {
156
+ translateBoundedReadOverflow(error, params.filePath, params.maxBytes);
157
+ }
158
+ throw error;
159
+ }
131
160
  return { buffer, stat };
132
161
  }
133
162
  export function readRegularFileSync(params) {
@@ -137,7 +166,7 @@ export function readRegularFileSync(params) {
137
166
  throw Object.assign(new Error(`File not found: ${params.filePath}`), { code: "ENOENT" });
138
167
  }
139
168
  if (params.maxBytes !== undefined && result.stat.size > params.maxBytes) {
140
- throw new FsSafeError("too-large", `file exceeds limit of ${params.maxBytes} bytes (got ${result.stat.size})`);
169
+ throw regularFileTooLargeError(params.filePath, params.maxBytes);
141
170
  }
142
171
  const fd = fsSync.openSync(params.filePath, resolveRegularFileReadFlags());
143
172
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/fs-safe",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Capability-style filesystem roots for Node.js apps that handle untrusted relative paths.",
5
5
  "license": "MIT",
6
6
  "repository": {