feat: move requireHooks to pnpm CLI (#3835)

Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
Cheng
2021-10-09 07:38:31 +08:00
committed by GitHub
parent 091ff5f127
commit 4027a3c691
22 changed files with 86 additions and 16 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/plugin-commands-installation": major
---
Hooks are passed in to the installation plugin, except when recursive installation happens on projects with own `.pnpmfile.js` files.

View File

@@ -0,0 +1,5 @@
---
"@pnpm/plugin-commands-rebuild": minor
---
New optional option added: hooks.

View File

@@ -0,0 +1,5 @@
---
"@pnpm/config": minor
---
New optional field added to the Config object: hooks.

View File

@@ -0,0 +1,5 @@
---
"@pnpm/pnpmfile": minor
---
Export interface for Hooks.

View File

@@ -33,6 +33,7 @@
"@pnpm/constants": "workspace:5.0.0",
"@pnpm/error": "workspace:2.0.0",
"@pnpm/global-bin-dir": "workspace:3.0.0",
"@pnpm/pnpmfile": "workspace:1.0.5",
"@pnpm/types": "workspace:7.4.0",
"@zkochan/npm-conf": "2.0.2",
"camelcase": "^6.2.0",

View File

@@ -3,6 +3,7 @@ import {
ProjectsGraph,
Registries,
} from '@pnpm/types'
import type { Hooks } from '@pnpm/pnpmfile'
export type UniversalOptions = Pick<Config, 'color' | 'dir' | 'rawConfig' | 'rawLocalConfig'>
@@ -101,6 +102,7 @@ export interface Config {
repeatInstallDepth?: number
ignorePnpmfile?: boolean
pnpmfile: string
hooks?: Hooks
packageImportMethod?: 'auto' | 'hardlink' | 'copy' | 'clone'
hoistPattern?: string[]
publicHoistPattern?: string[]

View File

@@ -21,6 +21,9 @@
{
"path": "../global-bin-dir"
},
{
"path": "../pnpmfile"
},
{
"path": "../types"
}

View File

@@ -261,6 +261,7 @@ export type InstallCommandOptions = Pick<Config,
| 'engineStrict'
| 'global'
| 'globalPnpmfile'
| 'hooks'
| 'ignorePnpmfile'
| 'ignoreScripts'
| 'linkWorkspacePackages'

View File

@@ -8,7 +8,6 @@ import PnpmError from '@pnpm/error'
import { filterPkgsBySelectorObjects } from '@pnpm/filter-workspace-packages'
import findWorkspacePackages, { arrayOfWorkspacePackagesToMap } from '@pnpm/find-workspace-packages'
import { rebuild } from '@pnpm/plugin-commands-rebuild/lib/implementation'
import { requireHooks } from '@pnpm/pnpmfile'
import { createOrConnectStoreController, CreateStoreControllerOptions } from '@pnpm/store-connection-manager'
import { IncludedDependencies, Project } from '@pnpm/types'
import {
@@ -39,6 +38,7 @@ export type InstallDepsOptions = Pick<Config,
| 'engineStrict'
| 'global'
| 'globalPnpmfile'
| 'hooks'
| 'ignorePnpmfile'
| 'ignoreScripts'
| 'linkWorkspacePackages'
@@ -174,9 +174,6 @@ when running add/update with the --workspace option')
storeDir: store.dir,
workspacePackages,
}
if (!opts.ignorePnpmfile) {
installOpts['hooks'] = requireHooks(opts.lockfileDir ?? dir, opts)
}
if (opts.global) {
installOpts['nodeExecPath'] = process.env.NODE ?? process.execPath
}

View File

@@ -44,6 +44,7 @@ type RecursiveOptions = CreateStoreControllerOptions & Pick<Config,
| 'depth'
| 'globalPnpmfile'
| 'hoistPattern'
| 'hooks'
| 'ignorePnpmfile'
| 'ignoreScripts'
| 'linkWorkspacePackages'
@@ -169,7 +170,6 @@ export default async function recursive (
const isFromWorkspace = isSubdir.bind(null, calculatedRepositoryRoot)
importers = await pFilter(importers, async ({ rootDir }: { rootDir: string }) => isFromWorkspace(await fs.realpath(rootDir)))
if (importers.length === 0) return true
const hooks = opts.ignorePnpmfile ? {} : requireHooks(opts.lockfileDir, opts)
const mutation = cmdFullName === 'remove' ? 'uninstallSome' : (params.length === 0 && !updateToLatest ? 'install' : 'installSome')
const writeProjectManifests = [] as Array<(manifest: ProjectManifest) => Promise<void>>
const mutatedImporters = [] as MutatedProject[]
@@ -260,7 +260,6 @@ export default async function recursive (
}
const mutatedPkgs = await mutateModules(mutatedImporters, {
...installOpts,
hooks,
storeController: store.ctrl,
})
if (opts.save !== false) {

View File

@@ -9,7 +9,6 @@ import { Config, types as allTypes } from '@pnpm/config'
import PnpmError from '@pnpm/error'
import findWorkspacePackages, { arrayOfWorkspacePackagesToMap } from '@pnpm/find-workspace-packages'
import { getAllDependenciesFromManifest } from '@pnpm/manifest-utils'
import { requireHooks } from '@pnpm/pnpmfile'
import { createOrConnectStoreController, CreateStoreControllerOptions } from '@pnpm/store-connection-manager'
import { DependenciesField } from '@pnpm/types'
import {
@@ -131,6 +130,7 @@ export async function handler (
| 'dev'
| 'engineStrict'
| 'globalPnpmfile'
| 'hooks'
| 'ignorePnpmfile'
| 'linkWorkspacePackages'
| 'lockfileDir'
@@ -165,9 +165,6 @@ export async function handler (
storeDir: store.dir,
include,
})
if (!opts.ignorePnpmfile) {
removeOpts['hooks'] = requireHooks(opts.lockfileDir ?? opts.dir, opts)
}
removeOpts['workspacePackages'] = opts.workspaceDir
? arrayOfWorkspacePackagesToMap(await findWorkspacePackages(opts.workspaceDir, opts))
: undefined

View File

@@ -46,6 +46,7 @@ export async function handler (
| 'bail'
| 'bin'
| 'engineStrict'
| 'hooks'
| 'linkWorkspacePackages'
| 'selectedProjectsGraph'
| 'rawLocalConfig'

View File

@@ -69,6 +69,7 @@ export async function handler (
| 'allProjects'
| 'dir'
| 'engineStrict'
| 'hooks'
| 'rawLocalConfig'
| 'registries'
| 'scriptShell'

View File

@@ -19,6 +19,7 @@ import { rebuild as rebuildAll, RebuildOptions, rebuildPkgs } from './implementa
type RecursiveRebuildOpts = CreateStoreControllerOptions & Pick<Config,
| 'hoistPattern'
| 'hooks'
| 'ignorePnpmfile'
| 'ignoreScripts'
| 'lockfileDir'

View File

@@ -51,6 +51,7 @@
"@pnpm/plugin-commands-server": "workspace:3.0.35",
"@pnpm/plugin-commands-setup": "workspace:1.1.7",
"@pnpm/plugin-commands-store": "workspace:4.0.19",
"@pnpm/pnpmfile": "workspace:1.0.5",
"@pnpm/prepare": "workspace:0.0.26",
"@pnpm/read-package-json": "workspace:5.0.4",
"@pnpm/read-project-manifest": "workspace:2.0.5",

View File

@@ -12,6 +12,7 @@ import findWorkspacePackages from '@pnpm/find-workspace-packages'
import logger from '@pnpm/logger'
import { ParsedCliArgs } from '@pnpm/parse-cli-args'
import { node } from '@pnpm/plugin-commands-env'
import { requireHooks } from '@pnpm/pnpmfile'
import chalk from 'chalk'
import checkForUpdates from './checkForUpdates'
import pnpmCmds, { rcOptionsTypes } from './cmd'
@@ -210,6 +211,13 @@ export default async function run (inputArgv: string[]) {
let { output, exitCode }: { output: string | null, exitCode: number } = await (async () => {
// NOTE: we defer the next stage, otherwise reporter might not catch all the logs
await new Promise<void>((resolve) => setTimeout(() => resolve(), 0))
// It would be nice to read the lockfile in @pnpm/config but in there reporting doesn't work yet
// and some info logs are printed when hooks are required.
if (!config.ignorePnpmfile) {
config.hooks = requireHooks(config.lockfileDir ?? config.dir, config)
}
if (!isCI && !selfUpdate && !config.offline && !config.preferOffline && !config.fallbackCommandUsed) {
checkForUpdates(config).catch(() => { /* Ignore */ })
}

View File

@@ -105,6 +105,9 @@
{
"path": "../plugin-commands-store"
},
{
"path": "../pnpmfile"
},
{
"path": "../read-package-json"
},

View File

@@ -34,6 +34,7 @@
"@pnpm/core-loggers": "workspace:6.0.4",
"@pnpm/error": "workspace:2.0.0",
"@pnpm/types": "workspace:7.4.0",
"@pnpm/lockfile-types": "workspace:3.0.0",
"chalk": "^4.1.0",
"path-absolute": "^1.0.1"
},

View File

@@ -1,4 +1,6 @@
import requireHooks from './requireHooks'
import type { CookedHooks } from './requireHooks'
import requirePnpmfile, { BadReadPackageHookError } from './requirePnpmfile'
export { requireHooks, requirePnpmfile, BadReadPackageHookError }
export type Hooks = CookedHooks

View File

@@ -2,27 +2,50 @@ import path from 'path'
import { hookLogger } from '@pnpm/core-loggers'
import logger from '@pnpm/logger'
import pathAbsolute from 'path-absolute'
import type { Lockfile } from '@pnpm/lockfile-types'
import requirePnpmfile from './requirePnpmfile'
interface HookContext {
log: (message: string) => void
}
interface Hooks {
// eslint-disable-next-line
readPackage?: (pkg: any, context: HookContext) => any
afterAllResolved?: (lockfile: Lockfile, context: HookContext) => Lockfile
}
// eslint-disable-next-line
type Cook<T extends (...args: any[]) => any> = (
arg: Parameters<T>[0],
// eslint-disable-next-line
...otherArgs: any[]
) => ReturnType<T>
export interface CookedHooks {
readPackage?: Cook<Required<Hooks>['readPackage']>
afterAllResolved?: Cook<Required<Hooks>['afterAllResolved']>
}
export default function requireHooks (
prefix: string,
opts: {
globalPnpmfile?: string
pnpmfile?: string
}
) {
): CookedHooks {
const globalPnpmfile = opts.globalPnpmfile && requirePnpmfile(pathAbsolute(opts.globalPnpmfile, prefix), prefix)
let globalHooks = globalPnpmfile?.hooks
let globalHooks: Hooks = globalPnpmfile?.hooks
const pnpmFile = opts.pnpmfile && requirePnpmfile(pathAbsolute(opts.pnpmfile, prefix), prefix) ||
requirePnpmfile(path.join(prefix, '.pnpmfile.cjs'), prefix)
let hooks = pnpmFile?.hooks
let hooks: Hooks = pnpmFile?.hooks
if (!globalHooks && !hooks) return {}
globalHooks = globalHooks || {}
hooks = hooks || {}
const cookedHooks = {}
if (globalHooks.readPackage || hooks.readPackage) {
const cookedHooks: CookedHooks = {}
if ((globalHooks.readPackage != null) || (hooks.readPackage != null)) {
logger.info({
message: 'readPackage hook is declared. Manifests of dependencies might get overridden',
prefix,
@@ -52,7 +75,7 @@ export default function requireHooks (
return cookedHooks
}
function createReadPackageHookContext (calledFrom: string, prefix: string, hook: string) {
function createReadPackageHookContext (calledFrom: string, prefix: string, hook: string): HookContext {
return {
log: (message: string) => hookLogger.debug({
from: calledFrom,

View File

@@ -15,6 +15,9 @@
{
"path": "../error"
},
{
"path": "../lockfile-types"
},
{
"path": "../types"
}

6
pnpm-lock.yaml generated
View File

@@ -339,6 +339,7 @@ importers:
'@pnpm/constants': workspace:5.0.0
'@pnpm/error': workspace:2.0.0
'@pnpm/global-bin-dir': workspace:3.0.0
'@pnpm/pnpmfile': workspace:1.0.5
'@pnpm/prepare': workspace:0.0.26
'@pnpm/types': workspace:7.4.0
'@types/ramda': 0.27.39
@@ -355,6 +356,7 @@ importers:
'@pnpm/constants': link:../constants
'@pnpm/error': link:../error
'@pnpm/global-bin-dir': link:../global-bin-dir
'@pnpm/pnpmfile': link:../pnpmfile
'@pnpm/types': link:../types
'@zkochan/npm-conf': 2.0.2
camelcase: 6.2.0
@@ -2511,6 +2513,7 @@ importers:
'@pnpm/plugin-commands-server': workspace:3.0.35
'@pnpm/plugin-commands-setup': workspace:1.1.7
'@pnpm/plugin-commands-store': workspace:4.0.19
'@pnpm/pnpmfile': workspace:1.0.5
'@pnpm/prepare': workspace:0.0.26
'@pnpm/read-package-json': workspace:5.0.4
'@pnpm/read-project-manifest': workspace:2.0.5
@@ -2603,6 +2606,7 @@ importers:
'@pnpm/plugin-commands-server': link:../plugin-commands-server
'@pnpm/plugin-commands-setup': link:../plugin-commands-setup
'@pnpm/plugin-commands-store': link:../plugin-commands-store
'@pnpm/pnpmfile': link:../pnpmfile
'@pnpm/prepare': link:../../privatePackages/prepare
'@pnpm/read-package-json': link:../read-package-json
'@pnpm/read-project-manifest': link:../read-project-manifest
@@ -2664,6 +2668,7 @@ importers:
specifiers:
'@pnpm/core-loggers': workspace:6.0.4
'@pnpm/error': workspace:2.0.0
'@pnpm/lockfile-types': workspace:3.0.0
'@pnpm/logger': ^4.0.0
'@pnpm/pnpmfile': 'link:'
'@pnpm/types': workspace:7.4.0
@@ -2672,6 +2677,7 @@ importers:
dependencies:
'@pnpm/core-loggers': link:../core-loggers
'@pnpm/error': link:../error
'@pnpm/lockfile-types': link:../lockfile-types
'@pnpm/types': link:../types
chalk: 4.1.2
path-absolute: 1.0.1