/home/lnzliplg/public_html/libcipm.tar
index.js 0000644 00000033656 15173127725 0006240 0 ustar 00 'use strict'
const BB = require('bluebird')
const binLink = require('bin-links')
const buildLogicalTree = require('npm-logical-tree')
const extract = require('./lib/extract.js')
const figgyPudding = require('figgy-pudding')
const fs = require('graceful-fs')
const getPrefix = require('find-npm-prefix')
const lifecycle = require('npm-lifecycle')
const lockVerify = require('lock-verify')
const mkdirp = BB.promisify(require('mkdirp'))
const npa = require('npm-package-arg')
const path = require('path')
const readPkgJson = BB.promisify(require('read-package-json'))
const rimraf = BB.promisify(require('rimraf'))
const readFileAsync = BB.promisify(fs.readFile)
const statAsync = BB.promisify(fs.stat)
const symlinkAsync = BB.promisify(fs.symlink)
const writeFileAsync = BB.promisify(fs.writeFile)
const LifecycleOpts = figgyPudding({
config: {},
'script-shell': {},
scriptShell: 'script-shell',
'ignore-scripts': {},
ignoreScripts: 'ignore-scripts',
'ignore-prepublish': {},
ignorePrepublish: 'ignore-prepublish',
'scripts-prepend-node-path': {},
scriptsPrependNodePath: 'scripts-prepend-node-path',
'unsafe-perm': {},
unsafePerm: 'unsafe-perm',
prefix: {},
dir: 'prefix',
failOk: { default: false }
}, { other () { return true } })
class Installer {
constructor (opts) {
this.opts = opts
// Stats
this.startTime = Date.now()
this.runTime = 0
this.timings = { scripts: 0 }
this.pkgCount = 0
// Misc
this.log = this.opts.log || require('./lib/silentlog.js')
this.pkg = null
this.tree = null
this.failedDeps = new Set()
}
timedStage (name) {
const start = Date.now()
return BB.resolve(this[name].apply(this, [].slice.call(arguments, 1)))
.tap(() => {
this.timings[name] = Date.now() - start
this.log.info(name, `Done in ${this.timings[name] / 1000}s`)
})
}
run () {
return this.timedStage('prepare')
.then(() => this.timedStage('extractTree', this.tree))
.then(() => this.timedStage('updateJson', this.tree))
.then(pkgJsons => this.timedStage('buildTree', this.tree, pkgJsons))
.then(() => this.timedStage('garbageCollect', this.tree))
.then(() => this.timedStage('runScript', 'prepublish', this.pkg, this.prefix))
.then(() => this.timedStage('runScript', 'prepare', this.pkg, this.prefix))
.then(() => this.timedStage('teardown'))
.then(() => {
this.runTime = Date.now() - this.startTime
this.log.info(
'run-scripts',
`total script time: ${this.timings.scripts / 1000}s`
)
this.log.info(
'run-time',
`total run time: ${this.runTime / 1000}s`
)
})
.catch(err => {
this.timedStage('teardown')
if (err.message.match(/aggregate error/)) {
throw err[0]
} else {
throw err
}
})
.then(() => this)
}
prepare () {
this.log.info('prepare', 'initializing installer')
this.log.level = this.opts.loglevel
this.log.verbose('prepare', 'starting workers')
extract.startWorkers()
return (
this.opts.prefix && this.opts.global
? BB.resolve(this.opts.prefix)
// There's some Specialâ„¢ logic around the `--prefix` config when it
// comes from a config file or env vs when it comes from the CLI
: process.argv.some(arg => arg.match(/^\s*--prefix\s*/i))
? BB.resolve(this.opts.prefix)
: getPrefix(process.cwd())
)
.then(prefix => {
this.prefix = prefix
this.log.verbose('prepare', 'installation prefix: ' + prefix)
return BB.join(
readJson(prefix, 'package.json'),
readJson(prefix, 'package-lock.json', true),
readJson(prefix, 'npm-shrinkwrap.json', true),
(pkg, lock, shrink) => {
if (shrink) {
this.log.verbose('prepare', 'using npm-shrinkwrap.json')
} else if (lock) {
this.log.verbose('prepare', 'using package-lock.json')
}
pkg._shrinkwrap = shrink || lock
this.pkg = pkg
}
)
})
.then(() => statAsync(
path.join(this.prefix, 'node_modules')
).catch(err => { if (err.code !== 'ENOENT') { throw err } }))
.then(stat => {
stat && this.log.warn(
'prepare', 'removing existing node_modules/ before installation'
)
return BB.join(
this.checkLock(),
stat && rimraf(path.join(this.prefix, 'node_modules/*'))
)
}).then(() => {
// This needs to happen -after- we've done checkLock()
this.tree = buildLogicalTree(this.pkg, this.pkg._shrinkwrap)
this.log.silly('tree', this.tree)
this.expectedTotal = 0
this.tree.forEach((dep, next) => {
this.expectedTotal++
next()
})
})
}
teardown () {
this.log.verbose('teardown', 'shutting down workers.')
return extract.stopWorkers()
}
checkLock () {
this.log.verbose('checkLock', 'verifying package-lock data')
const pkg = this.pkg
const prefix = this.prefix
if (!pkg._shrinkwrap || !pkg._shrinkwrap.lockfileVersion) {
return BB.reject(
new Error(`cipm can only install packages with an existing package-lock.json or npm-shrinkwrap.json with lockfileVersion >= 1. Run an install with npm@5 or later to generate it, then try again.`)
)
}
return lockVerify(prefix).then(result => {
if (result.status) {
result.warnings.forEach(w => this.log.warn('lockfile', w))
} else {
throw new Error(
'cipm can only install packages when your package.json and package-lock.json or ' +
'npm-shrinkwrap.json are in sync. Please update your lock file with `npm install` ' +
'before continuing.\n\n' +
result.warnings.map(w => 'Warning: ' + w).join('\n') + '\n' +
result.errors.join('\n') + '\n'
)
}
}).catch(err => {
throw err
})
}
extractTree (tree) {
this.log.verbose('extractTree', 'extracting dependencies to node_modules/')
const cg = this.log.newItem('extractTree', this.expectedTotal)
return tree.forEachAsync((dep, next) => {
if (!this.checkDepEnv(dep)) { return }
const depPath = dep.path(this.prefix)
const spec = npa.resolve(dep.name, dep.version, this.prefix)
if (dep.isRoot) {
return next()
} else if (spec.type === 'directory') {
const relative = path.relative(path.dirname(depPath), spec.fetchSpec)
this.log.silly('extractTree', `${dep.name}@${spec.fetchSpec} -> ${depPath} (symlink)`)
return mkdirp(path.dirname(depPath))
.then(() => symlinkAsync(relative, depPath, 'junction'))
.catch(
() => rimraf(depPath)
.then(() => symlinkAsync(relative, depPath, 'junction'))
).then(() => next())
.then(() => {
this.pkgCount++
cg.completeWork(1)
})
} else {
this.log.silly('extractTree', `${dep.name}@${dep.version} -> ${depPath}`)
return (
dep.bundled
? statAsync(path.join(depPath, 'package.json')).catch(err => {
if (err.code !== 'ENOENT') { throw err }
})
: BB.resolve(false)
)
.then(wasBundled => {
// Don't extract if a bundled dep is actually present
if (wasBundled) {
cg.completeWork(1)
return next()
} else {
return BB.resolve(extract.child(
dep.name, dep, depPath, this.opts
))
.then(() => cg.completeWork(1))
.then(() => { this.pkgCount++ })
.then(next)
}
})
}
}, {concurrency: 50, Promise: BB})
.then(() => cg.finish())
}
checkDepEnv (dep) {
const includeDev = (
// Covers --dev and --development (from npm config itself)
this.opts.dev ||
(
!/^prod(uction)?$/.test(this.opts.only) &&
!this.opts.production
) ||
/^dev(elopment)?$/.test(this.opts.only) ||
/^dev(elopment)?$/.test(this.opts.also)
)
const includeProd = !/^dev(elopment)?$/.test(this.opts.only)
const includeOptional = includeProd && this.opts.optional
return (dep.dev && includeDev) ||
(dep.optional && includeOptional) ||
(!dep.dev && !dep.optional && includeProd)
}
updateJson (tree) {
this.log.verbose('updateJson', 'updating json deps to include _from')
const pkgJsons = new Map()
return tree.forEachAsync((dep, next) => {
if (!this.checkDepEnv(dep)) { return }
const spec = npa.resolve(dep.name, dep.version)
const depPath = dep.path(this.prefix)
return next()
.then(() => readJson(depPath, 'package.json'))
.then(pkg => (spec.registry || spec.type === 'directory')
? pkg
: this.updateFromField(dep, pkg).then(() => pkg)
)
.then(pkg => (pkg.scripts && pkg.scripts.install)
? pkg
: this.updateInstallScript(dep, pkg).then(() => pkg)
)
.tap(pkg => { pkgJsons.set(dep, pkg) })
}, {concurrency: 100, Promise: BB})
.then(() => pkgJsons)
}
buildTree (tree, pkgJsons) {
this.log.verbose('buildTree', 'finalizing tree and running scripts')
return tree.forEachAsync((dep, next) => {
if (!this.checkDepEnv(dep)) { return }
const spec = npa.resolve(dep.name, dep.version)
const depPath = dep.path(this.prefix)
const pkg = pkgJsons.get(dep)
this.log.silly('buildTree', `linking ${spec}`)
return this.runScript('preinstall', pkg, depPath)
.then(next) // build children between preinstall and binLink
// Don't link root bins
.then(() => {
if (
dep.isRoot ||
!(pkg.bin || pkg.man || (pkg.directories && pkg.directories.bin))
) {
// We skip the relatively expensive readPkgJson if there's no way
// we'll actually be linking any bins or mans
return
}
return readPkgJson(path.join(depPath, 'package.json'))
.then(pkg => binLink(pkg, depPath, false, {
force: this.opts.force,
ignoreScripts: this.opts['ignore-scripts'],
log: Object.assign({}, this.log, { info: () => {} }),
name: pkg.name,
pkgId: pkg.name + '@' + pkg.version,
prefix: this.prefix,
prefixes: [this.prefix],
umask: this.opts.umask
}), e => {
this.log.verbose('buildTree', `error linking ${spec}: ${e.message} ${e.stack}`)
})
})
.then(() => this.runScript('install', pkg, depPath))
.then(() => this.runScript('postinstall', pkg, depPath))
.then(() => this)
.catch(e => {
if (dep.optional) {
this.failedDeps.add(dep)
} else {
throw e
}
})
}, {concurrency: 1, Promise: BB})
}
updateFromField (dep, pkg) {
const depPath = dep.path(this.prefix)
const depPkgPath = path.join(depPath, 'package.json')
const parent = dep.requiredBy.values().next().value
return readJson(parent.path(this.prefix), 'package.json')
.then(ppkg =>
(ppkg.dependencies && ppkg.dependencies[dep.name]) ||
(ppkg.devDependencies && ppkg.devDependencies[dep.name]) ||
(ppkg.optionalDependencies && ppkg.optionalDependencies[dep.name])
)
.then(from => npa.resolve(dep.name, from))
.then(from => { pkg._from = from.toString() })
.then(() => writeFileAsync(depPkgPath, JSON.stringify(pkg, null, 2)))
.then(() => pkg)
}
updateInstallScript (dep, pkg) {
const depPath = dep.path(this.prefix)
return statAsync(path.join(depPath, 'binding.gyp'))
.catch(err => { if (err.code !== 'ENOENT') { throw err } })
.then(stat => {
if (stat) {
if (!pkg.scripts) {
pkg.scripts = {}
}
pkg.scripts.install = 'node-gyp rebuild'
}
})
.then(() => pkg)
}
// A cute little mark-and-sweep collector!
garbageCollect (tree) {
if (!this.failedDeps.size) { return }
return sweep(
tree,
this.prefix,
mark(tree, this.failedDeps)
)
.then(purged => {
this.purgedDeps = purged
this.pkgCount -= purged.size
})
}
runScript (stage, pkg, pkgPath) {
const start = Date.now()
if (!this.opts['ignore-scripts']) {
// TODO(mikesherov): remove pkg._id when npm-lifecycle no longer relies on it
pkg._id = pkg.name + '@' + pkg.version
return BB.resolve(lifecycle(
pkg, stage, pkgPath, LifecycleOpts(this.opts).concat({
// TODO: can be removed once npm-lifecycle is updated to modern
// config practices.
config: Object.assign({}, this.opts, {
log: null,
dirPacker: null
}),
dir: this.prefix
}))
).tap(() => { this.timings.scripts += Date.now() - start })
}
return BB.resolve()
}
}
module.exports = Installer
function mark (tree, failed) {
const liveDeps = new Set()
tree.forEach((dep, next) => {
if (!failed.has(dep)) {
liveDeps.add(dep)
next()
}
})
return liveDeps
}
function sweep (tree, prefix, liveDeps) {
const purged = new Set()
return tree.forEachAsync((dep, next) => {
return next().then(() => {
if (
!dep.isRoot && // never purge root! 🙈
!liveDeps.has(dep) &&
!purged.has(dep)
) {
purged.add(dep)
return rimraf(dep.path(prefix))
}
})
}, {concurrency: 50, Promise: BB}).then(() => purged)
}
function stripBOM (str) {
return str.replace(/^\uFEFF/, '')
}
module.exports._readJson = readJson
function readJson (jsonPath, name, ignoreMissing) {
return readFileAsync(path.join(jsonPath, name), 'utf8')
.then(str => JSON.parse(stripBOM(str)))
.catch({code: 'ENOENT'}, err => {
if (!ignoreMissing) {
throw err
}
})
}
README.md 0000644 00000001673 15173127725 0006044 0 ustar 00 # Note: pending imminent deprecation
**This module will be deprecated once npm v7 is released. Please do not rely
on it more than absolutely necessary.**
----
[`libcipm`](https://github.com/npm/libcipm) installs npm projects in a way that's
optimized for continuous integration/deployment/etc scenarios. It gives up
the ability to build its own trees or install packages individually, as well
as other user-oriented features, in exchange for speed, and being more strict
about project state.
For documentation about the associated command-line tool, see
[`cipm`](https://npm.im/cipm).
## Install
`$ npm install libcipm`
## Table of Contents
* [Features](#features)
* [API](#api)
### Features
* npm-compatible project installation
* lifecycle script support
* blazing fast
* npm-compatible caching
* errors if `package.json` and `package-lock.json` are out of sync, instead of fixing it like npm does. Essentially provides a `--frozen` install.
CHANGELOG.md 0000644 00000033620 15173127725 0006373 0 ustar 00 # Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="4.0.8"></a>
## [4.0.8](https://github.com/npm/libcipm/compare/v4.0.7...v4.0.8) (2020-03-25)
### Bug Fixes
* add repo to bin pkg, bump to 2.0.1 ([ed2d735](https://github.com/npm/libcipm/commit/ed2d735))
<a name="4.0.7"></a>
## [4.0.7](https://github.com/npm/libcipm/compare/v4.0.4...v4.0.7) (2019-10-09)
### Bug Fixes
* delete node_modules contents but keep the dir itself ([f668181](https://github.com/npm/libcipm/commit/f668181)), closes [#3](https://github.com/npm/libcipm/issues/3)
<a name="4.0.4"></a>
## [4.0.4](https://github.com/npm/libcipm/compare/v4.0.3...v4.0.4) (2019-09-24)
### Bug Fixes
* pack git directories properly ([576ab36](https://github.com/npm/libcipm/commit/576ab36)), closes [#4](https://github.com/npm/libcipm/issues/4)
<a name="4.0.3"></a>
## [4.0.3](https://github.com/npm/libcipm/compare/v4.0.2...v4.0.3) (2019-08-12)
### Bug Fixes
* do not pass opts.log to lifecycle ([46b2101](https://github.com/npm/libcipm/commit/46b2101))
<a name="4.0.2"></a>
## [4.0.2](https://github.com/npm/libcipm/compare/v4.0.1...v4.0.2) (2019-08-12)
<a name="4.0.1"></a>
## [4.0.1](https://github.com/npm/libcipm/compare/v4.0.0...v4.0.1) (2019-08-12)
### Bug Fixes
* respect and retain all configs passed in ([20b7372](https://github.com/npm/libcipm/commit/20b7372))
<a name="4.0.0"></a>
# [4.0.0](https://github.com/npm/libcipm/compare/v3.0.3...v4.0.0) (2019-07-10)
* npm-lifecycle@3.0.0 ([84b8d7e](https://github.com/npm/libcipm/commit/84b8d7e))
### Bug Fixes
* **lifecycle:** remove warning from bluebird ([#59](https://github.com/npm/libcipm/issues/59)) ([7af39e6](https://github.com/npm/libcipm/commit/7af39e6)), closes [#58](https://github.com/npm/libcipm/issues/58)
### BREAKING CHANGES
* requires updating node-gyp in npm/cli
<a name="3.0.3"></a>
## [3.0.3](https://github.com/npm/libcipm/compare/v3.0.2...v3.0.3) (2019-01-22)
### Bug Fixes
* **scripts:** pass in opts.dir directly ([018df27](https://github.com/npm/libcipm/commit/018df27))
<a name="3.0.2"></a>
## [3.0.2](https://github.com/npm/libcipm/compare/v3.0.1...v3.0.2) (2018-08-31)
### Bug Fixes
* **worker:** missed a spot ([4371558](https://github.com/npm/libcipm/commit/4371558))
<a name="3.0.1"></a>
## [3.0.1](https://github.com/npm/libcipm/compare/v3.0.0...v3.0.1) (2018-08-31)
### Bug Fixes
* **workers:** disable workers for now ([64db490](https://github.com/npm/libcipm/commit/64db490))
<a name="3.0.0"></a>
# [3.0.0](https://github.com/npm/libcipm/compare/v2.0.2...v3.0.0) (2018-08-31)
### Features
* **config:** switch to modern, figgy-pudding configuration ([#57](https://github.com/npm/libcipm/issues/57)) ([161f6b2](https://github.com/npm/libcipm/commit/161f6b2))
### BREAKING CHANGES
* **config:** this updates cipm to use pacote@9, which consumes npm-style config objects, not pacoteOpts()-style objects.
<a name="2.0.2"></a>
## [2.0.2](https://github.com/npm/libcipm/compare/v2.0.1...v2.0.2) (2018-08-10)
### Bug Fixes
* **child:** only override dirPacker if opts.dirPacker is defined ([#55](https://github.com/npm/libcipm/issues/55)) ([13ab2f0](https://github.com/npm/libcipm/commit/13ab2f0))
<a name="2.0.1"></a>
## [2.0.1](https://github.com/npm/libcipm/compare/v2.0.0...v2.0.1) (2018-07-27)
### Bug Fixes
* **deps:** move mkdirp to prod deps ([6878f39](https://github.com/npm/libcipm/commit/6878f39))
<a name="2.0.0"></a>
# [2.0.0](https://github.com/npm/libcipm/compare/v1.6.3...v2.0.0) (2018-05-24)
### meta
* update node version support ([694b4d3](https://github.com/npm/libcipm/commit/694b4d3))
### BREAKING CHANGES
* node@4 is no longer supported
<a name="1.6.3"></a>
## [1.6.3](https://github.com/npm/libcipm/compare/v1.6.2...v1.6.3) (2018-05-24)
<a name="1.6.2"></a>
## [1.6.2](https://github.com/npm/libcipm/compare/v1.6.1...v1.6.2) (2018-04-08)
### Bug Fixes
* **lifecycle:** detect binding.gyp for default install lifecycle ([#46](https://github.com/npm/libcipm/issues/46)) ([9149631](https://github.com/npm/libcipm/commit/9149631)), closes [#45](https://github.com/npm/libcipm/issues/45)
<a name="1.6.1"></a>
## [1.6.1](https://github.com/npm/libcipm/compare/v1.6.0...v1.6.1) (2018-03-13)
### Bug Fixes
* **bin:** Set non-zero exit code on error ([#41](https://github.com/npm/libcipm/issues/41)) ([54d0106](https://github.com/npm/libcipm/commit/54d0106))
* **lifecycle:** defer to lifecycle’s internal logic as to whether or not to execute a run-script ([#42](https://github.com/npm/libcipm/issues/42)) ([7f27a52](https://github.com/npm/libcipm/commit/7f27a52)), closes [npm/npm#19258](https://github.com/npm/npm/issues/19258)
* **prefix:** don't reference prefix before computing it ([#40](https://github.com/npm/libcipm/issues/40)) ([08ed1cc](https://github.com/npm/libcipm/commit/08ed1cc))
* **prefix:** Resolve to promise when passing --prefix to npm ci ([#43](https://github.com/npm/libcipm/issues/43)) ([401d466](https://github.com/npm/libcipm/commit/401d466))
<a name="1.6.0"></a>
# [1.6.0](https://github.com/npm/libcipm/compare/v1.5.1...v1.6.0) (2018-03-01)
### Bug Fixes
* **bin:** cli.js was being excluded ([d62668e](https://github.com/npm/libcipm/commit/d62668e))
### Features
* **libcipm:** working standalone cipm release! ([a3383fd](https://github.com/npm/libcipm/commit/a3383fd))
<a name="1.5.1"></a>
## [1.5.1](https://github.com/npm/libcipm/compare/v1.5.0...v1.5.1) (2018-03-01)
### Bug Fixes
* **_from:** do not add _from to directory deps ([7405360](https://github.com/npm/libcipm/commit/7405360))
<a name="1.5.0"></a>
# [1.5.0](https://github.com/npm/libcipm/compare/v1.4.1...v1.5.0) (2018-03-01)
### Bug Fixes
* **errors:** handle aggregate errors better ([6239499](https://github.com/npm/libcipm/commit/6239499))
### Features
* **logger:** rudimentary progress bar update ([c5d9dc7](https://github.com/npm/libcipm/commit/c5d9dc7))
<a name="1.4.1"></a>
## [1.4.1](https://github.com/npm/libcipm/compare/v1.4.0...v1.4.1) (2018-02-27)
### Bug Fixes
* **buildTree:** linking in parallel causes hoist-clobbering ([5ffbc0e](https://github.com/npm/libcipm/commit/5ffbc0e)), closes [#39](https://github.com/npm/libcipm/issues/39)
* **buildTree:** use checkDepEnv here too ([41a4634](https://github.com/npm/libcipm/commit/41a4634))
* **perf:** split up updateJson and buildTree ([df5aba0](https://github.com/npm/libcipm/commit/df5aba0))
* **perf:** stop using the readPackageJson version to update packages ([8da3d5a](https://github.com/npm/libcipm/commit/8da3d5a))
<a name="1.4.0"></a>
# [1.4.0](https://github.com/npm/libcipm/compare/v1.3.3...v1.4.0) (2018-02-21)
### Features
* **extract:** add support for --only and --also ([ad143ae](https://github.com/npm/libcipm/commit/ad143ae))
<a name="1.3.3"></a>
## [1.3.3](https://github.com/npm/libcipm/compare/v1.3.2...v1.3.3) (2018-02-21)
### Bug Fixes
* **extract:** stop extracting deps before parent :\ ([c6847dc](https://github.com/npm/libcipm/commit/c6847dc))
<a name="1.3.2"></a>
## [1.3.2](https://github.com/npm/libcipm/compare/v1.3.1...v1.3.2) (2018-02-15)
<a name="1.3.1"></a>
## [1.3.1](https://github.com/npm/libcipm/compare/v1.3.0...v1.3.1) (2018-02-15)
<a name="1.3.0"></a>
# [1.3.0](https://github.com/npm/libcipm/compare/v1.2.0...v1.3.0) (2018-02-13)
### Features
* **extract:** link directory deps and install missing bundle deps ([8334e9e](https://github.com/npm/libcipm/commit/8334e9e))
<a name="1.2.0"></a>
# [1.2.0](https://github.com/npm/libcipm/compare/v1.1.2...v1.2.0) (2018-02-07)
### Features
* **metadata:** add _resolved, _integrity, and _from on install ([36642dc](https://github.com/npm/libcipm/commit/36642dc))
<a name="1.1.2"></a>
## [1.1.2](https://github.com/npm/libcipm/compare/v1.1.1...v1.1.2) (2018-01-19)
<a name="1.1.1"></a>
## [1.1.1](https://github.com/npm/libcipm/compare/v1.1.0...v1.1.1) (2018-01-19)
<a name="1.1.0"></a>
# [1.1.0](https://github.com/npm/libcipm/compare/v1.0.1...v1.1.0) (2018-01-07)
### Features
* **log:** add some helpful log output ([f443f03](https://github.com/npm/libcipm/commit/f443f03))
<a name="1.0.1"></a>
## [1.0.1](https://github.com/npm/libcipm/compare/v1.0.0...v1.0.1) (2018-01-07)
### Bug Fixes
* **deps:** added protoduck to pkgjson ([ecbe719](https://github.com/npm/libcipm/commit/ecbe719))
<a name="1.0.0"></a>
# [1.0.0](https://github.com/npm/libcipm/compare/v0.9.1...v1.0.0) (2018-01-07)
### Features
* **cli:** splitting off CLI into a separate tool ([cff65c1](https://github.com/npm/libcipm/commit/cff65c1))
### BREAKING CHANGES
* **cli:** libcipm is its own library now,
<a name="0.9.1"></a>
## [0.9.1](https://github.com/npm/libcipm/compare/v0.9.0...v0.9.1) (2018-01-07)
### Bug Fixes
* **prefix:** oops @ prefix ([cc5adac](https://github.com/npm/libcipm/commit/cc5adac))
<a name="0.9.0"></a>
# [0.9.0](https://github.com/npm/libcipm/compare/v0.8.0...v0.9.0) (2018-01-07)
### Bug Fixes
* **package:** add pacote to bundleDependencies ([#36](https://github.com/npm/libcipm/issues/36)) ([a69742e](https://github.com/npm/libcipm/commit/a69742e))
### Features
* **config:** allow injection of npm configs ([#35](https://github.com/npm/libcipm/issues/35)) ([1f5694b](https://github.com/npm/libcipm/commit/1f5694b))
<a name="0.8.0"></a>
# [0.8.0](https://github.com/npm/libcipm/compare/v0.7.2...v0.8.0) (2017-11-28)
### Features
* **gyp:** new npm-lifecycle[@2](https://github.com/2) with included node-gyp ([a4ed938](https://github.com/npm/libcipm/commit/a4ed938))
<a name="0.7.2"></a>
## [0.7.2](https://github.com/npm/libcipm/compare/v0.7.1...v0.7.2) (2017-10-13)
### Bug Fixes
* **extract:** idk why this was breaking. Seriously. ([433a2be](https://github.com/npm/libcipm/commit/433a2be))
* **tree:** pass through a custom Promise to logiTree ([2d29efb](https://github.com/npm/libcipm/commit/2d29efb))
### Performance Improvements
* zoomzoom. Even more concurrency! ([db9c2e0](https://github.com/npm/libcipm/commit/db9c2e0))
<a name="0.7.1"></a>
## [0.7.1](https://github.com/npm/libcipm/compare/v0.7.0...v0.7.1) (2017-10-13)
### Bug Fixes
* **scripts:** separate extract and build and fix ordering ([eb072a5](https://github.com/npm/libcipm/commit/eb072a5))
<a name="0.7.0"></a>
# [0.7.0](https://github.com/npm/libcipm/compare/v0.6.0...v0.7.0) (2017-10-12)
### Bug Fixes
* **lockfile:** npm-shrinkwrap takes precedence over package-lock (#28) ([3b98fb3](https://github.com/npm/libcipm/commit/3b98fb3))
### Features
* **optional:** ignore failed optional deps (#27) ([a654629](https://github.com/npm/libcipm/commit/a654629))
<a name="0.6.0"></a>
# [0.6.0](https://github.com/npm/libcipm/compare/v0.5.1...v0.6.0) (2017-10-09)
### Features
* **scripts:** run prepare and prepublish scripts in the root (#26) ([e0e35a3](https://github.com/npm/libcipm/commit/e0e35a3))
<a name="0.5.1"></a>
## [0.5.1](https://github.com/npm/libcipm/compare/v0.5.0...v0.5.1) (2017-10-09)
<a name="0.5.0"></a>
# [0.5.0](https://github.com/npm/libcipm/compare/v0.4.0...v0.5.0) (2017-10-09)
### Bug Fixes
* **output:** npm does not punctuate this ([e7ba976](https://github.com/npm/libcipm/commit/e7ba976))
* **shutdown:** make sure workers close ([7ab57d0](https://github.com/npm/libcipm/commit/7ab57d0))
### Features
* **bin:** link bins and run scripts (#25) ([fab74bf](https://github.com/npm/libcipm/commit/fab74bf))
* **lifecycle:** run scripts in dep order (#23) ([68ecfac](https://github.com/npm/libcipm/commit/68ecfac))
<a name="0.4.0"></a>
# [0.4.0](https://github.com/npm/libcipm/compare/v0.3.2...v0.4.0) (2017-10-04)
### Features
* **opts:** support full range of relevant CLI opts (#19) ([6f2bd51](https://github.com/npm/libcipm/commit/6f2bd51))
<a name="0.3.2"></a>
## [0.3.2](https://github.com/npm/libcipm/compare/v0.3.1...v0.3.2) (2017-09-06)
### Bug Fixes
* **bin:** make cli executable by default (#13) ([14a9a5f](https://github.com/npm/libcipm/commit/14a9a5f))
* **config:** use npm.cmd on win32 and fix tests (#12) ([d912d16](https://github.com/npm/libcipm/commit/d912d16)), closes [#12](https://github.com/npm/libcipm/issues/12)
* **json:** strip BOM when reading JSON files (#8) ([2529149](https://github.com/npm/libcipm/commit/2529149))
<a name="0.3.1"></a>
## [0.3.1](https://github.com/npm/libcipm/compare/v0.3.0...v0.3.1) (2017-09-05)
<a name="0.3.0"></a>
# [0.3.0](https://github.com/npm/libcipm/compare/v0.2.0...v0.3.0) (2017-09-05)
### Features
* **lockfile:** verify that lockfile matches package.json (#5) ([f631203](https://github.com/npm/libcipm/commit/f631203))
* **scripts:** support --ignore-scripts option (#9) ([213ca02](https://github.com/npm/libcipm/commit/213ca02))
<a name="0.2.0"></a>
# [0.2.0](https://github.com/npm/libcipm/compare/v0.1.1...v0.2.0) (2017-09-01)
### Bug Fixes
* **main:** default --prefix ([ff06a31](https://github.com/npm/libcipm/commit/ff06a31))
### Features
* **lifecycle:** actually run lifecycle scripts correctly ([7f8933e](https://github.com/npm/libcipm/commit/7f8933e))
<a name="0.1.1"></a>
## [0.1.1](https://github.com/npm/libcipm/compare/v0.1.0...v0.1.1) (2017-08-30)
### Bug Fixes
* **files:** oops. forgot to include new files in tarball ([1ee85c9](https://github.com/npm/libcipm/commit/1ee85c9))
<a name="0.1.0"></a>
# 0.1.0 (2017-08-30)
### Bug Fixes
* **config:** pipe stdout ([08e6af8](https://github.com/npm/libcipm/commit/08e6af8))
* **extract:** make sure to extract properly ([9643583](https://github.com/npm/libcipm/commit/9643583))
* **license:** switch to MIT ([0d10d0d](https://github.com/npm/libcipm/commit/0d10d0d))
### Features
* **impl:** rough prototype ([2970e43](https://github.com/npm/libcipm/commit/2970e43))
* **lifecycle:** Run lifecycle events, implement prefix option, add unit tests (#1) ([d6629be](https://github.com/npm/libcipm/commit/d6629be)), closes [#1](https://github.com/npm/libcipm/issues/1)
* **opts:** add usage string and --help ([efcc48d](https://github.com/npm/libcipm/commit/efcc48d))
LICENSE.md 0000644 00000002064 15173127725 0006164 0 ustar 00 Copyright npm, Inc., Kat Marchán, and Contributors
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
package.json 0000644 00000004503 15173127725 0007046 0 ustar 00 {
"_from": "libcipm@4.0.8",
"_id": "libcipm@4.0.8",
"_inBundle": false,
"_integrity": "sha512-IN3hh2yDJQtZZ5paSV4fbvJg4aHxCCg5tcZID/dSVlTuUiWktsgaldVljJv6Z5OUlYspx6xQkbR0efNodnIrOA==",
"_location": "/libcipm",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "libcipm@4.0.8",
"name": "libcipm",
"escapedName": "libcipm",
"rawSpec": "4.0.8",
"saveSpec": null,
"fetchSpec": "4.0.8"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/libcipm/-/libcipm-4.0.8.tgz",
"_shasum": "dcea4919e10dfbce420327e63901613b9141bc89",
"_spec": "libcipm@4.0.8",
"_where": "/Users/claudiahdz/npm/cli",
"author": {
"name": "Kat Marchán",
"email": "kzm@sykosomatic.org"
},
"bugs": {
"url": "https://github.com/npm/libcipm/issues"
},
"bundleDependencies": false,
"config": {
"nyc": {
"exclude": [
"node_modules/**",
"test/**"
]
}
},
"dependencies": {
"bin-links": "^1.1.2",
"bluebird": "^3.5.1",
"figgy-pudding": "^3.5.1",
"find-npm-prefix": "^1.0.2",
"graceful-fs": "^4.1.11",
"ini": "^1.3.5",
"lock-verify": "^2.1.0",
"mkdirp": "^0.5.1",
"npm-lifecycle": "^3.0.0",
"npm-logical-tree": "^1.2.1",
"npm-package-arg": "^6.1.0",
"pacote": "^9.1.0",
"read-package-json": "^2.0.13",
"rimraf": "^2.6.2",
"worker-farm": "^1.6.0"
},
"deprecated": false,
"description": "programmatic API for cipm: a ci-oriented package installer for npm",
"devDependencies": {
"npmlog": "^4.1.2",
"nyc": "^11.8.0",
"require-inject": "^1.4.3",
"standard": "^11.0.1",
"standard-version": "^4.4.0",
"tacks": "^1.2.6",
"tap": "^12.0.1"
},
"files": [
"*.js",
"lib"
],
"homepage": "https://github.com/npm/libcipm#readme",
"keywords": [
"npm",
"package manager",
"caching",
"downloader"
],
"license": "MIT",
"main": "index.js",
"name": "libcipm",
"repository": {
"type": "git",
"url": "git+https://github.com/npm/libcipm.git"
},
"scripts": {
"postrelease": "npm publish && git push --follow-tags",
"prerelease": "npm t",
"pretest": "standard",
"release": "standard-version -s",
"test": "tap -J --nyc-arg=--all --coverage test/specs"
},
"version": "4.0.8"
}
lib/config/npm-config.js 0000644 00000004265 15173127725 0011173 0 ustar 00 'use strict'
const BB = require('bluebird')
const fs = require('fs')
const figgyPudding = require('figgy-pudding')
const ini = require('ini')
const path = require('path')
const spawn = require('child_process').spawn
const readFileAsync = BB.promisify(fs.readFile)
const NpmConfig = figgyPudding({
cache: { default: '' },
then: {},
userconfig: {}
})
module.exports = NpmConfig
module.exports.fromNpm = getNpmConfig
function getNpmConfig (argv) {
return new BB((resolve, reject) => {
const npmBin = process.platform === 'win32' ? 'npm.cmd' : 'npm'
const child = spawn(npmBin, [
'config', 'ls', '--json', '-l'
// We add argv here to get npm to parse those options for us :D
].concat(argv || []), {
env: process.env,
cwd: process.cwd(),
stdio: [0, 'pipe', 2]
})
let stdout = ''
if (child.stdout) {
child.stdout.on('data', (chunk) => {
stdout += chunk
})
}
child.on('error', reject)
child.on('close', (code) => {
if (code === 127) {
reject(new Error('`npm` command not found. Please ensure you have npm@5.4.0 or later installed.'))
} else {
try {
resolve(JSON.parse(stdout))
} catch (e) {
reject(new Error('`npm config ls --json` failed to output json. Please ensure you have npm@5.4.0 or later installed.'))
}
}
})
}).then(opts => {
return BB.all(
process.cwd().split(path.sep).reduce((acc, next) => {
acc.path = path.join(acc.path, next)
acc.promises.push(maybeReadIni(path.join(acc.path, '.npmrc')))
acc.promises.push(maybeReadIni(path.join(acc.path, 'npmrc')))
return acc
}, {
path: '',
promises: []
}).promises.concat(
opts.userconfig ? maybeReadIni(opts.userconfig) : {}
)
).then(configs => NpmConfig(...configs, opts))
}).then(opts => {
if (opts.cache) {
return opts.concat({ cache: path.join(opts.cache, '_cacache') })
} else {
return opts
}
})
}
function maybeReadIni (f) {
return readFileAsync(f, 'utf8').catch(err => {
if (err.code === 'ENOENT') {
return ''
} else {
throw err
}
}).then(ini.parse)
}
lib/silentlog.js 0000644 00000000272 15173127725 0007663 0 ustar 00 'use strict'
const noop = Function.prototype
module.exports = {
error: noop,
warn: noop,
info: noop,
verbose: noop,
silly: noop,
http: noop,
pause: noop,
resume: noop
}
lib/extract.js 0000644 00000003342 15173127725 0007336 0 ustar 00 'use strict'
const BB = require('bluebird')
const extractionWorker = require('./worker.js')
const figgyPudding = require('figgy-pudding')
const npa = require('npm-package-arg')
const WORKER_PATH = require.resolve('./worker.js')
let workerFarm
// Broken for now, cause too many issues on some systems.
const ENABLE_WORKERS = false
const ExtractOpts = figgyPudding({
log: {},
dirPacker: {}
})
module.exports = {
startWorkers () {
if (ENABLE_WORKERS) {
if (!workerFarm) { workerFarm = require('worker-farm') }
this._workers = workerFarm({
maxConcurrentCallsPerWorker: 20,
maxRetries: 1
}, WORKER_PATH)
}
},
stopWorkers () {
if (ENABLE_WORKERS) {
if (!workerFarm) { workerFarm = require('worker-farm') }
workerFarm.end(this._workers)
}
},
child (name, child, childPath, opts) {
opts = ExtractOpts(opts)
const spec = npa.resolve(name, child.version)
let childOpts = opts.concat({
integrity: child.integrity,
resolved: child.resolved
})
const args = [spec, childPath, childOpts]
return BB.fromNode((cb) => {
let launcher = extractionWorker
let msg = args
const spec = typeof args[0] === 'string' ? npa(args[0]) : args[0]
if (ENABLE_WORKERS && (spec.registry || spec.type === 'remote')) {
if (!workerFarm) { workerFarm = require('worker-farm') }
// We can't serialize these options
childOpts = childOpts.concat({
log: null,
dirPacker: null
})
// workers will run things in parallel!
launcher = this._workers
try {
msg = JSON.stringify(msg)
} catch (e) {
return cb(e)
}
}
launcher(msg, cb)
})
}
}
lib/worker.js 0000644 00000000642 15173127725 0007175 0 ustar 00 'use strict'
const BB = require('bluebird')
// const log = require('npmlog')
const pacote = require('pacote')
module.exports = (args, cb) => {
const parsed = typeof args === 'string' ? JSON.parse(args) : args
const spec = parsed[0]
const extractTo = parsed[1]
const opts = parsed[2]
// opts.log = log
// log.level = opts.loglevel
return BB.resolve(pacote.extract(spec, extractTo, opts)).nodeify(cb)
}