# unenv
`unenv` is a framework-agnostic system that allows converting JavaScript code to be platform agnostic and work in any environment including Browsers, Workers, Node.js, or JavaScript runtime.
## Install
```bash
# Using npm
npm i -D unenv
# Using yarn
yarn add --dev unenv
# Using pnpm
pnpm add -D unenv
```
## Usage
Using `env` utility and built-in presets, `unenv` will provide an abstract configuration that can be used in building pipelines ([rollup.js](https://rollupjs.org), [webpack](https://webpack.js.org), etc.).
```js
import { env } from "unenv";
const { alias, inject, polyfill, external } = env({}, {}, {});
```
**Note:** You can provide as many presets as you want. unenv will merge them internally and the right-most preset has a higher priority.
## Presets
### `node`
[(view source)](./src/presets/node.ts)
Suitable to convert universal libraries working in Node.js.
- Add supports for global [`fetch` API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
- Set Node.js built-ins as externals
```js
import { env, nodeless } from "unenv";
const envConfig = env(node, {});
```
### `nodeless`
[(view source)](./src/presets/nodeless.ts)
Suitable to transform libraries made for Node.js to run in other JavaScript runtimes.
```js
import { env, nodeless } from "unenv";
const envConfig = env(nodeless, {});
```
### `deno`
[(view source)](./src/presets/deno.ts)
This preset can be used to extend `nodeless` to use Deno's Node.js API Compatibility ([docs](https://docs.deno.com/runtime/manual/node/compatibility), [docs](https://docs.deno.com/deploy/api/runtime-node)).
> [!WARNING]
> This preset is **experimental** and behavior might change!
```js
import { env, nodeless, deno } from "unenv";
const envConfig = env(nodeless, deno, {});
```
### `cloudflare`
[(view source)](./src/presets/cloudflare.ts)
This preset can be used to extend `nodeless` to use [Cloudflare Worker](https://workers.cloudflare.com/) Node.js API Compatibility ([docs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/)).
> [!WARNING]
> This preset is **experimental** and behavior might change!
> [!NOTE]
> Make sure to enable [`nodejs_compat`](https://developers.cloudflare.com/workers/configuration/compatibility-dates/#nodejs-compatibility-flag) compatibility flag.
```js
import { env, nodeless, cloudflare } from "unenv";
const envConfig = env(nodeless, cloudflare, {});
```
### `vercel`
This preset can be used to extend `nodeless` to use [Vercel Edge](https://vercel.com/docs/functions/edge-functions/edge-runtime) Node.js API Compatibility ([docs](https://vercel.com/docs/functions/edge-functions/edge-runtime#compatible-node.js-modules)).
> [!WARNING]
> This preset is **experimental** and behavior might change!
```js
import { env, nodeless, vercel } from "unenv";
const envConfig = env(nodeless, vercel, {});
```
## Built-in Node.js modules
`unenv` provides a replacement for all Node.js built-ins for cross-platform compatibility.
| Module | Status | Source |
| --------------------------------------------------------------------------- | ---------- | ------------------------------------------------------------------ |
| [node:assert](https://nodejs.org/api/assert.html) | Mocked | - |
| [node:async_hooks](https://nodejs.org/api/async_hooks.html) | Polyfilled | [unenv/node/async_hooks](./src/runtime/node/async_hooks) |
| [node:buffer](https://nodejs.org/api/buffer.html) | Polyfilled | [unenv/node/buffer](./src/runtime/node/buffer) |
| [node:child_process](https://nodejs.org/api/child_process.html) | Mocked | - |
| [node:cluster](https://nodejs.org/api/cluster.html) | Mocked | - |
| [node:console](https://nodejs.org/api/console.html) | Mocked | - |
| [node:constants](https://nodejs.org/api/constants.html) | Mocked | - |
| [node:crypto](https://nodejs.org/api/crypto.html) | Polyfilled | [unenv/node/crypto](./src/runtime/node/crypto) |
| [node:dgram](https://nodejs.org/api/dgram.html) | Mocked | - |
| [node:diagnostics_channel](https://nodejs.org/api/diagnostics_channel.html) | Mocked | - |
| [node:dns](https://nodejs.org/api/dns.html) | Mocked | - |
| [node:domain](https://nodejs.org/api/domain.html) | Mocked | - |
| [node:events](https://nodejs.org/api/events.html) | Polyfilled | [unenv/node/events](./src/runtime/node/events) |
| [node:fs](https://nodejs.org/api/fs.html) | Polyfilled | [unenv/node/fs](./src/runtime/node/fs) |
| [node:fs/promises](https://nodejs.org/api/fs/promises.html) | Polyfilled | [unenv/node/fs/promises](./src/runtime/node/fs/promises) |
| [node:http2](https://nodejs.org/api/http2.html) | Mocked | - |
| [node:http](https://nodejs.org/api/http.html) | Polyfilled | [unenv/node/http](./src/runtime/node/http) |
| [node:https](https://nodejs.org/api/https.html) | Polyfilled | [unenv/node/https](./src/runtime/node/https) |
| [node:inspector](https://nodejs.org/api/inspector.html) | Mocked | - |
| [node:module](https://nodejs.org/api/module.html) | Polyfilled | [unenv/node/module](./src/runtime/node/module) - |
| [node:net](https://nodejs.org/api/net.html) | Polyfilled | [unenv/node/net](./src/runtime/node/net) |
| [node:os](https://nodejs.org/api/os.html) | Mocked | - |
| [node:path](https://nodejs.org/api/path.html) | Polyfilled | [unenv/node/path](./src/runtime/node/path) |
| [node:perf_hooks](https://nodejs.org/api/perf_hooks.html) | Mocked | - |
| [node:process](https://nodejs.org/api/process.html) | Polyfilled | [unenv/node/process](./src/runtime/node/process) |
| [node:punycode](https://nodejs.org/api/punycode.html) | Mocked | - |
| [node:querystring](https://nodejs.org/api/querystring.html) | Mocked | - |
| [node:readline](https://nodejs.org/api/readline.html) | Mocked | - |
| [node:repl](https://nodejs.org/api/repl.html) | Mocked | - |
| [node:stream](https://nodejs.org/api/stream.html) | Polyfilled | [unenv/node/stream](./src/runtime/node/stream) |
| [node:stream/consumers](https://nodejs.org/api/stream.html) | Mocked | [unenv/node/stream/consumers](./src/runtime/node/stream/consumers) |
| [node:stream/promises](https://nodejs.org/api/stream.html) | Mocked | [unenv/node/stream/promises](./src/runtime/node/stream/promises) |
| [node:stream/web](https://nodejs.org/api/stream.html) | Native | [unenv/node/stream/web](./src/runtime/node/stream/web) |
| [node:string_decoder](https://nodejs.org/api/string_decoder.html) | Polyfilled | [unenv/node/string_decoder](./src/runtime/node/string_decoder) |
| [node:sys](https://nodejs.org/api/sys.html) | Mocked | - |
| [node:timers](https://nodejs.org/api/timers.html) | Mocked | - |
| [node:timers/promises](https://nodejs.org/api/timers.html) | Mocked | - |
| [node:tls](https://nodejs.org/api/tls.html) | Mocked | - |
| [node:trace_events](https://nodejs.org/api/trace_events.html) | Mocked | - |
| [node:tty](https://nodejs.org/api/tty.html) | Mocked | - |
| [node:url](https://nodejs.org/api/url.html) | Polyfilled | [unenv/node/url](./src/runtime/node/url) |
| [node:util](https://nodejs.org/api/util.html) | Polyfilled | [unenv/node/util](./src/runtime/node/util) |
| [node:util/types](https://nodejs.org/api/util.html) | Polyfilled | [unenv/node/util/types](./src/runtime/node/util/types) |
| [node:v8](https://nodejs.org/api/v8.html) | Mocked | - |
| [node:vm](https://nodejs.org/api/vm.html) | Mocked | - |
| [node:wasi](https://nodejs.org/api/wasi.html) | Mocked | - |
| [node:worker_threads](https://nodejs.org/api/worker_threads.html) | Mocked | - |
| [node:zlib](https://nodejs.org/api/zlib.html) | Mocked | - |
## npm packages
`unenv` provides a replacement for common npm packages for cross platform compatibility.
| Package | Status | Source |
| ----------------------------------------------------------- | --------------------------- | ----------------------------------------------------------------- |
| [npm/consola](https://www.npmjs.com/package/consola) | Use native `console` | [unenv/runtime/npm/consola](./src/runtime/npm/consola.ts) |
| [npm/cross-fetch](https://www.npmjs.com/package/node-fetch) | Use native `fetch` | [unenv/runtime/npm/cross-fetch](./src/runtime/npm/cross-fetch.ts) |
| [npm/debug](https://www.npmjs.com/package/debug) | Mocked with `console.debug` | [unenv/runtime/npm/debug](./src/runtime/npm/debug.ts) |
| [npm/fsevents](https://www.npmjs.com/package/fsevents) | Mocked | [unenv/runtime/npm/fsevents](./src/runtime/npm/fsevents.ts) |
| [npm/inherits](https://www.npmjs.com/package/inherits) | Inlined | [unenv/runtime/npm/inherits](./src/runtime/npm/inherits.ts) |
| [npm/mime-db](https://www.npmjs.com/package/mime-db) | Minimized | [unenv/runtime/npm/mime-db](./src/runtime/npm/mime-db.ts) |
| [npm/mime](https://www.npmjs.com/package/mime) | Minimized | [unenv/runtime/npm/mime](./src/runtime/npm/mime.ts) |
| [npm/node-fetch](https://www.npmjs.com/package/node-fetch) | Use native `fetch` | [unenv/runtime/npm/node-fetch](./src/runtime/npm/node-fetch.ts) |
| [npm/whatwg-url](https://www.npmjs.com/package/whatwg-url) | Use native `URL` | [unenv/runtime/npm/whatwg-url](./src/runtime/npm/whatwg-url.ts) |
## Auto-mocking proxy
```js
import MockProxy from "unenv/runtime/mock/proxy";
console.log(MockProxy().foo.bar()[0]);
```
The above package doesn't work outside of Node.js and neither we need any platform-specific logic! When aliasing `os` to `mock/proxy-cjs`, it will be auto-mocked using a [Proxy Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) which can be recursively traversed like an `Object`, called like a `Function`, Iterated like an `Array`, or instantiated like a `Class`.
We use this proxy for auto-mocking unimplemented internals. Imagine a package does this:
```js
const os = require("os");
if (os.platform() === "windows") {
/* do some fix */
}
module.exports = () => "Hello world";
```
By aliasing `os` to `unenv/runtime/mock/proxy-cjs`, the code will be compatible with other platforms.
## Other polyfills
To discover other polyfills, please check [./src/runtime](./src/runtime).
## License
MIT