mr-dep-walk
Advanced tools
Comparing version 1.3.1 to 1.4.0
@@ -6,3 +6,4 @@ 'use strict'; | ||
depsFromSource: require('./lib/deps-from-source'), | ||
depsFromAST: require('./lib/deps-from-ast'), | ||
depFilesFromFile: require('./lib/dep-files-from-file'), | ||
}; |
@@ -11,3 +11,5 @@ 'use strict'; | ||
let cwd = options.cwd || ''; | ||
let deps = depsFromFile(path.join(root, cwd, file)); | ||
let deps = depsFromFile(path.join(root, cwd, file), { | ||
parse: options.parse, | ||
}); | ||
@@ -29,2 +31,3 @@ for (let i = 0; i < deps.length; i++) { | ||
files.push(fullDependency); | ||
depFilesFromFile( | ||
@@ -36,2 +39,3 @@ root, | ||
external: options.external, | ||
parse: options.parse, | ||
}, | ||
@@ -38,0 +42,0 @@ files |
@@ -6,5 +6,5 @@ 'use strict'; | ||
module.exports = function depsFromFile(file) { | ||
module.exports = function depsFromFile(file, options) { | ||
if (fs.existsSync(file)) { | ||
return depsFromSource(fs.readFileSync(file, 'UTF8')); | ||
return depsFromSource(fs.readFileSync(file, 'UTF8'), options); | ||
} else { | ||
@@ -11,0 +11,0 @@ return []; |
'use strict'; | ||
const acorn = require('acorn'); | ||
// lifted from: https://github.com/ef4/ember-browserify/blob/master/lib/stubs.js (EF4 deserves credit); | ||
// | ||
const STOP = {}; | ||
function forEachNode(node, visit) { | ||
if (node && typeof node === 'object' && !node._eb_visited) { | ||
node._eb_visited = true; | ||
let shouldStop = visit(node); | ||
if (STOP === shouldStop) { | ||
return STOP; | ||
} | ||
let keys = Object.keys(node); | ||
for (let i = 0; i < keys.length; i++) { | ||
let shouldStop = forEachNode(node[keys[i]], visit); | ||
if (STOP === shouldStop) { | ||
return STOP; | ||
} | ||
} | ||
} | ||
} | ||
const depsFromAST = require('./deps-from-ast'); | ||
const defaultParser = require('./default-parser'); | ||
module.exports = function depsFromSource(source) { | ||
// TODO: add a persistent cache | ||
let imports = []; | ||
module.exports = function depsFromSource(source, _options) { | ||
let options = _options || {}; | ||
let parse = options.parse || defaultParser; | ||
let ast = acorn.parse(source, { | ||
ecmaVersion: 8, | ||
sourceType: 'module', | ||
}); | ||
let hasImportDeclaration = false; | ||
forEachNode(ast, function(entry) { | ||
if (entry.type === 'ImportDeclaration') { | ||
hasImportDeclaration = true; | ||
let value = entry.source.value; | ||
if (value === 'exports' || value === 'require') { | ||
return; | ||
} | ||
imports.push(value); | ||
} | ||
if (hasImportDeclaration) { | ||
return; | ||
} | ||
if (entry.type === 'CallExpression' && entry.callee.name === 'define') { | ||
for (let i = 0; i < entry.arguments.length; i++) { | ||
let item = entry.arguments[i]; | ||
if (item.type === 'ArrayExpression') { | ||
for (let j = 0; j < item.elements.length; j++) { | ||
let element = item.elements[j]; | ||
let value = element.value; | ||
if (value !== 'exports' && value !== 'require') { | ||
imports.push(value); | ||
} | ||
} | ||
return STOP; | ||
} | ||
} | ||
return STOP; | ||
} | ||
}); | ||
return imports; | ||
return depsFromAST( | ||
parse(source, { | ||
ecmaVersion: 8, | ||
sourceType: 'module', | ||
}) | ||
); | ||
}; |
@@ -32,3 +32,3 @@ { | ||
"name": "mr-dep-walk", | ||
"version": "1.3.1", | ||
"version": "1.4.0", | ||
"main": "index.js", | ||
@@ -35,0 +35,0 @@ "directories": { |
@@ -6,1 +6,86 @@ # mr-dep-walk | ||
This library extracts dependent files from both ES6 module syntax, and AMD module syntax; | ||
## Usage | ||
``` | ||
yarn add mr-dep-walk | ||
``` | ||
```js | ||
const { | ||
depFilesFromFile, | ||
depsFromFile, | ||
depsFromSource, | ||
depsFromAST | ||
} = require('mr-dep-walk'); | ||
``` | ||
For `depFilesFromFile` given an entry file, it will produce a list of all dependent files (recursively): | ||
```js | ||
// file.js | ||
import x from 'y'; | ||
// y.js | ||
``` | ||
```js | ||
depFilesFromFile({ | ||
entry: 'file.js', | ||
/* cwd: optional, */ | ||
/* parse: optional, */ | ||
}); // => 'y.js'; | ||
``` | ||
For `depsFromFile` given a file, it will produce a list of its immediate dependent moduleNames; | ||
```js | ||
// file.js | ||
import x from 'y'; | ||
// y.js | ||
``` | ||
```js | ||
depsFromFile({ | ||
entry: 'file.js', | ||
/* cwd: optional, */ | ||
/* parse: optional, */ | ||
}); // => 'y'; | ||
``` | ||
For `depsFromSource` given the raw source, it will produce a list of its immediate dependent moduleNames; | ||
```js | ||
depsFromSource(`import x from 'y'`/*, options */); // => 'y' | ||
``` | ||
For `depsFromAST` given the AST, it will produce a list of its immediate dependent moduleNames; | ||
```js | ||
depsFromSource(acorn.parse(`import x from 'y'`, { | ||
ecmaVersion: 8, | ||
sourceType: 'module' | ||
})); // => 'y' | ||
``` | ||
### Custom Parse Step | ||
By default mr-dep-walk will use: | ||
```js | ||
source => acorn.parse(source, { ecmaVersion: 8, sourceType: 'module'}) | ||
``` | ||
But some methods (`depFilesFromFile`, `depsFromFile`, `depsFromSource`) support | ||
an alt-parser, example: | ||
```js | ||
depFilesFromFile('some-file.js', { | ||
entry: 'foo.js', | ||
parse(source) { | ||
return customParser(source); | ||
}, | ||
}); | ||
``` |
@@ -9,2 +9,3 @@ 'use strict'; | ||
const depsFromFile = require('../lib/deps-from-file'); | ||
const defaultParser = require('../lib/default-parser'); | ||
@@ -58,2 +59,33 @@ describe('.depsFromFile', function() { | ||
}); | ||
describe('pluggable parse', function() { | ||
fs.removeSync(ROOT); | ||
fixturify.writeSync(ROOT + 'es6', { | ||
'foo.js': ` | ||
import x from 'a'; | ||
import y from 'b/c';`, | ||
'a.js': ``, | ||
b: { | ||
'c.js': ` | ||
import a from '../a'; | ||
import d from '../d'; | ||
`, | ||
}, | ||
'd.js': `import foo from 'foo';`, | ||
}); | ||
it('provide alternative parser', function() { | ||
let parseCount = 0; | ||
expect( | ||
depsFromFile(ROOT + 'es6/foo.js', { | ||
parse(source) { | ||
parseCount++; | ||
return defaultParser(source); | ||
}, | ||
}) | ||
).to.eql(['a', 'b/c']); | ||
expect(parseCount).to.eql(1); | ||
}); | ||
}); | ||
}); |
@@ -5,2 +5,3 @@ 'use strict'; | ||
const depsFromSrouce = require('../lib/deps-from-source'); | ||
const defaultParser = require('../lib/default-parser'); | ||
@@ -63,2 +64,24 @@ describe('.depsFromSource', function() { | ||
}); | ||
describe('pluggable parse', function() { | ||
it('provide alternative parser', function() { | ||
let parseCount = 0; | ||
expect( | ||
depsFromSrouce( | ||
` | ||
import x from 'a'; | ||
import y from 'b/c'; | ||
`, | ||
{ | ||
parse(source) { | ||
parseCount++; | ||
return defaultParser(source); | ||
}, | ||
} | ||
) | ||
).to.eql(['a', 'b/c']); | ||
expect(parseCount).to.eql(1); | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
73066
18
577
91
1