auto-install
Advanced tools
Comparing version 1.3.1 to 1.3.2
297
helpers.js
@@ -1,7 +0,5 @@ | ||
'use strict' | ||
const fs = require('fs'); | ||
const glob = require('glob'); | ||
const isBuiltInModule = require('is-builtin-module'); | ||
const syncExec = require("sync-exec"); | ||
const syncExec = require('sync-exec'); | ||
const ora = require('ora'); | ||
@@ -12,3 +10,17 @@ const logSymbols = require('log-symbols'); | ||
const detective = require('detective'); | ||
const colors = require('colors'); | ||
/* Secure mode */ | ||
let secureMode = false; | ||
if (argv.secure) secureMode = true; | ||
/* File reader | ||
* Return contents of given file | ||
*/ | ||
let readFile = (path) => { | ||
let content = fs.readFileSync(path, 'utf8'); | ||
return content; | ||
}; | ||
/* Get installed modules | ||
@@ -21,66 +33,102 @@ * Read dependencies array from package.json | ||
let installedModules = []; | ||
for (let key in content.dependencies) installedModules.push({ | ||
name: key, | ||
dev: false | ||
}); | ||
for (let key in content.devDependencies) installedModules.push({ | ||
name: key, | ||
dev: true | ||
}); | ||
for (let key of Object.keys(content.dependencies)) { | ||
installedModules.push({ | ||
name: key, | ||
dev: false | ||
}); | ||
} | ||
if (content.devDependencies) { | ||
for (let key of Object.keys(content.devDependencies)) { | ||
installedModules.push({ | ||
name: key, | ||
dev: true | ||
}); | ||
} | ||
} | ||
return installedModules; | ||
}; | ||
/* Get used modules | ||
* Read all .js files and grep for modules | ||
/* Get all js files | ||
* Return path of all js files | ||
*/ | ||
let getFiles = () => glob.sync('**/*.js', {ignore: ['node_modules/**/*']}); | ||
let getUsedModules = () => { | ||
let files = getFiles(); | ||
let usedModules = []; | ||
for (let fileName of files) { | ||
let modulesFromFile = getModulesFromFile(fileName); | ||
let dev = isTestFile(fileName); | ||
for (let name of modulesFromFile) usedModules.push({name, dev}); | ||
} | ||
usedModules = deduplicate(usedModules); | ||
return usedModules; | ||
/* Check for valid string - to stop malicious intentions */ | ||
let isValidModule = ({name}) => { | ||
let regex = new RegExp('^([a-z0-9-_]{1,})$'); | ||
return regex.test(name); | ||
}; | ||
/* Install module | ||
* Install given module | ||
/* Find modules from file | ||
* Returns array of modules from a file | ||
*/ | ||
let installModule = ({name, dev}) => { | ||
let spinner = startSpinner('Installing ' + name, 'green'); | ||
if (secureMode && !isModulePopular(name)) { | ||
stopSpinner(spinner, name + ' not trusted', 'yellow'); | ||
return; | ||
} | ||
let getModulesFromFile = (path) => { | ||
let content = fs.readFileSync(path, 'utf8'); | ||
let modules = detective(content); | ||
modules = modules.filter((module) => isValidModule(module)); | ||
return modules; | ||
}; | ||
let command = 'npm install ' + name + ' --save'; | ||
let message = name + ' installed'; | ||
/* Is test file? | ||
* [.spec.js, .test.js] are supported test file formats | ||
*/ | ||
if (dev) command += '-dev'; | ||
if (dev) message += ' in devDependencies'; | ||
let isTestFile = (name) => (name.endsWith('.spec.js') || name.endsWith('.test.js')); | ||
let success = runCommand(command); | ||
if (success) stopSpinner(spinner, message, 'green'); | ||
else stopSpinner(spinner, name + ' installation failed', 'yellow'); | ||
/* Dedup similar modules | ||
* Deduplicates list | ||
* Ignores/assumes type of the modules in list | ||
*/ | ||
let deduplicateSimilarModules = (modules) => { | ||
let dedupedModules = []; | ||
let dedupedModuleNames = []; | ||
for (let module of modules) { | ||
if (dedupedModuleNames.indexOf(module.name) === -1) { | ||
dedupedModules.push(module); | ||
dedupedModuleNames.push(module.name); | ||
} | ||
} | ||
return dedupedModules; | ||
}; | ||
/* Uninstall module */ | ||
/* Dedup modules | ||
* Divide modules into prod and dev | ||
* Deduplicates each list | ||
*/ | ||
let uninstallModule = ({name, dev}) => { | ||
let spinner = startSpinner('Uninstalling ' + name, 'red'); | ||
let deduplicate = (modules) => { | ||
let dedupedModules = []; | ||
let command = 'npm uninstall ' + name + ' --save'; | ||
let message = name + ' removed'; | ||
let testModules = modules.filter(module => module.dev); | ||
dedupedModules = dedupedModules.concat(deduplicateSimilarModules(testModules)); | ||
if (dev) command += '-dev'; | ||
if (dev) message += ' from devDependencies'; | ||
let prodModules = modules.filter(module => !module.dev); | ||
dedupedModules = dedupedModules.concat(deduplicateSimilarModules(prodModules)); | ||
runCommand(command); | ||
stopSpinner(spinner, message, 'red'); | ||
return dedupedModules; | ||
}; | ||
/* Get used modules | ||
* Read all .js files and grep for modules | ||
*/ | ||
let getUsedModules = () => { | ||
let files = getFiles(); | ||
let usedModules = []; | ||
for (let fileName of files) { | ||
let modulesFromFile = getModulesFromFile(fileName); | ||
let dev = isTestFile(fileName); | ||
for (let name of modulesFromFile) usedModules.push({name, dev}); | ||
} | ||
usedModules = deduplicate(usedModules); | ||
return usedModules; | ||
}; | ||
/* Command runner | ||
@@ -92,2 +140,6 @@ * Run a given command | ||
let response = syncExec(command); | ||
if (response.stderr) { | ||
console.log(); | ||
console.log(response.stderr.red); | ||
} | ||
return !response.status; // status = 0 for success | ||
@@ -118,43 +170,48 @@ }; | ||
/* Get all js files | ||
* Return path of all js files | ||
*/ | ||
let getFiles = (path) => { | ||
return glob.sync("**/*.js", {'ignore': ['node_modules/**/*']}); | ||
}; | ||
/* Is module popular? - for secure mode */ | ||
/* File reader | ||
* Return contents of given file | ||
*/ | ||
let readFile = (path) => { | ||
let content = fs.readFileSync(path, 'utf8'); | ||
return content; | ||
const POPULARITY_THRESHOLD = 10000; | ||
let isModulePopular = (name) => { | ||
let url = `https://api.npmjs.org/downloads/point/last-month/${name}`; | ||
request('GET', url, (error, response, body) => { | ||
let downloads = JSON.parse(body).downloads; | ||
return (downloads > POPULARITY_THRESHOLD); | ||
}); | ||
}; | ||
/* Find modules from file | ||
* Returns array of modules from a file | ||
/* Install module | ||
* Install given module | ||
*/ | ||
let pattern = /require\((.*?)\)/g; | ||
let installModule = ({name, dev}) => { | ||
let spinner = startSpinner(`Installing ${name}`, 'green'); | ||
if (secureMode && !isModulePopular(name)) { | ||
stopSpinner(spinner, `${name} not trusted`, 'yellow'); | ||
return; | ||
} | ||
let getModulesFromFile = (path) => { | ||
let content = fs.readFileSync(path, 'utf8'); | ||
let modules = detective(content); | ||
modules = modules.filter((module) => isValidModule(module)); | ||
return modules; | ||
}; | ||
let command = `npm install ${name} --save`; | ||
let message = `${name} installed`; | ||
/* Check for valid string - to stop malicious intentions */ | ||
if (dev) command += '-dev'; | ||
if (dev) message += ' in devDependencies'; | ||
let isValidModule = ({name, dev}) => { | ||
let regex = new RegExp("^([a-z0-9-_]{1,})$"); | ||
return regex.test(name); | ||
let success = runCommand(command); | ||
if (success) stopSpinner(spinner, message, 'green'); | ||
else stopSpinner(spinner, `${name} installation failed`, 'yellow'); | ||
}; | ||
/* Filter registry modules */ | ||
/* Uninstall module */ | ||
let filterRegistryModules = (modules) => { | ||
modules = removeBuiltInModules(modules); | ||
modules = removeLocalFiles(modules); | ||
return modules; | ||
let uninstallModule = ({name, dev}) => { | ||
let spinner = startSpinner(`Uninstalling ${name}`, 'red'); | ||
let command = `npm uninstall ${name} --save`; | ||
let message = `${name} removed`; | ||
if (dev) command += '-dev'; | ||
if (dev) message += ' from devDependencies'; | ||
runCommand(command); | ||
stopSpinner(spinner, message, 'red'); | ||
}; | ||
@@ -164,18 +221,16 @@ | ||
let removeBuiltInModules = (modules) => { | ||
modules = modules.filter((module) => { | ||
return !isBuiltInModule(module.name); | ||
}); | ||
return modules; | ||
}; | ||
let removeBuiltInModules = (modules) => modules.filter((module) => !isBuiltInModule(module.name)); | ||
/* Remove local files that are required */ | ||
let removeLocalFiles = (modules) => { | ||
modules = modules.filter((module) => { | ||
return (module.name.indexOf('./') !== 0) | ||
}); | ||
return modules; | ||
}; | ||
let removeLocalFiles = (modules) => modules.filter((module) => (module.name.indexOf('./') !== 0)); | ||
/* Filter registry modules */ | ||
let filterRegistryModules = (modules) => removeBuiltInModules(removeLocalFiles(modules)); | ||
/* Get module names from array of module objects */ | ||
let getNamesFromModules = (modules) => modules.map(module => module.name); | ||
/* Modules diff */ | ||
@@ -196,66 +251,2 @@ | ||
/* Secure mode */ | ||
let secureMode = false; | ||
if (argv.secure) secureMode = true; | ||
/* Is module popular? - for secure mode */ | ||
const POPULARITY_THRESHOLD = 10000; | ||
let isModulePopular = (name) => { | ||
let url = 'https://api.npmjs.org/downloads/point/last-month/' + name; | ||
request('GET', url, (error, response, body) => { | ||
let downloads = JSON.parse(body).downloads; | ||
return (downloads > POPULARITY_THRESHOLD); | ||
}); | ||
}; | ||
/* Is test file? */ | ||
let isTestFile = (name) => { | ||
return (name.endsWith('.spec.js') || name.endsWith('.test.js')); | ||
}; | ||
/* Get module names from array of module objects */ | ||
let getNamesFromModules = (modules) => { | ||
return modules.map(module => module.name); | ||
}; | ||
/* Dedup modules | ||
* Divide modules into prod and dev | ||
* Deduplicates each list | ||
*/ | ||
let deduplicate = (modules) => { | ||
let dedupedModules = []; | ||
let testModules = modules.filter(module => module.dev); | ||
dedupedModules = dedupedModules.concat(deduplicateSimilarModules(testModules)); | ||
let prodModules = modules.filter(module => !module.dev); | ||
dedupedModules = dedupedModules.concat(deduplicateSimilarModules(prodModules)); | ||
return dedupedModules; | ||
}; | ||
/* Dedup similar modules | ||
* Deduplicates list | ||
* Ignores/assumes type of the modules in list | ||
*/ | ||
let deduplicateSimilarModules = (modules) => { | ||
let dedupedModules = []; | ||
let dedupedModuleNames = []; | ||
for (let module of modules) { | ||
if (dedupedModuleNames.indexOf(module.name) === -1) { | ||
dedupedModules.push(module); | ||
dedupedModuleNames.push(module.name); | ||
} | ||
} | ||
return dedupedModules; | ||
}; | ||
/* Public helper functions */ | ||
@@ -262,0 +253,0 @@ |
44
index.js
#!/usr/bin/env node | ||
'use strict'; | ||
const helpers = require('./helpers'); | ||
const chokidar = require('chokidar'); | ||
let watchersInitialized = false; | ||
let main; | ||
/* Watch files and repeat drill | ||
* Add a watcher, call main wrapper to repeat cycle | ||
*/ | ||
let initializeWatchers = () => { | ||
let watcher = chokidar.watch('**/*.js', { | ||
ignored: 'node_modules' | ||
}); | ||
watcher.on('change', main) | ||
.on('unlink', main); | ||
watchersInitialized = true; | ||
console.log('Watchers initialized'); | ||
}; | ||
/* Main wrapper | ||
@@ -16,3 +32,3 @@ * Get installed modules from package.json | ||
let main = () => { | ||
main = () => { | ||
let installedModules = []; | ||
@@ -24,7 +40,8 @@ installedModules = helpers.getInstalledModules(); | ||
//installModules | ||
// installModules | ||
let modulesNotInstalled = helpers.diff(usedModules, installedModules); | ||
for (let module of modulesNotInstalled) helpers.installModule(module); | ||
//removeUnusedModules | ||
// removeUnusedModules | ||
let unusedModules = helpers.diff(installedModules, usedModules); | ||
@@ -37,21 +54,4 @@ for (let module of unusedModules) helpers.uninstallModule(module); | ||
/* Watch files and repeat drill | ||
* Add a watcher, call main wrapper to repeat cycle | ||
*/ | ||
let watchersInitialized = false; | ||
let initializeWatchers = () => { | ||
let watcher = chokidar.watch('**/*.js', { | ||
ignored: 'node_modules' | ||
}); | ||
watcher.on('change', main) | ||
.on('unlink', main); | ||
watchersInitialized = true; | ||
console.log('Watchers initialized'); | ||
} | ||
/* Turn the key */ | ||
main(); | ||
{ | ||
"name": "auto-install", | ||
"version": "1.3.1", | ||
"version": "1.3.2", | ||
"description": "Auto installs dependencies as you code", | ||
@@ -20,2 +20,3 @@ "keywords": "auto, dependencies, install, package, watch", | ||
"chokidar": "1.6.0", | ||
"colors": "1.1.2", | ||
"detective": "4.3.1", | ||
@@ -22,0 +23,0 @@ "glob": "7.0.5", |
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
503962
8
250
10
1
+ Addedcolors@1.1.2
+ Addedcolors@1.1.2(transitive)