node:fs and node:path
A small part of Node's standard library is built in, implemented in the runtime with Node's semantics. Import it the usual way, in named, default or namespace form.
// node:fs (sync and promises) and node:path. The path includes the pid so concurrent runs of
// the same program (the test harness runs Node and two native builds at once) do not collide.
import { writeFileSync, readFileSync, existsSync, unlinkSync } from "node:fs";
import { readFile } from "node:fs/promises";
import * as path from "node:path";
const file = path.join("/tmp", `chad-docs-${process.pid}`, "..", `notes-${process.pid}.txt`);
console.log(path.basename(file).startsWith("notes-"), path.extname(file), path.dirname(file));
writeFileSync(file, "line one\nline two\n");
const lines = readFileSync(file, "utf8").trimEnd().split("\n");
console.log(lines.length, lines[1]);
async function main(): Promise<void> {
const text = await readFile(file, "utf8");
console.log("async read", text.length, "bytes");
unlinkSync(file);
console.log("exists after unlink:", existsSync(file));
}
main();true .txt /tmp
2 line two
async read 18 bytes
exists after unlink: falseWhat is available
The ambient declarations in stdlib/globals.d.ts are the whole surface; importing anything else fails to typecheck (CS0001).
| Module | Functions |
|---|---|
node:fs | readFileSync(path, "utf8"), writeFileSync, appendFileSync, existsSync, unlinkSync |
node:fs/promises | readFile(path, "utf8"), writeFile, appendFile, unlink |
node:path | join, resolve, normalize, dirname, basename, extname, isAbsolute |
A failing file operation (reading a missing file, say) throws, as in Node, so try/catch is how you handle it; existsSync is the non-throwing check.
process
The global process provides process.argv.slice(2) (the arguments after the program), process.exit(code) and process.pid. Only the exact expression process.argv.slice(2) is accepted (CS1229): Node's argv[0] and argv[1] are the node binary and the script path, which a compiled binary does not have. With that slice, the same arguments mean the same thing to both.
// @args: ada lin
const args = process.argv.slice(2);
if (args.length === 0) {
console.log("usage: greet <name>...");
process.exit(2);
}
for (const name of args) console.log(`hello ${name}`);$ bin/chad build argv.ts -o greet && ./greet ada linhello ada
hello linPlanned: more of fs (directories, stat), node:process as an importable module, and environment variables.
Next: console.log.