feat: pnpm:devPreinstall script (#3968)

ref #3836
This commit is contained in:
Zoltan Kochan
2021-11-09 11:59:56 +02:00
committed by GitHub
parent fa03cbdc85
commit 2511c82cd2
3 changed files with 33 additions and 11 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/core": minor
"pnpm": minor
---
Added support for a new lifecycle script: `pnpm:devPreinstall`. This script works only in the root `package.json` file, only during local development, and runs before installation happens.

View File

@@ -13,7 +13,7 @@ import {
import PnpmError from '@pnpm/error'
import getContext, { PnpmContext, ProjectOptions } from '@pnpm/get-context'
import headless from '@pnpm/headless'
import {
import runLifecycleHook, {
makeNodeRequireOption,
runLifecycleHooksConcurrently,
RunLifecycleHooksConcurrentlyOptions,
@@ -82,6 +82,8 @@ const BROKEN_LOCKFILE_INTEGRITY_ERRORS = new Set([
'ERR_PNPM_TARBALL_INTEGRITY',
])
const DEV_PREINSTALL = 'pnpm:devPreinstall'
export type DependenciesMutation = (
{
buildIndex: number
@@ -200,6 +202,28 @@ export async function mutateModules (
return result
async function _install (): Promise<Array<{ rootDir: string, manifest: ProjectManifest }>> {
const scriptsOpts: RunLifecycleHooksConcurrentlyOptions = {
extraBinPaths: opts.extraBinPaths,
rawConfig: opts.rawConfig,
scriptShell: opts.scriptShell,
shellEmulator: opts.shellEmulator,
stdio: opts.ownLifecycleHooksStdio,
storeController: opts.storeController,
unsafePerm: opts.unsafePerm || false,
}
if (!opts.ignoreScripts && !opts.ignorePackageManifest && rootProjectManifest?.scripts?.[DEV_PREINSTALL]) {
await runLifecycleHook(
DEV_PREINSTALL,
rootProjectManifest,
{
...scriptsOpts,
depPath: opts.lockfileDir,
pkgRoot: opts.lockfileDir,
rootModulesDir: ctx.rootModulesDir,
}
)
}
const packageExtensionsChecksum = isEmpty(packageExtensions ?? {}) ? undefined : createObjectChecksum(packageExtensions!)
let needsFullResolution = !maybeOpts.ignorePackageManifest && (
!equals(ctx.wantedLockfile.overrides ?? {}, overrides ?? {}) ||
@@ -321,16 +345,6 @@ export async function mutateModules (
const projectsToInstall = [] as ImporterToUpdate[]
const projectsToBeInstalled = ctx.projects.filter(({ mutation }) => mutation === 'install') as ProjectToBeInstalled[]
const scriptsOpts: RunLifecycleHooksConcurrentlyOptions = {
extraBinPaths: opts.extraBinPaths,
rawConfig: opts.rawConfig,
scriptShell: opts.scriptShell,
shellEmulator: opts.shellEmulator,
stdio: opts.ownLifecycleHooksStdio,
storeController: opts.storeController,
unsafePerm: opts.unsafePerm || false,
}
let preferredSpecs: Record<string, string> | null = null
// TODO: make it concurrent

View File

@@ -97,6 +97,7 @@ test('run install scripts in the current project', async () => {
prepareEmpty()
const manifest = await addDependenciesToPackage({
scripts: {
'pnpm:devPreinstall': 'node -e "require(\'fs\').writeFileSync(\'test.txt\', \'\', \'utf-8\')"',
install: 'node -e "process.stdout.write(\'install\')" | json-append output.json',
postinstall: 'node -e "process.stdout.write(\'postinstall\')" | json-append output.json',
preinstall: 'node -e "process.stdout.write(\'preinstall\')" | json-append output.json',
@@ -107,6 +108,7 @@ test('run install scripts in the current project', async () => {
const output = await loadJsonFile<string[]>('output.json')
expect(output).toStrictEqual(['preinstall', 'install', 'postinstall'])
expect(await exists('test.txt')).toBeTruthy()
})
test('run install scripts in the current project when its name is different than its directory', async () => {