feat: add an option to pass in a logs listener

Ref https://github.com/pnpm/pnpm/issues/572
This commit is contained in:
zkochan
2017-07-01 16:05:31 +03:00
parent e1476af76e
commit fd2b23ebf0
9 changed files with 101 additions and 21 deletions

View File

@@ -32,6 +32,7 @@ Install packages.
* `options.metaCache` - *Map* - a cache for package meta info.
* `options.networkConcurrency` - *Number* - `16` by default. Max amount of network requests to perform concurrently.
* `options.offline` - *Boolean* - `false` by default. Install packages using only the local registry mirror, w/o doing any network requests.
* `options.reporter` - *Function* - A function that listens for logs.
**Returns:** a Promise
@@ -65,6 +66,7 @@ Uninstalls a package, completely removing everything pnpm installed on its behal
* `options.saveDev` - *Boolean* - the package will be removed from `devDependencies`.
* `options.saveOptional` - *Boolean* - the package will be removed from `optionalDependencies`.
* `options.global` - *Boolean* - the packages will be uninstalled globally.
* `options.reporter` - *Function* - A function that listens for logs.
### `pnpm.link(linkFrom, lintTo, [options])`
@@ -74,6 +76,7 @@ Create a symbolic link from the linked package to the target package's `node_mod
* `linkFrom` - *String* - path to the package that should be linked.
* `lintTo` - *String* - path to the dependent package.
* `options.reporter` - *Function* - A function that listens for logs.
### `pnpm.linkToGlobal(linkFrom, options)`
@@ -83,6 +86,7 @@ Create a symbolic link from the specified package to the global `node_modules`.
* `linkFrom` - *String* - path to the package that should be linked.
* `globalPrefix` - *String* - path to the global directory.
* `options.reporter` - *Function* - A function that listens for logs.
### `pnpm.linkFromGlobal(pkgName, linkTo, options)`
@@ -93,6 +97,7 @@ Create a symbolic link from the global `pkgName` to the `linkTo/node_modules` fo
* `pkgName` - *String* - package to link.
* `linkTo` - *String* - package to link to.
* `globalPrefix` - *String* - path to the global directory.
* `options.reporter` - *Function* - A function that listens for logs.
### `pnpm.prune([options])`
@@ -102,11 +107,16 @@ Remove extraneous packages. Extraneous packages are packages that are not listed
* `options.production` - *Boolean* - by default `false`. If this property is `true`, prune will remove the packages specified in `devDependencies`.
* `options.prefix` - *String* - by default `process.cwd()`.
* `options.reporter` - *Function* - A function that listens for logs.
### `pnpm.storeStatus([options])`
Return the list of modified dependencies.
**Arguments:**
* `options.reporter` - *Function* - A function that listens for logs.
**Returns:** `Promise<string[]>` - the paths to the modified packages of the current project. The paths contain the location of packages in the store,
not in the projects `node_modules` folder.

View File

