mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-27 09:08:13 -05:00
feat: move requireHooks to pnpm CLI (#3835)
Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
5
.changeset/new-dryers-travel.md
Normal file
5
.changeset/new-dryers-travel.md
Normal 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.
|
||||
5
.changeset/olive-drinks-smile.md
Normal file
5
.changeset/olive-drinks-smile.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-rebuild": minor
|
||||
---
|
||||
|
||||
New optional option added: hooks.
|
||||
5
.changeset/real-experts-perform.md
Normal file
5
.changeset/real-experts-perform.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/config": minor
|
||||
---
|
||||
|
||||
New optional field added to the Config object: hooks.
|
||||
5
.changeset/thick-ghosts-count.md
Normal file
5
.changeset/thick-ghosts-count.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/pnpmfile": minor
|
||||
---
|
||||
|
||||
Export interface for Hooks.
|
||||
@@ -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",
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
{
|
||||
"path": "../global-bin-dir"
|
||||
},
|
||||
{
|
||||
"path": "../pnpmfile"
|
||||
},
|
||||
{
|
||||
"path": "../types"
|
||||
}
|
||||
|
||||
@@ -261,6 +261,7 @@ export type InstallCommandOptions = Pick<Config,
|
||||
| 'engineStrict'
|
||||
| 'global'
|
||||
| 'globalPnpmfile'
|
||||
| 'hooks'
|
||||
| 'ignorePnpmfile'
|
||||
| 'ignoreScripts'
|
||||
| 'linkWorkspacePackages'
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -46,6 +46,7 @@ export async function handler (
|
||||
| 'bail'
|
||||
| 'bin'
|
||||
| 'engineStrict'
|
||||
| 'hooks'
|
||||
| 'linkWorkspacePackages'
|
||||
| 'selectedProjectsGraph'
|
||||
| 'rawLocalConfig'
|
||||
|
||||
@@ -69,6 +69,7 @@ export async function handler (
|
||||
| 'allProjects'
|
||||
| 'dir'
|
||||
| 'engineStrict'
|
||||
| 'hooks'
|
||||
| 'rawLocalConfig'
|
||||
| 'registries'
|
||||
| 'scriptShell'
|
||||
|
||||
@@ -19,6 +19,7 @@ import { rebuild as rebuildAll, RebuildOptions, rebuildPkgs } from './implementa
|
||||
|
||||
type RecursiveRebuildOpts = CreateStoreControllerOptions & Pick<Config,
|
||||
| 'hoistPattern'
|
||||
| 'hooks'
|
||||
| 'ignorePnpmfile'
|
||||
| 'ignoreScripts'
|
||||
| 'lockfileDir'
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 */ })
|
||||
}
|
||||
|
||||
@@ -105,6 +105,9 @@
|
||||
{
|
||||
"path": "../plugin-commands-store"
|
||||
},
|
||||
{
|
||||
"path": "../pnpmfile"
|
||||
},
|
||||
{
|
||||
"path": "../read-package-json"
|
||||
},
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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
|
||||
@@ -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,
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
{
|
||||
"path": "../error"
|
||||
},
|
||||
{
|
||||
"path": "../lockfile-types"
|
||||
},
|
||||
{
|
||||
"path": "../types"
|
||||
}
|
||||
|
||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user