@dbx-tools/cli 0.6.40 → 0.6.41

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/lib/src/pnpm.js DELETED
@@ -1,190 +0,0 @@
1
- /**
2
- * pnpm discovery, workspace install, and projen forwarding for the `dbx-tools` CLI.
3
- *
4
- * ## Forcing a custom registry
5
- *
6
- * pnpm and npm do NOT agree on how a registry is configured, and getting this
7
- * wrong is silent. Measured against pnpm 11.0.6 and npm 11:
8
- *
9
- * | mechanism | npm | pnpm |
10
- * | ---------------------------------------- | --- | ---- |
11
- * | `--registry <url>` CLI flag | yes | yes |
12
- * | project `.npmrc` | yes | yes |
13
- * | `npm_config_registry` env var | yes | NO |
14
- *
15
- * So an env var alone reads back correctly from `npm config get registry` while
16
- * pnpm ignores it and silently falls through to its built-in
17
- * `https://registry.npmjs.org/`. That produced a bootstrap which logged the
18
- * local registry and then tried to fetch `typescript` / `projen` / `tsx` from
19
- * npmjs, failing with ECONNREFUSED on a machine that had no route to it.
20
- *
21
- * Hence all three channels, each where it actually applies:
22
- *
23
- * - {@link pnpmRegistryArgs} passes `--registry` to pnpm, but only for the
24
- * subcommands that resolve packages. It must NOT be appended to
25
- * `pnpm exec <cmd>`, where trailing arguments belong to `<cmd>`, not pnpm.
26
- * - {@link npxRegistryArgs} passes `--registry` to npx, before the package
27
- * name, so the npx fallback can fetch pnpm itself from the same registry.
28
- * - {@link childEnv} keeps `npm_config_registry` set for npm-based children
29
- * (npx included), which is the only channel npm exposes to nested tools.
30
- *
31
- * `@dbx-tools/core`'s `npmRegistry({ overrideOnly: true })` returns nothing when
32
- * the effective registry IS npmjs, so none of this touches a default install.
33
- *
34
- * @module
35
- */
36
- import { createRequire } from "node:module";
37
- import { delimiter, dirname, join } from "node:path";
38
- import { exec, project } from "@dbx-tools/core";
39
- import { functionModule, log } from "@dbx-tools/shared-core";
40
- import { needsInstall } from "./root.js";
41
- const logger = log.logger("dbx-tools:pnpm");
42
- /**
43
- * pnpm subcommands that resolve packages from a registry, and therefore accept a
44
- * meaningful `--registry`. Everything else (`exec`, `run`, `config`, ...) is left
45
- * alone: `exec` in particular forwards trailing arguments to the command it runs,
46
- * so a `--registry` appended there would land on projen or tsx instead.
47
- */
48
- const REGISTRY_SUBCOMMANDS = new Set([
49
- "add",
50
- "create",
51
- "dlx",
52
- "i",
53
- "import",
54
- "install",
55
- "link",
56
- "up",
57
- "update",
58
- ]);
59
- /**
60
- * The registry to force onto child package managers, or `undefined` when the
61
- * effective one is already the public default.
62
- *
63
- * `envVars: true` also consults `npm_config_registry` directly, because a
64
- * container may export it without any `.npmrc` for `npm config get` to read.
65
- * Memoized: resolution shells out to npm.
66
- */
67
- const registryOverride = functionModule.memoize(() => project.npmRegistry(null, { overrideOnly: true, envVars: true })?.toString());
68
- /** `--registry <url>` for npx, or `[]`. Placed BEFORE the package name by callers. */
69
- export function npxRegistryArgs() {
70
- const url = registryOverride();
71
- return url ? ["--registrsy", url] : [];
72
- }
73
- /** `--registry <url>` for a pnpm invocation, or `[]` when the subcommand does not resolve. */
74
- export function pnpmRegistryArgs(args) {
75
- const url = registryOverride();
76
- if (!url)
77
- return [];
78
- return pnpmUsesRegistry(args) ? ["--registry", url] : [];
79
- }
80
- /** Whether the first pnpm subcommand resolves packages and accepts `--registry`. */
81
- export function pnpmUsesRegistry(args) {
82
- const subcommand = args.find((arg) => !arg.startsWith("-"));
83
- return subcommand !== undefined && REGISTRY_SUBCOMMANDS.has(subcommand);
84
- }
85
- /**
86
- * `process.env` plus the current Node executable directory and registry aliases.
87
- *
88
- * The executable directory matters when this CLI was launched by absolute path
89
- * (for example from QuickJS or mise activation that was not exported): pnpm
90
- * itself runs, but lifecycle scripts invoke `node` by name and otherwise fail
91
- * with `sh: node: not found`.
92
- */
93
- export function childEnv(extra) {
94
- const env = { ...process.env, ...extra };
95
- const nodeBin = dirname(process.execPath);
96
- const pathEntries = (env.PATH ?? "").split(delimiter).filter(Boolean);
97
- if (!pathEntries.includes(nodeBin)) {
98
- env.PATH = [nodeBin, ...pathEntries].join(delimiter);
99
- }
100
- const url = registryOverride();
101
- if (url) {
102
- // Both cases: env is case-sensitive on POSIX, and npm lowercases when reading.
103
- env.npm_config_registry = url;
104
- env.NPM_CONFIG_REGISTRY = url;
105
- }
106
- return env;
107
- }
108
- /** True when `pnpm --version` runs, i.e. pnpm is already on PATH. */
109
- function pnpmOnPath() {
110
- try {
111
- exec.spawnSync("pnpm", ["--version"], {
112
- stderr: "ignore",
113
- stdin: "ignore",
114
- stdout: "ignore",
115
- check: true,
116
- });
117
- return true;
118
- }
119
- catch {
120
- return false;
121
- }
122
- }
123
- function resolvePnpmArgvImpl() {
124
- // 1. A resolvable `pnpm` dependency (the normal in-workspace case): run its
125
- // bin directly with the current node - no PATH or package-manager shim.
126
- // pnpm's own `--registry` rides in with the ARGS, after this entry point.
127
- try {
128
- const require = createRequire(import.meta.url);
129
- const pkgJsonPath = require.resolve("pnpm/package.json");
130
- const pkg = require(pkgJsonPath);
131
- const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin.pnpm;
132
- if (bin)
133
- return [process.execPath, join(dirname(pkgJsonPath), bin)];
134
- }
135
- catch {
136
- // fall through
137
- }
138
- // 2. A bare `pnpm` already on PATH (e.g. running under `pnpm dlx`). Prefer
139
- // this over the corepack/npx fallbacks so we never shell through npm -
140
- // `npx -y pnpm` runs under npm, which rejects a bootstrapped
141
- // `devEngines.packageManager: pnpm` manifest with EBADDEVENGINES.
142
- if (pnpmOnPath())
143
- return ["pnpm"];
144
- // 3. Try to enable pnpm via corepack, then use it.
145
- try {
146
- exec.spawnSync("corepack", ["enable", "pnpm"], {
147
- stderr: "ignore",
148
- stdin: "ignore",
149
- stdout: "ignore",
150
- check: true,
151
- });
152
- if (pnpmOnPath())
153
- return ["pnpm"];
154
- }
155
- catch {
156
- // fall through
157
- }
158
- // 4. Last resort: fetch pnpm on demand via npx. Pass `--engine-strict=false`
159
- // (and skip npm's devEngines gate) so npm doesn't refuse to run just
160
- // because the target manifest declares `devEngines.packageManager: pnpm`.
161
- // npm-level flags, `--registry` among them, must precede the package name,
162
- // or npx forwards them to pnpm instead of acting on them itself.
163
- return ["npx", ...npxRegistryArgs(), "-y", "--engine-strict=false", "pnpm"];
164
- }
165
- /** Memoized `[command, ...prefix]` argv prefix to run pnpm (resolved install, else corepack, else npx). */
166
- export const resolvePnpmArgv = functionModule.memoize(resolvePnpmArgvImpl);
167
- /** Run pnpm with inherited stdio from `cwd`, forcing the resolved registry. */
168
- export function runPnpm(args, cwd) {
169
- const [command, ...prefix] = resolvePnpmArgv();
170
- const registryArgs = pnpmRegistryArgs(args);
171
- if (registryArgs.length > 0) {
172
- logger.info(`running pnpm with registry: ${registryArgs[1]}`);
173
- }
174
- exec.spawnSync(command, [...prefix, ...args, ...registryArgs], {
175
- cwd,
176
- check: true,
177
- env: childEnv(),
178
- });
179
- }
180
- /** Install workspace dependencies when `node_modules` or projen is missing. */
181
- export function ensureWorkspaceReady(root) {
182
- if (needsInstall(root)) {
183
- runPnpm(["install", "--no-frozen-lockfile"], root);
184
- }
185
- }
186
- /** Run `pnpm exec projen` with the given args from `root`. */
187
- export function runProjen(args, root) {
188
- runPnpm(["exec", "projen", ...args], root);
189
- }
190
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG5wbS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wbnBtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0NHO0FBQ0gsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUM1QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDckQsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsY0FBYyxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzdELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFekMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0FBSzVDOzs7OztHQUtHO0FBQ0gsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLEdBQUcsQ0FBQztJQUNuQyxLQUFLO0lBQ0wsUUFBUTtJQUNSLEtBQUs7SUFDTCxHQUFHO0lBQ0gsUUFBUTtJQUNSLFNBQVM7SUFDVCxNQUFNO0lBQ04sSUFBSTtJQUNKLFFBQVE7Q0FDVCxDQUFDLENBQUM7QUFFSDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxnQkFBZ0IsR0FBRyxjQUFjLENBQUMsT0FBTyxDQUFDLEdBQXVCLEVBQUUsQ0FDdkUsT0FBTyxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUM3RSxDQUFDO0FBRUYsc0ZBQXNGO0FBQ3RGLE1BQU0sVUFBVSxlQUFlO0lBQzdCLE1BQU0sR0FBRyxHQUFHLGdCQUFnQixFQUFFLENBQUM7SUFDL0IsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsYUFB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O0lBQy9DLE1BQU0sWUFBWSxHQUFHLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzVDLElBQUksWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM1QixNQUFNLENBQUMsSUFBSSxDQUFDLCtCQUErQixZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFDRCxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsTUFBTSxFQUFFLEdBQUcsSUFBSSxFQUFFLEdBQUcsWUFBWSxDQUFDLEVBQUU7UUFDN0QsR0FBRztRQUNILEtBQUssRUFBRSxJQUFJO1FBQ1gsR0FBRyxFQUFFLFFBQVEsRUFBRTtLQUNoQixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsK0VBQStFO0FBQy9FLE1BQU0sVUFBVSxvQkFBb0IsQ0FBQyxJQUFZO0lBQy9DLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDdkIsT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLHNCQUFzQixDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDckQsQ0FBQztBQUNILENBQUM7QUFFRCw4REFBOEQ7QUFDOUQsTUFBTSxVQUFVLFNBQVMsQ0FBQyxJQUFjLEVBQUUsSUFBWTtJQUNwRCxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDN0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogcG5wbSBkaXNjb3ZlcnksIHdvcmtzcGFjZSBpbnN0YWxsLCBhbmQgcHJvamVuIGZvcndhcmRpbmcgZm9yIHRoZSBgZGJ4LXRvb2xzYCBDTEkuXG4gKlxuICogIyMgRm9yY2luZyBhIGN1c3RvbSByZWdpc3RyeVxuICpcbiAqIHBucG0gYW5kIG5wbSBkbyBOT1QgYWdyZWUgb24gaG93IGEgcmVnaXN0cnkgaXMgY29uZmlndXJlZCwgYW5kIGdldHRpbmcgdGhpc1xuICogd3JvbmcgaXMgc2lsZW50LiBNZWFzdXJlZCBhZ2FpbnN0IHBucG0gMTEuMC42IGFuZCBucG0gMTE6XG4gKlxuICogfCBtZWNoYW5pc20gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgbnBtIHwgcG5wbSB8XG4gKiB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0gfCAtLS0tIHxcbiAqIHwgYC0tcmVnaXN0cnkgPHVybD5gIENMSSBmbGFnICAgICAgICAgICAgICB8IHllcyB8IHllcyAgfFxuICogfCBwcm9qZWN0IGAubnBtcmNgICAgICAgICAgICAgICAgICAgICAgICAgIHwgeWVzIHwgeWVzICB8XG4gKiB8IGBucG1fY29uZmlnX3JlZ2lzdHJ5YCBlbnYgdmFyICAgICAgICAgICAgfCB5ZXMgfCBOTyAgIHxcbiAqXG4gKiBTbyBhbiBlbnYgdmFyIGFsb25lIHJlYWRzIGJhY2sgY29ycmVjdGx5IGZyb20gYG5wbSBjb25maWcgZ2V0IHJlZ2lzdHJ5YCB3aGlsZVxuICogcG5wbSBpZ25vcmVzIGl0IGFuZCBzaWxlbnRseSBmYWxscyB0aHJvdWdoIHRvIGl0cyBidWlsdC1pblxuICogYGh0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnL2AuIFRoYXQgcHJvZHVjZWQgYSBib290c3RyYXAgd2hpY2ggbG9nZ2VkIHRoZVxuICogbG9jYWwgcmVnaXN0cnkgYW5kIHRoZW4gdHJpZWQgdG8gZmV0Y2ggYHR5cGVzY3JpcHRgIC8gYHByb2plbmAgLyBgdHN4YCBmcm9tXG4gKiBucG1qcywgZmFpbGluZyB3aXRoIEVDT05OUkVGVVNFRCBvbiBhIG1hY2hpbmUgdGhhdCBoYWQgbm8gcm91dGUgdG8gaXQuXG4gKlxuICogSGVuY2UgYWxsIHRocmVlIGNoYW5uZWxzLCBlYWNoIHdoZXJlIGl0IGFjdHVhbGx5IGFwcGxpZXM6XG4gKlxuICogIC0ge0BsaW5rIHBucG1SZWdpc3RyeUFyZ3N9IHBhc3NlcyBgLS1yZWdpc3RyeWAgdG8gcG5wbSwgYnV0IG9ubHkgZm9yIHRoZVxuICogICAgc3ViY29tbWFuZHMgdGhhdCByZXNvbHZlIHBhY2thZ2VzLiBJdCBtdXN0IE5PVCBiZSBhcHBlbmRlZCB0b1xuICogICAgYHBucG0gZXhlYyA8Y21kPmAsIHdoZXJlIHRyYWlsaW5nIGFyZ3VtZW50cyBiZWxvbmcgdG8gYDxjbWQ+YCwgbm90IHBucG0uXG4gKiAgLSB7QGxpbmsgbnB4UmVnaXN0cnlBcmdzfSBwYXNzZXMgYC0tcmVnaXN0cnlgIHRvIG5weCwgYmVmb3JlIHRoZSBwYWNrYWdlXG4gKiAgICBuYW1lLCBzbyB0aGUgbnB4IGZhbGxiYWNrIGNhbiBmZXRjaCBwbnBtIGl0c2VsZiBmcm9tIHRoZSBzYW1lIHJlZ2lzdHJ5LlxuICogIC0ge0BsaW5rIGNoaWxkRW52fSBrZWVwcyBgbnBtX2NvbmZpZ19yZWdpc3RyeWAgc2V0IGZvciBucG0tYmFzZWQgY2hpbGRyZW5cbiAqICAgIChucHggaW5jbHVkZWQpLCB3aGljaCBpcyB0aGUgb25seSBjaGFubmVsIG5wbSBleHBvc2VzIHRvIG5lc3RlZCB0b29scy5cbiAqXG4gKiBgQGRieC10b29scy9jb3JlYCdzIGBucG1SZWdpc3RyeSh7IG92ZXJyaWRlT25seTogdHJ1ZSB9KWAgcmV0dXJucyBub3RoaW5nIHdoZW5cbiAqIHRoZSBlZmZlY3RpdmUgcmVnaXN0cnkgSVMgbnBtanMsIHNvIG5vbmUgb2YgdGhpcyB0b3VjaGVzIGEgZGVmYXVsdCBpbnN0YWxsLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuaW1wb3J0IHsgY3JlYXRlUmVxdWlyZSB9IGZyb20gXCJub2RlOm1vZHVsZVwiO1xuaW1wb3J0IHsgZGVsaW1pdGVyLCBkaXJuYW1lLCBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgZXhlYywgcHJvamVjdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2NvcmVcIjtcbmltcG9ydCB7IGZ1bmN0aW9uTW9kdWxlLCBsb2cgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgbmVlZHNJbnN0YWxsIH0gZnJvbSBcIi4vcm9vdC50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwiZGJ4LXRvb2xzOnBucG1cIik7XG5cbi8qKiBBIHBhY2thZ2UuanNvbiBgYmluYCBmaWVsZDogZWl0aGVyIGEgc2luZ2xlIGNvbW1hbmQgc3RyaW5nLCBvciBhIG5hbWUgLT4gcGF0aCBtYXAuICovXG50eXBlIEJpbkZpZWxkID0gc3RyaW5nIHwgUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblxuLyoqXG4gKiBwbnBtIHN1YmNvbW1hbmRzIHRoYXQgcmVzb2x2ZSBwYWNrYWdlcyBmcm9tIGEgcmVnaXN0cnksIGFuZCB0aGVyZWZvcmUgYWNjZXB0IGFcbiAqIG1lYW5pbmdmdWwgYC0tcmVnaXN0cnlgLiBFdmVyeXRoaW5nIGVsc2UgKGBleGVjYCwgYHJ1bmAsIGBjb25maWdgLCAuLi4pIGlzIGxlZnRcbiAqIGFsb25lOiBgZXhlY2AgaW4gcGFydGljdWxhciBmb3J3YXJkcyB0cmFpbGluZyBhcmd1bWVudHMgdG8gdGhlIGNvbW1hbmQgaXQgcnVucyxcbiAqIHNvIGEgYC0tcmVnaXN0cnlgIGFwcGVuZGVkIHRoZXJlIHdvdWxkIGxhbmQgb24gcHJvamVuIG9yIHRzeCBpbnN0ZWFkLlxuICovXG5jb25zdCBSRUdJU1RSWV9TVUJDT01NQU5EUyA9IG5ldyBTZXQoW1xuICBcImFkZFwiLFxuICBcImNyZWF0ZVwiLFxuICBcImRseFwiLFxuICBcImlcIixcbiAgXCJpbXBvcnRcIixcbiAgXCJpbnN0YWxsXCIsXG4gIFwibGlua1wiLFxuICBcInVwXCIsXG4gIFwidXBkYXRlXCIsXG5dKTtcblxuLyoqXG4gKiBUaGUgcmVnaXN0cnkgdG8gZm9yY2Ugb250byBjaGlsZCBwYWNrYWdlIG1hbmFnZXJzLCBvciBgdW5kZWZpbmVkYCB3aGVuIHRoZVxuICogZWZmZWN0aXZlIG9uZSBpcyBhbHJlYWR5IHRoZSBwdWJsaWMgZGVmYXVsdC5cbiAqXG4gKiBgZW52VmFyczogdHJ1ZWAgYWxzbyBjb25zdWx0cyBgbnBtX2NvbmZpZ19yZWdpc3RyeWAgZGlyZWN0bHksIGJlY2F1c2UgYVxuICogY29udGFpbmVyIG1heSBleHBvcnQgaXQgd2l0aG91dCBhbnkgYC5ucG1yY2AgZm9yIGBucG0gY29uZmlnIGdldGAgdG8gcmVhZC5cbiAqIE1lbW9pemVkOiByZXNvbHV0aW9uIHNoZWxscyBvdXQgdG8gbnBtLlxuICovXG5jb25zdCByZWdpc3RyeU92ZXJyaWRlID0gZnVuY3Rpb25Nb2R1bGUubWVtb2l6ZSgoKTogc3RyaW5nIHwgdW5kZWZpbmVkID0+XG4gIHByb2plY3QubnBtUmVnaXN0cnkobnVsbCwgeyBvdmVycmlkZU9ubHk6IHRydWUsIGVudlZhcnM6IHRydWUgfSk/LnRvU3RyaW5nKCksXG4pO1xuXG4vKiogYC0tcmVnaXN0cnkgPHVybD5gIGZvciBucHgsIG9yIGBbXWAuIFBsYWNlZCBCRUZPUkUgdGhlIHBhY2thZ2UgbmFtZSBieSBjYWxsZXJzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5weFJlZ2lzdHJ5QXJncygpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHVybCA9IHJlZ2lzdHJ5T3ZlcnJpZGUoKTtcbiAgcmV0dXJuIHVybCA/IFtcIi0tcmVnaXN0cnN5XCIsIHVybF0gOiBbXTtcbn1cblxuLyoqIGAtLXJlZ2lzdHJ5IDx1cmw+YCBmb3IgYSBwbnBtIGludm9jYXRpb24sIG9yIGBbXWAgd2hlbiB0aGUgc3ViY29tbWFuZCBkb2VzIG5vdCByZXNvbHZlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBucG1SZWdpc3RyeUFyZ3MoYXJnczogcmVhZG9ubHkgc3RyaW5nW10pOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHVybCA9IHJlZ2lzdHJ5T3ZlcnJpZGUoKTtcbiAgaWYgKCF1cmwpIHJldHVybiBbXTtcbiAgcmV0dXJuIHBucG1Vc2VzUmVnaXN0cnkoYXJncykgPyBbXCItLXJlZ2lzdHJ5XCIsIHVybF0gOiBbXTtcbn1cblxuLyoqIFdoZXRoZXIgdGhlIGZpcnN0IHBucG0gc3ViY29tbWFuZCByZXNvbHZlcyBwYWNrYWdlcyBhbmQgYWNjZXB0cyBgLS1yZWdpc3RyeWAuICovXG5leHBvcnQgZnVuY3Rpb24gcG5wbVVzZXNSZWdpc3RyeShhcmdzOiByZWFkb25seSBzdHJpbmdbXSk6IGJvb2xlYW4ge1xuICBjb25zdCBzdWJjb21tYW5kID0gYXJncy5maW5kKChhcmcpID0+ICFhcmcuc3RhcnRzV2l0aChcIi1cIikpO1xuICByZXR1cm4gc3ViY29tbWFuZCAhPT0gdW5kZWZpbmVkICYmIFJFR0lTVFJZX1NVQkNPTU1BTkRTLmhhcyhzdWJjb21tYW5kKTtcbn1cblxuLyoqXG4gKiBgcHJvY2Vzcy5lbnZgIHBsdXMgdGhlIGN1cnJlbnQgTm9kZSBleGVjdXRhYmxlIGRpcmVjdG9yeSBhbmQgcmVnaXN0cnkgYWxpYXNlcy5cbiAqXG4gKiBUaGUgZXhlY3V0YWJsZSBkaXJlY3RvcnkgbWF0dGVycyB3aGVuIHRoaXMgQ0xJIHdhcyBsYXVuY2hlZCBieSBhYnNvbHV0ZSBwYXRoXG4gKiAoZm9yIGV4YW1wbGUgZnJvbSBRdWlja0pTIG9yIG1pc2UgYWN0aXZhdGlvbiB0aGF0IHdhcyBub3QgZXhwb3J0ZWQpOiBwbnBtXG4gKiBpdHNlbGYgcnVucywgYnV0IGxpZmVjeWNsZSBzY3JpcHRzIGludm9rZSBgbm9kZWAgYnkgbmFtZSBhbmQgb3RoZXJ3aXNlIGZhaWxcbiAqIHdpdGggYHNoOiBub2RlOiBub3QgZm91bmRgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2hpbGRFbnYoZXh0cmE/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogTm9kZUpTLlByb2Nlc3NFbnYge1xuICBjb25zdCBlbnY6IE5vZGVKUy5Qcm9jZXNzRW52ID0geyAuLi5wcm9jZXNzLmVudiwgLi4uZXh0cmEgfTtcbiAgY29uc3Qgbm9kZUJpbiA9IGRpcm5hbWUocHJvY2Vzcy5leGVjUGF0aCk7XG4gIGNvbnN0IHBhdGhFbnRyaWVzID0gKGVudi5QQVRIID8/IFwiXCIpLnNwbGl0KGRlbGltaXRlcikuZmlsdGVyKEJvb2xlYW4pO1xuICBpZiAoIXBhdGhFbnRyaWVzLmluY2x1ZGVzKG5vZGVCaW4pKSB7XG4gICAgZW52LlBBVEggPSBbbm9kZUJpbiwgLi4ucGF0aEVudHJpZXNdLmpvaW4oZGVsaW1pdGVyKTtcbiAgfVxuICBjb25zdCB1cmwgPSByZWdpc3RyeU92ZXJyaWRlKCk7XG4gIGlmICh1cmwpIHtcbiAgICAvLyBCb3RoIGNhc2VzOiBlbnYgaXMgY2FzZS1zZW5zaXRpdmUgb24gUE9TSVgsIGFuZCBucG0gbG93ZXJjYXNlcyB3aGVuIHJlYWRpbmcuXG4gICAgZW52Lm5wbV9jb25maWdfcmVnaXN0cnkgPSB1cmw7XG4gICAgZW52Lk5QTV9DT05GSUdfUkVHSVNUUlkgPSB1cmw7XG4gIH1cbiAgcmV0dXJuIGVudjtcbn1cblxuLyoqIFRydWUgd2hlbiBgcG5wbSAtLXZlcnNpb25gIHJ1bnMsIGkuZS4gcG5wbSBpcyBhbHJlYWR5IG9uIFBBVEguICovXG5mdW5jdGlvbiBwbnBtT25QYXRoKCk6IGJvb2xlYW4ge1xuICB0cnkge1xuICAgIGV4ZWMuc3Bhd25TeW5jKFwicG5wbVwiLCBbXCItLXZlcnNpb25cIl0sIHtcbiAgICAgIHN0ZGVycjogXCJpZ25vcmVcIixcbiAgICAgIHN0ZGluOiBcImlnbm9yZVwiLFxuICAgICAgc3Rkb3V0OiBcImlnbm9yZVwiLFxuICAgICAgY2hlY2s6IHRydWUsXG4gICAgfSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZXNvbHZlUG5wbUFyZ3ZJbXBsKCk6IHN0cmluZ1tdIHtcbiAgLy8gMS4gQSByZXNvbHZhYmxlIGBwbnBtYCBkZXBlbmRlbmN5ICh0aGUgbm9ybWFsIGluLXdvcmtzcGFjZSBjYXNlKTogcnVuIGl0c1xuICAvLyAgICBiaW4gZGlyZWN0bHkgd2l0aCB0aGUgY3VycmVudCBub2RlIC0gbm8gUEFUSCBvciBwYWNrYWdlLW1hbmFnZXIgc2hpbS5cbiAgLy8gICAgcG5wbSdzIG93biBgLS1yZWdpc3RyeWAgcmlkZXMgaW4gd2l0aCB0aGUgQVJHUywgYWZ0ZXIgdGhpcyBlbnRyeSBwb2ludC5cbiAgdHJ5IHtcbiAgICBjb25zdCByZXF1aXJlID0gY3JlYXRlUmVxdWlyZShpbXBvcnQubWV0YS51cmwpO1xuICAgIGNvbnN0IHBrZ0pzb25QYXRoID0gcmVxdWlyZS5yZXNvbHZlKFwicG5wbS9wYWNrYWdlLmpzb25cIik7XG4gICAgY29uc3QgcGtnID0gcmVxdWlyZShwa2dKc29uUGF0aCkgYXMgeyBiaW46IEJpbkZpZWxkIH07XG4gICAgY29uc3QgYmluID0gdHlwZW9mIHBrZy5iaW4gPT09IFwic3RyaW5nXCIgPyBwa2cuYmluIDogcGtnLmJpbi5wbnBtO1xuICAgIGlmIChiaW4pIHJldHVybiBbcHJvY2Vzcy5leGVjUGF0aCwgam9pbihkaXJuYW1lKHBrZ0pzb25QYXRoKSwgYmluKV07XG4gIH0gY2F0Y2gge1xuICAgIC8vIGZhbGwgdGhyb3VnaFxuICB9XG5cbiAgLy8gMi4gQSBiYXJlIGBwbnBtYCBhbHJlYWR5IG9uIFBBVEggKGUuZy4gcnVubmluZyB1bmRlciBgcG5wbSBkbHhgKS4gUHJlZmVyXG4gIC8vICAgIHRoaXMgb3ZlciB0aGUgY29yZXBhY2svbnB4IGZhbGxiYWNrcyBzbyB3ZSBuZXZlciBzaGVsbCB0aHJvdWdoIG5wbSAtXG4gIC8vICAgIGBucHggLXkgcG5wbWAgcnVucyB1bmRlciBucG0sIHdoaWNoIHJlamVjdHMgYSBib290c3RyYXBwZWRcbiAgLy8gICAgYGRldkVuZ2luZXMucGFja2FnZU1hbmFnZXI6IHBucG1gIG1hbmlmZXN0IHdpdGggRUJBRERFVkVOR0lORVMuXG4gIGlmIChwbnBtT25QYXRoKCkpIHJldHVybiBbXCJwbnBtXCJdO1xuXG4gIC8vIDMuIFRyeSB0byBlbmFibGUgcG5wbSB2aWEgY29yZXBhY2ssIHRoZW4gdXNlIGl0LlxuICB0cnkge1xuICAgIGV4ZWMuc3Bhd25TeW5jKFwiY29yZXBhY2tcIiwgW1wiZW5hYmxlXCIsIFwicG5wbVwiXSwge1xuICAgICAgc3RkZXJyOiBcImlnbm9yZVwiLFxuICAgICAgc3RkaW46IFwiaWdub3JlXCIsXG4gICAgICBzdGRvdXQ6IFwiaWdub3JlXCIsXG4gICAgICBjaGVjazogdHJ1ZSxcbiAgICB9KTtcbiAgICBpZiAocG5wbU9uUGF0aCgpKSByZXR1cm4gW1wicG5wbVwiXTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gZmFsbCB0aHJvdWdoXG4gIH1cblxuICAvLyA0LiBMYXN0IHJlc29ydDogZmV0Y2ggcG5wbSBvbiBkZW1hbmQgdmlhIG5weC4gUGFzcyBgLS1lbmdpbmUtc3RyaWN0PWZhbHNlYFxuICAvLyAgICAoYW5kIHNraXAgbnBtJ3MgZGV2RW5naW5lcyBnYXRlKSBzbyBucG0gZG9lc24ndCByZWZ1c2UgdG8gcnVuIGp1c3RcbiAgLy8gICAgYmVjYXVzZSB0aGUgdGFyZ2V0IG1hbmlmZXN0IGRlY2xhcmVzIGBkZXZFbmdpbmVzLnBhY2thZ2VNYW5hZ2VyOiBwbnBtYC5cbiAgLy8gICAgbnBtLWxldmVsIGZsYWdzLCBgLS1yZWdpc3RyeWAgYW1vbmcgdGhlbSwgbXVzdCBwcmVjZWRlIHRoZSBwYWNrYWdlIG5hbWUsXG4gIC8vICAgIG9yIG5weCBmb3J3YXJkcyB0aGVtIHRvIHBucG0gaW5zdGVhZCBvZiBhY3Rpbmcgb24gdGhlbSBpdHNlbGYuXG4gIHJldHVybiBbXCJucHhcIiwgLi4ubnB4UmVnaXN0cnlBcmdzKCksIFwiLXlcIiwgXCItLWVuZ2luZS1zdHJpY3Q9ZmFsc2VcIiwgXCJwbnBtXCJdO1xufVxuXG4vKiogTWVtb2l6ZWQgYFtjb21tYW5kLCAuLi5wcmVmaXhdYCBhcmd2IHByZWZpeCB0byBydW4gcG5wbSAocmVzb2x2ZWQgaW5zdGFsbCwgZWxzZSBjb3JlcGFjaywgZWxzZSBucHgpLiAqL1xuZXhwb3J0IGNvbnN0IHJlc29sdmVQbnBtQXJndiA9IGZ1bmN0aW9uTW9kdWxlLm1lbW9pemUocmVzb2x2ZVBucG1Bcmd2SW1wbCk7XG5cbi8qKiBSdW4gcG5wbSB3aXRoIGluaGVyaXRlZCBzdGRpbyBmcm9tIGBjd2RgLCBmb3JjaW5nIHRoZSByZXNvbHZlZCByZWdpc3RyeS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBydW5QbnBtKGFyZ3M6IHN0cmluZ1tdLCBjd2Q6IHN0cmluZyk6IHZvaWQge1xuICBjb25zdCBbY29tbWFuZCwgLi4ucHJlZml4XSA9IHJlc29sdmVQbnBtQXJndigpO1xuICBjb25zdCByZWdpc3RyeUFyZ3MgPSBwbnBtUmVnaXN0cnlBcmdzKGFyZ3MpO1xuICBpZiAocmVnaXN0cnlBcmdzLmxlbmd0aCA+IDApIHtcbiAgICBsb2dnZXIuaW5mbyhgcnVubmluZyBwbnBtIHdpdGggcmVnaXN0cnk6ICR7cmVnaXN0cnlBcmdzWzFdfWApO1xuICB9XG4gIGV4ZWMuc3Bhd25TeW5jKGNvbW1hbmQsIFsuLi5wcmVmaXgsIC4uLmFyZ3MsIC4uLnJlZ2lzdHJ5QXJnc10sIHtcbiAgICBjd2QsXG4gICAgY2hlY2s6IHRydWUsXG4gICAgZW52OiBjaGlsZEVudigpLFxuICB9KTtcbn1cblxuLyoqIEluc3RhbGwgd29ya3NwYWNlIGRlcGVuZGVuY2llcyB3aGVuIGBub2RlX21vZHVsZXNgIG9yIHByb2plbiBpcyBtaXNzaW5nLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZVdvcmtzcGFjZVJlYWR5KHJvb3Q6IHN0cmluZyk6IHZvaWQge1xuICBpZiAobmVlZHNJbnN0YWxsKHJvb3QpKSB7XG4gICAgcnVuUG5wbShbXCJpbnN0YWxsXCIsIFwiLS1uby1mcm96ZW4tbG9ja2ZpbGVcIl0sIHJvb3QpO1xuICB9XG59XG5cbi8qKiBSdW4gYHBucG0gZXhlYyBwcm9qZW5gIHdpdGggdGhlIGdpdmVuIGFyZ3MgZnJvbSBgcm9vdGAuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuUHJvamVuKGFyZ3M6IHN0cmluZ1tdLCByb290OiBzdHJpbmcpOiB2b2lkIHtcbiAgcnVuUG5wbShbXCJleGVjXCIsIFwicHJvamVuXCIsIC4uLmFyZ3NdLCByb290KTtcbn1cbiJdfQ==
package/src/pnpm.ts DELETED
@@ -1,203 +0,0 @@
1
- /**
2
- * pnpm discovery, workspace install, and projen forwarding for the `dbx-tools` CLI.
3
- *
4
- * ## Forcing a custom registry
5
- *
6
- * pnpm and npm do NOT agree on how a registry is configured, and getting this
7
- * wrong is silent. Measured against pnpm 11.0.6 and npm 11:
8
- *
9
- * | mechanism | npm | pnpm |
10
- * | ---------------------------------------- | --- | ---- |
11
- * | `--registry <url>` CLI flag | yes | yes |
12
- * | project `.npmrc` | yes | yes |
13
- * | `npm_config_registry` env var | yes | NO |
14
- *
15
- * So an env var alone reads back correctly from `npm config get registry` while
16
- * pnpm ignores it and silently falls through to its built-in
17
- * `https://registry.npmjs.org/`. That produced a bootstrap which logged the
18
- * local registry and then tried to fetch `typescript` / `projen` / `tsx` from
19
- * npmjs, failing with ECONNREFUSED on a machine that had no route to it.
20
- *
21
- * Hence all three channels, each where it actually applies:
22
- *
23
- * - {@link pnpmRegistryArgs} passes `--registry` to pnpm, but only for the
24
- * subcommands that resolve packages. It must NOT be appended to
25
- * `pnpm exec <cmd>`, where trailing arguments belong to `<cmd>`, not pnpm.
26
- * - {@link npxRegistryArgs} passes `--registry` to npx, before the package
27
- * name, so the npx fallback can fetch pnpm itself from the same registry.
28
- * - {@link childEnv} keeps `npm_config_registry` set for npm-based children
29
- * (npx included), which is the only channel npm exposes to nested tools.
30
- *
31
- * `@dbx-tools/core`'s `npmRegistry({ overrideOnly: true })` returns nothing when
32
- * the effective registry IS npmjs, so none of this touches a default install.
33
- *
34
- * @module
35
- */
36
- import { createRequire } from "node:module";
37
- import { delimiter, dirname, join } from "node:path";
38
- import { exec, project } from "@dbx-tools/core";
39
- import { functionModule, log } from "@dbx-tools/shared-core";
40
- import { needsInstall } from "./root.ts";
41
-
42
- const logger = log.logger("dbx-tools:pnpm");
43
-
44
- /** A package.json `bin` field: either a single command string, or a name -> path map. */
45
- type BinField = string | Record<string, string>;
46
-
47
- /**
48
- * pnpm subcommands that resolve packages from a registry, and therefore accept a
49
- * meaningful `--registry`. Everything else (`exec`, `run`, `config`, ...) is left
50
- * alone: `exec` in particular forwards trailing arguments to the command it runs,
51
- * so a `--registry` appended there would land on projen or tsx instead.
52
- */
53
- const REGISTRY_SUBCOMMANDS = new Set([
54
- "add",
55
- "create",
56
- "dlx",
57
- "i",
58
- "import",
59
- "install",
60
- "link",
61
- "up",
62
- "update",
63
- ]);
64
-
65
- /**
66
- * The registry to force onto child package managers, or `undefined` when the
67
- * effective one is already the public default.
68
- *
69
- * `envVars: true` also consults `npm_config_registry` directly, because a
70
- * container may export it without any `.npmrc` for `npm config get` to read.
71
- * Memoized: resolution shells out to npm.
72
- */
73
- const registryOverride = functionModule.memoize((): string | undefined =>
74
- project.npmRegistry(null, { overrideOnly: true, envVars: true })?.toString(),
75
- );
76
-
77
- /** `--registry <url>` for npx, or `[]`. Placed BEFORE the package name by callers. */
78
- export function npxRegistryArgs(): string[] {
79
- const url = registryOverride();
80
- return url ? ["--registrsy", url] : [];
81
- }
82
-
83
- /** `--registry <url>` for a pnpm invocation, or `[]` when the subcommand does not resolve. */
84
- export function pnpmRegistryArgs(args: readonly string[]): string[] {
85
- const url = registryOverride();
86
- if (!url) return [];
87
- return pnpmUsesRegistry(args) ? ["--registry", url] : [];
88
- }
89
-
90
- /** Whether the first pnpm subcommand resolves packages and accepts `--registry`. */
91
- export function pnpmUsesRegistry(args: readonly string[]): boolean {
92
- const subcommand = args.find((arg) => !arg.startsWith("-"));
93
- return subcommand !== undefined && REGISTRY_SUBCOMMANDS.has(subcommand);
94
- }
95
-
96
- /**
97
- * `process.env` plus the current Node executable directory and registry aliases.
98
- *
99
- * The executable directory matters when this CLI was launched by absolute path
100
- * (for example from QuickJS or mise activation that was not exported): pnpm
101
- * itself runs, but lifecycle scripts invoke `node` by name and otherwise fail
102
- * with `sh: node: not found`.
103
- */
104
- export function childEnv(extra?: Record<string, string>): NodeJS.ProcessEnv {
105
- const env: NodeJS.ProcessEnv = { ...process.env, ...extra };
106
- const nodeBin = dirname(process.execPath);
107
- const pathEntries = (env.PATH ?? "").split(delimiter).filter(Boolean);
108
- if (!pathEntries.includes(nodeBin)) {
109
- env.PATH = [nodeBin, ...pathEntries].join(delimiter);
110
- }
111
- const url = registryOverride();
112
- if (url) {
113
- // Both cases: env is case-sensitive on POSIX, and npm lowercases when reading.
114
- env.npm_config_registry = url;
115
- env.NPM_CONFIG_REGISTRY = url;
116
- }
117
- return env;
118
- }
119
-
120
- /** True when `pnpm --version` runs, i.e. pnpm is already on PATH. */
121
- function pnpmOnPath(): boolean {
122
- try {
123
- exec.spawnSync("pnpm", ["--version"], {
124
- stderr: "ignore",
125
- stdin: "ignore",
126
- stdout: "ignore",
127
- check: true,
128
- });
129
- return true;
130
- } catch {
131
- return false;
132
- }
133
- }
134
-
135
- function resolvePnpmArgvImpl(): string[] {
136
- // 1. A resolvable `pnpm` dependency (the normal in-workspace case): run its
137
- // bin directly with the current node - no PATH or package-manager shim.
138
- // pnpm's own `--registry` rides in with the ARGS, after this entry point.
139
- try {
140
- const require = createRequire(import.meta.url);
141
- const pkgJsonPath = require.resolve("pnpm/package.json");
142
- const pkg = require(pkgJsonPath) as { bin: BinField };
143
- const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin.pnpm;
144
- if (bin) return [process.execPath, join(dirname(pkgJsonPath), bin)];
145
- } catch {
146
- // fall through
147
- }
148
-
149
- // 2. A bare `pnpm` already on PATH (e.g. running under `pnpm dlx`). Prefer
150
- // this over the corepack/npx fallbacks so we never shell through npm -
151
- // `npx -y pnpm` runs under npm, which rejects a bootstrapped
152
- // `devEngines.packageManager: pnpm` manifest with EBADDEVENGINES.
153
- if (pnpmOnPath()) return ["pnpm"];
154
-
155
- // 3. Try to enable pnpm via corepack, then use it.
156
- try {
157
- exec.spawnSync("corepack", ["enable", "pnpm"], {
158
- stderr: "ignore",
159
- stdin: "ignore",
160
- stdout: "ignore",
161
- check: true,
162
- });
163
- if (pnpmOnPath()) return ["pnpm"];
164
- } catch {
165
- // fall through
166
- }
167
-
168
- // 4. Last resort: fetch pnpm on demand via npx. Pass `--engine-strict=false`
169
- // (and skip npm's devEngines gate) so npm doesn't refuse to run just
170
- // because the target manifest declares `devEngines.packageManager: pnpm`.
171
- // npm-level flags, `--registry` among them, must precede the package name,
172
- // or npx forwards them to pnpm instead of acting on them itself.
173
- return ["npx", ...npxRegistryArgs(), "-y", "--engine-strict=false", "pnpm"];
174
- }
175
-
176
- /** Memoized `[command, ...prefix]` argv prefix to run pnpm (resolved install, else corepack, else npx). */
177
- export const resolvePnpmArgv = functionModule.memoize(resolvePnpmArgvImpl);
178
-
179
- /** Run pnpm with inherited stdio from `cwd`, forcing the resolved registry. */
180
- export function runPnpm(args: string[], cwd: string): void {
181
- const [command, ...prefix] = resolvePnpmArgv();
182
- const registryArgs = pnpmRegistryArgs(args);
183
- if (registryArgs.length > 0) {
184
- logger.info(`running pnpm with registry: ${registryArgs[1]}`);
185
- }
186
- exec.spawnSync(command, [...prefix, ...args, ...registryArgs], {
187
- cwd,
188
- check: true,
189
- env: childEnv(),
190
- });
191
- }
192
-
193
- /** Install workspace dependencies when `node_modules` or projen is missing. */
194
- export function ensureWorkspaceReady(root: string): void {
195
- if (needsInstall(root)) {
196
- runPnpm(["install", "--no-frozen-lockfile"], root);
197
- }
198
- }
199
-
200
- /** Run `pnpm exec projen` with the given args from `root`. */
201
- export function runProjen(args: string[], root: string): void {
202
- runPnpm(["exec", "projen", ...args], root);
203
- }