샘플
@rollup/plugin-commonjs 28.0.7: By default @rollup/plugin-commonjs renders external requires as default imports causing named exports to be inaccessible unless esmExternals is configured
검증된 샘플 — npm @rollup/plugin-commonjs 28.0.7: By default @rollup/plugin-commonjs renders external requires as default imports causing named exports to be…
sha256:4c5bf847bf0aa98a1bfd3b9919628d6ee74bd297513afb48edef8f7e4b2feb30
이 네트워크가 제공하는 것은 하나입니다. 빌드되는 샘플. 샌드박스에서 돌리고 서명된 영수증을 보관합니다. 등급을 매기지 않고 무엇도 보증하지 않습니다 — 같은 코드가 당신 환경에서 빌드되는지는 측정한 적이 없습니다.
통과한 계약 영수증을 낸 서로 다른 서명 키의 수입니다. 하나면 작성자 혼자이고, 둘 이상이면 다른 사람도 빌드했다는 뜻입니다. 키는 스스로 만드는 것이고 뒤에 등록된 신원이 없으므로, 세는 것은 사람이 아니라 키입니다.
MIT-0
실행 증거
선언된 환경과 서명된 실행을 분리해 두었습니다. 이 샘플이 무엇을 어디서 실행했는지 그대로 볼 수 있습니다.
- 증거 기준
- 서명된 컨트랙트 통과
- 검증 영수증
- 1
- 빌드한 서명 키
- 1
선언된 환경
node linux 24 · ubuntu · glibc 2.39 x64 node node npm
검증 실행 환경
| 환경 | 컨트랙트 | 단계 | 실행일 |
|---|---|---|---|
| node 22 · linux debian/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22@sha256:8a34c4ab3ea2… |
2026-09-03 |
케이스
HOW- 목표
- By default @rollup/plugin-commonjs renders external requires as default imports causing named exports to be inaccessible unless esmExternals is configured
- 심벌
-
- commonjs
- esmExternals
- 환경
- node
- 생성일
- 2026-09-03T09:28:03Z
컨트랙트
- assert @rollup/plugin-commonjs with default esmExternals: false emits default imports for external dependencies, causing named exports to be inaccessible (undefined) when required from CommonJS
- assert setting esmExternals: true emits namespace imports for external dependencies, creating an augmented namespace that exposes both named exports and default export
- assert esmExternals accepts an array of package IDs to selectively emit namespace imports for specified ESM dependencies while leaving other externals as default imports
- assert esmExternals accepts a predicate function to dynamically determine which external dependencies are imported as ES module namespaces
파일
- NOTES.md
- PROMPT.md
- csx.json
- package-lock.json
- package.json
- spec.json
- test/contract.mjs
소스
# Notes: Rollup CommonJS Plugin External ES Modules and esmExternals
## Search Result
`search_known_solution` returned `NO_SAFE_MATCH` for `@rollup/plugin-commonjs@28.0.7` with symbol `esmExternals`. Existing verified samples for this package covered `strictRequires`, `requireReturnsDefault`, and `transformMixedEsModules`, but none demonstrated how external dependencies are handled when required from CommonJS.
## Naive Model Assumption
A developer or coding model assumes that requiring an external ES module from a CommonJS module bundled with `@rollup/plugin-commonjs` preserves access to all exported symbols, including named exports (such as `const { helper } = require('external-pkg')`).
## Failure Mode
By default (`esmExternals: false`), `@rollup/plugin-commonjs` assumes all external dependencies are CommonJS and generates an unknown require proxy that emits only a default import (`export { default } from 'external-pkg'`). When the external ES module defines named exports, attempting to access them in CommonJS evaluates to `undefined`, causing silent functional failures or runtime `TypeError` when calling functions. Enabling `esmExternals: true` (or passing an array of IDs or a predicate function) switches the proxy to import the ES module namespace and wraps it in an augmented namespace, making both named exports and default exports accessible.
Clean-room public code sample — generation instructions
Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.
A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.
Goal: By default @rollup/plugin-commonjs renders external requires as default imports causing named exports to be inaccessible unless esmExternals is configured
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:npm/%40rollup/plugin-commonjs@28.0.7
- pkg:npm/rollup@4.34.8
Demonstrate these symbols/APIs:
- commonjs
- esmExternals
Rules:
- One focused purpose; the smallest project that proves the goal.
- Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
- Pin every dependency with a lockfile so resolution is reproducible.
- No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
- No personal names, emails, company names, or project identifiers of any kind.
- No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
- Keep it under 200 files and 256KB packed.
{"case":{"believed":"By default @rollup/plugin-commonjs allows CommonJS modules requiring external ES modules to access both default and named exports.","caseId":"case:sha256:042d2e62034055b487fd659dbd694e3a334e373ef1364a7caa266f6bcb694717","contract":["assert @rollup/plugin-commonjs with default esmExternals: false emits default imports for external dependencies, causing named exports to be inaccessible (undefined) when required from CommonJS","assert setting esmExternals: true emits namespace imports for external dependencies, creating an augmented namespace that exposes both named exports and default export","assert esmExternals accepts an array of package IDs to selectively emit namespace imports for specified ESM dependencies while leaving other externals as default imports","assert esmExternals accepts a predicate function to dynamically determine which external dependencies are imported as ES module namespaces"],"goal":"By default @rollup/plugin-commonjs renders external requires as default imports causing named exports to be inaccessible unless esmExternals is configured","kind":"HOW","packages":["pkg:npm/%40rollup/plugin-commonjs@28.0.7","pkg:npm/rollup@4.34.8"],"schemaVersion":1,"symbols":["commonjs","esmExternals"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","executionContext":"node","language":"node","libc":"glibc","libcVersion":"2.39","os":"linux","osVersionBucket":"24","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/%40rollup/plugin-commonjs@28.0.7","pkg:npm/rollup@4.34.8"],"schemaVersion":1,"symbols":["commonjs","esmExternals"],"verifierAdapter":"node-typescript@1"}
{
"name": "npm-rollup-plugin-commonjs-esm-externals",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "npm-rollup-plugin-commonjs-esm-externals",
"version": "1.0.0",
"license": "MIT-0",
"dependencies": {
"@rollup/plugin-commonjs": "28.0.7",
"rollup": "4.34.8"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
"integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==",
"license": "MIT"
},
"node_modules/@rollup/plugin-commonjs": {
"version": "28.0.7",
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.7.tgz",
"integrity": "sha512-6cE2Wr/MkpdtTS8gXlCn9Zdmf7e9Xm96yFqOwFEXuvYLAHtjRf57/n6GEVF4K8NSesT1eKdBtcDA/SQdpW/8nA==",
"license": "MIT",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"commondir": "^1.0.1",
"estree-walker": "^2.0.2",
"fdir": "^6.2.0",
"is-reference": "1.2.1",
"magic-string": "^0.30.3",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=16.0.0 || 14 >= 14.17"
},
"peerDependencies": {
"rollup": "^2.68.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz",
"integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==",
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz",
"integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz",
"integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz",
"integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz",
"integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz",
"integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz",
"integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz",
"integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz",
"integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz",
"integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz",
"integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz",
"integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==",
"cpu": [
"loong64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz",
"integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==",
"cpu": [
"ppc64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz",
"integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz",
"integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==",
"cpu": [
"s390x"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz",
"integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz",
"integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz",
"integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz",
"integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz",
"integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@types/estree": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
"integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
"license": "MIT"
},
"node_modules/commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
"license": "MIT"
},
"node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"license": "MIT"
},
"node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"license": "MIT",
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/is-reference": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
"integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
"license": "MIT",
"dependencies": {
"@types/estree": "*"
}
},
"node_modules/magic-string": {
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
"node_modules/picomatch": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
"integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/rollup": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz",
"integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==",
"license": "MIT",
"dependencies": {
"@types/estree": "1.0.6"
},
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=18.0.0",
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.34.8",
"@rollup/rollup-android-arm64": "4.34.8",
"@rollup/rollup-darwin-arm64": "4.34.8",
"@rollup/rollup-darwin-x64": "4.34.8",
"@rollup/rollup-freebsd-arm64": "4.34.8",
"@rollup/rollup-freebsd-x64": "4.34.8",
"@rollup/rollup-linux-arm-gnueabihf": "4.34.8",
"@rollup/rollup-linux-arm-musleabihf": "4.34.8",
"@rollup/rollup-linux-arm64-gnu": "4.34.8",
"@rollup/rollup-linux-arm64-musl": "4.34.8",
"@rollup/rollup-linux-loongarch64-gnu": "4.34.8",
"@rollup/rollup-linux-powerpc64le-gnu": "4.34.8",
"@rollup/rollup-linux-riscv64-gnu": "4.34.8",
"@rollup/rollup-linux-s390x-gnu": "4.34.8",
"@rollup/rollup-linux-x64-gnu": "4.34.8",
"@rollup/rollup-linux-x64-musl": "4.34.8",
"@rollup/rollup-win32-arm64-msvc": "4.34.8",
"@rollup/rollup-win32-ia32-msvc": "4.34.8",
"@rollup/rollup-win32-x64-msvc": "4.34.8",
"fsevents": "~2.3.2"
}
},
"node_modules/rollup/node_modules/@types/estree": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
"license": "MIT"
}
}
}
{
"name": "npm-rollup-plugin-commonjs-esm-externals",
"version": "1.0.0",
"license": "MIT-0",
"type": "module",
"scripts": {
"test": "node test/contract.mjs"
},
"dependencies": {
"@rollup/plugin-commonjs": "28.0.7",
"rollup": "4.34.8"
}
}
{
"schemaVersion": 1,
"goal": "By default @rollup/plugin-commonjs renders external requires as default imports causing named exports to be inaccessible unless esmExternals is configured",
"kind": "HOW",
"packages": [
"pkg:npm/%40rollup/plugin-commonjs@28.0.7",
"pkg:npm/rollup@4.34.8"
],
"symbols": [
"commonjs",
"esmExternals"
]
}
import assert from 'node:assert/strict';
import { rollup } from 'rollup';
import commonjs from '@rollup/plugin-commonjs';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const projectRoot = path.resolve(__dirname, '..');
async function runContract() {
const mockModuleDir = path.join(projectRoot, 'node_modules', 'mock-external-esm');
fs.mkdirSync(mockModuleDir, { recursive: true });
fs.writeFileSync(
path.join(mockModuleDir, 'package.json'),
JSON.stringify({
name: 'mock-external-esm',
version: '1.0.0',
type: 'module',
exports: './index.js'
})
);
fs.writeFileSync(
path.join(mockModuleDir, 'index.js'),
`export const version = '1.0.0';
export const helper = function() { return 'helped'; };
export default { defaultKey: 'defaultValue' };`
);
const mockOtherDir = path.join(projectRoot, 'node_modules', 'mock-other-pkg');
fs.mkdirSync(mockOtherDir, { recursive: true });
fs.writeFileSync(
path.join(mockOtherDir, 'package.json'),
JSON.stringify({
name: 'mock-other-pkg',
version: '1.0.0',
main: './index.js'
})
);
fs.writeFileSync(
path.join(mockOtherDir, 'index.js'),
`module.exports = { otherVal: 'from-other-cjs' };`
);
const virtualEntry = {
name: 'virtual-entry',
resolveId(id) {
if (id === 'entry-cjs.cjs') return id;
},
load(id) {
if (id === 'entry-cjs.cjs') {
return `
const ext = require('mock-external-esm');
const other = require('mock-other-pkg');
module.exports = { ext, other };
`;
}
}
};
const tmpFiles = [];
try {
// -------------------------------------------------------------------------
// Contract Assertion 1:
// By default (esmExternals: false), @rollup/plugin-commonjs treats external
// dependencies as CommonJS default imports, causing named exports from
// external ES modules to be inaccessible (undefined) when required from CommonJS.
// -------------------------------------------------------------------------
const defaultBundle = await rollup({
input: 'entry-cjs.cjs',
external: ['mock-external-esm', 'mock-other-pkg'],
plugins: [virtualEntry, commonjs()]
});
const { output: defaultOutput } = await defaultBundle.generate({ format: 'es' });
const defaultCode = defaultOutput[0].code;
assert.match(
defaultCode,
/import\s+require\$\$\d+\s+from\s+['"]mock-external-esm['"];/,
'assert @rollup/plugin-commonjs with default esmExternals: false emits default imports for external dependencies, causing named exports to be inaccessible (undefined) when required from CommonJS'
);
const tmpDefault = path.join(projectRoot, '.tmp-contract-default.mjs');
tmpFiles.push(tmpDefault);
fs.writeFileSync(tmpDefault, defaultCode);
const modDefault = (await import(`file://${tmpDefault.replace(/\\/g, '/')}`)).default;
assert.equal(
typeof modDefault.ext.helper,
'undefined',
'Named export is undefined when required from CommonJS under default esmExternals: false'
);
assert.equal(
modDefault.ext.defaultKey,
'defaultValue',
'Default export remains accessible through default import proxy'
);
// -------------------------------------------------------------------------
// Contract Assertion 2:
// Setting esmExternals: true renders external dependencies as namespace
// imports wrapped in an augmented namespace, exposing both named and default exports.
// -------------------------------------------------------------------------
const esmBundle = await rollup({
input: 'entry-cjs.cjs',
external: ['mock-external-esm', 'mock-other-pkg'],
plugins: [virtualEntry, commonjs({ esmExternals: true })]
});
const { output: esmOutput } = await esmBundle.generate({ format: 'es' });
const esmCode = esmOutput[0].code;
assert.match(
esmCode,
/import\s+\*\s+as\s+mockExternalEsm\s+from\s+['"]mock-external-esm['"];/,
'assert setting esmExternals: true emits namespace imports for external dependencies, creating an augmented namespace that exposes both named exports and default export'
);
const tmpEsm = path.join(projectRoot, '.tmp-contract-esm.mjs');
tmpFiles.push(tmpEsm);
fs.writeFileSync(tmpEsm, esmCode);
const modEsm = (await import(`file://${tmpEsm.replace(/\\/g, '/')}`)).default;
assert.equal(
typeof modEsm.ext.helper,
'function',
'Named exports are accessible from augmented namespace when esmExternals is true'
);
assert.equal(modEsm.ext.helper(), 'helped');
assert.equal(modEsm.ext.version, '1.0.0');
assert.deepEqual(modEsm.ext.default, { defaultKey: 'defaultValue' });
// -------------------------------------------------------------------------
// Contract Assertion 3:
// esmExternals accepts an array of package IDs to selectively emit namespace
// imports for specified ESM dependencies while leaving other externals as default imports.
// -------------------------------------------------------------------------
const selectiveBundle = await rollup({
input: 'entry-cjs.cjs',
external: ['mock-external-esm', 'mock-other-pkg'],
plugins: [virtualEntry, commonjs({ esmExternals: ['mock-external-esm'] })]
});
const { output: selectiveOutput } = await selectiveBundle.generate({ format: 'es' });
const selectiveCode = selectiveOutput[0].code;
assert.match(
selectiveCode,
/import\s+\*\s+as\s+mockExternalEsm\s+from\s+['"]mock-external-esm['"];/,
'assert esmExternals accepts an array of package IDs to selectively emit namespace imports for specified ESM dependencies while leaving other externals as default imports'
);
assert.match(
selectiveCode,
/import\s+require\$\$\d+\s+from\s+['"]mock-other-pkg['"];/,
'Non-targeted external module remains a default import'
);
// -------------------------------------------------------------------------
// Contract Assertion 4:
// esmExternals accepts a predicate function to dynamically determine which
// external dependencies are imported as ES module namespaces.
// -------------------------------------------------------------------------
const fnBundle = await rollup({
input: 'entry-cjs.cjs',
external: ['mock-external-esm', 'mock-other-pkg'],
plugins: [
virtualEntry,
commonjs({
esmExternals: (id) => id.includes('external-esm')
})
]
});
const { output: fnOutput } = await fnBundle.generate({ format: 'es' });
const fnCode = fnOutput[0].code;
assert.match(
fnCode,
/import\s+\*\s+as\s+mockExternalEsm\s+from\s+['"]mock-external-esm['"];/,
'assert esmExternals accepts a predicate function to dynamically determine which external dependencies are imported as ES module namespaces'
);
assert.match(
fnCode,
/import\s+require\$\$\d+\s+from\s+['"]mock-other-pkg['"];/,
'Predicate returning false renders default import'
);
console.log('All contract assertions passed successfully.');
} finally {
for (const f of tmpFiles) {
if (fs.existsSync(f)) {
fs.unlinkSync(f);
}
}
if (fs.existsSync(mockModuleDir)) {
fs.rmSync(mockModuleDir, { recursive: true, force: true });
}
if (fs.existsSync(mockOtherDir)) {
fs.rmSync(mockOtherDir, { recursive: true, force: true });
}
}
}
runContract().catch((err) => {
console.error('Contract failed:', err);
process.exit(1);
});
오리진 시더
익명