# node-cjs-interop

> A library to fix the default import interoperability issue in Node.js

Latest version **0.1.7** (published 2024-08-03) · MIT license · 0 weekly downloads

## Install

```sh
npm install node-cjs-interop
pnpm add node-cjs-interop
yarn add node-cjs-interop
bun add node-cjs-interop
```

## Health

**Score 45/100 (D)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities; high maintenance score; high quality score.

Warnings: low downloads; pre 1.0.

Negative: abandoned.

## Facts

| | |
|---|---|
| Version | 0.1.7 |
| Published | 2024-08-03 |
| First published | 2021-12-26 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 13.5 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 25 |
| Author | Masaki Hara |
| Maintainers | qnighy |
| Keywords | runtime, commonjs, node, esm, mjs, cjs, default import |

## Links

- npm: https://www.npmjs.com/package/node-cjs-interop
- Repository: https://github.com/qnighy/node-cjs-interop
- Homepage: https://github.com/qnighy/node-cjs-interop#readme
- Issues: https://github.com/qnighy/node-cjs-interop/issues
- npm.io page: https://npm.io/package/node-cjs-interop

## Alternatives

- [@expo/fingerprint](https://npm.io/package/@expo/fingerprint.md) — 6.2M weekly downloads
- [@azure/monitor-opentelemetry-exporter](https://npm.io/package/@azure/monitor-opentelemetry-exporter.md) — 850.0K weekly downloads
- [@azure/monitor-opentelemetry](https://npm.io/package/@azure/monitor-opentelemetry.md) — 624.0K weekly downloads
- [@posthog/ai](https://npm.io/package/@posthog/ai.md) — 423.3K weekly downloads
- [fakefilter](https://npm.io/package/fakefilter.md) — 63.9K weekly downloads

## Recent versions

- 0.1.7 (latest) — 2024-08-03
- 0.1.6 — 2024-02-01
- 0.1.5 — 2023-11-23
- 0.1.4 — 2023-11-23
- 0.1.3 — 2023-11-19
- 0.1.2 — 2023-11-19
- 0.1.1 — 2022-07-27
- 0.1.0 — 2021-12-26

## README

# `node-cjs-interop`: Import helpers for Babel ESM from Node.js native ESM

## The problem to solve

Consider the following modules:

```javascript
// a.js

export default function greet() {
  console.log("Hello, world!");
}
```

```javascript
// b.js

import greet from "a.js";

greet();
```

They usually work, unless the following conditions are met:

- `a.js` (the module being imported) is a **simulated ESM**. That is, the module is transpiled as a CommonJS module (by Babel or TypeScript) before execution. And,
- `b.js` (the importing module) is a **native ESM**, That is, the module is run on Node.js' native ES Module support.

You can reproduce the above condition by placing the following files:

```javascript
// a.cjs

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true,
});
exports.default = greet;

function greet() {
  console.log("Hello, world!");
}
```

```javascript
// b.mjs

import greet from "./a.cjs";

greet();
```

```
$ node ./b.mjs
./b.mjs:3
greet();
^

TypeError: greet is not a function
    at ./b.mjs:3:1
    at ModuleJob.run (node:internal/modules/esm/module_job:185:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:281:24)
    at async loadESM (node:internal/process/esm_loader:88:5)
    at async handleMainPromise (node:internal/modules/run_main:65:12)
```

The following packages solve the problem:

- [`babel-plugin-node-cjs-interop`](https://npmjs.com/package/babel-plugin-node-cjs-interop) / [`swc-plugin-node-cjs-interop`](https://npmjs.com/package/swc-plugin-node-cjs-interop): automatically inserts the compatibility wrapper.
- `node-cjs-interop` (this package): allows manually wrapping the exported value.

## Getting started

Install the package:

```
npm install node-cjs-interop
# or:
yarn add node-cjs-interop
```

Wrap a default import:

```javascript
import { interopImportCJSDefault } from "node-cjs-interop";
import styledOrig from "styled-components";

const styled = interopImportCJSDefault(styledOrig);

const CustomDiv = styled.div`
  ...
`;
```

Wrap a namespace import:

```javascript
import { interopImportCJSNamespace } from "node-cjs-interop";
import * as nsOrig from "your-package";
const ns = interopImportCJSNamespace(nsOrig);
```

## Difference between `interopImportCJSNamespace` and `interopCJSDefault`

`interopImportCJSNamespace` allows more accurate simulation of ESM semantics:

```javascript
import { interopImportCJSNamespace } from "node-cjs-interop";
// import styled from "styled-components";
import * as nsOrig from "styled-components";

const ns = interopImportCJSNamespace(nsOrig);

// const CustomDiv = styled.div`...`;
const CustomDiv = ns.default.div`...`;
```

However, using [`babel-plugin-node-cjs-interop`](https://npmjs.com/package/babel-plugin-node-cjs-interop) is recommend over manual wrapping.

## The "twisted" variant

You can also use the "twisted" variant of the functions:

```javascript
import { interopImportCJSNamespaceT } from "node-cjs-interop";
import * as TextareaAutosizeOrig from "react-textarea-autosize";

const {
  default: { default: TextareaAutosize },
} = interopImportCJSNamespaceT(TextareaAutosizeOrig);
```

This is useful when you have `"module"` or `"moduleResolution"` set to `"nodenext"` or `"node16"`
in your `tsconfig.json` and you need to import `default` from a "dual package" in which the
type definitions are recognized in the `.cts` mode.

There is no such thing as `interopImportCJSDefaultT` because in this mode, the imported `default` value
would be the namespace object, and if it was originally the proper default export
(i.e. in case it was imported like ESM), there is no way to reconstruct the whole namespace object from it.

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