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

Function readFile

packages/dofs/src/fs/readFile.ts:26–118  ·  view source on GitHub ↗
(
  db: Database,
  path: string,
  optionsOrEncoding?: "utf8" | ReadFileOptions,
)

Source from the content-addressed store, hash-verified

24 options: ReadFileOptions,
25): Promise<string | ReadableStream<Uint8Array>>;
26export async function readFile(
27 db: Database,
28 path: string,
29 optionsOrEncoding?: "utf8" | ReadFileOptions,
30): Promise<string | ReadableStream<Uint8Array>> {
31 const wantString =
32 optionsOrEncoding === "utf8" ||
33 (typeof optionsOrEncoding === "object" && optionsOrEncoding?.encoding === "utf8");
34
35 // Pending-create files surface through the path-keyed buffer.
36 const { path: canonical } = canonicalizePath(path);
37 const pending = getPendingWriteBufferByPath(db, canonical);
38 if (pending !== undefined) {
39 const snapshot = new Uint8Array(pending.size);
40 snapshot.set(pending.buf.subarray(0, pending.size));
41 if (wantString) return new TextDecoder().decode(snapshot);
42 return new ReadableStream<Uint8Array>({
43 start(controller) {
44 controller.enqueue(snapshot);
45 controller.close();
46 },
47 });
48 }
49
50 // Resolve up front so we surface ENOENT/EISDIR before doing any
51 // streaming work.
52 const node = resolveInode(db, path);
53 if (node === null) {
54 throw createWorkspaceError("ENOENT", `no such file: ${path}`, path);
55 }
56 if (node.type !== "file") {
57 throw createWorkspaceError("EISDIR", `path is a directory: ${path}`, path);
58 }
59
60 // While a write buffer is open for this inode it is the source of
61 // truth. Skip the chunk store and serve the buffered bytes.
62 const buffered = getWriteBuffer(db, node.inode);
63 if (buffered?.dirty) {
64 const snapshot = new Uint8Array(buffered.size);
65 snapshot.set(buffered.buf.subarray(0, buffered.size));
66 if (wantString) return new TextDecoder().decode(snapshot);
67 return new ReadableStream<Uint8Array>({
68 start(controller) {
69 controller.enqueue(snapshot);
70 controller.close();
71 },
72 });
73 }
74
75 const chunks = db.all<ChunkRow>(
76 "SELECT hash, size FROM vfs_chunks WHERE inode = ? ORDER BY idx",
77 node.inode,
78 );
79
80 if (wantString) {
81 // Fast path — concatenate everything and decode once. Matches the
82 // node:fs/promises.readFile semantics for an encoding argument:
83 // memory cost = whole file.

Callers 8

scanFileFunction · 0.70
readFileMethod · 0.70
readFile.test.tsFile · 0.70
readBytesFunction · 0.70
rm.test.tsFile · 0.70
apply.test.tsFile · 0.50
push.test.tsFile · 0.50
set-versions.mjsFile · 0.50

Calls 8

canonicalizePathFunction · 0.85
resolveInodeFunction · 0.85
getWriteBufferFunction · 0.85
getBlobBytesFunction · 0.85
allMethod · 0.80
setMethod · 0.65
createWorkspaceErrorFunction · 0.50

Tested by 1

readBytesFunction · 0.56