@@ -37,6 +37,7 @@ import {Package} from '../types'
import {PackageSpec, DirectoryResolution, Resolution} from '../resolve'
import {DependencyTreeNode} from '../link/resolvePeers'
import depsToSpecs, {similarDepsToSpecs} from '../depsToSpecs'
import streamParser from '../logging/streamParser'
export type InstalledPackages = {
[name: string]: InstalledPackage
@@ -91,13 +92,22 @@ export type InstallContext = {
}
export async function install (maybeOpts?: PnpmOptions) {
const reporter = maybeOpts && maybeOpts.reporter
if (reporter) {
streamParser.on('data', reporter)
}
const opts = extendOptions(maybeOpts)
if (opts.lock) {
return lock(opts.prefix, _install, {stale: opts.lockStaleDuration})
await lock(opts.prefix, _install, {stale: opts.lockStaleDuration})
} else {
await _install()
}
return _install()
if (reporter) {
streamParser.removeListener('data', opts.reporter)
}
async function _install() {
const installType = 'general'
@@ -180,12 +190,22 @@ function depsFromPackage (pkg: Package): Dependencies {
* install({'lodash': '1.0.0', 'foo': '^2.1.0' }, { silent: true })
*/
export async function installPkgs (fuzzyDeps: string[] | Dependencies, maybeOpts?: PnpmOptions) {
const reporter = maybeOpts && maybeOpts.reporter
if (reporter) {
streamParser.on('data', reporter)
}
const opts = extendOptions(maybeOpts)
if (opts.lock) {
return lock(opts.prefix, _installPkgs, {stale: opts.lockStaleDuration})
await lock(opts.prefix, _installPkgs, {stale: opts.lockStaleDuration})
} else {
await _installPkgs()
}
if (reporter) {
streamParser.removeListener('data', opts.reporter)
}
return _installPkgs()
async function _installPkgs () {
const installType = 'named'

View File

@@ -7,6 +7,7 @@ import expandTilde from '../fs/expandTilde'
import {linkPkgBins} from '../link/linkBins'
import {PnpmOptions} from '../types'
import extendOptions from './extendOptions'
import streamParser from '../logging/streamParser'
const linkLogger = logger('link')
@@ -15,6 +16,10 @@ export default async function link (
linkTo: string,
maybeOpts?: PnpmOptions & {skipInstall?: boolean}
) {
const reporter = maybeOpts && maybeOpts.reporter
if (reporter) {
streamParser.on('data', reporter)
}
const opts = extendOptions(maybeOpts)
if (!maybeOpts || !maybeOpts.skipInstall) {
@@ -26,6 +31,10 @@ export default async function link (
const bin = path.join(destModules, '.bin')
await linkPkgBins(linkFrom, bin)
if (reporter) {
streamParser.removeListener('data', reporter)
}
}
async function linkToModules (linkFrom: string, modules: string) {
@@ -40,18 +49,34 @@ export async function linkFromGlobal (
linkTo: string,
maybeOpts: PnpmOptions & {globalPrefix: string}
) {
const reporter = maybeOpts && maybeOpts.reporter
if (reporter) {
streamParser.on('data', reporter)
}
const opts = extendOptions(maybeOpts)
const globalPkgPath = expandTilde(maybeOpts.globalPrefix)
const linkedPkgPath = path.join(globalPkgPath, 'node_modules', pkgName)
await link(linkedPkgPath, linkTo, opts)
if (reporter) {
streamParser.removeListener('data', reporter)
}
}
export async function linkToGlobal (
linkFrom: string,
maybeOpts: PnpmOptions & {globalPrefix: string}
) {
const reporter = maybeOpts && maybeOpts.reporter
if (reporter) {
streamParser.on('data', reporter)
}
const opts = extendOptions(maybeOpts)
opts.global = true // bins will be linked to the global bin path
const globalPkgPath = expandTilde(maybeOpts.globalPrefix)
await link(linkFrom, globalPkgPath, opts)
if (reporter) {
streamParser.removeListener('data', reporter)
}
}

View File

@@ -12,17 +12,27 @@ import {
ResolvedDependencies,
prune as pruneShrinkwrap,
} from 'pnpm-shrinkwrap'
import streamParser from '../logging/streamParser'
export async function prune(maybeOpts?: PnpmOptions): Promise<void> {
const reporter = maybeOpts && maybeOpts.reporter
if (reporter) {
streamParser.on('data', reporter)
}
const opts = extendOptions(maybeOpts)
const ctx = await getContext(opts)
if (opts.lock === false) {
return run()
await run()
} else {
await lock(ctx.storePath, run, {stale: opts.lockStaleDuration})
}
return lock(ctx.storePath, run, {stale: opts.lockStaleDuration})
if (reporter) {
streamParser.removeListener('data', reporter)
}
async function run () {
if (!ctx.pkg) {

View File

@@ -5,8 +5,13 @@ import extendOptions from './extendOptions'
import getContext from './getContext'
import untouched from '../pkgIsUntouched'
import {shortIdToFullId} from '../fs/shrinkwrap'
import streamParser from '../logging/streamParser'
export default async function (maybeOpts: PnpmOptions) {
const reporter = maybeOpts && maybeOpts.reporter
if (reporter) {
streamParser.on('data', reporter)
}
const opts = extendOptions(maybeOpts)
const ctx = await getContext(opts)
if (!ctx.shrinkwrap) return []
@@ -19,5 +24,11 @@ export default async function (maybeOpts: PnpmOptions) {
.filter(pkgId => pkgId && !ctx.skipped.has(pkgId))
.map((pkgPath: string) => path.join(ctx.storePath, pkgPath))
return await pFilter(pkgPaths, async (pkgPath: string) => !await untouched(path.join(pkgPath, 'package')))
const modified = await pFilter(pkgPaths, async (pkgPath: string) => !await untouched(path.join(pkgPath, 'package')))
if (reporter) {
streamParser.removeListener('data', reporter)
}
return modified
}

View File

@@ -20,14 +20,25 @@ import {PackageSpec} from '../resolve'
import pnpmPkgJson from '../pnpmPkgJson'
import safeIsInnerLink from '../safeIsInnerLink'
import removeTopDependency from '../removeTopDependency'
import streamParser from '../logging/streamParser'
export default async function uninstall (pkgsToUninstall: string[], maybeOpts?: PnpmOptions) {
const reporter = maybeOpts && maybeOpts.reporter
if (reporter) {
streamParser.on('data', reporter)
}
const opts = extendOptions(maybeOpts)
if (opts.lock) {
return lock(opts.prefix, _uninstall, {stale: opts.lockStaleDuration})
await lock(opts.prefix, _uninstall, {stale: opts.lockStaleDuration})
} else {
await _uninstall()
}
if (reporter) {
streamParser.removeListener('data', opts.reporter)
}
return _uninstall()
async function _uninstall () {
const ctx = await getContext(opts)

View File

@@ -3,6 +3,7 @@ import bole = require('bole')
export type StreamParser = {
on: Function,
removeListener: Function,
}
const streamParser: StreamParser = ndjson.parse()

View File

@@ -54,9 +54,10 @@ export type PnpmOptions = {
// cannot be specified via configs
update?: boolean,
reporter?: (logObj: Object) => void,
}
export type StrictPnpmOptions = {
export type StrictPnpmOptions = PnpmOptions & {
rawNpmConfig: Object,
global: boolean,
prefix: string,

View File

@@ -7,7 +7,6 @@ import {
prepare,
testDefaults,
} from '../utils'
import streamParser from '../../src/logging/streamParser'
import deepRequireCwd = require('deep-require-cwd')
import rimraf = require('rimraf-then')
@@ -46,11 +45,7 @@ test('peer dependency is not grouped with dependent when the peer is a top depen
}
}
streamParser.on('data', reporter)
await installPkgs(['ajv@4.10.4', 'ajv-keywords@1.5.0'], testDefaults())
streamParser['removeListener']('data', reporter)
await installPkgs(['ajv@4.10.4', 'ajv-keywords@1.5.0'], testDefaults({reporter}))
t.ok(await exists(path.join(NM, '.localhost+4873', 'ajv-keywords', '1.5.0', NM, 'ajv-keywords')), 'dependent is at the normal location')
t.notOk(log, 'no warning is logged about unresolved peer dep')
@@ -66,11 +61,7 @@ test('warning is reported when cannot resolve peer dependency', async (t: tape.T
}
}
streamParser.on('data', reporter)
await installPkgs(['ajv-keywords@1.5.0'], testDefaults())
streamParser['removeListener']('data', reporter)
await installPkgs(['ajv-keywords@1.5.0'], testDefaults({reporter}))
t.ok(log)
})