docs/api/file/src/component/npm/npm-module.js.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../../">
<title data-ice="title">src/component/npm/npm-module.js | REciNK - Rethink Continuous Integration for JavaScript Applications API Document</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
</head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<a data-ice="repoURL" href="https://github.com/MitocGroup/recink.git" class="repo-url-github">Repository</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
</header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/container.js~Container.html">Container</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/emitter.js~Emitter.html">Emitter</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/logger.js~Logger.html">Logger</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/recink.js~Recink.html">Recink</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-variable">V</span><span data-ice="name"><span><a href="variable/index.html#static-variable-events">events</a></span></span></li>
<li data-ice="doc"><div data-ice="dirPath" class="nav-dir-path">component</div><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/abstract-component.js~AbstractComponent.html">AbstractComponent</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/cache-component.js~CacheComponent.html">CacheComponent</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/config-based-component.js~ConfigBasedComponent.html">ConfigBasedComponent</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/coverage-component.js~CoverageComponent.html">CoverageComponent</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/dependency-based-component.js~DependencyBasedComponent.html">DependencyBasedComponent</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/emit-component.js~EmitComponent.html">EmitComponent</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/factory.js~Factory.html">Factory</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/npm-component.js~NpmComponent.html">NpmComponent</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/preprocess-component.js~PreprocessComponent.html">PreprocessComponent</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/test-component.js~TestComponent.html">TestComponent</a></span></span></li>
<li data-ice="doc"><div data-ice="dirPath" class="nav-dir-path">component/cache</div><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/cache/abstract-driver.js~AbstractDriver.html">AbstractDriver</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/cache/factory.js~Factory.html">Factory</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/cache/s3-driver.js~S3Driver.html">S3Driver</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/cache/s3-unpacked-driver.js~S3UnpackedDriver.html">S3UnpackedDriver</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/cache/void-driver.js~VoidDriver.html">VoidDriver</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-variable">V</span><span data-ice="name"><span><a href="variable/index.html#static-variable-events">events</a></span></span></li>
<li data-ice="doc"><div data-ice="dirPath" class="nav-dir-path">component/coverage</div><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/coverage/abstract-driver.js~AbstractDriver.html">AbstractDriver</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/coverage/factory.js~Factory.html">Factory</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/coverage/s3-driver.js~S3Driver.html">S3Driver</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/coverage/volatile-driver.js~VolatileDriver.html">VolatileDriver</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-variable">V</span><span data-ice="name"><span><a href="variable/index.html#static-variable-events">events</a></span></span></li>
<li data-ice="doc"><div data-ice="dirPath" class="nav-dir-path">component/emit</div><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/emit/emit-module.js~EmitModule.html">EmitModule</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-variable">V</span><span data-ice="name"><span><a href="variable/index.html#static-variable-events">events</a></span></span></li>
<li data-ice="doc"><div data-ice="dirPath" class="nav-dir-path">component/helper</div><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/helper/aws-credentials.js~AwsCredentials.html">AwsCredentials</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/helper/container-transformer.js~ContainerTransformer.html">ContainerTransformer</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/helper/module-compile.js~ModuleCompile.html">ModuleCompile</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/helper/sequential-promise.js~SequentialPromise.html">SequentialPromise</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/helper/spinner.js~Spinner.html">Spinner</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/helper/transformer.js~Transformer.html">Transformer</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-patterntransformer">patterntransformer</a></span></span></li>
<li data-ice="doc"><div data-ice="dirPath" class="nav-dir-path">component/npm</div><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/npm/cache.js~Cache.html">Cache</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/npm/npm-module.js~NpmModule.html">NpmModule</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-variable">V</span><span data-ice="name"><span><a href="variable/index.html#static-variable-events">events</a></span></span></li>
<li data-ice="doc"><div data-ice="dirPath" class="nav-dir-path">component/preprocess</div><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/preprocess/abstract-transformer.js~AbstractTransformer.html">AbstractTransformer</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/preprocess/eval-transformer.js~EvalTransformer.html">EvalTransformer</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/preprocess/factory.js~Factory.html">Factory</a></span></span></li>
<li data-ice="doc"><div data-ice="dirPath" class="nav-dir-path">component/test</div><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/component/test/unit-runner.js~UnitRunner.html">UnitRunner</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-variable">V</span><span data-ice="name"><span><a href="variable/index.html#static-variable-events">events</a></span></span></li>
<li data-ice="doc"><div data-ice="dirPath" class="nav-dir-path">config</div><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/config/abstract-config.js~AbstractConfig.html">AbstractConfig</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/config/factory.js~Factory.html">Factory</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/config/yaml-config.js~YamlConfig.html">YamlConfig</a></span></span></li>
<li data-ice="doc"><div data-ice="dirPath" class="nav-dir-path">helper</div><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/helper/env.js~Env.html">Env</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-fillString">fillString</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-findFilesByPattern">findFilesByPattern</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-trimBoth">trimBoth</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-versionCompare">versionCompare</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><h1 data-ice="title">src/component/npm/npm-module.js</h1>
<pre class="source-code line-number raw-source-code"><code class="prettyprint linenums" data-ice="content">'use strict';
const packageHash = require('package-hash');
const path = require('path');
const fse = require('fs-extra');
const Spinner = require('../helper/spinner');
const { spawn } = require('child_process');
const md5Hex = require('md5-hex');
const SequentialPromise = require('../helper/sequential-promise');
/**
* Abstraction over an NPM module
*/
class NpmModule {
/**
* @param {string} rootDir
* @param {Cache} cache
* @param {*} logger
*/
constructor(rootDir, cache, logger) {
this._rootDir = rootDir;
this._cache = cache;
this._logger = logger;
}
/**
* @returns {*}
*/
get logger() {
return this._logger;
}
/**
* @returns {string}
*/
get rootDir() {
return this._rootDir;
}
/**
* @param {Cache} cache
*/
get cache() {
return this._cache;
}
/**
* @returns {string}
*/
get packageFileRelative() {
return path.relative(process.cwd(), this.packageFile);
}
/**
* @returns {string}
*/
get packageFile() {
return path.join(this.rootDir, NpmModule.PACKAGE_FILE);
}
/**
* @returns {string}
*/
get modulesDir() {
return path.join(this.rootDir, NpmModule.MODULES_DIR);
}
/**
* @returns {string}
*/
get debugFile() {
return path.join(this.rootDir, NpmModule.NPM_DEBUG_FILE);
}
/**
* @param {*} deps
* @param {array} scripts
*
* @returns {Promise}
*/
install(deps = {}, scripts = []) {
let cacheKey;
const packageFile = this.packageFile;
const modulesDir = this.modulesDir;
return fse.ensureDir(modulesDir)
.then(() => this._packageHash(packageFile, deps))
.then(hash => {
cacheKey = hash;
return this.cache.has(hash);
})
.then(inCache => {
if (inCache) {
this.logger.debug(`Restore ${ this.rootDir } cache from #${ cacheKey }`);
return this.cache.restore(cacheKey, modulesDir)
.then(() => this._runScripts(scripts));
}
this.logger.debug(`Install dependencies in ${ this.rootDir }`);
return this._install(packageFile, deps)
.then(() => this._runScripts(scripts))
.then(() => {
this.logger.debug(`Save ${ this.rootDir } cache to #${ cacheKey }`);
return this.cache.flush()
.then(() => this.cache.save(cacheKey, modulesDir));
});
});
}
/**
* @param {array} scripts
*
* @returns {Promise}
*
* @private
*/
_runScripts(scripts) {
if (scripts.length <= 0) {
return Promise.resolve();
}
return SequentialPromise.all(scripts.map(script => {
return () => this._runScript(script);
}));
}
/**
* @param {string} script
*
* @returns {Promise}
*
* @private
*/
_runScript(script) {
return (new Spinner(
`Running ${ script } script in ${ this.rootDir }`
)).then(
`Script ${ script } execution succeed in ${ this.rootDir }`
).catch(
`Script ${ script } execution failed in ${ this.rootDir }`
).promise(new Promise((resolve, reject) => {
const options = {
cwd: this.rootDir,
stdio: 'ignore',
};
const npmRunScript = spawn('npm', [ 'run', script ], options);
npmRunScript.on('close', code => {
if (code !== 0) {
return reject(new Error(
`Failed to run script ${ script } in ${ this.rootDir }.\n` +
`To open logs type: 'open ${ this.debugFile }'`
));
}
resolve();
});
}));
}
/**
* @param {string} packageFile
* @param {*} additionalDeps
*
* @returns {Promise}
*
* @private
*/
_install(packageFile, additionalDeps) {
return fse.pathExists(packageFile)
.then(hasPackageFile => {
return hasPackageFile ? this._doInstall() : Promise.resolve();
})
.then(() => {
const depsVector = Object.keys(additionalDeps)
.map(depName => {
return `${ depName }@${ additionalDeps[depName] }`;
});
return depsVector.length > 0
? this._doInstall(depsVector)
: Promise.resolve();
});
}
/**
* @param {string} depsDebug
*
* @returns {string}
*
* @private
*/
_trimDepsDebugInfo(depsDebug) {
if (depsDebug.length > 25) {
return depsDebug.substr(0, 25) + '...';
}
return depsDebug;
}
/**
* @param {array} deps
*
* @returns {Promise}
*
* @private
*/
_doInstall(deps = []) {
const depsDebug = this._trimDepsDebugInfo(deps.length > 0 ? deps.join(', ') : 'MAIN');
return (new Spinner(
`Installing dependencies in ${ this.rootDir } (${ depsDebug })`
)).then(
`Dependencies installation succeed in ${ this.rootDir } (${ depsDebug })`
).catch(
`Dependencies installation failed in ${ this.rootDir } (${ depsDebug })`
).promise(new Promise((resolve, reject) => {
const options = {
cwd: this.rootDir,
stdio: 'ignore',
};
// ignore running 'npm install' scripts
if (deps.length <= 0) {
deps = [ '--ignore-scripts' ];
}
const npmInstall = spawn('npm', [ 'install', '--no-shrinkwrap' ].concat(deps), options);
npmInstall.on('close', code => {
if (code !== 0) {
return reject(new Error(
`Failed to install dependencies in ${ this.rootDir }.\n` +
`To open logs type: 'open ${ this.debugFile }'`
));
}
resolve();
});
}));
}
/**
* @param {string} packageFile
* @param {*} deps
*
* @returns {Promise}
*
* @private
*/
_packageHash(packageFile, deps) {
return fse.pathExists(packageFile)
.then(hasPackageFile => {
const depsHash = this._depsHash(deps);
const packageDebug = hasPackageFile ? 'exists' : 'missing';
this.logger.debug(
`File ${ NpmModule.PACKAGE_FILE } ${ packageDebug } in ${ this.rootDir }`
);
if (!hasPackageFile) {
return Promise.resolve(`${ depsHash }-${ NpmModule.DEFAULT_HASH }`);
}
return packageHash(packageFile)
.then(hash => {
return Promise.resolve(`${ depsHash }-${ hash }`);
});
});
}
/**
* @param {*} deps
*
* @returns {string}
*
* @private
*/
_depsHash(deps) {
const normalizedDeps = {};
Object.keys(deps).sort().map(key => {
normalizedDeps[key] = deps[key];
});
return md5Hex(JSON.stringify(normalizedDeps));
}
/**
* @returns {string}
*/
static get DEFAULT_HASH() {
return 'x'.repeat(32);
}
/**
* @returns {string}
*/
static get NPM_DEBUG_FILE() {
return 'npm-debug.log';
}
/**
* @returns {string}
*/
static get PACKAGE_FILE() {
return 'package.json';
}
/**
* @returns {string}
*/
static get MODULES_DIR() {
return 'node_modules';
}
}
module.exports = NpmModule;
</code></pre>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(0.5.2)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>