---
title: 3.0 migration
sidebar_label: '3.0'
---

## Shifted supported platform versions

Since Node.js v14 has reached [end of life](https://nodejs.org/en/about/releases/), Packemon now
requires at minimum v16.12 and above to run. Furthermore, we're entirely dropping v12 support, and
shifting v14 into `legacy`, v16 into `stable`, v18 into `current`, and the new v19 into
`experimental`. As part of this process, we are also bumping minimum requirements and coupled npm
versions.

The updated [`support`](../config.md#support) compatibility table is as follows.

#### Before

|        | Legacy     | Stable     | Current    | Experimental |
| ------ | ---------- | ---------- | ---------- | ------------ |
| node   | >= 12.22.0 | >= 14.15.0 | >= 16.12.0 | >= 18.0.0    |
| npm    | >= 6.14.0  | >= 6.14.0  | >= 8.1.0   | >= 8.5.0     |
| native | iOS 12     | iOS 13     | iOS 14     | iOS 15       |

#### After

|        | Legacy     | Stable     | Current    | Experimental |
| ------ | ---------- | ---------- | ---------- | ------------ |
| node   | >= 14.15.0 | >= 16.12.0 | >= 18.12.0 | >= 19.0.0    |
| npm    | >= 6.14.0  | >= 8.1.0   | >= 8.19.0  | >= 9.0.0     |
| native | iOS 13     | iOS 14     | iOS 15     | iOS 16       |

Notable changes:

- [Optional chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining),
  [nullish coalescing](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator)
  are no longer transformed for _all_ targets.
- [Logical assignment operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment)
  are no longer transformed for `stable` and up targets.
- [Dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import)
  is no longer transformed to `require()` for all `node` targets.
- Node built-in imports will now use the `node:` prefix.

### Dropped ES5 support

Furthermore, we have dropped `es5` support from the `legacy` target, and replaced it with `es2018`.
The `stable` target has also been updated to `es2019`.

## No longer workspaces aware by default

Packemon was originally designed to work in both polyrepo's and monorepo's. When the `packemon`
command was ran in a workspace root, it would apply to _all_ packages in the workspace. This was
pretty cool and worked great. However, it overcomplicated our implementation and required many poly
vs mono checks everywhere. It was becoming a nightmare to maintain and ensure correct boundaries.

To remedy this, we refactored every piece of Packemon from the ground up to break these 2 patterns
apart. The `packemon build`, `packemon pack`, and other commands (below) will only apply to 1
package now, the one found in the current working directory.

For workspaces, we've added new `packemon build-workspace` and `packemon pack-workspace` commands,
which mimic the previous functionality, and should be ran in the workspace root.

## Commands must now be ran from the package root

Because of the above change, all the primary commands -- `build`, `clean`, `files`, `init`, `pack`,
`validate`, `watch` -- must now be ran from the package root, as our tooling assumes the package is
located in the current working directory. They can no longer be ran from the workspace root if using
a monorepo.

This does not apply to the `scaffold` command (and the new `build-workspace` and `pack-workspace`
commands), as they should always be ran from the repository root.

## TypeScript declarations now require explicitly named configs

When the `--declaration` option is passed, Packemon will generate TypeScript declarations for all
inputs. This process would assume that a `tsconfig.json` existed in the package root. This file
could then be overridden with the `--declarationConfig` option.

However, in TypeScript v4.7, the
[new `.cts` and `.mts` file extensions were released](https://devblogs.microsoft.com/typescript/announcing-typescript-4-7/#new-file-extensions).
With this release, the declaration outputs have also changed, and may produce _different outputs_
depending on the source file type (cjs vs esm). Because of this, we can no longer generate
declarations _for all formats using a single tsconfig_, especially when building multiple formats in
parallel!

To solve this problem, Packemon now requires a `tsconfig.<format>.json` file. For example, if you're
building the formats `lib` and `esm`, you'll now need `tsconfig.lib.json` and `tsconfig.esm.json`
files. This _cannot_ be changed, as as such, the `--declarationConfig` option has been removed.

## TypeScript declaration output directory has changed

As a side-effect of the change above, the output directory of declarations have also changed.
Instead of generating to a `dts` folder, they will now generate to the format folders, `lib`, `esm`,
etc.

If using project references, you'll need to manually update `outDir` as we cannot pass the
`--outDir` option for composite builds.

```json
{
  "extends": "../../tsconfig.options.json",
  "compilerOptions": {
    "outDir": "lib"
  },
  "include": ["src/**/*"]
}
```

## Package `exports` have changed

To support the TypeScript differences mentioned above, the `package.json` `exports` had to also
change. Instead of having a `types` export at the top-level, it will now be nested within `import`
or `require`, depending on the format and combinations. This also means that `import` and `require`
may have different type declarations if need be.

```json
// Before
".": {
  "types": "./dts/index.d.ts",
  "node": "./lib/index.js",
  "default": "./lib/index.js"
}

// After
".": {
  "node": {
    "types": "./lib/index.d.ts",
    "default": "./lib/index.js"
  },
  "default": "./lib/index.js"
}
```

## Publishable files are now lenient

When the `--addFiles` option is passed, we update the `files` field in the package's `package.json`
with a whitelist of files that should be published. Previously, this would use a glob with a strict
match on file extension, for example `src/**/*.{ts,tsx,json}` or `cjs/**/*.{cjs,mjs,map}`.

With the amount of file extensions now available in the JavaScript ecosystem, this has become very
tedious to determine accurately, and as such, these globs have dropped the file extension
requirement. For example, these are simply now `src/**/*` and `cjs/**/*`.

> Do note, we _do not_ remove the previous globs, so you'll need to manually fix each
> `package.json`!

## Removed sourcemaps from Node.js

Packemon would always create sourcemaps, as it provides a mechanism for consumers to debug issues
with their code, specifically when it was bundled with Webpack or Metro. However, this wasn't really
necessary for Node.js packages, as they are typically developer tooling or scripts related, and _are
not_ bundled. Consumers can inspect `node_modules` directly to debug these packages.

Because of this, we have removed sourcemaps entirely from Node.js based packages. This will grealy
reduce the overall package size.

## Other minor changes

- The `pack` and `pack-workspace` commands will automatically set `NODE_ENV=production` now.
- The `type` field in `package.json` will no longer be set.
- The `lib` format is _no longer_ automatically enabled when using the `esm` format.
- Removed most of the React/Ink integration for rendering to the terminal, as it was major
  bottleneck for performance.
- Removed `babelrcRoots` support from our internal Babel configuration.
- Removed the `engines` version constraint feature.
- Removed the `npm` engine when adding engines with `--addEngines`.
- Removed the `--files` option from `packemon validate`.
