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

Function createWriteAPI

packages/computer/src/mounts/index.ts:183–271  ·  view source on GitHub ↗
(opts: WriteAPIOptions)

Source from the content-addressed store, hash-verified

181}
182
183function createWriteAPI(opts: WriteAPIOptions): MountWriteAPI {
184 const { fs, root, mount } = opts;
185 const maxBytes = mount.maxBytes;
186 const maxEntries = mount.maxEntries;
187 let bytesWritten = 0;
188 let entriesWritten = 0;
189
190 function checkPath(absPath: string): void {
191 if (!absPath.startsWith(`${root}/`) && absPath !== root) {
192 throw new Error(`mount ${root}: writeFile/mkdir target ${absPath} is outside the mount root`);
193 }
194 }
195
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(

Callers 1

runIndexFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected