# package-json-exports

> A file based package.json exports generator depending on fast-glob

Latest version **0.0.2** (published 2023-01-29) · MIT license · 0 weekly downloads

## Install

```sh
npm install package-json-exports
pnpm add package-json-exports
yarn add package-json-exports
bun add package-json-exports
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities.

Warnings: low downloads; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.0.2 |
| Published | 2023-01-29 |
| First published | 2023-01-29 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 6 |
| Unpacked size | 40.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | VdustR |
| Maintainers | vdustr |
| Keywords | package.json, exports, esm, cjs, d.ts, glob, typescript, fast-glob, modules, import, require, module, commonjs |

## Links

- npm: https://www.npmjs.com/package/package-json-exports
- npm.io page: https://npm.io/package/package-json-exports

## Dependencies (6)

- [fast-glob](https://npm.io/package/fast-glob.md) ^3.2.12
- [@types/node](https://npm.io/package/@types/node.md) ^18.11.18
- [lodash.merge](https://npm.io/package/lodash.merge.md) ^4.6.2
- [lodash.mapvalues](https://npm.io/package/lodash.mapvalues.md) ^4.6.0
- [@types/lodash.merge](https://npm.io/package/@types/lodash.merge.md) ^4.6.7
- [@types/lodash.mapvalues](https://npm.io/package/@types/lodash.mapvalues.md) ^4.6.7

## Alternatives

- [@mapbox/jsonlint-lines-primitives](https://npm.io/package/@mapbox/jsonlint-lines-primitives.md) — 5.3M weekly downloads
- [reftools](https://npm.io/package/reftools.md) — 3.5M weekly downloads
- [@hey-api/openapi-ts](https://npm.io/package/@hey-api/openapi-ts.md) — 3.5M weekly downloads
- [@mapbox/geojson-rewind](https://npm.io/package/@mapbox/geojson-rewind.md) — 2.4M weekly downloads
- [turbo-stream](https://npm.io/package/turbo-stream.md) — 1.7M weekly downloads

## Recent versions

- 0.0.2 (latest) — 2023-01-29
- 0.0.0-experimental.ff30525 (experimental) — 2023-01-29
- 0.0.1 — 2023-01-29
- 0.0.0-experimental.9050eb7 — 2023-01-29
- 0.0.0-experimental.db4781e — 2023-01-29
- 0.0.0-experimental.536771c — 2023-01-29
- 0.0.0-experimental.3c9d950 — 2023-01-29

## README

# package-json-exports

A file based `package.json` [`exports`](https://nodejs.org/api/packages.html#exports) generator depending on [`fast-glob`](https://github.com/mrmlnc/fast-glob).

## Installation

```bash
pnpm i -D package-json-exports
```

## Concepts

As a library maintainer, maintaining `exports` in the `package.json` file can be challenging when there are many files in the package, especially if we choose to provide individual files for certain reasons, instead of bundling them into a single file. Keeping the `exports` up-to-date manually when the files change is error-prone and time-consuming. This library solves this issue by generating `exports` automatically based on the files in the package. It can be integrated into the build process and used with rules to generate `exports` with ease.

## Usage

```ts
import { generateExports } from "package-json-exports";

const packageJson = JSON.parse(await fs.readFile("package.json", "utf-8"));
packageJson.main = "./index.js";
packageJson.module = "./esm/index.js";
packageJson.types = "./index.d.ts";
packageJson.exports = await generateExports(options);

await fs.writeFile("package.json", JSON.stringify(packageJson, null, 2));
```

## Recipes

The `exports` in this library's `package.json` follows [DAISHI KATO's **How Jotai Specifies Package Entry Points**](https://blog.axlight.com/posts/how-jotai-specifies-package-entry-points/), and here is the generating script: [scripts/generatePackageJson.ts](https://github.com/VdustR/package-json-exports/blob/main/scripts/generatePackageJson.ts).

## Options

### `rules`

- Type: `Rule[]`

The rules to generate the `exports`.

Each rule is applied in order, and later rules override previous ones.

Each rule only executes fast-glob once. To improve performance, try to use fewer rules.

### `rules.pattern`

- Type: `string`

The matching pattern for `fast-glob`.

### `rules.exports`

- Type: `(matchedFilePath: string) => condition[]`

You can return an array of conditions. A condition is an array of the property path from `exports`. For example, if you want to generate:

```json
{
  "exports": {
    "foo": {
      "bar": "./src/index.js"
    }
  }
}
```

the condition should be `["foo", "bar"]`.

You can return several conditions:

```ts
{
  exports: (matchedFilePath) => {
    return [
      ["foo", "bar"],
      ["foo", "baz"],
    ];
  },
}
```

The result will be:

```json
{
  "exports": {
    "foo": {
      "bar": "./src/index.js",
      "baz": "./src/index.js"
    }
  }
}
```

You can also return `[]` to ignore the file.

Notice that the `matchedFilePath` is always starts with `./`.

### `rules.fastGlobOptions`

- Type: `FastGlob.Options`

This option is passed to `fast-glob` when matching the files. It's useful when you want to ignore some files.

### `defaultConditionKey`

- Type: `string`
- Default: `undefined`

The default condition key to use when conditions conflict.

For example if there are files:

```
src/index.js
```

And the rules are:

```ts
[
  {
    pattern: "**/*.js",
    exports: (matchedFilePath) => {
      return [[generateExports.pathCondition(matchedFilePath), "require"]];
    },
  },
  {
    pattern: "**/*",
    exports: (matchedFilePath) => {
      return [[generateExports.pathCondition(matchedFilePath)]];
    },
  },
];
```

The result will be:

```json
{
  "exports": {
    "./src/index.js": {
      "require": "./src/index.js",
      "default": "./src/index.js"
    }
  }
}
```

Without setting `defaultConditionKey`, it throws an error when conditions conflict.

### `fastGlobOptions`

- Type: `FastGlob.Options`

You can set the `cwd` and `ignore` options here. `dot` option is set to `true` by default. You can override it by setting it to `false`.

### `simplify`

- Type: `boolean`
- Default: `false`

Simplify the exports. It will replace the object with only one property with the value of the property recursively.

For example, if the exports was:

```json
{
  "exports": {
    "./src/index.js": {
      "browser": {
        "import": "./src/index.js"
      }
    },
    "./src/foo.js": {
      "require": "./src/foo.js",
      "default": "./src/foo.js"
    }
  }
}
```

It will be simplified to:

```json
{
  "exports": {
    "./src/index.js": "./src/index.js",
    "./src/foo.js": {
      "require": "./src/foo.js",
      "default": "./src/foo.js"
    }
  }
}
```

If the exports was:

```json
{
  "exports": {
    "node": {
      "production": {
        "import": "./dist/index.js"
      }
    }
  }
}
```

It will be simplified to:

```json
{
  "exports": "./dist/index.js"
}
```

## Utilities

### `generateExports.normalizePath`

- Type: `(path: string) => string`

This function can be used to normalize the path with leading `./`.

For example:

```ts
generateExports.pathCondition("foo"); // ➡️ "./foo"
generateExports.pathCondition("./foo"); // ➡️ "./foo"
generateExports.pathCondition("./foo.js"); // ➡️ "./foo.js"
```

### `generateExports.removeExtension`

- Type: `(path: string, extname?: string) => string`

This function can be used to remove the extension name.

For example:

```ts
generateExports.pathCondition("foo"); // ➡️ "foo"
generateExports.pathCondition("./foo"); // ➡️ "./foo"
generateExports.pathCondition("./foo.js"); // ➡️ "./foo"
generateExports.pathCondition("./foo/bar.js"); // ➡️ "./foo/bar"
```

### `generateExports.pathCondition`

- Type: `(path: string, extname?: string) => string`

`pathCondition` is a combination of `normalizePath` and `removeExtension`. This function can be used to generate either the path condition. It will remove the extension name and add `./` if the path doesn't start with `./`.

For example:

```ts
generateExports.pathCondition("foo"); // ➡️ "./foo"
generateExports.pathCondition("./foo"); // ➡️ "./foo"
generateExports.pathCondition("./foo.js"); // ➡️ "./foo"
generateExports.pathCondition("./foo.js", ".js"); // ➡️ "./foo"
generateExports.pathCondition("./foo.d.ts"); // ➡️ "./foo.d"
generateExports.pathCondition("./foo.d.ts", ".d.ts"); // ➡️ "./foo"
```

## To Learn More

- [publint](https://publint.dev/) - A tool to lint your `package.json`.
- [package.json exports](https://nodejs.org/api/packages.html#exports)

## License

[ViPro](https://vdustr.dev/) ©️ MIT

---
_Source: https://npm.io/package/package-json-exports · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
