MCPcopy Create free account
hub / github.com/cloudflare/computer / writeFile

Function writeFile

packages/computer/src/mounts/index.ts:198–260  ·  view source on GitHub ↗
(
      absPath: string,
      source: ReadableStream<Uint8Array>,
      mode?: number,
    )

Source from the content-addressed store, hash-verified

196 return {
197 root,
198 async writeFile(
199 absPath: string,
200 source: ReadableStream<Uint8Array>,
201 mode?: number,
202 ): Promise<void> {
203 checkPath(absPath);
204 if (maxEntries !== undefined && entriesWritten + 1 > maxEntries) {
205 throw new Error(`mount ${root}: maxEntries=${maxEntries} exceeded`);
206 }
207 entriesWritten += 1;
208
209 // Ensure the parent directory chain exists. mkdir on an
210 // existing path is EEXIST, which is fine here because the
211 // recursive flag swallows that for the already-a-directory
212 // case.
213 const lastSlash = absPath.lastIndexOf("/");
214 if (lastSlash > 0) {
215 await fs.mkdir(absPath.slice(0, lastSlash), { recursive: true });
216 }
217
218 // When a byte cap is set, tee the source stream so we can
219 // count bytes without buffering. The tee keeps the streaming
220 // contract: bytes still flow chunk-by-chunk into writeFile.
221 let toWrite: ReadableStream<Uint8Array> = source;
222 if (maxBytes !== undefined) {
223 const [counted, forwarded] = source.tee();
224 toWrite = forwarded;
225 // Drain the counted side concurrently; if the cap is
226 // exceeded mid-stream, cancel the forwarded side to short
227 // circuit the write.
228 const cancelForwarded = (reason: unknown): void => {
229 forwarded.cancel(reason).catch(() => {});
230 };
231 const counter = (async () => {
232 const reader = counted.getReader();
233 try {
234 while (true) {
235 const { value, done } = await reader.read();
236 if (done) break;
237 if (value === undefined) continue;
238 bytesWritten += value.byteLength;
239 if (bytesWritten > maxBytes) {
240 const err = new Error(
241 `mount ${root}: maxBytes=${maxBytes} exceeded (saw ${bytesWritten})`,
242 );
243 cancelForwarded(err);
244 throw err;
245 }
246 }
247 } finally {
248 reader.releaseLock();
249 }
250 })();
251 // Await both sides. If the counter rejects, surface that;
252 // otherwise let writeFile propagate.
253 const writePromise = fs.writeFile(absPath, toWrite, { mode });
254 const [counterResult, writeResult] = await Promise.allSettled([counter, writePromise]);
255 if (counterResult.status === "rejected") throw counterResult.reason;

Callers

nothing calls this directly

Calls 7

checkPathFunction · 0.85
cancelForwardedFunction · 0.85
mkdirMethod · 0.65
teeMethod · 0.65
getReaderMethod · 0.65
readMethod · 0.65
writeFileMethod · 0.65

Tested by

no test coverage detected