@pnpm/exec.lifecycle 1001.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +50 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.js +28 -0
- package/lib/runLifecycleHook.d.ts +19 -0
- package/lib/runLifecycleHook.js +166 -0
- package/lib/runLifecycleHooksConcurrently.d.ts +18 -0
- package/lib/runLifecycleHooksConcurrently.js +84 -0
- package/package.json +69 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2015-2016 Rico Sta. Cruz and other contributors
|
|
4
|
+
Copyright (c) 2016-2026 Zoltan Kochan and other contributors
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# @pnpm/lifecycle
|
|
2
|
+
|
|
3
|
+
> Package lifecycle hook runner
|
|
4
|
+
|
|
5
|
+
<!--@shields('npm')-->
|
|
6
|
+
[](https://www.npmjs.com/package/@pnpm/lifecycle)
|
|
7
|
+
<!--/@-->
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
pnpm add @pnpm/logger @pnpm/lifecycle
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import runLifecycleHook, {runPostinstallHooks} from '@pnpm/lifecycle'
|
|
19
|
+
|
|
20
|
+
const targetPkgRoot = path.resolve('node_modules/target-pkg')
|
|
21
|
+
const pkg = require(path.join(targetPkgRoot, 'package.json'))
|
|
22
|
+
|
|
23
|
+
// Run a specific hook
|
|
24
|
+
await runLifecycleHook('preinstall', pkg, {
|
|
25
|
+
pkgId: 'target-pkg/1.0.0',
|
|
26
|
+
pkgRoot: targetPkgRoot,
|
|
27
|
+
rawConfig: {},
|
|
28
|
+
rootModulesDir: path.resolve('node_modules'),
|
|
29
|
+
unsafePerm: true,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
// Run all install hooks
|
|
33
|
+
await runPostinstallHooks({
|
|
34
|
+
pkgId: 'target-pkg/1.0.0',
|
|
35
|
+
pkgRoot: targetPkgRoot,
|
|
36
|
+
rawConfig: {},
|
|
37
|
+
rootModulesDir: path.resolve('node_modules'),
|
|
38
|
+
unsafePerm: true,
|
|
39
|
+
})
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## API
|
|
43
|
+
|
|
44
|
+
### `runLifecycleHook(stage, packageManifest, opts): Promise<void>`
|
|
45
|
+
|
|
46
|
+
### `runPostinstallHooks(opts): Promise<void>`
|
|
47
|
+
|
|
48
|
+
## License
|
|
49
|
+
|
|
50
|
+
MIT
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { runLifecycleHook, type RunLifecycleHookOptions } from './runLifecycleHook.js';
|
|
2
|
+
import { runLifecycleHooksConcurrently, type RunLifecycleHooksConcurrentlyOptions } from './runLifecycleHooksConcurrently.js';
|
|
3
|
+
export declare function makeNodeRequireOption(modulePath: string): {
|
|
4
|
+
NODE_OPTIONS: string;
|
|
5
|
+
};
|
|
6
|
+
export { runLifecycleHook, type RunLifecycleHookOptions, runLifecycleHooksConcurrently, type RunLifecycleHooksConcurrentlyOptions, };
|
|
7
|
+
export declare function runPostinstallHooks(opts: RunLifecycleHookOptions): Promise<boolean>;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { safeReadPackageJsonFromDir } from '@pnpm/pkg-manifest.reader';
|
|
2
|
+
import { runLifecycleHook } from './runLifecycleHook.js';
|
|
3
|
+
import { runLifecycleHooksConcurrently } from './runLifecycleHooksConcurrently.js';
|
|
4
|
+
export function makeNodeRequireOption(modulePath) {
|
|
5
|
+
let { NODE_OPTIONS } = process.env;
|
|
6
|
+
NODE_OPTIONS = `${NODE_OPTIONS ?? ''} --require=${modulePath}`.trim();
|
|
7
|
+
return { NODE_OPTIONS };
|
|
8
|
+
}
|
|
9
|
+
export { runLifecycleHook, runLifecycleHooksConcurrently, };
|
|
10
|
+
export async function runPostinstallHooks(opts) {
|
|
11
|
+
const pkg = await safeReadPackageJsonFromDir(opts.pkgRoot);
|
|
12
|
+
if (pkg == null)
|
|
13
|
+
return false;
|
|
14
|
+
if (pkg.scripts == null) {
|
|
15
|
+
pkg.scripts = {};
|
|
16
|
+
}
|
|
17
|
+
if (pkg.scripts.preinstall) {
|
|
18
|
+
await runLifecycleHook('preinstall', pkg, opts);
|
|
19
|
+
}
|
|
20
|
+
const executedAnInstallScript = await runLifecycleHook('install', pkg, opts);
|
|
21
|
+
if (pkg.scripts.postinstall) {
|
|
22
|
+
await runLifecycleHook('postinstall', pkg, opts);
|
|
23
|
+
}
|
|
24
|
+
return pkg.scripts.preinstall != null ||
|
|
25
|
+
executedAnInstallScript ||
|
|
26
|
+
pkg.scripts.postinstall != null;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DependencyManifest, ProjectManifest } from '@pnpm/types';
|
|
2
|
+
export interface RunLifecycleHookOptions {
|
|
3
|
+
args?: string[];
|
|
4
|
+
depPath: string;
|
|
5
|
+
extraBinPaths?: string[];
|
|
6
|
+
extraEnv?: Record<string, string>;
|
|
7
|
+
initCwd?: string;
|
|
8
|
+
optional?: boolean;
|
|
9
|
+
pkgRoot: string;
|
|
10
|
+
rawConfig: object;
|
|
11
|
+
rootModulesDir: string;
|
|
12
|
+
scriptShell?: string;
|
|
13
|
+
silent?: boolean;
|
|
14
|
+
scriptsPrependNodePath?: boolean | 'warn-only';
|
|
15
|
+
shellEmulator?: boolean;
|
|
16
|
+
stdio?: string;
|
|
17
|
+
unsafePerm: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function runLifecycleHook(stage: string, manifest: ProjectManifest | DependencyManifest, opts: RunLifecycleHookOptions): Promise<boolean>;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { lifecycleLogger } from '@pnpm/core-loggers';
|
|
4
|
+
import { PnpmError } from '@pnpm/error';
|
|
5
|
+
import { globalWarn } from '@pnpm/logger';
|
|
6
|
+
import lifecycle from '@pnpm/npm-lifecycle';
|
|
7
|
+
import isWindows from 'is-windows';
|
|
8
|
+
import { join as shellQuote } from 'shlex';
|
|
9
|
+
function noop() { } // eslint-disable-line:no-empty
|
|
10
|
+
export async function runLifecycleHook(stage, manifest, opts) {
|
|
11
|
+
const optional = opts.optional === true;
|
|
12
|
+
// To remediate CVE_2024_27980, Node.js does not allow .bat or .cmd files to
|
|
13
|
+
// be spawned without the "shell: true" option.
|
|
14
|
+
//
|
|
15
|
+
// https://nodejs.org/api/child_process.html#spawning-bat-and-cmd-files-on-windows
|
|
16
|
+
//
|
|
17
|
+
// Unfortunately, setting spawn's shell option also causes arguments to be
|
|
18
|
+
// evaluated before they're passed to the shell, resulting in a surprising
|
|
19
|
+
// behavior difference only with .bat/.cmd files.
|
|
20
|
+
//
|
|
21
|
+
// Instead of showing a "spawn EINVAL" error, let's throw a clearer error that
|
|
22
|
+
// this isn't supported.
|
|
23
|
+
//
|
|
24
|
+
// If this behavior needs to be supported in the future, the arguments would
|
|
25
|
+
// need to be escaped before they're passed to the .bat/.cmd file. For
|
|
26
|
+
// example, scripts such as "echo %PATH%" should be passed verbatim rather
|
|
27
|
+
// than expanded. This is difficult to do correctly. Other open source tools
|
|
28
|
+
// (e.g. Rust) attempted and introduced bugs. The Rust blog has a good
|
|
29
|
+
// high-level explanation of the same security vulnerability Node.js patched.
|
|
30
|
+
//
|
|
31
|
+
// https://blog.rust-lang.org/2024/04/09/cve-2024-24576.html#overview
|
|
32
|
+
//
|
|
33
|
+
// Note that npm (as of version 10.5.0) doesn't support setting script-shell
|
|
34
|
+
// to a .bat or .cmd file either.
|
|
35
|
+
if (opts.scriptShell != null && typeof opts.scriptShell === 'string' && isWindowsBatchFile(opts.scriptShell)) {
|
|
36
|
+
throw new PnpmError('ERR_PNPM_INVALID_SCRIPT_SHELL_WINDOWS', 'Cannot spawn .bat or .cmd as a script shell.', {
|
|
37
|
+
hint: `\
|
|
38
|
+
The pnpm-workspace.yaml scriptShell option was configured to a .bat or .cmd file. These cannot be used as a script shell reliably.
|
|
39
|
+
|
|
40
|
+
Please unset the scriptShell option, or configure it to a .exe instead.
|
|
41
|
+
`,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const m = { _id: getId(manifest), ...manifest };
|
|
45
|
+
m.scripts = { ...m.scripts };
|
|
46
|
+
switch (stage) {
|
|
47
|
+
case 'start':
|
|
48
|
+
if (!m.scripts.start) {
|
|
49
|
+
if (!existsSync('server.js')) {
|
|
50
|
+
throw new PnpmError('NO_SCRIPT_OR_SERVER', 'Missing script start or file server.js');
|
|
51
|
+
}
|
|
52
|
+
m.scripts.start = 'node server.js';
|
|
53
|
+
}
|
|
54
|
+
break;
|
|
55
|
+
case 'install':
|
|
56
|
+
if (!m.scripts.install && !m.scripts.preinstall) {
|
|
57
|
+
checkBindingGyp(opts.pkgRoot, m.scripts);
|
|
58
|
+
}
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
if (opts.args?.length && m.scripts?.[stage]) {
|
|
62
|
+
// It is impossible to quote a command line argument that contains newline for Windows cmd.
|
|
63
|
+
const escapedArgs = isWindows()
|
|
64
|
+
? opts.args.map((arg) => JSON.stringify(arg)).join(' ')
|
|
65
|
+
: shellQuote(opts.args);
|
|
66
|
+
m.scripts[stage] = `${m.scripts[stage]} ${escapedArgs}`;
|
|
67
|
+
}
|
|
68
|
+
// This script is used to prevent the usage of npm or Yarn.
|
|
69
|
+
// It does nothing, when pnpm is used, so we may skip its execution.
|
|
70
|
+
if (m.scripts[stage] === 'npx only-allow pnpm' || !m.scripts[stage])
|
|
71
|
+
return false;
|
|
72
|
+
if (opts.stdio !== 'inherit') {
|
|
73
|
+
lifecycleLogger.debug({
|
|
74
|
+
depPath: opts.depPath,
|
|
75
|
+
optional,
|
|
76
|
+
script: m.scripts[stage],
|
|
77
|
+
stage,
|
|
78
|
+
wd: opts.pkgRoot,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const logLevel = (opts.stdio !== 'inherit' || opts.silent)
|
|
82
|
+
? 'silent'
|
|
83
|
+
: undefined;
|
|
84
|
+
await lifecycle(m, stage, opts.pkgRoot, {
|
|
85
|
+
config: {
|
|
86
|
+
...opts.rawConfig,
|
|
87
|
+
'frozen-lockfile': false,
|
|
88
|
+
},
|
|
89
|
+
dir: opts.rootModulesDir,
|
|
90
|
+
extraBinPaths: opts.extraBinPaths,
|
|
91
|
+
extraEnv: {
|
|
92
|
+
...opts.extraEnv,
|
|
93
|
+
INIT_CWD: opts.initCwd ?? process.cwd(),
|
|
94
|
+
PNPM_SCRIPT_SRC_DIR: opts.pkgRoot,
|
|
95
|
+
},
|
|
96
|
+
log: {
|
|
97
|
+
clearProgress: noop,
|
|
98
|
+
info: noop,
|
|
99
|
+
level: logLevel,
|
|
100
|
+
pause: noop,
|
|
101
|
+
resume: noop,
|
|
102
|
+
showProgress: noop,
|
|
103
|
+
silly: npmLog,
|
|
104
|
+
verbose: npmLog,
|
|
105
|
+
warn: (...msg) => {
|
|
106
|
+
globalWarn(msg.join(' '));
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
runConcurrently: true,
|
|
110
|
+
scriptsPrependNodePath: opts.scriptsPrependNodePath,
|
|
111
|
+
scriptShell: opts.scriptShell,
|
|
112
|
+
shellEmulator: opts.shellEmulator,
|
|
113
|
+
stdio: opts.stdio ?? 'pipe',
|
|
114
|
+
unsafePerm: opts.unsafePerm,
|
|
115
|
+
});
|
|
116
|
+
return true;
|
|
117
|
+
function npmLog(prefix, logId, stdtype, line) {
|
|
118
|
+
switch (stdtype) {
|
|
119
|
+
case 'stdout':
|
|
120
|
+
case 'stderr':
|
|
121
|
+
lifecycleLogger.debug({
|
|
122
|
+
depPath: opts.depPath,
|
|
123
|
+
line: (line ?? 0).toString(),
|
|
124
|
+
stage,
|
|
125
|
+
stdio: stdtype,
|
|
126
|
+
wd: opts.pkgRoot,
|
|
127
|
+
});
|
|
128
|
+
return;
|
|
129
|
+
case 'Returned: code:': {
|
|
130
|
+
if (opts.stdio === 'inherit') {
|
|
131
|
+
// Preventing the pnpm reporter from overriding the project's script output
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const code = line ?? 1;
|
|
135
|
+
lifecycleLogger.debug({
|
|
136
|
+
depPath: opts.depPath,
|
|
137
|
+
exitCode: code,
|
|
138
|
+
optional,
|
|
139
|
+
stage,
|
|
140
|
+
wd: opts.pkgRoot,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Run node-gyp when binding.gyp is available. Only do this when there are no
|
|
148
|
+
* `install` and `preinstall` scripts (see `npm help scripts`).
|
|
149
|
+
*/
|
|
150
|
+
function checkBindingGyp(root, scripts) {
|
|
151
|
+
if (existsSync(path.join(root, 'binding.gyp'))) {
|
|
152
|
+
scripts.install = 'node-gyp rebuild';
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function getId(manifest) {
|
|
156
|
+
return `${manifest.name ?? ''}@${manifest.version ?? ''}`;
|
|
157
|
+
}
|
|
158
|
+
function isWindowsBatchFile(scriptShell) {
|
|
159
|
+
// Node.js performs a similar check to determine whether it should throw
|
|
160
|
+
// EINVAL when spawning a .cmd/.bat file.
|
|
161
|
+
//
|
|
162
|
+
// https://github.com/nodejs/node/commit/6627222409#diff-1e725bfa950eda4d4b5c0c00a2bb6be3e5b83d819872a1adf2ef87c658273903
|
|
163
|
+
const scriptShellLower = scriptShell.toLowerCase();
|
|
164
|
+
return isWindows() && (scriptShellLower.endsWith('.cmd') || scriptShellLower.endsWith('.bat'));
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=runLifecycleHook.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { StoreController } from '@pnpm/store.controller-types';
|
|
2
|
+
import type { ProjectManifest, ProjectRootDir } from '@pnpm/types';
|
|
3
|
+
import { type RunLifecycleHookOptions } from './runLifecycleHook.js';
|
|
4
|
+
export type RunLifecycleHooksConcurrentlyOptions = Omit<RunLifecycleHookOptions, 'depPath' | 'pkgRoot' | 'rootModulesDir'> & {
|
|
5
|
+
resolveSymlinksInInjectedDirs?: boolean;
|
|
6
|
+
storeController: StoreController;
|
|
7
|
+
extraNodePaths?: string[];
|
|
8
|
+
preferSymlinkedExecutables?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export interface Importer {
|
|
11
|
+
buildIndex: number;
|
|
12
|
+
manifest: ProjectManifest;
|
|
13
|
+
rootDir: ProjectRootDir;
|
|
14
|
+
modulesDir: string;
|
|
15
|
+
stages?: string[];
|
|
16
|
+
targetDirs?: string[];
|
|
17
|
+
}
|
|
18
|
+
export declare function runLifecycleHooksConcurrently(stages: string[], importers: Importer[], childConcurrency: number, opts: RunLifecycleHooksConcurrentlyOptions): Promise<void>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { linkBins } from '@pnpm/bins.linker';
|
|
4
|
+
import { fetchFromDir } from '@pnpm/fetching.directory-fetcher';
|
|
5
|
+
import { logger } from '@pnpm/logger';
|
|
6
|
+
import { runGroups } from 'run-groups';
|
|
7
|
+
import { runLifecycleHook } from './runLifecycleHook.js';
|
|
8
|
+
export async function runLifecycleHooksConcurrently(stages, importers, childConcurrency, opts) {
|
|
9
|
+
const importersByBuildIndex = new Map();
|
|
10
|
+
for (const importer of importers) {
|
|
11
|
+
if (!importersByBuildIndex.has(importer.buildIndex)) {
|
|
12
|
+
importersByBuildIndex.set(importer.buildIndex, [importer]);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
importersByBuildIndex.get(importer.buildIndex).push(importer);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const sortedBuildIndexes = Array.from(importersByBuildIndex.keys()).sort((a, b) => a - b);
|
|
19
|
+
const groups = sortedBuildIndexes.map((buildIndex) => {
|
|
20
|
+
const importers = importersByBuildIndex.get(buildIndex);
|
|
21
|
+
return importers.map(({ manifest, modulesDir, rootDir, stages: importerStages, targetDirs }) => async () => {
|
|
22
|
+
// We are linking the bin files, in case they were created by lifecycle scripts of other workspace packages.
|
|
23
|
+
await linkBins(modulesDir, path.join(modulesDir, '.bin'), {
|
|
24
|
+
extraNodePaths: opts.extraNodePaths,
|
|
25
|
+
allowExoticManifests: true,
|
|
26
|
+
preferSymlinkedExecutables: opts.preferSymlinkedExecutables,
|
|
27
|
+
projectManifest: manifest,
|
|
28
|
+
warn: (message) => {
|
|
29
|
+
logger.warn({ message, prefix: rootDir });
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
const runLifecycleHookOpts = {
|
|
33
|
+
...opts,
|
|
34
|
+
depPath: rootDir,
|
|
35
|
+
pkgRoot: rootDir,
|
|
36
|
+
rootModulesDir: modulesDir,
|
|
37
|
+
};
|
|
38
|
+
let isBuilt = false;
|
|
39
|
+
for (const stage of (importerStages ?? stages)) {
|
|
40
|
+
if (await runLifecycleHook(stage, manifest, runLifecycleHookOpts)) { // eslint-disable-line no-await-in-loop
|
|
41
|
+
isBuilt = true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (targetDirs == null || targetDirs.length === 0 || !isBuilt)
|
|
45
|
+
return;
|
|
46
|
+
const filesResponse = await fetchFromDir(rootDir, { resolveSymlinks: opts.resolveSymlinksInInjectedDirs });
|
|
47
|
+
await Promise.all(targetDirs.map(async (targetDir) => {
|
|
48
|
+
const targetModulesDir = path.join(targetDir, 'node_modules');
|
|
49
|
+
const newFilesMap = new Map(filesResponse.filesMap);
|
|
50
|
+
if (fs.existsSync(targetModulesDir)) {
|
|
51
|
+
// If the target directory contains a node_modules directory
|
|
52
|
+
// (it may happen when the hoisted node linker is used)
|
|
53
|
+
// then we need to preserve this node_modules.
|
|
54
|
+
// So we scan this node_modules directory and pass it as part of the new package.
|
|
55
|
+
await scanDir('node_modules', targetModulesDir, targetModulesDir, newFilesMap);
|
|
56
|
+
}
|
|
57
|
+
return opts.storeController.importPackage(targetDir, {
|
|
58
|
+
filesResponse: {
|
|
59
|
+
resolvedFrom: 'local-dir',
|
|
60
|
+
...filesResponse,
|
|
61
|
+
filesMap: newFilesMap,
|
|
62
|
+
},
|
|
63
|
+
force: false,
|
|
64
|
+
});
|
|
65
|
+
}));
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
await runGroups(childConcurrency, groups);
|
|
69
|
+
}
|
|
70
|
+
async function scanDir(prefix, rootDir, currentDir, index) {
|
|
71
|
+
const files = await fs.promises.readdir(currentDir);
|
|
72
|
+
await Promise.all(files.map(async (file) => {
|
|
73
|
+
const fullPath = path.join(currentDir, file);
|
|
74
|
+
const stat = await fs.promises.stat(fullPath);
|
|
75
|
+
if (stat.isDirectory()) {
|
|
76
|
+
return scanDir(prefix, rootDir, fullPath, index);
|
|
77
|
+
}
|
|
78
|
+
if (stat.isFile()) {
|
|
79
|
+
const relativePath = path.relative(rootDir, fullPath);
|
|
80
|
+
index.set(path.join(prefix, relativePath), fullPath);
|
|
81
|
+
}
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=runLifecycleHooksConcurrently.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pnpm/exec.lifecycle",
|
|
3
|
+
"version": "1001.0.25",
|
|
4
|
+
"description": "Package lifecycle hook runner",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"pnpm",
|
|
7
|
+
"pnpm11",
|
|
8
|
+
"lifecycle",
|
|
9
|
+
"scripts"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"funding": "https://opencollective.com/pnpm",
|
|
13
|
+
"repository": "https://github.com/pnpm/pnpm/tree/main/exec/lifecycle",
|
|
14
|
+
"homepage": "https://github.com/pnpm/pnpm/tree/main/exec/lifecycle#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/pnpm/pnpm/issues"
|
|
17
|
+
},
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "lib/index.js",
|
|
20
|
+
"types": "lib/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": "./lib/index.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"lib",
|
|
26
|
+
"!*.map"
|
|
27
|
+
],
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@pnpm/npm-lifecycle": "^1001.0.0",
|
|
30
|
+
"is-windows": "^1.0.2",
|
|
31
|
+
"path-exists": "^5.0.0",
|
|
32
|
+
"run-groups": "^5.0.0",
|
|
33
|
+
"shlex": "^3.0.0",
|
|
34
|
+
"@pnpm/core-loggers": "1001.0.4",
|
|
35
|
+
"@pnpm/bins.linker": "1000.2.6",
|
|
36
|
+
"@pnpm/fetching.directory-fetcher": "1000.1.14",
|
|
37
|
+
"@pnpm/error": "1000.0.5",
|
|
38
|
+
"@pnpm/store.cafs-types": "1000.0.0",
|
|
39
|
+
"@pnpm/store.controller-types": "1004.1.0",
|
|
40
|
+
"@pnpm/types": "1000.9.0",
|
|
41
|
+
"@pnpm/pkg-manifest.reader": "1000.1.2"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"@pnpm/logger": ">=1001.0.0 <1002.0.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/is-windows": "^1.0.2",
|
|
48
|
+
"@zkochan/rimraf": "^4.0.0",
|
|
49
|
+
"load-json-file": "^7.0.1",
|
|
50
|
+
"@pnpm/prepare": "1000.0.4",
|
|
51
|
+
"@pnpm/exec.lifecycle": "1001.0.25",
|
|
52
|
+
"@pnpm/test-fixtures": "1000.0.0",
|
|
53
|
+
"@pnpm/test-ipc-server": "1000.0.0",
|
|
54
|
+
"@pnpm/logger": "1001.0.1"
|
|
55
|
+
},
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=22.13"
|
|
58
|
+
},
|
|
59
|
+
"jest": {
|
|
60
|
+
"preset": "@pnpm/jest-config"
|
|
61
|
+
},
|
|
62
|
+
"scripts": {
|
|
63
|
+
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
64
|
+
"_test": "cross-env NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules --disable-warning=ExperimentalWarning --disable-warning=DEP0169\" jest",
|
|
65
|
+
"test": "pnpm run compile && pnpm run _test",
|
|
66
|
+
"fix": "tslint -c tslint.json src/**/*.ts test/**/*.ts --fix",
|
|
67
|
+
"compile": "tsgo --build && pnpm run lint --fix"
|
|
68
|
+
}
|
|
69
|
+
}
|