# Libraries

> Which npm packages don't work with bun compile and what to use instead, the flags that frameworks need, and how to publish a package that keeps its types

<Warning>Ahead-of-time compilation is experimental.</Warning>

Nearly every npm package works with [`bun compile`](/compiler/aot) as it is. This page has the exceptions.

## Packages that don't work

These [replace part of a built-in object](/compiler/compatibility#built-in-objects-are-read-only), and stop with `TypeError: Cannot assign to ...`.

| Package                                                                                               | Use instead                                                               |
| ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| `core-js` 2                                                                                           | `core-js` 3                                                               |
| `es5-shim`, `es6-shim`, `harmony-reflect`                                                             | Nothing. Bun has what they add                                            |
| `array.prototype.map/auto`, `set.prototype.union/auto`, `string.prototype.matchall/auto` and the like | What the package exports, as in `map(list, f)`                            |
| `zone.js`                                                                                             | Zoneless change detection in Angular                                      |
| `chai.should()`                                                                                       | `expect` or `assert`                                                      |
| `should`, `must`                                                                                      | `should/as-function`, `must/must`                                         |
| `timezone-mock`                                                                                       | Set `process.env.TZ`                                                      |
| `sugar`                                                                                               | `Sugar.Array.sum(list)`, not `Sugar.extend()`                             |
| `ses`                                                                                                 | Freeze the prototypes with `Object.freeze()`                              |
| `asciidoctor` 2 and 3                                                                                 | `asciidoctor` 4                                                           |
| `private`                                                                                             | `recast` 0.20.4 or Babel 7, which dropped it                              |
| `@js-temporal/polyfill`                                                                               | Leave out the `Date.prototype.toTemporalInstant = ...` line of its README |
| `tar` 6, `minizlib` 2                                                                                 | `tar` 7                                                                   |
| `collections`, `prototype`                                                                            | No replacement                                                            |

Adding to a built-in object is allowed. `core-js` 3, `reflect-metadata`, `regenerator-runtime`, `colors`, `mockdate` and `sinon` with its fake timers all work. So does `next`, which logs a line that begins with `Failed to install` when it starts.

These [hook the module loader](/compiler/compatibility#loader-hooks-and-the-module-cache). The hook never runs for a compiled file. `--no-aot` doesn't change that.

| Package                                                   | Use instead                                        |
| --------------------------------------------------------- | -------------------------------------------------- |
| `module-alias`, `tsconfig-paths`                          | `paths` in `tsconfig.json`                         |
| `pirates`, `@babel/register`, `sucrase/register`          | Nothing. The build compiles TypeScript and JSX     |
| `require-in-the-middle`, `@opentelemetry/instrumentation` | No replacement. Nothing they patch is instrumented |
| `clear-module`                                            | No replacement. A module runs once                 |

A package that reads files beside its own code needs them [embedded](/compiler/compatibility#files-beside-your-code).

## Frameworks

Next.js and Angular put the paths of your pages together while the server runs, so the build doesn't find them. Pass the pages as entry points, and what the server reads from disk with [`--asset`](/compiler/executables#embed-directories). The other frameworks only need the assets.

```bash terminal icon="terminal"
# Next.js with output: "standalone", in .next/standalone
bun compile ./server.js ".next/server/**/*.js" --asset .next --asset public
# Nuxt
bun compile ./.output/server/index.mjs --asset .output/public
# Astro
bun compile ./dist/server/entry.mjs --asset dist/client
# SvelteKit
bun compile ./build/index.js --asset build/client --asset build/prerendered
```

For Angular, the pages are the `.mjs` files beside `server.mjs`. If you use `next/image`, add `--asset node_modules/@img`, the folder that holds `sharp`.

## Publish a package with its types

Most packages ship JavaScript and `.d.ts` files, so the types inside their functions are gone. `bun compile --library` also writes your TypeScript, and a `package.json` whose `exports` point `bun compile` at it.

```ts src/index.ts icon="/icons/typescript.svg"
export function greet(name: string): string {
  return "hello " + name;
}
```

```json package.json icon="file-json"
{ "name": "greeter", "version": "1.0.0" }
```

```bash terminal icon="terminal"
bun compile --library
```

```txt
  index.js      87 bytes   (entry point)
  index.d.ts    53 bytes   (declaration)
  index.aot.ts  103 bytes  (aot source)
  package.json  430 bytes  (asset)
```

```json title="dist/package.json" icon="file-json"
{
  "exports": {
    ".": {
      "aot": "./index.aot.ts",
      "types": "./index.d.ts",
      "default": "./index.js"
    }
  }
}
```

`bun compile` loads `index.aot.ts`, and so do `bun run`, `bun test` and `bun check` with `--aot`. Everything else loads `index.js`.

To keep your own `package.json`, run [`bun build --dts`](/bundler#dts) and add the `"aot"` condition yourself. Put it first, because the first condition that matches wins.

The build of a program doesn't report type errors in your package, so run `bun check` before you publish, and try the package in an app. There, `bun check --aot --all ./main.ts` lists them too.

```bash terminal icon="terminal"
cd dist && bun pm pack            # greeter-1.0.0.tgz
cd ../../app && bun add ../greeter/dist/greeter-1.0.0.tgz
bun compile ./main.ts --explain   # shows where types are missing
```
