feat: require hooks from pnpmfile.js

Ref #861
This commit is contained in:
zkochan
2017-09-01 01:58:33 +03:00
parent b570bb2ab6
commit 0330ff0ee5
6 changed files with 92 additions and 5 deletions

View File

@@ -27,6 +27,7 @@ Like this project? Let people know with a [tweet](https://bit.ly/tweet-pnpm).
* [Install](#install)
* [Usage](#usage)
* [Configuring](#configuring)
* [Hooks](#hooks)
* [Benchmark](#benchmark)
* [Limitations](#limitations)
* [Frequently Asked Questions](#frequently-asked-questions)
@@ -144,6 +145,32 @@ that rely on location but gives an average of **8% installation speed improvemen
If false, doesn't check whether packages in the store were mutated.
### Hooks
pnpm allows to step directly into the installation process via special functions called *hooks*.
Hooks can be declared in a file called `pnpmfile.js`. `pnpmfile.js` should live in the root of the project.
An example of a `pnpmfile.js` that changes the dependencies field of a dependency:
```js
module.exports = {
hooks: {
readPackage
}
}
// This hook will override the manifest of foo@1 after downloading it from the registry
// foo@1 will always be installed with the second version of bar
function readPackage (pkg) {
if (pkg.name === 'foo' && pkg.version.startsWith('1.')) {
pkg.dependencies = {
bar: '^2.0.0'
}
}
return pkg
}
```
## Benchmark
pnpm is faster than npm and Yarn. See [this](https://github.com/zkochan/node-package-manager-benchmark)

View File

@@ -38,7 +38,7 @@
"pnpm-list": "^1.0.0",
"pnpm-logger": "^0.5.4",
"ramda": "^0.24.1",
"supi": "^0.2.16",
"supi": "^0.2.17",
"update-notifier": "^2.1.0"
},
"devDependencies": {

View File

@@ -24,7 +24,7 @@ dependencies:
pnpm-logger: 0.5.4
ramda: 0.24.1
rimraf: 2.6.1
supi: 0.2.16
supi: 0.2.17
update-notifier: 2.2.0
devDependencies:
'@types/mkdirp': 0.5.1
@@ -2234,7 +2234,7 @@ packages:
/strip-json-comments/2.0.1:
resolution:
integrity: sha1-PFMZQukIwml8DsNEhYwobHygpgo=
/supi/0.2.16:
/supi/0.2.17:
dependencies:
'@types/byline': 4.2.31
'@types/common-tags': 1.2.5
@@ -2292,7 +2292,7 @@ packages:
write-pkg: 3.1.0
write-yaml-file: 1.0.0
resolution:
integrity: sha512-BKYNiwcn9LeMczysq2CoyDK1IWNBD+ar0oFDZ3hHZSu70jjNyQaErz09FzELvXH1cc29Ekm5i/SL8PSmp+dNjA==
integrity: sha512-vnfuOLiCHw4XxhG6fnyxo2oF/ly0U9LT/+y8d0IDSA+eukJGw6AhUsVEZhFdXh07txMRK2QFSMGFT4622YMYew==
/supports-color/2.0.0:
resolution:
integrity: sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
@@ -2609,7 +2609,7 @@ specifiers:
pnpm-logger: ^0.5.4
ramda: ^0.24.1
rimraf: ^2.5.4
supi: ^0.2.16
supi: ^0.2.17
tslint: ^5.4.2
typescript: ^2.4.1
update-notifier: ^2.1.0

View File

@@ -1,4 +1,6 @@
import {install, installPkgs, PnpmOptions} from 'supi'
import path = require('path')
import logger from 'pnpm-logger'
/**
* Perform installation.
@@ -9,8 +11,30 @@ export default function installCmd (input: string[], opts: PnpmOptions) {
// `pnpm install ""` is going to be just `pnpm install`
input = input.filter(Boolean)
const prefix = opts.prefix || process.cwd()
opts['hooks'] = requireHooks(prefix)
if (!input || !input.length) {
return install(opts)
}
return installPkgs(input, opts)
}
function requireHooks (prefix: string) {
try {
const pnpmFilePath = path.join(prefix, 'pnpmfile.js')
const pnpmFile = require(pnpmFilePath)
const hooks = pnpmFile && pnpmFile.hooks
if (!hooks) return {}
if (hooks.readPackage) {
if (typeof hooks.readPackage !== 'function') {
throw new TypeError('hooks.readPackage should be a function')
}
logger.info('readPackage hook is declared. Manifests of dependencies might get overridden')
}
return hooks
} catch (err) {
if (err['code'] !== 'MODULE_NOT_FOUND') throw err
return {}
}
}

35
test/install/hooks.ts Normal file
View File

@@ -0,0 +1,35 @@
import tape = require('tape')
import promisifyTape from 'tape-promise'
import {
prepare,
addDistTag,
execPnpm
} from '../utils'
import fs = require('mz/fs')
const test = promisifyTape(tape)
test('readPackage hook', async (t: tape.Test) => {
const project = prepare(t)
await fs.writeFile('pnpmfile.js', `
'use strict'
module.exports = {
hooks: {
readPackage (pkg) {
if (pkg.name === 'pkg-with-1-dep') {
pkg.dependencies['dep-of-pkg-with-1-dep'] = '100.0.0'
}
return pkg
}
}
}
`, 'utf8')
// w/o the hook, 100.1.0 would be installed
await addDistTag('dep-of-pkg-with-1-dep', '100.1.0', 'latest')
await execPnpm('install', 'pkg-with-1-dep')
await project.storeHas('dep-of-pkg-with-1-dep', '100.0.0')
})

View File

@@ -1,2 +1,3 @@
import './misc'
import './lifecycleScripts'
import './hooks'