@pnpm/global.commands 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 +151 -0
- package/lib/checkGlobalBinConflicts.d.ts +11 -0
- package/lib/checkGlobalBinConflicts.js +44 -0
- package/lib/checkGlobalBinConflicts.js.map +1 -0
- package/lib/globalAdd.d.ts +21 -0
- package/lib/globalAdd.js +128 -0
- package/lib/globalAdd.js.map +1 -0
- package/lib/globalRemove.d.ts +4 -0
- package/lib/globalRemove.js +29 -0
- package/lib/globalRemove.js.map +1 -0
- package/lib/globalUpdate.d.ts +20 -0
- package/lib/globalUpdate.js +112 -0
- package/lib/globalUpdate.js.map +1 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +7 -0
- package/lib/index.js.map +1 -0
- package/lib/installGlobalPackages.d.ts +24 -0
- package/lib/installGlobalPackages.js +34 -0
- package/lib/installGlobalPackages.js.map +1 -0
- package/lib/listGlobalPackages.d.ts +1 -0
- package/lib/listGlobalPackages.js +22 -0
- package/lib/listGlobalPackages.js.map +1 -0
- package/lib/readInstalledPackages.d.ts +5 -0
- package/lib/readInstalledPackages.js +12 -0
- package/lib/readInstalledPackages.js.map +1 -0
- package/package.json +59 -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,151 @@
|
|
|
1
|
+
# @pnpm/global.commands
|
|
2
|
+
|
|
3
|
+
Command handlers for pnpm's global package management (`pnpm add -g`, `pnpm remove -g`, `pnpm update -g`, `pnpm list -g`).
|
|
4
|
+
|
|
5
|
+
## Architecture: Isolated Global Packages
|
|
6
|
+
|
|
7
|
+
Unlike npm, where all global packages share a single `node_modules/` directory, pnpm installs each global package (or group of packages installed together) into its own **isolated installation directory**. This prevents global packages from interfering with each other through peer dependency conflicts, hoisting changes, or version resolution shifts.
|
|
8
|
+
|
|
9
|
+
### Directory layout
|
|
10
|
+
|
|
11
|
+
All global package data lives under `{pnpmHomeDir}/global/v11/` (the "global package directory", referred to as `globalPkgDir` in the code). The layout is:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
{pnpmHomeDir}/global/v11/
|
|
15
|
+
{hash-1} -> symlink to {pid}-{timestamp-1}/ (hash symlink)
|
|
16
|
+
{pid}-{timestamp-1}/ (install dir)
|
|
17
|
+
package.json
|
|
18
|
+
node_modules/
|
|
19
|
+
.pnpm/
|
|
20
|
+
{pkg-a}/
|
|
21
|
+
{pkg-b}/
|
|
22
|
+
pnpm-lock.yaml
|
|
23
|
+
{hash-2} -> symlink to {pid}-{timestamp-2}/
|
|
24
|
+
{pid}-{timestamp-2}/
|
|
25
|
+
package.json
|
|
26
|
+
node_modules/
|
|
27
|
+
.pnpm/
|
|
28
|
+
{pkg-c}/
|
|
29
|
+
pnpm-lock.yaml
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Each install group has two entries:
|
|
33
|
+
|
|
34
|
+
1. **Install directory** (`{pid}-{timestamp}`): A regular directory containing a complete pnpm project with its own `package.json`, `node_modules/`, and lockfile. Named with the process ID and timestamp at creation time to avoid collisions.
|
|
35
|
+
|
|
36
|
+
2. **Hash symlink** (`{hash}`): A symbolic link named with a deterministic hash of the package aliases and registries. Points to the install directory. This serves as the lookup key for finding where a set of packages is installed.
|
|
37
|
+
|
|
38
|
+
The hash is computed from the sorted list of package aliases and sorted registry URLs, making it deterministic for a given set of packages.
|
|
39
|
+
|
|
40
|
+
### How each command works
|
|
41
|
+
|
|
42
|
+
#### `pnpm add -g <pkg> [pkg2 ...]`
|
|
43
|
+
|
|
44
|
+
Handled by `handleGlobalAdd()`:
|
|
45
|
+
|
|
46
|
+
1. Clean up orphaned install directories (those not referenced by any hash symlink).
|
|
47
|
+
2. Create a new install directory `{pid}-{timestamp}`.
|
|
48
|
+
3. Run `installGlobalPackages()` to install the requested packages into this directory using `@pnpm/core`'s `mutateModulesInSingleProject()`.
|
|
49
|
+
4. Read the resolved aliases from the resulting `package.json` (this is more reliable than parsing aliases from CLI params, which may be tarballs, git URLs, etc.).
|
|
50
|
+
5. Check for bin name conflicts with existing global packages via `checkGlobalBinConflicts()`.
|
|
51
|
+
6. Remove any existing global installations of the same aliases.
|
|
52
|
+
7. Create a hash symlink pointing to the new install directory.
|
|
53
|
+
8. Link bins from the installed packages into the global bin directory.
|
|
54
|
+
|
|
55
|
+
#### `pnpm remove -g <pkg> [pkg2 ...]`
|
|
56
|
+
|
|
57
|
+
Handled by `handleGlobalRemove()`:
|
|
58
|
+
|
|
59
|
+
1. Look up each requested package alias to find its install group (via `findGlobalPackage()`).
|
|
60
|
+
2. For each affected group: remove all bin shims, delete the hash symlink, and delete the install directory.
|
|
61
|
+
|
|
62
|
+
#### `pnpm update -g [pkg ...]`
|
|
63
|
+
|
|
64
|
+
Handled by `handleGlobalUpdate()`:
|
|
65
|
+
|
|
66
|
+
1. Scan all existing global packages.
|
|
67
|
+
2. Filter to groups containing the requested packages (or all groups if no args).
|
|
68
|
+
3. For each group:
|
|
69
|
+
- Create a new install directory.
|
|
70
|
+
- Re-install the same packages (at `--latest` versions if the `--latest` flag is set, or within existing ranges otherwise).
|
|
71
|
+
- Check for bin conflicts, remove old bins, swap the hash symlink to point to the new directory, clean up the old directory, and link new bins.
|
|
72
|
+
|
|
73
|
+
#### `pnpm list -g [pattern ...]`
|
|
74
|
+
|
|
75
|
+
Handled by `listGlobalPackages()`:
|
|
76
|
+
|
|
77
|
+
1. Scan all global packages.
|
|
78
|
+
2. Read package details (alias, version) from each install group's `node_modules/`.
|
|
79
|
+
3. Filter by glob patterns if provided (via `@pnpm/matcher`).
|
|
80
|
+
4. Sort and display.
|
|
81
|
+
|
|
82
|
+
### `installGlobalPackages()` — the core install function
|
|
83
|
+
|
|
84
|
+
This is a focused ~30-line function that replaces the 450-line `installDeps()` from `plugin-commands-installation`. Global installs don't need workspace logic, recursive installs, update matching, rebuild orchestration, or any of the other complexity in `installDeps()`. The function does exactly:
|
|
85
|
+
|
|
86
|
+
1. Create a store controller.
|
|
87
|
+
2. Read (or create) a manifest for the install directory.
|
|
88
|
+
3. Call `mutateModulesInSingleProject()` with `mutation: 'installSome'`.
|
|
89
|
+
4. Write the updated manifest.
|
|
90
|
+
|
|
91
|
+
### Bin conflict detection
|
|
92
|
+
|
|
93
|
+
`checkGlobalBinConflicts()` prevents a common footgun: installing a global package whose binaries would shadow binaries from a different globally-installed package. Before any bin linking happens, it:
|
|
94
|
+
|
|
95
|
+
1. Collects bin names from the packages about to be installed.
|
|
96
|
+
2. Checks if any of those bin names already exist in the global bin directory.
|
|
97
|
+
3. If they do, verifies whether they belong to a package being replaced (ok) or to a different package (error).
|
|
98
|
+
|
|
99
|
+
### Orphan cleanup
|
|
100
|
+
|
|
101
|
+
`cleanOrphanedInstallDirs()` (from `@pnpm/global.packages`) runs at the start of `add` and `update` to remove install directories that are no longer referenced by any hash symlink. This handles cases where a previous install was interrupted or crashed. A 5-minute safety window prevents cleaning up directories from concurrent installs that haven't created their hash symlink yet.
|
|
102
|
+
|
|
103
|
+
## Package structure
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
global/
|
|
107
|
+
commands/ @pnpm/global.commands (this package)
|
|
108
|
+
src/
|
|
109
|
+
globalAdd.ts handleGlobalAdd()
|
|
110
|
+
globalRemove.ts handleGlobalRemove()
|
|
111
|
+
globalUpdate.ts handleGlobalUpdate()
|
|
112
|
+
listGlobalPackages.ts listGlobalPackages()
|
|
113
|
+
installGlobalPackages.ts core install function
|
|
114
|
+
checkGlobalBinConflicts.ts bin conflict detection
|
|
115
|
+
readInstalledPackages.ts shared helper
|
|
116
|
+
index.ts
|
|
117
|
+
packages/ @pnpm/global.packages
|
|
118
|
+
src/
|
|
119
|
+
scanGlobalPackages.ts directory scanning, package lookup
|
|
120
|
+
globalPackageDir.ts install dir / hash link management
|
|
121
|
+
cacheKey.ts deterministic hash computation
|
|
122
|
+
index.ts
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`@pnpm/global.packages` provides the low-level utilities for reading and managing the directory structure. `@pnpm/global.commands` provides the high-level command handlers that orchestrate installs, removals, updates, and listing.
|
|
126
|
+
|
|
127
|
+
## Integration points
|
|
128
|
+
|
|
129
|
+
The CLI command handlers in `plugin-commands-installation` and `plugin-commands-listing` delegate to this package with a simple early return:
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// In add.ts handler:
|
|
133
|
+
if (opts.global) {
|
|
134
|
+
return handleGlobalAdd(opts, params)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// In remove.ts handler:
|
|
138
|
+
if (opts.global) {
|
|
139
|
+
return handleGlobalRemove(opts, params)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// In update/index.ts handler:
|
|
143
|
+
if (opts.global) {
|
|
144
|
+
return handleGlobalUpdate(opts, params)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// In list.ts handler:
|
|
148
|
+
if (opts.global && opts.globalPkgDir) {
|
|
149
|
+
return listGlobalPackages(opts.globalPkgDir, params)
|
|
150
|
+
}
|
|
151
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type GlobalPackageInfo } from '@pnpm/global.packages';
|
|
2
|
+
import { type DependencyManifest } from '@pnpm/types';
|
|
3
|
+
export declare function checkGlobalBinConflicts(opts: {
|
|
4
|
+
globalDir: string;
|
|
5
|
+
globalBinDir: string;
|
|
6
|
+
newPkgs: Array<{
|
|
7
|
+
manifest: DependencyManifest;
|
|
8
|
+
location: string;
|
|
9
|
+
}>;
|
|
10
|
+
shouldSkip: (pkg: GlobalPackageInfo) => boolean;
|
|
11
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { scanGlobalPackages, } from '@pnpm/global.packages';
|
|
4
|
+
import { PnpmError } from '@pnpm/error';
|
|
5
|
+
import { getBinsFromPackageManifest } from '@pnpm/package-bins';
|
|
6
|
+
import { safeReadPackageJsonFromDir } from '@pnpm/read-package-json';
|
|
7
|
+
export async function checkGlobalBinConflicts(opts) {
|
|
8
|
+
const newBinNames = new Set();
|
|
9
|
+
await Promise.all(opts.newPkgs.map(async (pkg) => {
|
|
10
|
+
const bins = await getBinsFromPackageManifest(pkg.manifest, pkg.location);
|
|
11
|
+
for (const bin of bins) {
|
|
12
|
+
newBinNames.add(bin.name);
|
|
13
|
+
}
|
|
14
|
+
}));
|
|
15
|
+
if (newBinNames.size === 0)
|
|
16
|
+
return;
|
|
17
|
+
// Quick check: only investigate if a bin with the same name already exists
|
|
18
|
+
const conflicting = [...newBinNames].filter((name) => fs.existsSync(path.join(opts.globalBinDir, name)));
|
|
19
|
+
if (conflicting.length === 0)
|
|
20
|
+
return;
|
|
21
|
+
// Some bins already exist — find out if they belong to packages being replaced
|
|
22
|
+
// (in which case it's fine) or to other packages (conflict).
|
|
23
|
+
const existingPackages = scanGlobalPackages(opts.globalDir);
|
|
24
|
+
for (const existingPkg of existingPackages) {
|
|
25
|
+
if (opts.shouldSkip(existingPkg))
|
|
26
|
+
continue;
|
|
27
|
+
const modulesDir = path.join(existingPkg.installDir, 'node_modules');
|
|
28
|
+
for (const alias of Object.keys(existingPkg.dependencies)) {
|
|
29
|
+
const depDir = path.join(modulesDir, alias);
|
|
30
|
+
const manifest = await safeReadPackageJsonFromDir(depDir); // eslint-disable-line no-await-in-loop
|
|
31
|
+
if (!manifest)
|
|
32
|
+
continue;
|
|
33
|
+
const bins = await getBinsFromPackageManifest(manifest, depDir); // eslint-disable-line no-await-in-loop
|
|
34
|
+
for (const bin of bins) {
|
|
35
|
+
if (conflicting.includes(bin.name)) {
|
|
36
|
+
throw new PnpmError('GLOBAL_BIN_CONFLICT', `Cannot install: binary "${bin.name}" would conflict with package "${alias}" that is already installed globally`, {
|
|
37
|
+
hint: `Remove the conflicting package first: pnpm remove -g ${alias}`,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=checkGlobalBinConflicts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkGlobalBinConflicts.js","sourceRoot":"","sources":["../src/checkGlobalBinConflicts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EACL,kBAAkB,GAEnB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAA;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAA;AAGpE,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAE,IAK9C,EAAiB;IAChB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAA;IACrC,MAAM,OAAO,CAAC,GAAG,CACf,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,MAAM,0BAA0B,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAA;QACzE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC3B,CAAC;IAAA,CACF,CAAC,CACH,CAAA;IACD,IAAI,WAAW,CAAC,IAAI,KAAK,CAAC;QAAE,OAAM;IAElC,2EAA2E;IAC3E,MAAM,WAAW,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,MAAM,CACzC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAC5D,CAAA;IACD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAEpC,iFAA+E;IAC/E,6DAA6D;IAC7D,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IAC3D,KAAK,MAAM,WAAW,IAAI,gBAAgB,EAAE,CAAC;QAC3C,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;YAAE,SAAQ;QAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,cAAc,CAAC,CAAA;QACpE,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,CAAC;YAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAA;YAC3C,MAAM,QAAQ,GAAG,MAAM,0BAA0B,CAAC,MAAM,CAAC,CAAA,CAAC,uCAAuC;YACjG,IAAI,CAAC,QAAQ;gBAAE,SAAQ;YACvB,MAAM,IAAI,GAAG,MAAM,0BAA0B,CAAC,QAA8B,EAAE,MAAM,CAAC,CAAA,CAAC,uCAAuC;YAC7H,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACnC,MAAM,IAAI,SAAS,CACjB,qBAAqB,EACrB,2BAA2B,GAAG,CAAC,IAAI,kCAAkC,KAAK,sCAAsC,EAChH;wBACE,IAAI,EAAE,wDAAwD,KAAK,EAAE;qBACtE,CACF,CAAA;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;AAAA,CACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type CreateStoreControllerOptions } from '@pnpm/store-connection-manager';
|
|
2
|
+
export type GlobalAddOptions = CreateStoreControllerOptions & {
|
|
3
|
+
bin?: string;
|
|
4
|
+
globalPkgDir?: string;
|
|
5
|
+
registries: Record<string, string>;
|
|
6
|
+
allowBuild?: string[];
|
|
7
|
+
allowBuilds?: Record<string, string | boolean>;
|
|
8
|
+
saveExact?: boolean;
|
|
9
|
+
savePrefix?: string;
|
|
10
|
+
supportedArchitectures?: {
|
|
11
|
+
libc?: string[];
|
|
12
|
+
};
|
|
13
|
+
rootProjectManifest?: {
|
|
14
|
+
pnpm?: {
|
|
15
|
+
supportedArchitectures?: {
|
|
16
|
+
libc?: string[];
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export declare function handleGlobalAdd(opts: GlobalAddOptions, params: string[]): Promise<void>;
|
package/lib/globalAdd.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { cleanOrphanedInstallDirs, createGlobalCacheKey, createInstallDir, findGlobalPackage, getHashLink, getInstalledBinNames, } from '@pnpm/global.packages';
|
|
4
|
+
import { linkBinsOfPackages } from '@pnpm/link-bins';
|
|
5
|
+
import { removeBin } from '@pnpm/remove-bins';
|
|
6
|
+
import { readPackageJsonFromDirRawSync } from '@pnpm/read-package-json';
|
|
7
|
+
import isSubdir from 'is-subdir';
|
|
8
|
+
import symlinkDir from 'symlink-dir';
|
|
9
|
+
import { approveBuilds } from '@pnpm/exec.build-commands';
|
|
10
|
+
import { installGlobalPackages } from './installGlobalPackages.js';
|
|
11
|
+
import { checkGlobalBinConflicts } from './checkGlobalBinConflicts.js';
|
|
12
|
+
import { readInstalledPackages } from './readInstalledPackages.js';
|
|
13
|
+
export async function handleGlobalAdd(opts, params) {
|
|
14
|
+
const globalDir = opts.globalPkgDir;
|
|
15
|
+
const globalBinDir = opts.bin;
|
|
16
|
+
cleanOrphanedInstallDirs(globalDir);
|
|
17
|
+
// Install into a new directory first, then read the resolved aliases
|
|
18
|
+
// from the resulting package.json. This is more reliable than parsing
|
|
19
|
+
// aliases from CLI params (which may be tarballs, git URLs, etc.).
|
|
20
|
+
const installDir = createInstallDir(globalDir);
|
|
21
|
+
// Convert allowBuild array to allowBuilds Record (same conversion as add.handler)
|
|
22
|
+
let allowBuilds = opts.allowBuilds ?? {};
|
|
23
|
+
if (opts.allowBuild?.length) {
|
|
24
|
+
allowBuilds = { ...allowBuilds };
|
|
25
|
+
for (const pkg of opts.allowBuild) {
|
|
26
|
+
allowBuilds[pkg] = true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const include = {
|
|
30
|
+
dependencies: true,
|
|
31
|
+
devDependencies: false,
|
|
32
|
+
optionalDependencies: true,
|
|
33
|
+
};
|
|
34
|
+
const fetchFullMetadata = (opts.supportedArchitectures?.libc ?? opts.rootProjectManifest?.pnpm?.supportedArchitectures?.libc) && true;
|
|
35
|
+
const makeInstallOpts = (dir, builds) => ({
|
|
36
|
+
...opts,
|
|
37
|
+
global: false,
|
|
38
|
+
bin: path.join(dir, 'node_modules/.bin'),
|
|
39
|
+
dir,
|
|
40
|
+
lockfileDir: dir,
|
|
41
|
+
rootProjectManifestDir: dir,
|
|
42
|
+
rootProjectManifest: undefined,
|
|
43
|
+
saveProd: true,
|
|
44
|
+
saveDev: false,
|
|
45
|
+
saveOptional: false,
|
|
46
|
+
savePeer: false,
|
|
47
|
+
workspaceDir: undefined,
|
|
48
|
+
sharedWorkspaceLockfile: false,
|
|
49
|
+
lockfileOnly: false,
|
|
50
|
+
fetchFullMetadata,
|
|
51
|
+
include,
|
|
52
|
+
includeDirect: include,
|
|
53
|
+
allowBuilds: builds,
|
|
54
|
+
});
|
|
55
|
+
const ignoredBuilds = await installGlobalPackages(makeInstallOpts(installDir, allowBuilds), params);
|
|
56
|
+
// If any packages had their builds skipped, prompt the user to approve them
|
|
57
|
+
// (reuses the same interactive flow as `pnpm approve-builds`)
|
|
58
|
+
if (ignoredBuilds?.size && process.stdin.isTTY) {
|
|
59
|
+
await approveBuilds.handler({
|
|
60
|
+
...opts,
|
|
61
|
+
modulesDir: path.join(installDir, 'node_modules'),
|
|
62
|
+
dir: installDir,
|
|
63
|
+
lockfileDir: installDir,
|
|
64
|
+
rootProjectManifest: undefined,
|
|
65
|
+
rootProjectManifestDir: installDir,
|
|
66
|
+
workspaceDir: opts.globalPkgDir,
|
|
67
|
+
global: false,
|
|
68
|
+
pending: false,
|
|
69
|
+
allowBuilds,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
// Read resolved aliases from the installed package.json
|
|
73
|
+
const pkgJson = readPackageJsonFromDirRawSync(installDir);
|
|
74
|
+
const aliases = Object.keys(pkgJson.dependencies ?? {});
|
|
75
|
+
// Check for bin name conflicts with other global packages
|
|
76
|
+
// (must happen before removeExistingGlobalInstalls so we don't lose existing packages on failure)
|
|
77
|
+
const pkgs = await readInstalledPackages(installDir);
|
|
78
|
+
try {
|
|
79
|
+
await checkGlobalBinConflicts({
|
|
80
|
+
globalDir,
|
|
81
|
+
globalBinDir,
|
|
82
|
+
newPkgs: pkgs,
|
|
83
|
+
shouldSkip: (pkg) => aliases.some((alias) => alias in pkg.dependencies),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
await fs.promises.rm(installDir, { recursive: true, force: true });
|
|
88
|
+
throw err;
|
|
89
|
+
}
|
|
90
|
+
// Remove any existing global installations of these aliases
|
|
91
|
+
await removeExistingGlobalInstalls(globalDir, globalBinDir, aliases);
|
|
92
|
+
// Compute cache key and create hash symlink pointing to install dir
|
|
93
|
+
const cacheHash = createGlobalCacheKey({
|
|
94
|
+
aliases,
|
|
95
|
+
registries: opts.registries,
|
|
96
|
+
});
|
|
97
|
+
const hashLink = getHashLink(globalDir, cacheHash);
|
|
98
|
+
await symlinkDir(installDir, hashLink, { overwrite: true });
|
|
99
|
+
// Link bins from installed packages into global bin dir
|
|
100
|
+
await linkBinsOfPackages(pkgs, globalBinDir);
|
|
101
|
+
}
|
|
102
|
+
async function removeExistingGlobalInstalls(globalDir, globalBinDir, aliases) {
|
|
103
|
+
// Collect unique groups to remove (dedup by hash)
|
|
104
|
+
const groupsToRemove = new Map();
|
|
105
|
+
for (const alias of aliases) {
|
|
106
|
+
const existing = findGlobalPackage(globalDir, alias);
|
|
107
|
+
if (existing && !groupsToRemove.has(existing.hash)) {
|
|
108
|
+
groupsToRemove.set(existing.hash, getInstalledBinNames(existing));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Remove all groups in parallel
|
|
112
|
+
await Promise.all([...groupsToRemove.entries()].map(async ([hash, binNamesPromise]) => {
|
|
113
|
+
const binNames = await binNamesPromise;
|
|
114
|
+
await Promise.all(binNames.map((binName) => removeBin(path.join(globalBinDir, binName))));
|
|
115
|
+
// Remove both the hash symlink and the install dir it points to
|
|
116
|
+
const hashLink = getHashLink(globalDir, hash);
|
|
117
|
+
let installDir = null;
|
|
118
|
+
try {
|
|
119
|
+
installDir = fs.realpathSync(hashLink);
|
|
120
|
+
}
|
|
121
|
+
catch { }
|
|
122
|
+
await fs.promises.rm(hashLink, { force: true });
|
|
123
|
+
if (installDir && isSubdir(globalDir, installDir)) {
|
|
124
|
+
await fs.promises.rm(installDir, { recursive: true, force: true });
|
|
125
|
+
}
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=globalAdd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"globalAdd.js","sourceRoot":"","sources":["../src/globalAdd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { PnpmError } from '@pnpm/error';
|
|
4
|
+
import { findGlobalPackage, getHashLink, getInstalledBinNames, } from '@pnpm/global.packages';
|
|
5
|
+
import { removeBin } from '@pnpm/remove-bins';
|
|
6
|
+
import isSubdir from 'is-subdir';
|
|
7
|
+
export async function handleGlobalRemove(opts, params) {
|
|
8
|
+
const globalDir = opts.globalPkgDir;
|
|
9
|
+
const globalBinDir = opts.bin;
|
|
10
|
+
// Find all groups that contain the packages to remove (dedup by hash)
|
|
11
|
+
const groupsToRemove = new Map();
|
|
12
|
+
for (const param of params) {
|
|
13
|
+
const pkg = findGlobalPackage(globalDir, param);
|
|
14
|
+
if (!pkg) {
|
|
15
|
+
throw new PnpmError('GLOBAL_PKG_NOT_FOUND', `Cannot remove '${param}': not found in global packages`);
|
|
16
|
+
}
|
|
17
|
+
groupsToRemove.set(pkg.hash, pkg);
|
|
18
|
+
}
|
|
19
|
+
// Remove bins, hash symlinks, and install dirs for all affected groups in parallel
|
|
20
|
+
await Promise.all([...groupsToRemove.entries()].map(async ([hash, pkg]) => {
|
|
21
|
+
const binNames = await getInstalledBinNames(pkg);
|
|
22
|
+
await Promise.all(binNames.map((binName) => removeBin(path.join(globalBinDir, binName))));
|
|
23
|
+
await fs.promises.rm(getHashLink(globalDir, hash), { force: true });
|
|
24
|
+
if (isSubdir(globalDir, pkg.installDir)) {
|
|
25
|
+
await fs.promises.rm(pkg.installDir, { recursive: true, force: true });
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=globalRemove.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"globalRemove.js","sourceRoot":"","sources":["../src/globalRemove.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,oBAAoB,GAErB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC7C,OAAO,QAAQ,MAAM,WAAW,CAAA;AAEhC,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAGC,EACD,MAAgB,EACD;IACf,MAAM,SAAS,GAAG,IAAI,CAAC,YAAa,CAAA;IACpC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAI,CAAA;IAE9B,sEAAsE;IACtE,MAAM,cAAc,GAAG,IAAI,GAAG,EAA6B,CAAA;IAC3D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,iBAAiB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QAC/C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,SAAS,CAAC,sBAAsB,EAAE,kBAAkB,KAAK,iCAAiC,CAAC,CAAA;QACvG,CAAC;QACD,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACnC,CAAC;IAED,mFAAmF;IACnF,MAAM,OAAO,CAAC,GAAG,CACf,CAAC,GAAG,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;QACvD,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,GAAG,CAAC,CAAA;QAChD,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;QACzF,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QACnE,IAAI,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YACxC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QACxE,CAAC;IAAA,CACF,CAAC,CACH,CAAA;AAAA,CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type CreateStoreControllerOptions } from '@pnpm/store-connection-manager';
|
|
2
|
+
export type GlobalUpdateOptions = CreateStoreControllerOptions & {
|
|
3
|
+
bin?: string;
|
|
4
|
+
globalPkgDir?: string;
|
|
5
|
+
latest?: boolean;
|
|
6
|
+
allowBuilds?: Record<string, string | boolean>;
|
|
7
|
+
saveExact?: boolean;
|
|
8
|
+
savePrefix?: string;
|
|
9
|
+
supportedArchitectures?: {
|
|
10
|
+
libc?: string[];
|
|
11
|
+
};
|
|
12
|
+
rootProjectManifest?: {
|
|
13
|
+
pnpm?: {
|
|
14
|
+
supportedArchitectures?: {
|
|
15
|
+
libc?: string[];
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export declare function handleGlobalUpdate(opts: GlobalUpdateOptions, params: string[]): Promise<string | undefined>;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { cleanOrphanedInstallDirs, createInstallDir, getHashLink, getInstalledBinNames, scanGlobalPackages, } from '@pnpm/global.packages';
|
|
4
|
+
import { linkBinsOfPackages } from '@pnpm/link-bins';
|
|
5
|
+
import { removeBin } from '@pnpm/remove-bins';
|
|
6
|
+
import isSubdir from 'is-subdir';
|
|
7
|
+
import symlinkDir from 'symlink-dir';
|
|
8
|
+
import { approveBuilds } from '@pnpm/exec.build-commands';
|
|
9
|
+
import { installGlobalPackages } from './installGlobalPackages.js';
|
|
10
|
+
import { checkGlobalBinConflicts } from './checkGlobalBinConflicts.js';
|
|
11
|
+
import { readInstalledPackages } from './readInstalledPackages.js';
|
|
12
|
+
export async function handleGlobalUpdate(opts, params) {
|
|
13
|
+
const globalDir = opts.globalPkgDir;
|
|
14
|
+
const globalBinDir = opts.bin;
|
|
15
|
+
cleanOrphanedInstallDirs(globalDir);
|
|
16
|
+
const allPackages = scanGlobalPackages(globalDir);
|
|
17
|
+
if (allPackages.length === 0) {
|
|
18
|
+
return 'No global packages found';
|
|
19
|
+
}
|
|
20
|
+
// If specific packages are requested, filter to only groups containing them
|
|
21
|
+
let packagesToUpdate;
|
|
22
|
+
if (params.length > 0) {
|
|
23
|
+
packagesToUpdate = allPackages.filter((pkg) => params.some((p) => p in pkg.dependencies));
|
|
24
|
+
if (packagesToUpdate.length === 0) {
|
|
25
|
+
return 'No matching global packages found';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
packagesToUpdate = allPackages;
|
|
30
|
+
}
|
|
31
|
+
// Update each package group sequentially to avoid overwhelming the system
|
|
32
|
+
for (const pkg of packagesToUpdate) {
|
|
33
|
+
await updateGlobalPackageGroup(opts, globalDir, globalBinDir, pkg); // eslint-disable-line no-await-in-loop
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
async function updateGlobalPackageGroup(opts, globalDir, globalBinDir, pkg) {
|
|
38
|
+
const installDir = createInstallDir(globalDir);
|
|
39
|
+
// When --latest, just pass alias names to get the latest version.
|
|
40
|
+
// Otherwise, pass alias@spec to update within the existing range.
|
|
41
|
+
const depSpecs = Object.entries(pkg.dependencies).map(([alias, spec]) => opts.latest ? alias : `${alias}@${spec}`);
|
|
42
|
+
const include = {
|
|
43
|
+
dependencies: true,
|
|
44
|
+
devDependencies: false,
|
|
45
|
+
optionalDependencies: true,
|
|
46
|
+
};
|
|
47
|
+
const fetchFullMetadata = (opts.supportedArchitectures?.libc ?? opts.rootProjectManifest?.pnpm?.supportedArchitectures?.libc) && true;
|
|
48
|
+
const allowBuilds = opts.allowBuilds ?? {};
|
|
49
|
+
const ignoredBuilds = await installGlobalPackages({
|
|
50
|
+
...opts,
|
|
51
|
+
global: false,
|
|
52
|
+
bin: path.join(installDir, 'node_modules/.bin'),
|
|
53
|
+
dir: installDir,
|
|
54
|
+
lockfileDir: installDir,
|
|
55
|
+
rootProjectManifestDir: installDir,
|
|
56
|
+
rootProjectManifest: undefined,
|
|
57
|
+
saveProd: true,
|
|
58
|
+
saveDev: false,
|
|
59
|
+
saveOptional: false,
|
|
60
|
+
savePeer: false,
|
|
61
|
+
workspaceDir: undefined,
|
|
62
|
+
sharedWorkspaceLockfile: false,
|
|
63
|
+
lockfileOnly: false,
|
|
64
|
+
fetchFullMetadata,
|
|
65
|
+
include,
|
|
66
|
+
includeDirect: include,
|
|
67
|
+
allowBuilds,
|
|
68
|
+
}, depSpecs);
|
|
69
|
+
// If any packages had their builds skipped, prompt the user to approve them
|
|
70
|
+
// (reuses the same interactive flow as `pnpm approve-builds`)
|
|
71
|
+
if (ignoredBuilds?.size && process.stdin.isTTY) {
|
|
72
|
+
await approveBuilds.handler({
|
|
73
|
+
...opts,
|
|
74
|
+
modulesDir: path.join(installDir, 'node_modules'),
|
|
75
|
+
dir: installDir,
|
|
76
|
+
lockfileDir: installDir,
|
|
77
|
+
rootProjectManifest: undefined,
|
|
78
|
+
rootProjectManifestDir: installDir,
|
|
79
|
+
workspaceDir: opts.globalPkgDir,
|
|
80
|
+
global: false,
|
|
81
|
+
pending: false,
|
|
82
|
+
allowBuilds,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
// Check for bin name conflicts with other global packages
|
|
86
|
+
const pkgs = await readInstalledPackages(installDir);
|
|
87
|
+
try {
|
|
88
|
+
await checkGlobalBinConflicts({
|
|
89
|
+
globalDir,
|
|
90
|
+
globalBinDir,
|
|
91
|
+
newPkgs: pkgs,
|
|
92
|
+
shouldSkip: (existingPkg) => existingPkg.hash === pkg.hash,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
await fs.promises.rm(installDir, { recursive: true, force: true });
|
|
97
|
+
throw err;
|
|
98
|
+
}
|
|
99
|
+
// Remove stale bins from old installation before swapping
|
|
100
|
+
const oldBinNames = await getInstalledBinNames(pkg);
|
|
101
|
+
await Promise.all(oldBinNames.map((binName) => removeBin(path.join(globalBinDir, binName))));
|
|
102
|
+
// Swap hash symlink to new install dir, then clean up old one
|
|
103
|
+
const hashLink = getHashLink(globalDir, pkg.hash);
|
|
104
|
+
const oldInstallDir = pkg.installDir;
|
|
105
|
+
await symlinkDir(installDir, hashLink, { overwrite: true });
|
|
106
|
+
if (isSubdir(globalDir, oldInstallDir)) {
|
|
107
|
+
await fs.promises.rm(oldInstallDir, { recursive: true, force: true });
|
|
108
|
+
}
|
|
109
|
+
// Link bins from new installation
|
|
110
|
+
await linkBinsOfPackages(pkgs, globalBinDir);
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=globalUpdate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"globalUpdate.js","sourceRoot":"","sources":["../src/globalUpdate.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { handleGlobalAdd, type GlobalAddOptions } from './globalAdd.js';
|
|
2
|
+
export { handleGlobalRemove } from './globalRemove.js';
|
|
3
|
+
export { handleGlobalUpdate, type GlobalUpdateOptions } from './globalUpdate.js';
|
|
4
|
+
export { checkGlobalBinConflicts } from './checkGlobalBinConflicts.js';
|
|
5
|
+
export { listGlobalPackages } from './listGlobalPackages.js';
|
|
6
|
+
export { installGlobalPackages, type InstallGlobalPackagesOptions } from './installGlobalPackages.js';
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { handleGlobalAdd } from './globalAdd.js';
|
|
2
|
+
export { handleGlobalRemove } from './globalRemove.js';
|
|
3
|
+
export { handleGlobalUpdate } from './globalUpdate.js';
|
|
4
|
+
export { checkGlobalBinConflicts } from './checkGlobalBinConflicts.js';
|
|
5
|
+
export { listGlobalPackages } from './listGlobalPackages.js';
|
|
6
|
+
export { installGlobalPackages } from './installGlobalPackages.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAyB,MAAM,gBAAgB,CAAA;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAA4B,MAAM,mBAAmB,CAAA;AAChF,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAC5D,OAAO,EAAE,qBAAqB,EAAqC,MAAM,4BAA4B,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type CreateStoreControllerOptions } from '@pnpm/store-connection-manager';
|
|
2
|
+
import { type IgnoredBuilds, type IncludedDependencies } from '@pnpm/types';
|
|
3
|
+
export interface InstallGlobalPackagesOptions extends CreateStoreControllerOptions {
|
|
4
|
+
bin: string;
|
|
5
|
+
dir: string;
|
|
6
|
+
global?: boolean;
|
|
7
|
+
lockfileDir: string;
|
|
8
|
+
lockfileOnly?: boolean;
|
|
9
|
+
allowBuilds?: Record<string, string | boolean>;
|
|
10
|
+
include: IncludedDependencies;
|
|
11
|
+
includeDirect?: IncludedDependencies;
|
|
12
|
+
fetchFullMetadata?: boolean;
|
|
13
|
+
rootProjectManifest?: unknown;
|
|
14
|
+
rootProjectManifestDir?: string;
|
|
15
|
+
saveDev?: boolean;
|
|
16
|
+
saveExact?: boolean;
|
|
17
|
+
saveOptional?: boolean;
|
|
18
|
+
savePeer?: boolean;
|
|
19
|
+
savePrefix?: string;
|
|
20
|
+
saveProd?: boolean;
|
|
21
|
+
sharedWorkspaceLockfile?: boolean;
|
|
22
|
+
workspaceDir?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function installGlobalPackages(opts: InstallGlobalPackagesOptions, params: string[]): Promise<IgnoredBuilds | undefined>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { tryReadProjectManifest } from '@pnpm/cli-utils';
|
|
2
|
+
import { getOptionsFromRootManifest } from '@pnpm/config';
|
|
3
|
+
import { mutateModulesInSingleProject } from '@pnpm/core';
|
|
4
|
+
import { createStoreController } from '@pnpm/store-connection-manager';
|
|
5
|
+
export async function installGlobalPackages(opts, params) {
|
|
6
|
+
const store = await createStoreController(opts);
|
|
7
|
+
let { manifest, writeProjectManifest } = await tryReadProjectManifest(opts.dir, opts);
|
|
8
|
+
if (manifest == null) {
|
|
9
|
+
manifest = {};
|
|
10
|
+
}
|
|
11
|
+
const rootManifestOpts = getOptionsFromRootManifest(opts.dir, manifest);
|
|
12
|
+
const installOpts = {
|
|
13
|
+
...opts,
|
|
14
|
+
...rootManifestOpts,
|
|
15
|
+
allowBuilds: { ...rootManifestOpts.allowBuilds, ...opts.allowBuilds },
|
|
16
|
+
storeController: store.ctrl,
|
|
17
|
+
storeDir: store.dir,
|
|
18
|
+
};
|
|
19
|
+
const pinnedVersion = opts.saveExact ? 'patch' : (opts.savePrefix === '~' ? 'minor' : 'major');
|
|
20
|
+
const { updatedProject, ignoredBuilds } = await mutateModulesInSingleProject({
|
|
21
|
+
allowNew: true,
|
|
22
|
+
binsDir: opts.bin,
|
|
23
|
+
dependencySelectors: params,
|
|
24
|
+
manifest,
|
|
25
|
+
mutation: 'installSome',
|
|
26
|
+
peer: false,
|
|
27
|
+
pinnedVersion,
|
|
28
|
+
rootDir: opts.dir,
|
|
29
|
+
targetDependenciesField: 'dependencies',
|
|
30
|
+
}, installOpts);
|
|
31
|
+
await writeProjectManifest(updatedProject.manifest);
|
|
32
|
+
return ignoredBuilds;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=installGlobalPackages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installGlobalPackages.js","sourceRoot":"","sources":["../src/installGlobalPackages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,EAAE,qBAAqB,EAAqC,MAAM,gCAAgC,CAAA;AAyBzG,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAAkC,EAClC,MAAgB,EACoB;IACpC,MAAM,KAAK,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAA;IAC/C,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,GAAG,MAAM,sBAAsB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IACrF,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;QACrB,QAAQ,GAAG,EAAE,CAAA;IACf,CAAC;IACD,MAAM,gBAAgB,GAAG,0BAA0B,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IACvE,MAAM,WAAW,GAAG;QAClB,GAAG,IAAI;QACP,GAAG,gBAAgB;QACnB,WAAW,EAAE,EAAE,GAAG,gBAAgB,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE;QACrE,eAAe,EAAE,KAAK,CAAC,IAAI;QAC3B,QAAQ,EAAE,KAAK,CAAC,GAAG;KACpB,CAAA;IACD,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IAC9F,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,MAAM,4BAA4B,CAC1E;QACE,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,IAAI,CAAC,GAAG;QACjB,mBAAmB,EAAE,MAAM;QAC3B,QAAQ;QACR,QAAQ,EAAE,aAAsB;QAChC,IAAI,EAAE,KAAK;QACX,aAAa;QACb,OAAO,EAAE,IAAI,CAAC,GAAqB;QACnC,uBAAuB,EAAE,cAAuB;KACjD,EACD,WAAW,CACZ,CAAA;IACD,MAAM,oBAAoB,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAA;IACnD,OAAO,aAAa,CAAA;AAAA,CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function listGlobalPackages(globalPkgDir: string, params: string[]): Promise<string>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { scanGlobalPackages, getGlobalPackageDetails, } from '@pnpm/global.packages';
|
|
2
|
+
import { createMatcher } from '@pnpm/matcher';
|
|
3
|
+
import { lexCompare } from '@pnpm/util.lex-comparator';
|
|
4
|
+
export async function listGlobalPackages(globalPkgDir, params) {
|
|
5
|
+
const packages = scanGlobalPackages(globalPkgDir);
|
|
6
|
+
const allDetails = await Promise.all(packages.map((pkg) => getGlobalPackageDetails(pkg)));
|
|
7
|
+
const matches = params.length > 0 ? createMatcher(params) : () => true;
|
|
8
|
+
const lines = [];
|
|
9
|
+
for (const installed of allDetails.flat()) {
|
|
10
|
+
if (!matches(installed.alias))
|
|
11
|
+
continue;
|
|
12
|
+
lines.push(`${installed.alias}@${installed.version}`);
|
|
13
|
+
}
|
|
14
|
+
if (lines.length === 0) {
|
|
15
|
+
return params.length > 0
|
|
16
|
+
? 'No matching global packages found'
|
|
17
|
+
: 'No global packages found';
|
|
18
|
+
}
|
|
19
|
+
lines.sort(lexCompare);
|
|
20
|
+
return lines.join('\n');
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=listGlobalPackages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listGlobalPackages.js","sourceRoot":"","sources":["../src/listGlobalPackages.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAEtD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAE,YAAoB,EAAE,MAAgB,EAAmB;IACjG,MAAM,QAAQ,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAA;IACjD,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACzF,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAA;IACtE,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,SAAS,IAAI,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;QAC1C,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC;YAAE,SAAQ;QACvC,KAAK,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC,CAAA;IACvD,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC;YACtB,CAAC,CAAC,mCAAmC;YACrC,CAAC,CAAC,0BAA0B,CAAA;IAChC,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACtB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAAA,CACxB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { readPackageJsonFromDir, readPackageJsonFromDirRawSync } from '@pnpm/read-package-json';
|
|
3
|
+
export async function readInstalledPackages(installDir) {
|
|
4
|
+
const pkgJson = readPackageJsonFromDirRawSync(installDir);
|
|
5
|
+
const depNames = Object.keys(pkgJson.dependencies ?? {});
|
|
6
|
+
const manifests = await Promise.all(depNames.map((depName) => readPackageJsonFromDir(path.join(installDir, 'node_modules', depName))));
|
|
7
|
+
return depNames.map((depName, i) => ({
|
|
8
|
+
manifest: manifests[i],
|
|
9
|
+
location: path.join(installDir, 'node_modules', depName),
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=readInstalledPackages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readInstalledPackages.js","sourceRoot":"","sources":["../src/readInstalledPackages.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,sBAAsB,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAA;AAG/F,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAE,UAAkB,EAAsE;IACnI,MAAM,OAAO,GAAG,6BAA6B,CAAC,UAAU,CAAC,CAAA;IACzD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC,CAAA;IACxD,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CACjC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,CAClG,CAAA;IACD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACnC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAuB;QAC5C,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC;KACzD,CAAC,CAAC,CAAA;AAAA,CACJ"}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pnpm/global.commands",
|
|
3
|
+
"version": "1000.0.0-0",
|
|
4
|
+
"description": "Global package command handlers for pnpm",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"pnpm",
|
|
7
|
+
"pnpm11",
|
|
8
|
+
"global"
|
|
9
|
+
],
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"funding": "https://opencollective.com/pnpm",
|
|
12
|
+
"repository": "https://github.com/pnpm/pnpm/tree/main/global/commands",
|
|
13
|
+
"homepage": "https://github.com/pnpm/pnpm/tree/main/global/commands#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/util.lex-comparator": "^3.0.2",
|
|
29
|
+
"is-subdir": "^1.2.0",
|
|
30
|
+
"symlink-dir": "^7.0.0",
|
|
31
|
+
"@pnpm/cli-utils": "1001.2.8",
|
|
32
|
+
"@pnpm/core": "1012.0.1",
|
|
33
|
+
"@pnpm/error": "1000.0.5",
|
|
34
|
+
"@pnpm/exec.build-commands": "1001.0.33",
|
|
35
|
+
"@pnpm/global.packages": "1000.0.0-0",
|
|
36
|
+
"@pnpm/config": "1004.4.2",
|
|
37
|
+
"@pnpm/matcher": "1000.1.0",
|
|
38
|
+
"@pnpm/package-bins": "1000.0.11",
|
|
39
|
+
"@pnpm/read-package-json": "1000.1.2",
|
|
40
|
+
"@pnpm/remove-bins": "1000.0.15",
|
|
41
|
+
"@pnpm/store-connection-manager": "1002.2.4",
|
|
42
|
+
"@pnpm/types": "1000.9.0",
|
|
43
|
+
"@pnpm/link-bins": "1000.2.6"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@pnpm/global.commands": "1000.0.0-0"
|
|
47
|
+
},
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=22.13"
|
|
50
|
+
},
|
|
51
|
+
"jest": {
|
|
52
|
+
"preset": "@pnpm/jest-config"
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
56
|
+
"compile": "tsgo --build && pnpm run lint --fix",
|
|
57
|
+
"test": "pnpm run compile"
|
|
58
|
+
}
|
|
59
|
+
}
|