@pnpm/building.after-install 1000.0.0-0
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 +17 -0
- package/lib/extendBuildOptions.d.ts +51 -0
- package/lib/extendBuildOptions.js +54 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.js +369 -0
- package/package.json +76 -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,17 @@
|
|
|
1
|
+
# @pnpm/building.after-install
|
|
2
|
+
|
|
3
|
+
> Rebuild packages that are already installed by running their lifecycle scripts
|
|
4
|
+
|
|
5
|
+
<!--@shields('npm')-->
|
|
6
|
+
[](https://www.npmjs.com/package/@pnpm/building.after-install)
|
|
7
|
+
<!--/@-->
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
pnpm add @pnpm/building.after-install
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## License
|
|
16
|
+
|
|
17
|
+
MIT
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type Config } from '@pnpm/config';
|
|
2
|
+
import type { LogBase } from '@pnpm/logger';
|
|
3
|
+
import type { StoreController } from '@pnpm/store-controller-types';
|
|
4
|
+
import type { Registries } from '@pnpm/types';
|
|
5
|
+
export type StrictBuildOptions = {
|
|
6
|
+
autoInstallPeers: boolean;
|
|
7
|
+
cacheDir: string;
|
|
8
|
+
childConcurrency: number;
|
|
9
|
+
excludeLinksFromLockfile: boolean;
|
|
10
|
+
extraBinPaths: string[];
|
|
11
|
+
extraEnv: Record<string, string>;
|
|
12
|
+
lockfileDir: string;
|
|
13
|
+
nodeLinker: 'isolated' | 'hoisted' | 'pnp';
|
|
14
|
+
preferSymlinkedExecutables?: boolean;
|
|
15
|
+
scriptShell?: string;
|
|
16
|
+
sideEffectsCacheRead: boolean;
|
|
17
|
+
sideEffectsCacheWrite: boolean;
|
|
18
|
+
scriptsPrependNodePath: boolean | 'warn-only';
|
|
19
|
+
shellEmulator: boolean;
|
|
20
|
+
skipIfHasSideEffectsCache?: boolean;
|
|
21
|
+
storeDir: string;
|
|
22
|
+
storeController: StoreController;
|
|
23
|
+
force: boolean;
|
|
24
|
+
useLockfile: boolean;
|
|
25
|
+
registries: Registries;
|
|
26
|
+
dir: string;
|
|
27
|
+
pnpmHomeDir: string;
|
|
28
|
+
reporter: (logObj: LogBase) => void;
|
|
29
|
+
production: boolean;
|
|
30
|
+
development: boolean;
|
|
31
|
+
optional: boolean;
|
|
32
|
+
rawConfig: object;
|
|
33
|
+
userConfig: Record<string, string>;
|
|
34
|
+
userAgent: string;
|
|
35
|
+
packageManager: {
|
|
36
|
+
name: string;
|
|
37
|
+
version: string;
|
|
38
|
+
};
|
|
39
|
+
unsafePerm: boolean;
|
|
40
|
+
pending: boolean;
|
|
41
|
+
shamefullyHoist: boolean;
|
|
42
|
+
deployAllFiles: boolean;
|
|
43
|
+
neverBuiltDependencies?: string[];
|
|
44
|
+
allowBuilds?: Record<string, boolean | string>;
|
|
45
|
+
virtualStoreDirMaxLength: number;
|
|
46
|
+
peersSuffixMaxLength: number;
|
|
47
|
+
strictStorePkgContentCheck: boolean;
|
|
48
|
+
fetchFullMetadata?: boolean;
|
|
49
|
+
} & Pick<Config, 'sslConfigs' | 'allowBuilds'>;
|
|
50
|
+
export type BuildOptions = Partial<StrictBuildOptions> & Pick<StrictBuildOptions, 'storeDir' | 'storeController'> & Pick<Config, 'rootProjectManifest' | 'rootProjectManifestDir'>;
|
|
51
|
+
export declare function extendBuildOptions(opts: BuildOptions): Promise<StrictBuildOptions>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { getOptionsFromRootManifest } from '@pnpm/config';
|
|
3
|
+
import { normalizeRegistries, DEFAULT_REGISTRIES } from '@pnpm/normalize-registries';
|
|
4
|
+
import { loadJsonFile } from 'load-json-file';
|
|
5
|
+
const defaults = async (opts) => {
|
|
6
|
+
const packageManager = opts.packageManager ??
|
|
7
|
+
await loadJsonFile(path.join(import.meta.dirname, '../package.json'));
|
|
8
|
+
const dir = opts.dir ?? process.cwd();
|
|
9
|
+
const lockfileDir = opts.lockfileDir ?? dir;
|
|
10
|
+
return {
|
|
11
|
+
childConcurrency: 5,
|
|
12
|
+
development: true,
|
|
13
|
+
dir,
|
|
14
|
+
force: false,
|
|
15
|
+
lockfileDir,
|
|
16
|
+
nodeLinker: 'isolated',
|
|
17
|
+
optional: true,
|
|
18
|
+
packageManager,
|
|
19
|
+
pending: false,
|
|
20
|
+
production: true,
|
|
21
|
+
rawConfig: {},
|
|
22
|
+
registries: DEFAULT_REGISTRIES,
|
|
23
|
+
scriptsPrependNodePath: false,
|
|
24
|
+
shamefullyHoist: false,
|
|
25
|
+
shellEmulator: false,
|
|
26
|
+
sideEffectsCacheRead: false,
|
|
27
|
+
storeDir: opts.storeDir,
|
|
28
|
+
unsafePerm: process.platform === 'win32' ||
|
|
29
|
+
process.platform === 'cygwin' ||
|
|
30
|
+
!process.setgid ||
|
|
31
|
+
process.getuid?.() !== 0,
|
|
32
|
+
useLockfile: true,
|
|
33
|
+
userAgent: `${packageManager.name}/${packageManager.version} npm/? node/${process.version} ${process.platform} ${process.arch}`,
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export async function extendBuildOptions(opts) {
|
|
37
|
+
if (opts) {
|
|
38
|
+
for (const key in opts) {
|
|
39
|
+
if (opts[key] === undefined) {
|
|
40
|
+
delete opts[key];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const defaultOpts = await defaults(opts);
|
|
45
|
+
const extendedOpts = {
|
|
46
|
+
...defaultOpts,
|
|
47
|
+
...opts,
|
|
48
|
+
storeDir: defaultOpts.storeDir,
|
|
49
|
+
...(opts.rootProjectManifest ? getOptionsFromRootManifest(opts.rootProjectManifestDir, opts.rootProjectManifest) : {}),
|
|
50
|
+
};
|
|
51
|
+
extendedOpts.registries = normalizeRegistries(extendedOpts.registries);
|
|
52
|
+
return extendedOpts;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=extendBuildOptions.js.map
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { IgnoredBuilds, ProjectManifest, ProjectRootDir } from '@pnpm/types';
|
|
2
|
+
import { type BuildOptions } from './extendBuildOptions.js';
|
|
3
|
+
export type { BuildOptions };
|
|
4
|
+
export declare function buildSelectedPkgs(projects: Array<{
|
|
5
|
+
buildIndex: number;
|
|
6
|
+
manifest: ProjectManifest;
|
|
7
|
+
rootDir: ProjectRootDir;
|
|
8
|
+
}>, pkgSpecs: string[], maybeOpts: BuildOptions): Promise<{
|
|
9
|
+
ignoredBuilds?: IgnoredBuilds;
|
|
10
|
+
}>;
|
|
11
|
+
export declare function buildProjects(projects: Array<{
|
|
12
|
+
buildIndex: number;
|
|
13
|
+
manifest: ProjectManifest;
|
|
14
|
+
rootDir: ProjectRootDir;
|
|
15
|
+
}>, maybeOpts: BuildOptions): Promise<void>;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import util from 'util';
|
|
4
|
+
import { pkgRequiresBuild } from '@pnpm/building.pkg-requires-build';
|
|
5
|
+
import { createAllowBuildFunction } from '@pnpm/building.policy';
|
|
6
|
+
import { calcDepState, lockfileToDepGraph } from '@pnpm/calc-dep-state';
|
|
7
|
+
import { LAYOUT_VERSION, WANTED_LOCKFILE, } from '@pnpm/constants';
|
|
8
|
+
import { skippedOptionalDependencyLogger } from '@pnpm/core-loggers';
|
|
9
|
+
import * as dp from '@pnpm/dependency-path';
|
|
10
|
+
import { graphSequencer } from '@pnpm/deps.graph-sequencer';
|
|
11
|
+
import { PnpmError } from '@pnpm/error';
|
|
12
|
+
import { getContext } from '@pnpm/get-context';
|
|
13
|
+
import { runLifecycleHooksConcurrently, runPostinstallHooks, } from '@pnpm/lifecycle';
|
|
14
|
+
import { linkBins } from '@pnpm/link-bins';
|
|
15
|
+
import { nameVerFromPkgSnapshot, packageIsIndependent, } from '@pnpm/lockfile.utils';
|
|
16
|
+
import { lockfileWalker } from '@pnpm/lockfile.walker';
|
|
17
|
+
import { logger, streamParser } from '@pnpm/logger';
|
|
18
|
+
import { writeModulesManifest } from '@pnpm/modules-yaml';
|
|
19
|
+
import npa from '@pnpm/npm-package-arg';
|
|
20
|
+
import { safeReadPackageJsonFromDir } from '@pnpm/read-package-json';
|
|
21
|
+
import { StoreIndex, storeIndexKey } from '@pnpm/store.index';
|
|
22
|
+
import { createStoreController } from '@pnpm/store-connection-manager';
|
|
23
|
+
import { hardLinkDir } from '@pnpm/worker';
|
|
24
|
+
import pLimit from 'p-limit';
|
|
25
|
+
import { runGroups } from 'run-groups';
|
|
26
|
+
import semver from 'semver';
|
|
27
|
+
import { extendBuildOptions, } from './extendBuildOptions.js';
|
|
28
|
+
function findPackages(packages, searched, opts) {
|
|
29
|
+
return Object.keys(packages)
|
|
30
|
+
.filter((relativeDepPath) => {
|
|
31
|
+
const pkgLockfile = packages[relativeDepPath];
|
|
32
|
+
const pkgInfo = nameVerFromPkgSnapshot(relativeDepPath, pkgLockfile);
|
|
33
|
+
if (!pkgInfo.name) {
|
|
34
|
+
logger.warn({
|
|
35
|
+
message: `Skipping ${relativeDepPath} because cannot get the package name from ${WANTED_LOCKFILE}.
|
|
36
|
+
Try to run \`pnpm update --depth 100\` to create a new ${WANTED_LOCKFILE} with all the necessary info.`,
|
|
37
|
+
prefix: opts.prefix,
|
|
38
|
+
});
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return matches(searched, pkgInfo);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
// TODO: move this logic to separate package as this is also used in dependencies-hierarchy
|
|
45
|
+
function matches(searched, manifest) {
|
|
46
|
+
return searched.some((searchedPkg) => {
|
|
47
|
+
if (typeof searchedPkg === 'string') {
|
|
48
|
+
return manifest.name === searchedPkg;
|
|
49
|
+
}
|
|
50
|
+
return searchedPkg.name === manifest.name && !!manifest.version &&
|
|
51
|
+
semver.satisfies(manifest.version, searchedPkg.range);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export async function buildSelectedPkgs(projects, pkgSpecs, maybeOpts) {
|
|
55
|
+
const reporter = maybeOpts?.reporter;
|
|
56
|
+
if ((reporter != null) && typeof reporter === 'function') {
|
|
57
|
+
streamParser.on('data', reporter);
|
|
58
|
+
}
|
|
59
|
+
const opts = await extendBuildOptions(maybeOpts);
|
|
60
|
+
const ctx = await getContext({ ...opts, allProjects: projects });
|
|
61
|
+
if (ctx.currentLockfile?.packages == null)
|
|
62
|
+
return {};
|
|
63
|
+
const packages = ctx.currentLockfile.packages;
|
|
64
|
+
const searched = pkgSpecs.map((arg) => {
|
|
65
|
+
const { fetchSpec, name, raw, type } = npa(arg);
|
|
66
|
+
if (raw === name) {
|
|
67
|
+
return name;
|
|
68
|
+
}
|
|
69
|
+
if (type !== 'version' && type !== 'range') {
|
|
70
|
+
throw new Error(`Invalid argument - ${arg}. Rebuild can only select by version or range`);
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
name,
|
|
74
|
+
range: fetchSpec,
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
let pkgs = [];
|
|
78
|
+
for (const { rootDir } of projects) {
|
|
79
|
+
pkgs = [
|
|
80
|
+
...pkgs,
|
|
81
|
+
...findPackages(packages, searched, { prefix: rootDir }),
|
|
82
|
+
];
|
|
83
|
+
}
|
|
84
|
+
const { ignoredPkgs } = await _rebuild({
|
|
85
|
+
pkgsToRebuild: new Set(pkgs),
|
|
86
|
+
...ctx,
|
|
87
|
+
}, opts);
|
|
88
|
+
await writeModulesManifest(ctx.rootModulesDir, {
|
|
89
|
+
prunedAt: new Date().toUTCString(),
|
|
90
|
+
...ctx.modulesFile,
|
|
91
|
+
hoistedDependencies: ctx.hoistedDependencies,
|
|
92
|
+
hoistPattern: ctx.hoistPattern,
|
|
93
|
+
included: ctx.include,
|
|
94
|
+
ignoredBuilds: ignoredPkgs,
|
|
95
|
+
layoutVersion: LAYOUT_VERSION,
|
|
96
|
+
packageManager: `${opts.packageManager.name}@${opts.packageManager.version}`,
|
|
97
|
+
pendingBuilds: ctx.pendingBuilds,
|
|
98
|
+
publicHoistPattern: ctx.publicHoistPattern,
|
|
99
|
+
registries: ctx.registries,
|
|
100
|
+
skipped: Array.from(ctx.skipped),
|
|
101
|
+
storeDir: ctx.storeDir,
|
|
102
|
+
virtualStoreDir: ctx.virtualStoreDir,
|
|
103
|
+
virtualStoreDirMaxLength: ctx.virtualStoreDirMaxLength,
|
|
104
|
+
});
|
|
105
|
+
return {
|
|
106
|
+
ignoredBuilds: ignoredPkgs,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export async function buildProjects(projects, maybeOpts) {
|
|
110
|
+
const reporter = maybeOpts?.reporter;
|
|
111
|
+
if ((reporter != null) && typeof reporter === 'function') {
|
|
112
|
+
streamParser.on('data', reporter);
|
|
113
|
+
}
|
|
114
|
+
const opts = await extendBuildOptions(maybeOpts);
|
|
115
|
+
const ctx = await getContext({ ...opts, allProjects: projects });
|
|
116
|
+
let idsToRebuild = [];
|
|
117
|
+
if (opts.pending) {
|
|
118
|
+
idsToRebuild = ctx.pendingBuilds;
|
|
119
|
+
}
|
|
120
|
+
else if ((ctx.currentLockfile?.packages) != null) {
|
|
121
|
+
idsToRebuild = Object.keys(ctx.currentLockfile.packages);
|
|
122
|
+
}
|
|
123
|
+
const { pkgsThatWereRebuilt, ignoredPkgs } = await _rebuild({
|
|
124
|
+
pkgsToRebuild: new Set(idsToRebuild),
|
|
125
|
+
...ctx,
|
|
126
|
+
}, opts);
|
|
127
|
+
ctx.pendingBuilds = ctx.pendingBuilds.filter((depPath) => !pkgsThatWereRebuilt.has(depPath));
|
|
128
|
+
const store = await createStoreController(opts);
|
|
129
|
+
const scriptsOpts = {
|
|
130
|
+
extraBinPaths: ctx.extraBinPaths,
|
|
131
|
+
extraNodePaths: ctx.extraNodePaths,
|
|
132
|
+
extraEnv: opts.extraEnv,
|
|
133
|
+
preferSymlinkedExecutables: opts.preferSymlinkedExecutables,
|
|
134
|
+
rawConfig: opts.rawConfig,
|
|
135
|
+
scriptsPrependNodePath: opts.scriptsPrependNodePath,
|
|
136
|
+
scriptShell: opts.scriptShell,
|
|
137
|
+
shellEmulator: opts.shellEmulator,
|
|
138
|
+
storeController: store.ctrl,
|
|
139
|
+
unsafePerm: opts.unsafePerm || false,
|
|
140
|
+
};
|
|
141
|
+
await runLifecycleHooksConcurrently(['preinstall', 'install', 'postinstall', 'prepublish', 'prepare'], Object.values(ctx.projects), opts.childConcurrency || 5, scriptsOpts);
|
|
142
|
+
for (const { id, manifest } of Object.values(ctx.projects)) {
|
|
143
|
+
if (((manifest?.scripts) != null) && (!opts.pending || ctx.pendingBuilds.includes(id))) {
|
|
144
|
+
ctx.pendingBuilds.splice(ctx.pendingBuilds.indexOf(id), 1);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
await writeModulesManifest(ctx.rootModulesDir, {
|
|
148
|
+
prunedAt: new Date().toUTCString(),
|
|
149
|
+
...ctx.modulesFile,
|
|
150
|
+
hoistedDependencies: ctx.hoistedDependencies,
|
|
151
|
+
hoistPattern: ctx.hoistPattern,
|
|
152
|
+
included: ctx.include,
|
|
153
|
+
ignoredBuilds: ignoredPkgs,
|
|
154
|
+
layoutVersion: LAYOUT_VERSION,
|
|
155
|
+
packageManager: `${opts.packageManager.name}@${opts.packageManager.version}`,
|
|
156
|
+
pendingBuilds: ctx.pendingBuilds,
|
|
157
|
+
publicHoistPattern: ctx.publicHoistPattern,
|
|
158
|
+
registries: ctx.registries,
|
|
159
|
+
skipped: Array.from(ctx.skipped),
|
|
160
|
+
storeDir: ctx.storeDir,
|
|
161
|
+
virtualStoreDir: ctx.virtualStoreDir,
|
|
162
|
+
virtualStoreDirMaxLength: ctx.virtualStoreDirMaxLength,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
function getSubgraphToBuild(step, nodesToBuildAndTransitive, opts) {
|
|
166
|
+
let currentShouldBeBuilt = false;
|
|
167
|
+
for (const { depPath, next } of step.dependencies) {
|
|
168
|
+
if (nodesToBuildAndTransitive.has(depPath)) {
|
|
169
|
+
currentShouldBeBuilt = true;
|
|
170
|
+
}
|
|
171
|
+
const childShouldBeBuilt = getSubgraphToBuild(next(), nodesToBuildAndTransitive, opts) ||
|
|
172
|
+
opts.pkgsToRebuild.has(depPath);
|
|
173
|
+
if (childShouldBeBuilt) {
|
|
174
|
+
nodesToBuildAndTransitive.add(depPath);
|
|
175
|
+
currentShouldBeBuilt = true;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
for (const depPath of step.missing) {
|
|
179
|
+
// It might make sense to fail if the depPath is not in the skipped list from .modules.yaml
|
|
180
|
+
// However, the skipped list currently contains package IDs, not dep paths.
|
|
181
|
+
logger.debug({ message: `No entry for "${depPath}" in ${WANTED_LOCKFILE}` });
|
|
182
|
+
}
|
|
183
|
+
return currentShouldBeBuilt;
|
|
184
|
+
}
|
|
185
|
+
const limitLinking = pLimit(16);
|
|
186
|
+
async function _rebuild(ctx, opts) {
|
|
187
|
+
const depGraph = lockfileToDepGraph(ctx.currentLockfile);
|
|
188
|
+
const depsStateCache = {};
|
|
189
|
+
const pkgsThatWereRebuilt = new Set();
|
|
190
|
+
const graph = new Map();
|
|
191
|
+
const pkgSnapshots = ctx.currentLockfile.packages ?? {};
|
|
192
|
+
const nodesToBuildAndTransitive = new Set();
|
|
193
|
+
getSubgraphToBuild(lockfileWalker(ctx.currentLockfile, Object.values(ctx.projects).map(({ id }) => id), {
|
|
194
|
+
include: {
|
|
195
|
+
dependencies: opts.production,
|
|
196
|
+
devDependencies: opts.development,
|
|
197
|
+
optionalDependencies: opts.optional,
|
|
198
|
+
},
|
|
199
|
+
}).step, nodesToBuildAndTransitive, { pkgsToRebuild: ctx.pkgsToRebuild });
|
|
200
|
+
const nodesToBuildAndTransitiveArray = Array.from(nodesToBuildAndTransitive);
|
|
201
|
+
for (const depPath of nodesToBuildAndTransitiveArray) {
|
|
202
|
+
const pkgSnapshot = pkgSnapshots[depPath];
|
|
203
|
+
graph.set(depPath, Object.entries({ ...pkgSnapshot.dependencies, ...pkgSnapshot.optionalDependencies })
|
|
204
|
+
.map(([pkgName, reference]) => dp.refToRelative(reference, pkgName))
|
|
205
|
+
.filter((childRelDepPath) => childRelDepPath && nodesToBuildAndTransitive.has(childRelDepPath)));
|
|
206
|
+
}
|
|
207
|
+
const graphSequencerResult = graphSequencer(graph, nodesToBuildAndTransitiveArray);
|
|
208
|
+
const chunks = graphSequencerResult.chunks;
|
|
209
|
+
const warn = (message) => {
|
|
210
|
+
logger.info({ message, prefix: opts.dir });
|
|
211
|
+
};
|
|
212
|
+
const ignoredPkgs = new Set();
|
|
213
|
+
const _allowBuild = createAllowBuildFunction(opts) ?? (() => undefined);
|
|
214
|
+
const allowBuild = (pkgName, version, depPath) => {
|
|
215
|
+
switch (_allowBuild(pkgName, version)) {
|
|
216
|
+
case true: return true;
|
|
217
|
+
case undefined: {
|
|
218
|
+
ignoredPkgs.add(depPath);
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return false;
|
|
223
|
+
};
|
|
224
|
+
const builtDepPaths = new Set();
|
|
225
|
+
const storeIndex = opts.skipIfHasSideEffectsCache ? new StoreIndex(opts.storeDir) : undefined;
|
|
226
|
+
const groups = chunks.map((chunk) => chunk.filter((depPath) => ctx.pkgsToRebuild.has(depPath) && !ctx.skipped.has(depPath)).map((depPath) => async () => {
|
|
227
|
+
const pkgSnapshot = pkgSnapshots[depPath];
|
|
228
|
+
const pkgInfo = nameVerFromPkgSnapshot(depPath, pkgSnapshot);
|
|
229
|
+
const pkgRoots = opts.nodeLinker === 'hoisted'
|
|
230
|
+
? (ctx.modulesFile?.hoistedLocations?.[depPath] ?? []).map((hoistedLocation) => path.join(opts.lockfileDir, hoistedLocation))
|
|
231
|
+
: [path.join(ctx.virtualStoreDir, dp.depPathToFilename(depPath, opts.virtualStoreDirMaxLength), 'node_modules', pkgInfo.name)];
|
|
232
|
+
if (pkgRoots.length === 0) {
|
|
233
|
+
if (pkgSnapshot.optional)
|
|
234
|
+
return;
|
|
235
|
+
throw new PnpmError('MISSING_HOISTED_LOCATIONS', `${depPath} is not found in hoistedLocations inside node_modules/.modules.yaml`, {
|
|
236
|
+
hint: 'If you installed your node_modules with pnpm older than v7.19.0, you may need to remove it and run "pnpm install"',
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
const pkgRoot = pkgRoots[0];
|
|
240
|
+
try {
|
|
241
|
+
const extraBinPaths = ctx.extraBinPaths;
|
|
242
|
+
if (opts.nodeLinker !== 'hoisted') {
|
|
243
|
+
const modules = path.join(ctx.virtualStoreDir, dp.depPathToFilename(depPath, opts.virtualStoreDirMaxLength), 'node_modules');
|
|
244
|
+
const binPath = path.join(pkgRoot, 'node_modules', '.bin');
|
|
245
|
+
await linkBins(modules, binPath, { extraNodePaths: ctx.extraNodePaths, warn });
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
extraBinPaths.push(...binDirsInAllParentDirs(pkgRoot, opts.lockfileDir));
|
|
249
|
+
}
|
|
250
|
+
const resolution = pkgSnapshot.resolution;
|
|
251
|
+
let sideEffectsCacheKey;
|
|
252
|
+
const pkgId = `${pkgInfo.name}@${pkgInfo.version}`;
|
|
253
|
+
if (opts.skipIfHasSideEffectsCache && resolution.integrity) {
|
|
254
|
+
const filesIndexFile = storeIndexKey(resolution.integrity.toString(), pkgId);
|
|
255
|
+
const pkgFilesIndex = storeIndex.get(filesIndexFile);
|
|
256
|
+
if (pkgFilesIndex) {
|
|
257
|
+
sideEffectsCacheKey = calcDepState(depGraph, depsStateCache, depPath, {
|
|
258
|
+
includeDepGraphHash: true,
|
|
259
|
+
});
|
|
260
|
+
if (pkgFilesIndex.sideEffects?.has(sideEffectsCacheKey)) {
|
|
261
|
+
pkgsThatWereRebuilt.add(depPath);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
let requiresBuild = true;
|
|
267
|
+
const pgkManifest = await safeReadPackageJsonFromDir(pkgRoot);
|
|
268
|
+
if (pgkManifest != null) {
|
|
269
|
+
// This won't return the correct result for packages with binding.gyp as we don't pass the filesIndex to the function.
|
|
270
|
+
// However, currently rebuild doesn't work for such packages at all, which should be fixed.
|
|
271
|
+
requiresBuild = pkgRequiresBuild(pgkManifest, new Map());
|
|
272
|
+
}
|
|
273
|
+
const hasSideEffects = requiresBuild && allowBuild(pkgInfo.name, pkgInfo.version, depPath) && await runPostinstallHooks({
|
|
274
|
+
depPath,
|
|
275
|
+
extraBinPaths,
|
|
276
|
+
extraEnv: opts.extraEnv,
|
|
277
|
+
optional: pkgSnapshot.optional === true,
|
|
278
|
+
pkgRoot,
|
|
279
|
+
rawConfig: opts.rawConfig,
|
|
280
|
+
rootModulesDir: ctx.rootModulesDir,
|
|
281
|
+
scriptsPrependNodePath: opts.scriptsPrependNodePath,
|
|
282
|
+
shellEmulator: opts.shellEmulator,
|
|
283
|
+
unsafePerm: opts.unsafePerm || false,
|
|
284
|
+
});
|
|
285
|
+
if (hasSideEffects && (opts.sideEffectsCacheWrite ?? true) && resolution.integrity) {
|
|
286
|
+
builtDepPaths.add(depPath);
|
|
287
|
+
const filesIndexFile = storeIndexKey(resolution.integrity.toString(), pkgId);
|
|
288
|
+
try {
|
|
289
|
+
if (!sideEffectsCacheKey) {
|
|
290
|
+
sideEffectsCacheKey = calcDepState(depGraph, depsStateCache, depPath, {
|
|
291
|
+
includeDepGraphHash: true,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
await opts.storeController.upload(pkgRoot, {
|
|
295
|
+
sideEffectsCacheKey,
|
|
296
|
+
filesIndexFile,
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
catch (err) {
|
|
300
|
+
assert(util.types.isNativeError(err));
|
|
301
|
+
logger.warn({
|
|
302
|
+
error: err,
|
|
303
|
+
message: `An error occurred while uploading ${pkgRoot}`,
|
|
304
|
+
prefix: opts.lockfileDir,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
pkgsThatWereRebuilt.add(depPath);
|
|
309
|
+
}
|
|
310
|
+
catch (err) {
|
|
311
|
+
assert(util.types.isNativeError(err));
|
|
312
|
+
if (pkgSnapshot.optional) {
|
|
313
|
+
// TODO: add parents field to the log
|
|
314
|
+
skippedOptionalDependencyLogger.debug({
|
|
315
|
+
details: err.toString(),
|
|
316
|
+
package: {
|
|
317
|
+
id: pkgSnapshot.id ?? depPath,
|
|
318
|
+
name: pkgInfo.name,
|
|
319
|
+
version: pkgInfo.version,
|
|
320
|
+
},
|
|
321
|
+
prefix: opts.dir,
|
|
322
|
+
reason: 'build_failure',
|
|
323
|
+
});
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
throw err;
|
|
327
|
+
}
|
|
328
|
+
if (pkgRoots.length > 1) {
|
|
329
|
+
await hardLinkDir(pkgRoot, pkgRoots.slice(1));
|
|
330
|
+
}
|
|
331
|
+
}));
|
|
332
|
+
await runGroups(opts.childConcurrency || 5, groups);
|
|
333
|
+
storeIndex?.close();
|
|
334
|
+
if (builtDepPaths.size > 0) {
|
|
335
|
+
// It may be optimized because some bins were already linked before running lifecycle scripts
|
|
336
|
+
await Promise.all(Object
|
|
337
|
+
.keys(pkgSnapshots)
|
|
338
|
+
.filter((depPath) => !packageIsIndependent(pkgSnapshots[depPath]))
|
|
339
|
+
.map(async (depPath) => limitLinking(async () => {
|
|
340
|
+
const pkgSnapshot = pkgSnapshots[depPath];
|
|
341
|
+
const pkgInfo = nameVerFromPkgSnapshot(depPath, pkgSnapshot);
|
|
342
|
+
const modules = path.join(ctx.virtualStoreDir, dp.depPathToFilename(depPath, opts.virtualStoreDirMaxLength), 'node_modules');
|
|
343
|
+
const binPath = path.join(modules, pkgInfo.name, 'node_modules', '.bin');
|
|
344
|
+
return linkBins(modules, binPath, { warn });
|
|
345
|
+
})));
|
|
346
|
+
await Promise.all(Object.values(ctx.projects).map(async ({ rootDir }) => limitLinking(async () => {
|
|
347
|
+
const modules = path.join(rootDir, 'node_modules');
|
|
348
|
+
const binPath = path.join(modules, '.bin');
|
|
349
|
+
return linkBins(modules, binPath, {
|
|
350
|
+
allowExoticManifests: true,
|
|
351
|
+
warn,
|
|
352
|
+
});
|
|
353
|
+
})));
|
|
354
|
+
}
|
|
355
|
+
return { pkgsThatWereRebuilt, ignoredPkgs };
|
|
356
|
+
}
|
|
357
|
+
function binDirsInAllParentDirs(pkgRoot, lockfileDir) {
|
|
358
|
+
const binDirs = [];
|
|
359
|
+
let dir = pkgRoot;
|
|
360
|
+
do {
|
|
361
|
+
if (!(path.dirname(dir)[0] === '@')) {
|
|
362
|
+
binDirs.push(path.join(dir, 'node_modules/.bin'));
|
|
363
|
+
}
|
|
364
|
+
dir = path.dirname(dir);
|
|
365
|
+
} while (path.relative(dir, lockfileDir) !== '');
|
|
366
|
+
binDirs.push(path.join(lockfileDir, 'node_modules/.bin'));
|
|
367
|
+
return binDirs;
|
|
368
|
+
}
|
|
369
|
+
//# sourceMappingURL=index.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pnpm/building.after-install",
|
|
3
|
+
"version": "1000.0.0-0",
|
|
4
|
+
"description": "Rebuild packages that are already installed by running their lifecycle scripts",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"pnpm",
|
|
7
|
+
"pnpm11",
|
|
8
|
+
"rebuild"
|
|
9
|
+
],
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"funding": "https://opencollective.com/pnpm",
|
|
12
|
+
"repository": "https://github.com/pnpm/pnpm/tree/main/building/after-install",
|
|
13
|
+
"homepage": "https://github.com/pnpm/pnpm/tree/main/building/after-install#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/pnpm/pnpm/issues"
|
|
16
|
+
},
|
|
17
|
+
"type": "module",
|
|
18
|
+
"main": "lib/index.js",
|
|
19
|
+
"types": "lib/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": "./lib/index.js"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"lib",
|
|
25
|
+
"!*.map"
|
|
26
|
+
],
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@pnpm/npm-package-arg": "^2.0.0",
|
|
29
|
+
"load-json-file": "^7.0.1",
|
|
30
|
+
"p-limit": "^7.1.0",
|
|
31
|
+
"run-groups": "^4.0.0",
|
|
32
|
+
"semver": "^7.7.2",
|
|
33
|
+
"@pnpm/building.pkg-requires-build": "1000.0.0-0",
|
|
34
|
+
"@pnpm/building.policy": "1000.0.0-0",
|
|
35
|
+
"@pnpm/calc-dep-state": "1002.0.8",
|
|
36
|
+
"@pnpm/config": "1004.4.2",
|
|
37
|
+
"@pnpm/core-loggers": "1001.0.4",
|
|
38
|
+
"@pnpm/constants": "1001.3.1",
|
|
39
|
+
"@pnpm/error": "1000.0.5",
|
|
40
|
+
"@pnpm/get-context": "1001.1.8",
|
|
41
|
+
"@pnpm/lifecycle": "1001.0.25",
|
|
42
|
+
"@pnpm/link-bins": "1000.2.6",
|
|
43
|
+
"@pnpm/deps.graph-sequencer": "1000.0.0",
|
|
44
|
+
"@pnpm/dependency-path": "1001.1.3",
|
|
45
|
+
"@pnpm/lockfile.types": "1002.0.2",
|
|
46
|
+
"@pnpm/lockfile.utils": "1003.0.3",
|
|
47
|
+
"@pnpm/modules-yaml": "1000.3.6",
|
|
48
|
+
"@pnpm/normalize-registries": "1000.1.4",
|
|
49
|
+
"@pnpm/store-connection-manager": "1002.2.4",
|
|
50
|
+
"@pnpm/read-package-json": "1000.1.2",
|
|
51
|
+
"@pnpm/store.cafs": "1000.0.19",
|
|
52
|
+
"@pnpm/lockfile.walker": "1001.0.16",
|
|
53
|
+
"@pnpm/store.index": "1000.0.0-0",
|
|
54
|
+
"@pnpm/store-controller-types": "1004.1.0",
|
|
55
|
+
"@pnpm/types": "1000.9.0"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"@pnpm/logger": ">=1001.0.0 <1002.0.0",
|
|
59
|
+
"@pnpm/worker": "^1000.3.0"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@types/semver": "7.7.1",
|
|
63
|
+
"@pnpm/building.after-install": "1000.0.0-0"
|
|
64
|
+
},
|
|
65
|
+
"engines": {
|
|
66
|
+
"node": ">=22.13"
|
|
67
|
+
},
|
|
68
|
+
"jest": {
|
|
69
|
+
"preset": "@pnpm/jest-config"
|
|
70
|
+
},
|
|
71
|
+
"scripts": {
|
|
72
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
73
|
+
"compile": "tsgo --build && pnpm run lint --fix",
|
|
74
|
+
"test": "pnpm run compile"
|
|
75
|
+
}
|
|
76
|
+
}
|