Socket
Socket
Sign inDemoInstall

rollup-plugin-cjs-es

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rollup-plugin-cjs-es - npm Package Compare versions

Comparing version 0.3.2 to 0.4.0

214

index.js

@@ -0,3 +1,3 @@

const fs = require("fs");
const path = require("path");
const {promisify} = require("util");

@@ -7,4 +7,3 @@ const {transform: cjsEs} = require("cjs-es");

const {createFilter} = require("rollup-pluginutils");
const esInfo = require("es-info");
const nodeResolve = promisify(require("resolve"));
const {analyze: esInfoAnalyze} = require("es-info");
const {wrapImport} = require("./lib/wrap-import");

@@ -20,4 +19,3 @@ const {unwrapImport} = require("./lib/unwrap-import");

function isEsModule(ast) {
const result = esInfo.analyze(ast);
function isEsModule(result) {
return Object.keys(result.import).length ||

@@ -29,52 +27,13 @@ result.export.default ||

function createResolve(rollupOptions) {
return (importee, importer) => {
return new Promise((resolve, reject) => {
const plugins = rollupOptions.plugins || [];
resolveId(0);
function resolveId(i) {
if (i >= plugins.length) {
const basedir = path.dirname(importer);
nodeResolve(importee, {basedir})
.then(resolve, reject);
return;
}
if (!plugins[i].resolveId) {
setImmediate(resolveId, i + 1);
return;
}
let pending;
try {
pending = Promise.resolve(plugins[i].resolveId(importee, importer));
} catch (err) {
reject(err);
return;
}
pending
.then(result => {
if (result) {
resolve(result);
return;
}
setImmediate(resolveId, i + 1);
})
.catch(reject);
}
});
};
}
function factory(options = {}) {
let isImportWrapped = false;
let parse = null;
const rollupOptions = {};
const exportTable = {};
const exportCache = {};
const {_fs = fs} = options;
if (!options.resolve) {
options.resolve = createResolve(rollupOptions);
}
if (typeof options.exportType === "object") {
const newMap = {};
for (const key of Object.keys(options.exportType)) {
const newKey = require.resolve(path.resolve(key));
const newKey = path.resolve(key);
newMap[newKey] = options.exportType[key];

@@ -85,3 +44,41 @@ }

function getExportType(id, importer) {
if (options.sourceMap == null) {
options.sourceMap = true;
}
if (options.cache == null) {
options.cache = true;
}
const filter = createFilter(options.include, options.exclude);
if (options.cache) {
loadCjsEsCache();
}
function loadCjsEsCache() {
let data;
try {
data = _fs.readFileSync(".cjsescache", "utf8");
} catch (err) {
return;
}
data = JSON.parse(data);
for (const [id, type] of Object.entries(data)) {
exportCache[path.resolve(id)] = type;
}
}
function writeCjsEsCache() {
const data = Object.entries(exportTable).filter(e => e[1].trusted || e[1].external)
.sort((a, b) => a[0].localeCompare(b[0]))
.reduce((output, [id, info]) => {
id = path.relative(".", id).replace(/\\/g, "/");
output[id] = info.named ? "named" : "default";
return output;
}, {});
_fs.writeFileSync(".cjsescache", JSON.stringify(data, null, 2), "utf8");
}
function getExportTypeFromOptions(id) {
if (!options.exportType) {

@@ -93,20 +90,89 @@ return;

}
return Promise.resolve(importer ? options.resolve(id, importer) : id)
.then(id => {
return typeof options.exportType === "function" ?
options.exportType(id, importer) : options.exportType[id];
return typeof options.exportType === "function" ?
options.exportType(id) : options.exportType[id];
}
function getExportType(id) {
// get export type from trusted table
if (exportTable[id] && exportTable[id].trusted) {
return exportTable[id].named ? "named" : "default";
}
// get export type from options
return Promise.resolve(getExportTypeFromOptions(id))
.then(result => {
if (result) {
return result;
}
// get export type from guess table
if (exportTable[id]) {
return exportTable[id].named ? "named" : "default";
}
// get export type from cache
return exportCache[id];
});
}
if (options.sourceMap == null) {
options.sourceMap = true;
function updateExportTable({id, code, context, info}) {
if (!info) {
info = esInfoAnalyze(context.parse(code));
}
if (exportTable[id]) {
if (exportTable[id].default && !info.export.default) {
warnExport("default");
}
if (exportTable[id].named && !info.export.named.length && !info.export.all) {
warnExport("names");
}
}
exportTable[id] = {
default: info.default,
named: info.export.named.length > 0 || info.all,
expectBy: id,
trusted: true
};
return Promise.all(Object.entries(info.import).map(([name, importInfo]) => {
return context.resolveId(name, id)
.then(importee => {
let external = false;
if (!importee) {
importee = name;
external = true;
}
if (exportTable[importee]) {
if (exportTable[importee].default && !importInfo.default) {
warnImport(importee, "default");
}
if (exportTable[importee].named && !importInfo.named.length && !importInfo.all) {
warnImport(importee, "names");
}
} else {
const newGuess = {
default: importInfo.default,
named: importInfo.named.length > 0 || importInfo.all,
expectBy: id,
external
};
if (newGuess.default || newGuess.named) {
exportTable[importee] = newGuess;
}
}
});
}));
function warnImport(importee, type) {
const shortId = path.relative(".", id);
const shortImportee = path.relative(".", importee);
const expectBy = path.relative(".", exportTable[importee].expectBy);
context.warn(`'${expectBy}' thinks '${shortImportee}' export ${type} but '${shortId}' disagrees`);
}
function warnExport(type) {
const shortId = path.relative(".", id);
const expectBy = path.relative(".", exportTable[id].expectBy);
context.warn(`'${shortId}' doesn't export ${type} expected by '${expectBy}'`);
}
}
const filter = createFilter(options.include, options.exclude);
return {
name: "rollup-plugin-cjs-es",
options(_rollupOptions) {
Object.assign(rollupOptions, _rollupOptions);
},
transform(code, id) {

@@ -118,4 +184,6 @@ if (!filter(id)) {

let ast = parse(code);
if (isEsModule(ast)) {
return;
const info = esInfoAnalyze(ast);
if (isEsModule(info)) {
return updateExportTable({context: this, info, id})
.then(() => undefined);
}

@@ -149,4 +217,6 @@ const maps = [];

sourceMap: options.sourceMap,
importStyle: requireId => getExportType(requireId, id),
exportStyle: () => getExportType(id),
importStyle: requireId =>
this.resolveId(requireId, id)
.then(newId => getExportType(newId || requireId)),
exportStyle: () => getExportTypeFromOptions(id),
nested: options.nested,

@@ -165,10 +235,11 @@ warn: (message, pos) => {

if (isTouched) {
return {
code,
map: options.sourceMap && maps.length && joinMaps(maps)
};
return updateExportTable({context: this, code, id})
.then(() => ({
code,
map: options.sourceMap && maps.length && joinMaps(maps)
}));
}
});
},
transformBundle(code, {format}) {
transformChunk(code, {format}) {
if (!isImportWrapped) {

@@ -191,2 +262,7 @@ return;

}
},
buildEnd() {
if (options.cache) {
writeCjsEsCache();
}
}

@@ -193,0 +269,0 @@ };

{
"name": "rollup-plugin-cjs-es",
"version": "0.3.2",
"version": "0.4.0",
"description": "Convert CommonJS module into ES module",

@@ -26,20 +26,19 @@ "keywords": [

"devDependencies": {
"coveralls": "^3.0.0",
"coveralls": "^3.0.1",
"eslint": "^4.19.1",
"mocha": "^5.1.1",
"nyc": "^11.7.1",
"rollup": "^0.58.2"
"mocha": "^5.2.0",
"nyc": "^12.0.2",
"rollup": "^0.60.7"
},
"dependencies": {
"cjs-es": "^0.4.4",
"cjs-es": "^0.4.7",
"es-info": "^0.1.1",
"estree-walker": "^0.5.1",
"magic-string": "^0.24.0",
"estree-walker": "^0.5.2",
"magic-string": "^0.25.0",
"merge-source-map": "^1.1.0",
"resolve": "^1.7.1",
"rollup-pluginutils": "^2.0.1"
"rollup-pluginutils": "^2.3.0"
},
"peerDependencies": {
"rollup": ">=0.58.2"
"rollup": ">=0.60"
}
}

@@ -16,2 +16,9 @@ rollup-plugin-cjs-es

Features
--------
* Transform some cases and emit warnings for unconverted `require`s.
* Use a cache file to solve export type conflicts instead of using proxy modules.
* Split code with sync `require()` or async `Promise.resolve(require())`.
Usage

@@ -31,7 +38,2 @@ -----

cjsEs({
include: ["*.js"],
exclude: [],
exportType: "default",
sourceMap: true,
splitCode: true,
nested: true

@@ -46,3 +48,3 @@ })

`cjs-es` can transform top-level `require`, `exports`, and `module.exports` statements. For those non-top-level statements, the transformer hoist them to top-level (optional, off by default):
`cjs-es` can transform top-level `require`, `exports`, and `module.exports` statements. For those non-top-level statements, the transformer hoist them to top-level:

@@ -67,3 +69,3 @@ ```js

However, if `require`, `exports`, or `module` are dynamically assigned, the transformer can't find them e.g.
However, if `require`, `exports`, or `module` are dynamically assigned, the transformer can't find them and it will emit a warning e.g.

@@ -179,6 +181,8 @@ ```js

> Although the bundle is created, it is unusable in this case.
That is because cjs-es tends to import named exports by default.
That is because cjs-es tends to import named export by default. To fix it, [mark the require as `// default`](https://github.com/eight04/cjs-es#import-style), or use `exportType` option to tell the plugin that *foo.js* exports default member:
To solve this problem, the plugin generates a `.cjsescache` file when a build is finished (whether it succeeded or not), which record the export type of each imported module. In the next build, it will read the cache file and determine the export type according to the cache.
You can also use `exportType` option to tell the plugin that *foo.js* exports default member manually:
```js

@@ -196,19 +200,2 @@ {

When there are bunch of these warnings, manually adding those modules into `exportType` could be a problem. Therefore, you might want to dump the information about all modules with other plugins e.g. [rollup-plugin-es-info](https://github.com/eight04/rollup-plugin-es-info) then convert it into a `exportType` map.
If you don't care about tree-shaking feature (tree-shaking only works with named exports), you can simply set `options.exportType` to `"default"` so that every modules use default member when importing/exporting:
```js
{
plugins: [
resolve({
module: false // don't resolve to ES modules since they may export named members.
}),
cjsEs({
exportType: "default"
})
]
}
```
### Dynamic import() problem with default export

@@ -294,3 +281,3 @@

With this method, it can first look into the `"foo"` module to check its export type, then generate the proxy module which maps named exports into a default export. However, if the required module `"foo"` uses named exports, it has to be converted into a single object:
With this technic, it can first look into the `"foo"` module to check its export type, then generate the proxy module which maps named exports into a default export. However, if the required module `"foo"` uses named exports, it has to be converted into a single object:

@@ -338,2 +325,4 @@ *commonjs-proxy:foo*

> Note that this won't be true after rollup supports tree-shaking for object literal. See https://github.com/rollup/rollup/issues/2201
API reference

@@ -350,2 +339,3 @@ -------------

* `exclude`: `Array<string>`. A list of minimatch pattern. Override `options.include`. Default: `[]`.
* `cache`: `Boolean`. If true then read/write the cache file. Default: `true`.
* `sourceMap`: `boolean`. If true then generate the source map. Default: `true`.

@@ -364,12 +354,11 @@ * `splitCode`: `boolean|function`. If true then enable code-splitting for require statements which are marked as `// split`. See [Lazy load and code splitting](#lazy-load-and-code-splitting) for details.

* `nested?`: `boolean`. If true then analyze the AST recursively, otherwise only top-level nodes are analyzed. Default: `false`.
* `exportType`: `string|object|function`. Tell the plugin what type of the export does the module use.
* `exportType`: `string|object|function`. Tell the plugin how to determine the export type.
If `exportType` is a function, it receives 2 arguments:
If `exportType` is a function, it receives 1 argument:
- `modulId`: `string`. The ID of the module.
- `importer`: `null|string`. If the module is imported by an importer, this would be the ID of the importer module.
The return value should be the type of export for `moduleId`.
If `exportType` is an object, it is a `"path/to/module": type` map.
If `exportType` is an object, it is a `"path/to/file.js": type` map.

@@ -381,2 +370,7 @@ Default: `"named"`.

* 0.4.0 (Jun 16, 2018)
- **Update rollup to 0.60.**
- **Add: `options.cache`. Now the plugin would generate a cache file by default.**
* 0.3.2 (May 4, 2018)

@@ -383,0 +377,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc