···11+MIT License
22+33+Copyright (c) 2022 0no.co
44+55+Permission is hereby granted, free of charge, to any person obtaining a copy
66+of this software and associated documentation files (the "Software"), to deal
77+in the Software without restriction, including without limitation the rights
88+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99+copies of the Software, and to permit persons to whom the Software is
1010+furnished to do so, subject to the following conditions:
1111+1212+The above copyright notice and this permission notice shall be included in all
1313+copies or substantial portions of the Software.
1414+1515+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1616+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1717+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1818+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121+SOFTWARE.
+59
README.md
···11+# rollup-plugin-cjs-check
22+33+A Rollup plugin for checking CommonJS exports against `cjs-module-lexer`.
44+55+## Why?
66+77+As Node.js defines it, CommonJS modules consist of a `module.exports` object which can be of any type.
88+When importing a `CommonJS`, while Node.js is in ESM mode, a CommonJS module will always be reliably
99+importable via a default import.
1010+1111+For modern modules, it's common to use Rollup to bundle and build both CommonJS and ECMAScript Modules (ESM)
1212+outputs for any given module. This means that to achieve compatibility between both modules either requires
1313+the module to only have a default-export, or to rely on Node.js' compatibility mode.
1414+1515+For better compatibility, Node.js attempts to detect the CommonJS exports of every CommonJS module that's
1616+exported. Since sometimes, especially in legacy CommonJS mode, the import of a given CommonJS module built with
1717+Rollup cannot be prevented entirely, the module has to be compatible with `cjs-module-lexer`.
1818+1919+The [`cjs-module-lexer` library](https://github.com/nodejs/cjs-module-lexer) is what Node.js uses to detect
2020+exports of a given CommonJS module and hence, when choosing how to configure Rollup, the Rollup bundle outputs
2121+have to be compatible with it, or otherwise, the module's exports won't be detected.
2222+2323+**This plugin checks that `cjs-module-lexer` agrees with the ECMAScript modules exports that Rollup detects.**
2424+2525+For more information, check out [the Node.js documentation on CommonJS namespaces.](https://nodejs.org/api/esm.html#commonjs-namespaces)
2626+2727+## Requirements
2828+2929+This plugin requires an [LTS](https://github.com/nodejs/Release) Node version (v14.0.0+) and Rollup v1.20.0+.
3030+3131+## Install
3232+3333+```console
3434+npm install --save-dev rollup-plugin-cjs-check
3535+# or
3636+yarn add -D rollup-plugin-cjs-check
3737+# or
3838+pnpm add --save-dev rollup-plugin-cjs-check
3939+```
4040+4141+## Usage
4242+4343+Import the `rollup-plugin-cjs-check` plugin in your [Rollup configuration file](https://www.rollupjs.org/guide/en/#configuration-files),
4444+and add it to your plugins:
4545+4646+```js
4747+import cjsCheck from 'rollup-plugin-cjs-check';
4848+4949+export default {
5050+ input: 'src/index.js',
5151+ output: {
5252+ dir: 'output',
5353+ format: 'cjs'
5454+ },
5555+ plugins: [
5656+ cjsCheck(),
5757+ ]
5858+};
5959+```
···11+import { Plugin } from 'rollup';
22+import { FilterPattern } from '@rollup/pluginutils';
33+44+export interface CJSCheckOptions {
55+ /**
66+ * A picomatch pattern, or array of patterns, which specifies the files in
77+ * the build the plugin should operate on. By default, all files with
88+ * extension `".cjs"` or those in `extensions` are included, but you can
99+ * narrow this list by only including specific files. These files will be
1010+ * analyzed and transpiled if either the analysis does not find ES module
1111+ * specific statements or `transformMixedEsModules` is `true`.
1212+ * @default undefined
1313+ */
1414+ include?: FilterPattern;
1515+ /**
1616+ * A picomatch pattern, or array of patterns, which specifies the files in
1717+ * the build the plugin should _ignore_. By default, all files with
1818+ * extensions other than those in `extensions` or `".cjs"` are ignored, but you
1919+ * can exclude additional files. See also the `include` option.
2020+ * @default undefined
2121+ */
2222+ exclude?: FilterPattern;
2323+}
2424+2525+/** A Rollup plugin for checking CommonJS exports against `cjs-module-lexer`. */
2626+export default function cjsCheck(options?: CJSCheckOptions): Plugin;
+61
src/index.mjs
···11+import { parse, init } from 'cjs-module-lexer';
22+import { createFilter } from '@rollup/pluginutils';
33+44+function cjsCheck(opts = {}) {
55+ const filter = createFilter(opts.include, opts.exclude, {
66+ resolve: false
77+ });
88+99+ return {
1010+ name: "cjs-check",
1111+1212+ async renderChunk(code, chunk) {
1313+ if (opts.extension !== '.js') {
1414+ return null;
1515+ } else if (!filter(chunk.fileName)) {
1616+ return null;
1717+ }
1818+1919+ await init()
2020+ const output = parse(code);
2121+ const missingReexports = [];
2222+ const missingExports = [];
2323+2424+ let hasMissing = false;
2525+ for (const mod of chunk.exports) {
2626+ if (mod[0] == '*' && !output.reexports.includes(mod.slice(1))) {
2727+ hasMissing = true;
2828+ missingReexports.push(mod.slice(1));
2929+ } else if (mod[0] != '*' && !output.exports.includes(mod)) {
3030+ hasMissing = true;
3131+ missingExports.push(mod);
3232+ }
3333+ }
3434+3535+ if (hasMissing) {
3636+ let message = '';
3737+ if (missingReexports.length) {
3838+ message += 'The following re-exports are undetected:\n';
3939+ message += missingReexports.map(x => `- ${x}\n`).join('');
4040+ }
4141+4242+ if (missingExports.length) {
4343+ message += 'The following exports are undetected:\n';
4444+ message += missingExports.map(x => `- ${x}\n`).join('');
4545+ }
4646+4747+ if (missingExports.length + missingReexports.length >= chunk.exports.length) {
4848+ message = 'All chunk exports have not been detected. Is the chunk a CommonJS module?'
4949+ }
5050+5151+ throw new Error(
5252+ `cjs-module-lexer did not agree with Rollup\'s exports for ${chunk.fileName}.\n${message}`
5353+ );
5454+ }
5555+5656+ return null;
5757+ }
5858+ };
5959+}
6060+6161+export default cjsCheck;