# Node API mapping

Deno supports a broad set of `node:` APIs, so migration does not require rewriting every call. Start with compatibility APIs, then adopt Web or Deno APIs where they reduce dependencies or improve portability.

| Node.js | Deno / Web API | Guidance |
| --- | --- | --- |
| `fs.promises.readFile(path, "utf8")` | `Deno.readTextFile(path)` | both need file permission |
| `fs.promises.writeFile` | `Deno.writeTextFile` | scope access to a directory |
| `http.createServer` | `Deno.serve` | prefer Web Request/Response for new servers |
| `process.env.NAME` | `Deno.env.get("NAME")` | grant only named variables |
| `process.argv.slice(2)` | `Deno.args` | direct CLI equivalent |
| `child_process.spawn` | `new Deno.Command()` | needs `--allow-run=<cmd>` |
| `__dirname` | `new URL(".", import.meta.url)` | keep URL semantics, convert only if needed |
| `crypto.randomUUID()` | `crypto.randomUUID()` | reuse the Web API |
| `Buffer` | `Uint8Array` / `TextEncoder` | prefer Web types at protocol boundaries |

## File-reading example

```ts
// Compatibility first: keep the Node API
import { readFile } from "node:fs/promises";
const a = await readFile("config.json", "utf8");

// Deno-first: use the shorter text API
const b = await Deno.readTextFile("config.json");
```

Both should run with the same least privilege:

```bash
deno run --allow-read=config.json main.ts
```

Migration tests should cover paths, encoding, stream backpressure, signals, timeouts, and error shapes. Similar names do not guarantee identical boundary behavior.

Official references: [Node APIs](https://docs.deno.com/api/node/), [Deno APIs](https://docs.deno.com/api/deno/), and [Web APIs](https://docs.deno.com/api/web/).
