# unenv preset

The `@aziontech/unenv-preset` package is the [Azion Lib](/en/documentation/devtools/azion-lib/) preset for unenv: one configuration object that lists the Node.js globals, modules, and polyfills a build for [Azion Runtime](/en/documentation/devtools/runtime/) replaces. Azion Bundler, which the Azion CLI runs to build a project, applies the preset. The package has no functions to call: a [function](/en/documentation/platform/functions/) reaches the polyfills by importing `node:*` modules, such as `node:fs` and `node:crypto`.

Install the package:

```bash
npm install @aziontech/unenv-preset
```

The preset sample on this page is a JavaScript ES module that runs in Node.js. The function samples run inside a function served locally with [azion dev](/en/documentation/devtools/cli/dev-command/). For what `node:fs` returns in a deployed function, refer to [node:fs](/en/documentation/devtools/runtime/node/fs/).

---

## Preset object

The default export of `@aziontech/unenv-preset` is the preset object, `{ inject, alias, external, polyfill }`. The package has no named exports, so `import { preset } from '@aziontech/unenv-preset'` returns `undefined`. Import the object as the default:

```javascript
import preset from '@aziontech/unenv-preset';

// The package has a default export only: { inject, alias, external, polyfill }
console.log('keys:', Object.keys(preset));
console.log('inject:', Object.keys(preset.inject));
console.log('alias:', Object.keys(preset.alias));
console.log('external:', preset.external);
console.log('polyfill:', preset.polyfill);
```

Output:

```text
keys: [ 'inject', 'alias', 'external', 'polyfill' ]
inject: [
  '__dirname',
  '__filename',
  'import.meta.url',
  'process',
  'performance',
  'setInterval',
  'clearInterval',
  'console',
  'asyncStorage',
  'dateToString'
]
alias: [
  '@aziontech/utils',
  '@aziontech/utils/edge',
  '@aziontech/utils/node',
  'fetch-to-node',
  'accepts',
  'assert',
  'buffer',
  'https',
  'module',
  'string_decoder',
  'timers',
  'util',
  'zlib'
]
external: [
  'node:async_hooks',
  'node:fs/promises',
  'node:stream',
  'node:crypto'
]
polyfill: [
  'aziondev:async_hooks:/async-hooks/async-hooks.polyfills.js',
  'aziondev:fs:/fs/fs.polyfills.js',
  'aziondev:fs/promises:/fs/promises/promises.polyfills.js',
  'aziondev:stream:/stream/stream.polyfills.js',
  'aziondev:crypto:/crypto/crypto.polyfills.js',
  'azionprd:fs:/fs.js'
]
```

The object has four properties:

| Property   | Type       | Description                                                                                                                                                                                                                                                             |
| ---------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `inject`   | `object`   | The globals the build injects, each key mapped to a string. For the list, refer to [Global polyfills](#global-polyfills).                                                                                                                                               |
| `alias`    | `object`   | The module names the build maps to a replacement, each key mapped to a string: `@aziontech/utils`, `@aziontech/utils/edge`, `@aziontech/utils/node`, `fetch-to-node`, `accepts`, `assert`, `buffer`, `https`, `module`, `string_decoder`, `timers`, `util`, and `zlib`. |
| `external` | `string[]` | Four module names: `node:async_hooks`, `node:fs/promises`, `node:stream`, and `node:crypto`.                                                                                                                                                                            |
| `polyfill` | `string[]` | The polyfill entries. Entries that start with `aziondev:` serve development builds and cover `async_hooks`, `fs`, `fs/promises`, `stream`, and `crypto`. The one `azionprd:` entry serves production builds and covers `fs`.                                            |

The build applies this object for you, so a project does not pass it to unenv by hand. The unenv preset is not the `preset` field of `build` in [azion.config.js](/en/documentation/devtools/cli/azion-config-js/#build), which names the framework or language preset of a project.

---

## Global polyfills

The `inject` property of the unenv preset lists the Node.js globals that the build adds to a function. A function uses these globals as it would in Node.js, with nothing to import.

| Global        | Description                                                                   |
| ------------- | ----------------------------------------------------------------------------- |
| `__dirname`   | The name of the current directory.                                            |
| `__filename`  | The name of the current file.                                                 |
| `process`     | Process information and the environment, including the environment variables. |
| `performance` | Performance timing.                                                           |

The preset also injects `import.meta.url`, `setInterval`, `clearInterval`, `console`, `asyncStorage`, and `dateToString`.

---

## Node.js modules in a function

A function reaches the polyfills of the unenv preset through the Node.js module names. Import `node:fs` or `node:crypto` in the function code, and the build swaps in the polyfill when `build.polyfills` is `true` in [azion.config.js](/en/documentation/devtools/cli/azion-config-js/#build). The JavaScript template that `azion init` creates sets `polyfills` to `true`.

Import the Node.js module, never a file of the package. The polyfill files of `@aziontech/unenv-preset` cannot be imported in Node.js or in a function, and the package has no `crypto` polyfill file. The messages each attempt returns are in [Errors](#errors).

The `node:fs` calls read the files that `build.memoryFS` embeds in the build. A file is read by its path relative to `removePathPrefix`. The `node:fs` samples on this page use a project whose `azion.config.js` sets `build.memoryFS` to `{ injectionDirs: ['./data'], removePathPrefix: './data' }`. Its `data/` folder holds `hello.txt`, `index.html`, `about/index.html`, and `docs/readme.txt`, so `data/hello.txt` is read as `/hello.txt`.

Under `azion dev`, `node:fs` reads the embedded files from the `.edge/storage/` folder of the project. The local `node:fs` has no `writeFileSync`, `mkdirSync`, or `readSync`.

---

## createHash and randomUUID

The `createHash` and `randomUUID` functions come from `node:crypto`. `createHash` returns a hash object for an algorithm, such as `sha256`, and `randomUUID` returns a random UUID. For the full module, refer to [node:crypto](/en/documentation/devtools/runtime/node/crypto/).

This function hashes a string and generates a UUID:

```javascript
import { createHash, randomUUID } from 'node:crypto';

export default {
  async fetch() {
    // Create a hash
    const hash = createHash('sha256');
    hash.update('some data');
    const digest = hash.digest('hex');

    // Generate a UUID
    const uuid = randomUUID();

    return new Response(`sha256=${digest}\nuuid=${uuid}\n`);
  },
};
```

Served locally with `azion dev`, the function returns:

```text
$ curl http://localhost:3333/x
HTTP/1.1 200 OK
content-type: text/plain;charset=UTF-8

sha256=1307990e6ba5ca145eb35e99182a9bec46531bc54ddf656a602c780fa0240dee
uuid=e2ebf3ce-e7e9-4393-855c-ccdd93ea26f3
```

---

## readFileSync

The `readFileSync` function of `node:fs` reads the whole content of a file that `build.memoryFS` embeds in the build.

| Parameter | Type     | Required | Description                                        |
| --------- | -------- | -------- | -------------------------------------------------- |
| `path`    | `string` | Yes      | The path of the file.                              |
| `options` | —        | No       | Options for the read, such as the encoding `utf8`. |

Returns the content of the file as a `string` or a `Buffer`. With the encoding `utf8`, the content is a `string`.

This function returns the content of `/hello.txt`, the file `data/hello.txt` of the project:

```javascript
import { readFileSync } from 'node:fs';

export default {
  async fetch() {
    // Read a file embedded with build.memoryFS (data/hello.txt is served as /hello.txt)
    const content = readFileSync('/hello.txt', 'utf8');
    return new Response(content);
  },
};
```

Served locally with `azion dev`, the function returns:

```text
$ curl http://localhost:3333/x
HTTP/1.1 200 OK
content-type: text/plain;charset=UTF-8

Hello from memoryFS
```

---

## readdirSync

The `readdirSync` function of `node:fs` lists the content of a directory that `build.memoryFS` embeds in the build.

| Parameter | Type     | Required | Description                |
| --------- | -------- | -------- | -------------------------- |
| `path`    | `string` | Yes      | The path of the directory. |
| `options` | —        | No       | Options for the listing.   |

Returns a `string[]` with the names of the files and directories in the directory.

This function lists the root directory and the `/docs` directory:

```javascript
import { readdirSync } from 'node:fs';

export default {
  async fetch() {
    // List directory contents
    const files = readdirSync('/');
    const docs = readdirSync('/docs');
    return Response.json({ files, docs });
  },
};
```

Served locally with `azion dev`, the function returns:

```text
$ curl http://localhost:3333/x
HTTP/1.1 200 OK
content-type: application/json

{"files":["about","docs","hello.txt","index.html"],"docs":["readme.txt"]}
```

---

## statSync and existsSync

The `existsSync` function of `node:fs` checks whether a path exists in the files that `build.memoryFS` embeds.

| Parameter | Type     | Required | Description        |
| --------- | -------- | -------- | ------------------ |
| `path`    | `string` | Yes      | The path to check. |

Returns `true` when the path exists and `false` when it does not.

The `statSync` function of `node:fs` returns the stats of a file or a directory.

| Parameter | Type     | Required | Description                        |
| --------- | -------- | -------- | ---------------------------------- |
| `path`    | `string` | Yes      | The path of the file or directory. |
| `options` | —        | No       | Options for the call.              |

Returns an `fs.Stats` object, with `size`, `isFile()`, and `isDirectory()`.

This function checks `/hello.txt`, reads its stats, and checks a path the build did not embed:

```javascript
import { statSync, existsSync } from 'node:fs';

export default {
  async fetch() {
    const lines = [];
    // Check if file exists
    if (existsSync('/hello.txt')) {
      // Get file stats
      const stats = statSync('/hello.txt');
      lines.push(`File size: ${stats.size}`);
      lines.push(`Is directory: ${stats.isDirectory()}`);
      lines.push(`Is file: ${stats.isFile()}`);
    }
    lines.push(`existsSync('/missing.txt'): ${existsSync('/missing.txt')}`);
    return new Response(lines.join('\n') + '\n');
  },
};
```

Served locally with `azion dev`, the function returns:

```text
$ curl http://localhost:3333/x
HTTP/1.1 200 OK
content-type: text/plain;charset=UTF-8

File size: 20
Is directory: false
Is file: true
existsSync('/missing.txt'): false
```

---

## openSync and closeSync

The `openSync` function of `node:fs` opens a file.

| Parameter | Type     | Required | Description                            |
| --------- | -------- | -------- | -------------------------------------- |
| `path`    | `string` | Yes      | The path of the file.                  |
| `flags`   | `string` | Yes      | The open mode, such as `'r'` or `'w'`. |
| `mode`    | —        | No       | The file mode.                         |

Returns the file descriptor, a `number`.

The `closeSync` function of `node:fs` closes a file descriptor.

| Parameter | Type     | Required | Description                   |
| --------- | -------- | -------- | ----------------------------- |
| `fd`      | `number` | Yes      | The file descriptor to close. |

This function opens `/hello.txt` and closes its file descriptor:

```javascript
import { openSync, closeSync } from 'node:fs';

export default {
  async fetch() {
    // Open file and get file descriptor
    const fd = openSync('/hello.txt', 'r');
    // Close file descriptor
    closeSync(fd);
    return new Response(`opened and closed fd ${fd}\n`);
  },
};
```

Served locally with `azion dev`, the function returns:

```text
$ curl http://localhost:3333/x
HTTP/1.1 200 OK
content-type: text/plain;charset=UTF-8

opened and closed fd 17
```

Under `azion dev`, the file descriptor is one the operating system assigns.

---

## Errors

These messages appear when code imports a file of `@aziontech/unenv-preset` or calls a `node:fs` function the local runtime does not have.

| Message                                                                                                        | Cause                                                                                                                                                                                                                   | What to do                                                                                              |
| -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `ERR_MODULE_NOT_FOUND` `Cannot find module '…/node_modules/@aziontech/unenv-preset/src/polyfills/node/crypto'` | The code imports `@aziontech/unenv-preset/polyfills/node/crypto`. The package has no `crypto` polyfill file.                                                                                                            | Import from `node:crypto` in a function, as in [createHash and randomUUID](#createhash-and-randomuuid). |
| `TypeError: Cannot read properties of undefined (reading '__FILES__')`                                         | A Node.js script imports `@aziontech/unenv-preset/polyfills/node/fs.js`. The file reads the embedded files of a build, which a Node.js script does not have.                                                            | Import from `node:fs` in a function that the Azion CLI builds.                                          |
| `ReferenceError: SRC_NODE_FS is not defined`                                                                   | A function imports `@aziontech/unenv-preset/polyfills/node/fs.js`, and `azion dev` stops at server start.                                                                                                               | Import from `node:fs`, as in [readFileSync](#readfilesync).                                             |
| `TypeError: (void 0) is not a function`                                                                        | A function calls `writeFileSync`, `mkdirSync`, or `readSync` from `node:fs` under `azion dev`. The build warns that the import `will always be undefined because there is no matching export in "internal-env-dev:fs"`. | Read files with the calls on this page.                                                                 |

---

## Related resources

- [How Azion Lib works](/en/documentation/devtools/azion-lib/how-it-works.md): Where each Azion Lib module runs, in Node.js or in a function, and what differs between the two.
- [Use Node.js APIs through polyfills](/en/documentation/guides/application-development/functions-and-runtime/use-polyfills.md): Create a function project, import a Node.js API, and run it locally and deployed.
- [Node.js APIs](/en/documentation/devtools/runtime/node.md): The Node.js modules Azion Runtime resolves, with the behavior of each one.
- [azion.config.js](/en/documentation/devtools/cli/azion-config-js.md): The `build.polyfills` and `build.memoryFS` settings that decide which polyfills and files a build carries.
