UNPKG

dependency-cruiser

Version:

Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.

132 lines (115 loc) 4.95 kB
"use strict"; const acorn = require('acorn'); const acorn_loose = require('acorn/dist/acorn_loose'); const typescript = require('typescript'); const coffeeScript = require('coffee-script'); const fs = require('fs'); const _ = require('lodash'); const path = require('path'); const resolver = require('../resolve'); const validator = require('../validate'); const utl = require('../utl'); const extractES6Dependencies = require('./extractor-ES6'); const extractCommonJSDependencies = require('./extractor-commonJS'); const extractAMDDependencies = require('./extractor-AMD'); function getASTBare(pFileName) { let lFile = fs.readFileSync(pFileName, 'utf8'); if (path.extname(pFileName) === ".ts"){ lFile = typescript.transpileModule( lFile, { compilerOptions: { "target": "es2015" } } ).outputText; } if (path.extname(pFileName) === ".coffee"){ lFile = coffeeScript.compile(lFile); } if ([".litcoffee", ".coffee.md"].some(pExt => path.extname(pFileName) === pExt)){ lFile = coffeeScript.compile(lFile, {literate:true}); } try { return acorn.parse(lFile, {sourceType: 'module'}); } catch (e) { return acorn_loose.parse_dammit(lFile, {sourceType: 'module'}); } } const getAST = _.memoize(getASTBare); /** * Returns an array of dependencies present in the given file. Of * each dependency it returns * module - the name of the module as found in the file * resolved - the filename the dependency resides in (including the path * to the current directory or the directory passed as * 'baseDir' in the options) * moduleSystem - the module system * coreModule - a boolean indicating whether it is a (nodejs) core module * * * @param {string} pFileName path to the file * @param {object} pOptions an object with one or more of these properties: * - baseDir - the directory to consider as the * base for all files * Default: the current working directory * - moduleSystems - an array of module systems to * consider. * Default: ["cjs", "es6", "amd"] * - exclude - a regular expression string * with a pattern of modules to exclude (e.g. * "(node_modules)"). Default: none * @return {array} an array of dependency objects (see above) */ function extractDependencies(pFileName, pOptions) { try { const lAST = getAST(pFileName); let lDependencies = []; pOptions = _.defaults( pOptions, { baseDir: process.cwd(), moduleSystems: ["cjs", "es6", "amd"] } ); if (_.includes(pOptions.moduleSystems, "cjs")){ extractCommonJSDependencies(lAST, lDependencies); } if (_.includes(pOptions.moduleSystems, "es6")){ extractES6Dependencies(lAST, lDependencies); } if (_.includes(pOptions.moduleSystems, "amd")){ extractAMDDependencies(lAST, lDependencies); } return _(lDependencies) .uniqBy(pDependency => `${pDependency.moduleName} ${pDependency.moduleSystem}`) .sortBy(pDependency => `${pDependency.moduleName} ${pDependency.moduleSystem}`) .map( pDependency => { const lResolved = resolver( pDependency, pOptions.baseDir, path.dirname(pFileName) ); return Object.assign( lResolved, { module : pDependency.moduleName, moduleSystem : pDependency.moduleSystem }, validator.validate( pOptions.validate, pOptions.rulesFile, pFileName, lResolved ) ); } ) .filter(pDep => utl.ignore(pDep.resolved, pOptions.exclude)) .value(); } catch (e) { throw new Error(`Extracting dependencies ran afoul of...\n\n ${e.message}\n... in ${pFileName}\n\n`); } } module.exports = extractDependencies;