diff --git a/package-lock.json b/package-lock.json index 966cfd4..ac61def 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6096,8 +6096,7 @@ "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" }, "lodash.ismatch": { "version": "4.4.0", diff --git a/package.json b/package.json index 7163bcd..aa58afb 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "dependencies": { "@babel/parser": "^7.6.4", "cosmiconfig": "^5.2.0", + "lodash.get": "^4.4.2", "relative-require-regex": "^1.0.1", "require-package-name": "^2.0.1", "yargs": "^14.0.0" diff --git a/src/Adio.js b/src/Adio.js index 7a803f4..244fe48 100644 --- a/src/Adio.js +++ b/src/Adio.js @@ -4,7 +4,7 @@ const cosmiconfig = require("cosmiconfig"); const fs = require("fs"); const explorer = cosmiconfig("adio"); const { extractDepsFromPackageJson, isIgnoredDep } = require("./utils/testPackage"); -const { extractSrcDeps } = require("./utils/extractSrcDeps"); +const extractSrcDeps = require("./utils/extractSrcDeps"); class Adio { constructor(config) { diff --git a/src/__tests__/mocks/multiple.imports.js b/src/__tests__/mocks/multiple.imports.js index a7458a3..c3bad12 100644 --- a/src/__tests__/mocks/multiple.imports.js +++ b/src/__tests__/mocks/multiple.imports.js @@ -10,4 +10,5 @@ export default ` import withId from "@commodo/fields-storage/utils/withId"; export * from "repropose"; export { default as testDefaultExport } from "testing-default-exports-pckg"; + export const resolveGetSettings = () => {}; `; diff --git a/src/__tests__/parser.test.js b/src/__tests__/parser.test.js index 99b03a6..6156191 100644 --- a/src/__tests__/parser.test.js +++ b/src/__tests__/parser.test.js @@ -1,9 +1,9 @@ -import { extractImportsRequires } from "adio/utils/extractSrcDeps"; +import parse from "adio/utils/parse"; import mockImports from "./mocks/multiple.imports"; import mockRequires from "./mocks/multiple.requires"; test("must correctly return all imported packages", () => { - const packages = extractImportsRequires(mockImports); + const packages = parse({ src: mockImports }); expect(packages).toEqual([ "react", @@ -18,7 +18,7 @@ test("must correctly return all imported packages", () => { }); test("must correctly return all required packages", () => { - const packages = extractImportsRequires(mockRequires); + const packages = parse({ src: mockRequires }); expect(packages).toEqual([ "react", diff --git a/src/utils/extractSrcDeps.js b/src/utils/extractSrcDeps.js index 7945a45..b4847ee 100644 --- a/src/utils/extractSrcDeps.js +++ b/src/utils/extractSrcDeps.js @@ -1,45 +1,10 @@ const glob = require("glob"); const fs = require("fs"); -const parser = require("@babel/parser"); -const { default: traverse } = require("@babel/traverse"); -const name = require("require-package-name"); -const relative = require("relative-require-regex"); -const isRelative = value => relative().test(value); - -const STD_NODE_TYPES = ["ImportDeclaration", "ExportNamedDeclaration", "ExportAllDeclaration"]; - -const extractImportsRequires = source => { - const ast = parser.parse(source, { - sourceType: "module" - }); - - const imports = {}; - traverse(ast, { - enter(path) { - const { node } = path; - if (STD_NODE_TYPES.includes(node.type)) { - let { value } = node.source; - if (!isRelative(value)) { - imports[name(value)] = true; - } - } - - if (node.type === "CallExpression") { - if (node.callee.name === "require") { - let { value } = node.arguments[0]; - if (!isRelative(value)) { - imports[name(value)] = true; - } - } - } - } - }); - - return Object.keys(imports); -}; +const get = require("lodash.get"); +const parse = require("./parse"); const isIgnoredPath = ({ path, instance, adioRc }) => { - let dirs = instance.config.ignoreDirs || []; + let dirs = get(instance, "config.ignoreDirs") || []; for (let i = 0; i < dirs.length; i++) { let dir = dirs[i]; if (path.includes(dir)) { @@ -47,20 +12,18 @@ const isIgnoredPath = ({ path, instance, adioRc }) => { } } - if (adioRc) { - dirs = adioRc.ignoreDirs || []; - for (let i = 0; i < dirs.length; i++) { - let dir = dirs[i]; - if (path.includes(dir)) { - return true; - } + dirs = get(adioRc, "ignoreDirs") || []; + for (let i = 0; i < dirs.length; i++) { + let dir = dirs[i]; + if (path.includes(dir)) { + return true; } } return false; }; -const extractSrcDeps = ({ dir, instance, adioRc }) => { +module.exports = ({ dir, instance, adioRc }) => { const paths = glob.sync(dir + "/**/*.js"); const deps = []; paths.forEach(path => { @@ -69,7 +32,16 @@ const extractSrcDeps = ({ dir, instance, adioRc }) => { } const src = fs.readFileSync(path, "utf8"); - const importsRequires = extractImportsRequires(src); + const importsRequires = parse({ + src, + config: { + parser: { + ...get(instance, "config.parser", {}), + ...get(adioRc, "parser", {}) + } + } + }); + importsRequires.forEach(name => { // is relative import? if (!name || name.startsWith(".")) { @@ -87,8 +59,3 @@ const extractSrcDeps = ({ dir, instance, adioRc }) => { return deps; }; - -module.exports = { - extractSrcDeps, - extractImportsRequires -}; diff --git a/src/utils/parse.js b/src/utils/parse.js new file mode 100644 index 0000000..784fd2a --- /dev/null +++ b/src/utils/parse.js @@ -0,0 +1,40 @@ +const parser = require("@babel/parser"); +const { default: traverse } = require("@babel/traverse"); +const name = require("require-package-name"); +const relative = require("relative-require-regex"); +const isRelative = value => relative().test(value); +const get = require("lodash.get"); + +const STD_NODE_TYPES = ["ImportDeclaration", "ExportNamedDeclaration", "ExportAllDeclaration"]; + +module.exports = ({ src, config = {} }) => { + const ast = parser.parse(src, { + sourceType: "module", + ...config.parser + }); + + const imports = {}; + traverse(ast, { + enter(path) { + const { node } = path; + if (STD_NODE_TYPES.includes(node.type)) { + const value = get(node, "source.value"); + if (value && !isRelative(value)) { + imports[name(value)] = true; + } + return; + } + + if (node.type === "CallExpression") { + if (get(node, "callee.name") === "require") { + let value = get(node, "arguments.0.value"); + if (value && !isRelative(value)) { + imports[name(value)] = true; + } + } + } + } + }); + + return Object.keys(imports); +};