@penvhq/cli 0.11.0 → 0.13.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.
@@ -21,6 +21,14 @@ import { PenvError } from '@penvhq/core';
21
21
  * has to get right is the plan, the consent, and the refusal when the install
22
22
  * does not happen.
23
23
  *
24
+ * A plan is a list of steps, because in a workspace "the project's dependency"
25
+ * is plural. pnpm refuses a bare `add` at a workspace root (`-w` is how you say
26
+ * you meant the root), and a workspace package that declares `@penvhq/penv`
27
+ * itself is a second copy of the very version the manifest pins — one repository
28
+ * ran the 0.8 bridge under a 0.11 pin for three releases because nothing looked
29
+ * below the root. So every `package.json` that declares it moves, under one
30
+ * consent, and the commands shown are the ones that run.
31
+ *
24
32
  * Two commands write that dependency line: `penv init`, which is the engine's,
25
33
  * and `penv upgrade`, which is the launcher's. This module is published at
26
34
  * `@penvhq/cli/install` so the launcher reaches it without loading the command
@@ -32,6 +40,25 @@ import { PenvError } from '@penvhq/core';
32
40
  declare const RUNTIME_PACKAGE = "@penvhq/penv";
33
41
  /** The peer `penv.schema.ts` imports, which the project supplies because a peer is not hoisted. */
34
42
  declare const SCHEMA_PACKAGE = "zod";
43
+ /**
44
+ * The module every committed provider declaration augments, which the project
45
+ * declares for the same reason it declares zod: nothing hoists it.
46
+ *
47
+ * `penv add` commits a `declare module "@penvhq/core"` block, and TypeScript
48
+ * resolves that specifier from the project's own files. Under pnpm's strict
49
+ * layout a transitive dependency is not at the project root, so the specifier
50
+ * resolves to nothing — and an augmentation whose module cannot be found is not
51
+ * an error, it silently degrades to an *ambient* declaration. The map
52
+ * `defineConfig` reads stays empty, a misspelled provider field compiles clean,
53
+ * and no diagnostic anywhere says so. A hoisting package manager hides this; the
54
+ * project declaring it is what makes the declaration bind under all of them.
55
+ *
56
+ * `devDependencies`, because that is the whole of what it is: a type-only
57
+ * augmentation target. No application code imports it, and `@penvhq/penv`
58
+ * carries its own copy of the runtime — so the PRD's one runtime dependency is
59
+ * still one.
60
+ */
61
+ declare const TYPES_PACKAGE = "@penvhq/core";
35
62
  type PackageManager = "pnpm" | "npm" | "yarn" | "bun";
36
63
  /** One package the adopted project needs, and what its `package.json` says today. */
37
64
  interface InstallPackage {
@@ -42,16 +69,30 @@ interface InstallPackage {
42
69
  /** True when this project already has it — nothing to install for this one. */
43
70
  readonly satisfied: boolean;
44
71
  }
72
+ /** One `package.json` the install rewrites, and the command that rewrites it. */
73
+ interface InstallStep {
74
+ /** The file the diff names — `package.json`, or a workspace package's path to it. */
75
+ readonly manifest: string;
76
+ /** Everything this file needs, in the order the diff shows them. */
77
+ readonly packages: readonly InstallPackage[];
78
+ /** The command, argv-shaped — run from the project root, whichever file it writes. */
79
+ readonly command: readonly string[];
80
+ /** The block this step writes into, which is what the diff shows. */
81
+ readonly dev: boolean;
82
+ /** True when this file already declares every one of them. */
83
+ readonly satisfied: boolean;
84
+ }
45
85
  interface InstallPlan {
46
86
  readonly root: string;
47
87
  readonly manager: PackageManager;
48
- /** Everything an adopted project needs, in the order the diff shows them. */
49
- readonly packages: readonly InstallPackage[];
50
- /** The command, argv-shaped — what runs, and what a refusal tells the user to run. */
51
- readonly command: readonly string[];
88
+ /**
89
+ * The root's `package.json` — one step per block it writes, since one command
90
+ * names one — then every workspace package that declares the runtime one.
91
+ */
92
+ readonly steps: readonly InstallStep[];
52
93
  /** The lockfile the manager will rewrite, when the project has one. */
53
94
  readonly lockfile?: string;
54
- /** True when every package is already there — nothing to install. */
95
+ /** True when every step is already satisfied — nothing to install. */
55
96
  readonly satisfied: boolean;
56
97
  }
57
98
  /** Runs an install plan, or throws. Replaced in tests; never spawns there. */
@@ -75,18 +116,35 @@ declare function engineVersion(): string;
75
116
  declare function schemaPackageVersion(): string;
76
117
  /** The package manager this project already uses: its lockfile, then what it declares, then npm. */
77
118
  declare function detectPackageManager(root: string): PackageManager;
119
+ /** True when `root` is the root of a pnpm workspace, which is what `-w` is for. */
120
+ declare function isPnpmWorkspaceRoot(root: string): boolean;
78
121
  declare function planInstall(root: string, version?: string): InstallPlan;
122
+ /** What this plan actually installs, once per package however many files declare it. */
123
+ declare function installedPackages(plan: InstallPlan): readonly InstallPackage[];
79
124
  /**
80
125
  * The change, as it will appear in the diff — the whole point of showing it is
81
126
  * that the reader recognises their own file, so these are the `package.json`
82
127
  * lines that land and the lockfile that gets rewritten, not a summary of both.
128
+ *
129
+ * In a workspace that is more than one file, and the commands underneath are the
130
+ * ones that run: a "Run with:" line the reader cannot paste is worse than none.
83
131
  */
84
132
  declare function renderInstallPlan(plan: InstallPlan): string[];
85
133
  /**
86
134
  * The real install: the project's own package manager, started the way any other
87
135
  * child is (`.cmd` shims on Windows included), with its output the user's to see.
136
+ *
137
+ * Every step runs from the project root — `-w` and `--filter` are how a workspace
138
+ * says which `package.json` it means, so the directory never changes.
88
139
  */
89
140
  declare const installWithPackageManager: InstallRuntime;
90
- declare function installFailed(plan: InstallPlan): PenvError;
141
+ /**
142
+ * What to do about a package manager that refused.
143
+ *
144
+ * Never the command that just failed: the one remediation guaranteed not to work
145
+ * is the one the reader already ran. The manager said why, on their screen, and
146
+ * nothing was migrated — so the answer is that line and a second `penv init`.
147
+ */
148
+ declare function installFailed(plan: InstallPlan, step: InstallStep): PenvError;
91
149
 
92
- export { type InstallPackage, type InstallPlan, type InstallRuntime, type PackageManager, RUNTIME_PACKAGE, SCHEMA_PACKAGE, detectPackageManager, engineVersion, installFailed, installWithPackageManager, planInstall, renderInstallPlan, schemaPackageVersion };
150
+ export { type InstallPackage, type InstallPlan, type InstallRuntime, type InstallStep, type PackageManager, RUNTIME_PACKAGE, SCHEMA_PACKAGE, TYPES_PACKAGE, detectPackageManager, engineVersion, installFailed, installWithPackageManager, installedPackages, isPnpmWorkspaceRoot, planInstall, renderInstallPlan, schemaPackageVersion };
package/dist/install.d.ts CHANGED
@@ -21,6 +21,14 @@ import { PenvError } from '@penvhq/core';
21
21
  * has to get right is the plan, the consent, and the refusal when the install
22
22
  * does not happen.
23
23
  *
24
+ * A plan is a list of steps, because in a workspace "the project's dependency"
25
+ * is plural. pnpm refuses a bare `add` at a workspace root (`-w` is how you say
26
+ * you meant the root), and a workspace package that declares `@penvhq/penv`
27
+ * itself is a second copy of the very version the manifest pins — one repository
28
+ * ran the 0.8 bridge under a 0.11 pin for three releases because nothing looked
29
+ * below the root. So every `package.json` that declares it moves, under one
30
+ * consent, and the commands shown are the ones that run.
31
+ *
24
32
  * Two commands write that dependency line: `penv init`, which is the engine's,
25
33
  * and `penv upgrade`, which is the launcher's. This module is published at
26
34
  * `@penvhq/cli/install` so the launcher reaches it without loading the command
@@ -32,6 +40,25 @@ import { PenvError } from '@penvhq/core';
32
40
  declare const RUNTIME_PACKAGE = "@penvhq/penv";
33
41
  /** The peer `penv.schema.ts` imports, which the project supplies because a peer is not hoisted. */
34
42
  declare const SCHEMA_PACKAGE = "zod";
43
+ /**
44
+ * The module every committed provider declaration augments, which the project
45
+ * declares for the same reason it declares zod: nothing hoists it.
46
+ *
47
+ * `penv add` commits a `declare module "@penvhq/core"` block, and TypeScript
48
+ * resolves that specifier from the project's own files. Under pnpm's strict
49
+ * layout a transitive dependency is not at the project root, so the specifier
50
+ * resolves to nothing — and an augmentation whose module cannot be found is not
51
+ * an error, it silently degrades to an *ambient* declaration. The map
52
+ * `defineConfig` reads stays empty, a misspelled provider field compiles clean,
53
+ * and no diagnostic anywhere says so. A hoisting package manager hides this; the
54
+ * project declaring it is what makes the declaration bind under all of them.
55
+ *
56
+ * `devDependencies`, because that is the whole of what it is: a type-only
57
+ * augmentation target. No application code imports it, and `@penvhq/penv`
58
+ * carries its own copy of the runtime — so the PRD's one runtime dependency is
59
+ * still one.
60
+ */
61
+ declare const TYPES_PACKAGE = "@penvhq/core";
35
62
  type PackageManager = "pnpm" | "npm" | "yarn" | "bun";
36
63
  /** One package the adopted project needs, and what its `package.json` says today. */
37
64
  interface InstallPackage {
@@ -42,16 +69,30 @@ interface InstallPackage {
42
69
  /** True when this project already has it — nothing to install for this one. */
43
70
  readonly satisfied: boolean;
44
71
  }
72
+ /** One `package.json` the install rewrites, and the command that rewrites it. */
73
+ interface InstallStep {
74
+ /** The file the diff names — `package.json`, or a workspace package's path to it. */
75
+ readonly manifest: string;
76
+ /** Everything this file needs, in the order the diff shows them. */
77
+ readonly packages: readonly InstallPackage[];
78
+ /** The command, argv-shaped — run from the project root, whichever file it writes. */
79
+ readonly command: readonly string[];
80
+ /** The block this step writes into, which is what the diff shows. */
81
+ readonly dev: boolean;
82
+ /** True when this file already declares every one of them. */
83
+ readonly satisfied: boolean;
84
+ }
45
85
  interface InstallPlan {
46
86
  readonly root: string;
47
87
  readonly manager: PackageManager;
48
- /** Everything an adopted project needs, in the order the diff shows them. */
49
- readonly packages: readonly InstallPackage[];
50
- /** The command, argv-shaped — what runs, and what a refusal tells the user to run. */
51
- readonly command: readonly string[];
88
+ /**
89
+ * The root's `package.json` — one step per block it writes, since one command
90
+ * names one — then every workspace package that declares the runtime one.
91
+ */
92
+ readonly steps: readonly InstallStep[];
52
93
  /** The lockfile the manager will rewrite, when the project has one. */
53
94
  readonly lockfile?: string;
54
- /** True when every package is already there — nothing to install. */
95
+ /** True when every step is already satisfied — nothing to install. */
55
96
  readonly satisfied: boolean;
56
97
  }
57
98
  /** Runs an install plan, or throws. Replaced in tests; never spawns there. */
@@ -75,18 +116,35 @@ declare function engineVersion(): string;
75
116
  declare function schemaPackageVersion(): string;
76
117
  /** The package manager this project already uses: its lockfile, then what it declares, then npm. */
77
118
  declare function detectPackageManager(root: string): PackageManager;
119
+ /** True when `root` is the root of a pnpm workspace, which is what `-w` is for. */
120
+ declare function isPnpmWorkspaceRoot(root: string): boolean;
78
121
  declare function planInstall(root: string, version?: string): InstallPlan;
122
+ /** What this plan actually installs, once per package however many files declare it. */
123
+ declare function installedPackages(plan: InstallPlan): readonly InstallPackage[];
79
124
  /**
80
125
  * The change, as it will appear in the diff — the whole point of showing it is
81
126
  * that the reader recognises their own file, so these are the `package.json`
82
127
  * lines that land and the lockfile that gets rewritten, not a summary of both.
128
+ *
129
+ * In a workspace that is more than one file, and the commands underneath are the
130
+ * ones that run: a "Run with:" line the reader cannot paste is worse than none.
83
131
  */
84
132
  declare function renderInstallPlan(plan: InstallPlan): string[];
85
133
  /**
86
134
  * The real install: the project's own package manager, started the way any other
87
135
  * child is (`.cmd` shims on Windows included), with its output the user's to see.
136
+ *
137
+ * Every step runs from the project root — `-w` and `--filter` are how a workspace
138
+ * says which `package.json` it means, so the directory never changes.
88
139
  */
89
140
  declare const installWithPackageManager: InstallRuntime;
90
- declare function installFailed(plan: InstallPlan): PenvError;
141
+ /**
142
+ * What to do about a package manager that refused.
143
+ *
144
+ * Never the command that just failed: the one remediation guaranteed not to work
145
+ * is the one the reader already ran. The manager said why, on their screen, and
146
+ * nothing was migrated — so the answer is that line and a second `penv init`.
147
+ */
148
+ declare function installFailed(plan: InstallPlan, step: InstallStep): PenvError;
91
149
 
92
- export { type InstallPackage, type InstallPlan, type InstallRuntime, type PackageManager, RUNTIME_PACKAGE, SCHEMA_PACKAGE, detectPackageManager, engineVersion, installFailed, installWithPackageManager, planInstall, renderInstallPlan, schemaPackageVersion };
150
+ export { type InstallPackage, type InstallPlan, type InstallRuntime, type InstallStep, type PackageManager, RUNTIME_PACKAGE, SCHEMA_PACKAGE, TYPES_PACKAGE, detectPackageManager, engineVersion, installFailed, installWithPackageManager, installedPackages, isPnpmWorkspaceRoot, planInstall, renderInstallPlan, schemaPackageVersion };
package/dist/install.js CHANGED
@@ -1,21 +1,27 @@
1
1
  import {
2
2
  RUNTIME_PACKAGE,
3
3
  SCHEMA_PACKAGE,
4
+ TYPES_PACKAGE,
4
5
  detectPackageManager,
5
6
  engineVersion,
6
7
  installFailed,
7
8
  installWithPackageManager,
9
+ installedPackages,
10
+ isPnpmWorkspaceRoot,
8
11
  planInstall,
9
12
  renderInstallPlan,
10
13
  schemaPackageVersion
11
- } from "./chunk-JJY4RLDJ.js";
14
+ } from "./chunk-OBIHFXCK.js";
12
15
  export {
13
16
  RUNTIME_PACKAGE,
14
17
  SCHEMA_PACKAGE,
18
+ TYPES_PACKAGE,
15
19
  detectPackageManager,
16
20
  engineVersion,
17
21
  installFailed,
18
22
  installWithPackageManager,
23
+ installedPackages,
24
+ isPnpmWorkspaceRoot,
19
25
  planInstall,
20
26
  renderInstallPlan,
21
27
  schemaPackageVersion
package/package.json CHANGED
@@ -1,8 +1,14 @@
1
1
  {
2
2
  "name": "@penvhq/cli",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "penv's command line. Dependency budget is deliberately looser than the runtime's.",
5
5
  "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/Itzfeminisce/penvhq.git",
9
+ "directory": "packages/cli"
10
+ },
11
+ "homepage": "https://github.com/Itzfeminisce/penvhq#readme",
6
12
  "type": "module",
7
13
  "main": "./dist/index.cjs",
8
14
  "module": "./dist/index.js",
@@ -30,10 +36,10 @@
30
36
  "@napi-rs/keyring": "1.3.0",
31
37
  "citty": "0.2.2",
32
38
  "jiti": "2.7.0",
33
- "@penvhq/core": "0.11.0",
34
- "@penvhq/provider-filesystem": "0.11.0",
35
- "@penvhq/provider-mock": "0.11.0",
36
- "@penvhq/runtime": "0.11.0"
39
+ "@penvhq/core": "0.13.0",
40
+ "@penvhq/provider-filesystem": "0.13.0",
41
+ "@penvhq/provider-mock": "0.13.0",
42
+ "@penvhq/runtime": "0.13.0"
37
43
  },
38
44
  "peerDependencies": {
39
45
  "zod": "^4.4.3"
@@ -41,8 +47,8 @@
41
47
  "devDependencies": {
42
48
  "server-only": "0.0.1",
43
49
  "zod": "4.4.3",
44
- "@penvhq/provider-github": "0.11.0",
45
- "@penvhq/provider-vault": "0.11.0"
50
+ "@penvhq/provider-github": "0.13.0",
51
+ "@penvhq/provider-vault": "0.13.0"
46
52
  },
47
53
  "scripts": {
48
54
  "build": "tsup"
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/install.ts","../src/child.ts"],"sourcesContent":["/**\n * The runtime dependencies an adopted project takes, and how they get there.\n *\n * PRD §3: an adopted project depends on `@penvhq/penv` at the engine's own\n * version — the typed `@env` surface, not a CLI distribution. It also depends on\n * zod, because the `penv.schema.ts` init scaffolds imports it: zod is a *peer* of\n * `@penvhq/penv`, and a peer is a package the project supplies. Under pnpm's\n * strict layout nothing hoists it to the project root, so an install that named\n * only `@penvhq/penv` left the very schema init had just written unable to\n * resolve `zod` — and adoption could never finish.\n *\n * Both are installed with the package manager the project already uses, and only\n * after showing the exact `package.json` and lockfile change: an install is the\n * one step of adoption that reaches outside the repository, so it is the one step\n * that is shown before it happens rather than reported after.\n *\n * The install itself is a seam. It shells out to a package manager, which the\n * tests must never do — and a fake here is not a weaker test, because what init\n * has to get right is the plan, the consent, and the refusal when the install\n * does not happen.\n *\n * Two commands write that dependency line: `penv init`, which is the engine's,\n * and `penv upgrade`, which is the launcher's. This module is published at\n * `@penvhq/cli/install` so the launcher reaches it without loading the command\n * surface — one answer to \"which package manager, which diff, which spawn\",\n * rather than a second copy on the other side of the launcher/engine split.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { PenvError } from \"@penvhq/core\";\nimport { startChild } from \"./child.js\";\n\n/** The package an adopted project depends on. The CLI engine is not one of its dependencies. */\nexport const RUNTIME_PACKAGE = \"@penvhq/penv\";\n\n/** The peer `penv.schema.ts` imports, which the project supplies because a peer is not hoisted. */\nexport const SCHEMA_PACKAGE = \"zod\";\n\nexport type PackageManager = \"pnpm\" | \"npm\" | \"yarn\" | \"bun\";\n\n/** The lockfile that names each manager, checked in this order. */\nconst LOCKFILES: readonly (readonly [PackageManager, string])[] = [\n [\"pnpm\", \"pnpm-lock.yaml\"],\n [\"yarn\", \"yarn.lock\"],\n [\"bun\", \"bun.lock\"],\n [\"bun\", \"bun.lockb\"],\n [\"npm\", \"package-lock.json\"],\n];\n\n/** How each manager is told to add one exact version. */\nconst ADD: Readonly<Record<PackageManager, readonly string[]>> = {\n pnpm: [\"pnpm\", \"add\", \"--save-exact\"],\n npm: [\"npm\", \"install\", \"--save-exact\"],\n yarn: [\"yarn\", \"add\", \"--exact\"],\n bun: [\"bun\", \"add\", \"--exact\"],\n};\n\n/** One package the adopted project needs, and what its `package.json` says today. */\nexport interface InstallPackage {\n readonly name: string;\n readonly version: string;\n /** What `package.json` already says about it, when it says anything. */\n readonly declared?: string;\n /** True when this project already has it — nothing to install for this one. */\n readonly satisfied: boolean;\n}\n\nexport interface InstallPlan {\n readonly root: string;\n readonly manager: PackageManager;\n /** Everything an adopted project needs, in the order the diff shows them. */\n readonly packages: readonly InstallPackage[];\n /** The command, argv-shaped — what runs, and what a refusal tells the user to run. */\n readonly command: readonly string[];\n /** The lockfile the manager will rewrite, when the project has one. */\n readonly lockfile?: string;\n /** True when every package is already there — nothing to install. */\n readonly satisfied: boolean;\n}\n\n/** Runs an install plan, or throws. Replaced in tests; never spawns there. */\nexport type InstallRuntime = (plan: InstallPlan) => Promise<void>;\n\n/**\n * The engine's own version, read from its manifest rather than restated in the\n * source: `@penvhq/penv` must match the engine exactly, and a constant beside\n * the version a release bumps is a second answer waiting to drift.\n */\nexport function engineVersion(): string {\n const version = ownManifest()?.version;\n if (typeof version === \"string\" && version.length > 0) {\n return version;\n }\n throw new PenvError(\n \"ENGINE_VERSION_UNREADABLE\",\n \"penv could not read its own version, so it cannot say which `@penvhq/penv` this project needs\",\n `Reinstall penv, then run \\`penv init\\` again.`,\n );\n}\n\n/**\n * The zod an adopted project installs: the floor of the peer range the engine\n * and `@penvhq/penv` both declare, which is the version penv is built and tested\n * against.\n *\n * The floor rather than the range, because the diff shown before the install has\n * to be the line that actually lands — `--save-exact` on `^4.4.3` would write\n * whatever the registry resolved that day, which is not something a reader can\n * consent to in advance.\n */\nexport function schemaPackageVersion(): string {\n const peers = ownManifest()?.peerDependencies;\n const declared =\n peers !== null && typeof peers === \"object\" && !Array.isArray(peers)\n ? (peers as Record<string, unknown>)[SCHEMA_PACKAGE]\n : undefined;\n const floor = typeof declared === \"string\" ? declared.replace(/^[\\^~>=\\s]+/, \"\").trim() : \"\";\n if (floor.length > 0) {\n return floor;\n }\n throw new PenvError(\n \"ENGINE_PEER_UNREADABLE\",\n `penv could not read its own \\`${SCHEMA_PACKAGE}\\` peer range, so it cannot say which ${SCHEMA_PACKAGE} this project needs`,\n `Reinstall penv, then run \\`penv init\\` again.`,\n );\n}\n\n/** The engine's own manifest, or `undefined` when it cannot be read. */\nfunction ownManifest(): Record<string, unknown> | undefined {\n try {\n const parsed: unknown = JSON.parse(\n readFileSync(new URL(\"../package.json\", import.meta.url), \"utf8\"),\n );\n return parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : undefined;\n } catch {\n // The callers refuse: a version penv guessed would pin a project's\n // dependency to something nobody chose.\n return undefined;\n }\n}\n\n/** The package manager this project already uses: its lockfile, then what it declares, then npm. */\nexport function detectPackageManager(root: string): PackageManager {\n for (const [manager, lockfile] of LOCKFILES) {\n if (existsSync(join(root, lockfile))) {\n return manager;\n }\n }\n return declaredManager(root) ?? \"npm\";\n}\n\n/** `\"packageManager\": \"pnpm@9.1.0\"` — corepack's field, and a project's own answer. */\nfunction declaredManager(root: string): PackageManager | undefined {\n const declared = manifestOf(root)?.packageManager;\n if (typeof declared !== \"string\") {\n return undefined;\n }\n const name = declared.split(\"@\")[0];\n return name === \"pnpm\" || name === \"npm\" || name === \"yarn\" || name === \"bun\" ? name : undefined;\n}\n\nfunction manifestOf(root: string): Record<string, unknown> | undefined {\n const file = join(root, \"package.json\");\n if (!existsSync(file)) {\n return undefined;\n }\n try {\n const manifest: unknown = JSON.parse(readFileSync(file, \"utf8\"));\n return manifest !== null && typeof manifest === \"object\" && !Array.isArray(manifest)\n ? (manifest as Record<string, unknown>)\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** What `package.json` says about one package today, from either dependency block. */\nfunction declaredVersion(root: string, name: string): string | undefined {\n const manifest = manifestOf(root);\n for (const field of [\"dependencies\", \"devDependencies\"] as const) {\n const block: unknown = manifest?.[field];\n if (block !== null && typeof block === \"object\" && !Array.isArray(block)) {\n const version: unknown = (block as Record<string, unknown>)[name];\n if (typeof version === \"string\") {\n return version;\n }\n }\n }\n return undefined;\n}\n\nexport function planInstall(root: string, version: string = engineVersion()): InstallPlan {\n const manager = detectPackageManager(root);\n const lockfile = LOCKFILES.find(\n ([name, file]) => name === manager && existsSync(join(root, file)),\n )?.[1];\n\n const runtimeDeclared = declaredVersion(root, RUNTIME_PACKAGE);\n const zodDeclared = declaredVersion(root, SCHEMA_PACKAGE);\n const packages: InstallPackage[] = [\n {\n name: RUNTIME_PACKAGE,\n version,\n ...(runtimeDeclared === undefined ? {} : { declared: runtimeDeclared }),\n satisfied: runtimeDeclared === version,\n },\n {\n name: SCHEMA_PACKAGE,\n version: schemaPackageVersion(),\n ...(zodDeclared === undefined ? {} : { declared: zodDeclared }),\n // Any declared zod counts: which zod a project uses is the project's\n // decision, and penv is here to make sure there is one, not to move it.\n satisfied: zodDeclared !== undefined,\n },\n ];\n\n const pending = packages.filter((entry) => !entry.satisfied);\n const specs = (pending.length === 0 ? packages : pending).map(\n (entry) => `${entry.name}@${entry.version}`,\n );\n return {\n root,\n manager,\n packages,\n command: [...ADD[manager], ...specs],\n ...(lockfile === undefined ? {} : { lockfile }),\n satisfied: pending.length === 0,\n };\n}\n\nfunction describe(entry: InstallPackage): string {\n return `${entry.name} ${entry.version}`;\n}\n\n/**\n * The change, as it will appear in the diff — the whole point of showing it is\n * that the reader recognises their own file, so these are the `package.json`\n * lines that land and the lockfile that gets rewritten, not a summary of both.\n */\nexport function renderInstallPlan(plan: InstallPlan): string[] {\n if (plan.satisfied) {\n return [\n `package.json already has ${plan.packages.map(describe).join(\" and \")} — nothing to install.`,\n ];\n }\n const pending = plan.packages.filter((entry) => !entry.satisfied);\n const added = pending.filter((entry) => entry.declared === undefined);\n const replaced = pending.filter((entry) => entry.declared !== undefined);\n return [\n \"package.json\",\n ...(added.length === 0\n ? []\n : [\n ' + \"dependencies\": {',\n ...added.map((entry) => ` + \"${entry.name}\": \"${entry.version}\"`),\n \" + }\",\n ]),\n ...replaced.flatMap((entry) => [\n ` - \"${entry.name}\": \"${entry.declared}\"`,\n ` + \"${entry.name}\": \"${entry.version}\"`,\n ]),\n ...(plan.lockfile === undefined\n ? []\n : [plan.lockfile, ...pending.map((entry) => ` + ${entry.name}@${entry.version}`)]),\n \"\",\n `Run with: ${plan.command.join(\" \")}`,\n ];\n}\n\n/**\n * The real install: the project's own package manager, started the way any other\n * child is (`.cmd` shims on Windows included), with its output the user's to see.\n */\nexport const installWithPackageManager: InstallRuntime = async (plan) => {\n const child = startChild({\n command: plan.command,\n env: process.env as Record<string, string>,\n cwd: plan.root,\n purpose: `install ${plan.packages.map(describe).join(\" and \")}`,\n });\n const ended = await child.ended;\n if (ended.exitCode !== 0 || ended.signal !== null) {\n throw installFailed(plan);\n }\n};\n\nexport function installFailed(plan: InstallPlan): PenvError {\n return new PenvError(\n \"INIT_INSTALL_FAILED\",\n `${plan.command.join(\" \")} did not finish, so penv migrated nothing`,\n `Run \\`${plan.command.join(\" \")}\\` yourself, then start this command again. Your dotenv files are exactly where they were.`,\n );\n}\n","/**\n * Starting someone else's command, opaquely.\n *\n * `penv run -- <command>` starts exactly what follows `--`: the argument\n * boundaries the shell already worked out are handed to the operating system\n * untouched, stdio is the parent's, and the child's exit code and terminating\n * signal come back out. penv never parses the command, never rebuilds a command\n * line from it, never wraps it in a shell — a shell would re-split what the user\n * already split, and `penv run -- node -e \"console.log(1 > 2)\"` would redirect to\n * a file called `2`.\n *\n * Windows is the one place where \"hand it to the operating system\" needs help.\n * `pnpm`, `next` and every other node-installed tool are `.cmd` shims there, and\n * Node refuses to execute one without a shell. So a `.cmd`/`.bat` target — and\n * only that — is started through `cmd.exe /d /s /c` with\n * `windowsVerbatimArguments`, building the one command line cmd will accept and\n * escaping every argument so that cmd hands the child the same bytes penv was\n * given. Everything else spawns directly, on every platform.\n */\n\nimport { spawn } from \"node:child_process\";\nimport { existsSync, statSync } from \"node:fs\";\nimport { delimiter, isAbsolute, join, win32 } from \"node:path\";\nimport { PenvError } from \"@penvhq/core\";\n\n/** How a child ended. Exactly one of these is meaningful, and both are forwarded. */\nexport interface ChildResult {\n /** The child's own exit code, or 1 when a signal ended it. */\n readonly exitCode: number;\n /** The signal that ended the child, when one did. */\n readonly signal: NodeJS.Signals | null;\n}\n\nexport interface ChildInvocation {\n /** The command exactly as it followed `--`: the executable, then its arguments. */\n readonly command: readonly string[];\n readonly env: Record<string, string>;\n readonly cwd: string;\n /**\n * What penv is starting this on its own behalf to do — `init`'s dependency\n * install. Absent means the command is the user's, from after `--`, and the\n * two failures have opposite remedies: one is about what they typed, the other\n * about a program penv chose to run.\n */\n readonly purpose?: string;\n}\n\n/** A started child: how it ends, and the one thing a wrapper may do to it. */\nexport interface ChildHandle {\n /** Resolves when the child has ended, however it ended. */\n readonly ended: Promise<ChildResult>;\n /** Asks the child to stop — what `--watch` does before it starts the next one. */\n kill(signal?: NodeJS.Signals): void;\n}\n\n/** The seam `run` starts a child through — replaced in tests that assert what it was given. */\nexport type StartChild = (invocation: ChildInvocation) => ChildHandle;\n\n/** The signals a wrapper must pass through rather than absorb. */\nconst FORWARDED: readonly NodeJS.Signals[] = [\"SIGINT\", \"SIGTERM\", \"SIGHUP\", \"SIGBREAK\"];\n\nexport const startChild: StartChild = (invocation) => {\n const [executable, ...args] = invocation.command;\n if (executable === undefined) {\n throw noCommand();\n }\n\n const target = resolveTarget(executable, args, invocation.env);\n const child = spawn(target.file, target.args, {\n cwd: invocation.cwd,\n env: invocation.env,\n stdio: \"inherit\",\n ...(target.verbatim ? { windowsVerbatimArguments: true } : {}),\n });\n\n // Forwarded rather than handled: penv is a wrapper, and a Ctrl-C belongs to\n // the program the user is looking at. The child decides what to do with it,\n // and its answer comes back as the signal below.\n const forward = new Map<NodeJS.Signals, () => void>();\n for (const signal of FORWARDED) {\n const handler = (): void => {\n child.kill(signal);\n };\n forward.set(signal, handler);\n process.on(signal, handler);\n }\n const release = (): void => {\n for (const [signal, handler] of forward) {\n process.off(signal, handler);\n }\n };\n\n const ended = new Promise<ChildResult>((resolve, reject) => {\n child.on(\"error\", (cause) => {\n release();\n reject(cannotStart(executable, cause, invocation.purpose));\n });\n child.on(\"exit\", (code, signal) => {\n release();\n resolve({ exitCode: code ?? 1, signal });\n });\n });\n\n return {\n ended,\n kill(signal) {\n child.kill(signal);\n },\n };\n};\n\nexport function noCommand(): PenvError {\n return new PenvError(\n \"RUN_NO_COMMAND\",\n \"`penv run` was given no command to start\",\n \"Put the command after `--`, e.g. `penv run -- pnpm dev`.\",\n );\n}\n\nfunction cannotStart(executable: string, cause: unknown, purpose: string | undefined): PenvError {\n const detail = cause instanceof Error ? cause.message : String(cause);\n if (purpose !== undefined) {\n return new PenvError(\n \"PENV_COMMAND_NOT_STARTED\",\n `penv could not start \\`${executable}\\` to ${purpose}: ${detail}`,\n `Check that \\`${executable}\\` runs on its own — penv starts it the way your shell does, so it has to be on PATH. Nothing was changed.`,\n );\n }\n return new PenvError(\n \"RUN_COMMAND_NOT_STARTED\",\n `\\`${executable}\\` could not be started: ${detail}`,\n `Check the command after \\`--\\` runs on its own — \\`${executable}\\` has to be on PATH, exactly as it is spelled here.`,\n );\n}\n\ninterface SpawnTarget {\n readonly file: string;\n readonly args: readonly string[];\n /** True when the args are one pre-built command line rather than a list. */\n readonly verbatim: boolean;\n}\n\nfunction resolveTarget(\n executable: string,\n args: readonly string[],\n env: Readonly<Record<string, string | undefined>>,\n): SpawnTarget {\n if (process.platform !== \"win32\") {\n return { file: executable, args, verbatim: false };\n }\n const resolved = findExecutable(executable, env);\n if (resolved === undefined || !/\\.(cmd|bat)$/i.test(resolved)) {\n return { file: resolved ?? executable, args, verbatim: false };\n }\n return {\n file: env.ComSpec ?? \"cmd.exe\",\n args: [\"/d\", \"/s\", \"/c\", `\"${cmdCommandLine(resolved, args)}\"`],\n verbatim: true,\n };\n}\n\n/** A package-manager shim, which re-invokes cmd on its own way through. */\nconst SHIM = /(?:^|\\\\)node_modules\\\\\\.bin\\\\[^\\\\]+\\.cmd$/i;\n\n/**\n * The one command line cmd.exe is handed, escaped so the child receives the\n * bytes penv was given.\n *\n * The path is normalized first and *then* judged: `./node_modules/.bin/next.cmd`\n * and `.\\node_modules\\.bin\\next.cmd` are the same shim, and deciding on the\n * un-normalized spelling would escape a forward-slash invocation once while cmd\n * expands it twice — so an argument holding `&` would run as a command inside\n * the shim's second round. Windows' own separator, whatever this process runs\n * on, because this line is only ever read by cmd.exe.\n */\nexport function cmdCommandLine(resolved: string, args: readonly string[]): string {\n const command = win32.normalize(resolved);\n const shim = SHIM.test(command);\n return [escapeCommand(command), ...args.map((argument) => escapeArgument(argument, shim))].join(\n \" \",\n );\n}\n\n/**\n * The extensions a name is tried with, in the order the platform's own launcher\n * tries them.\n *\n * On Windows PATHEXT leads and the bare name comes last, because the bare name\n * is almost never what Windows would run: `pnpm`, `npx` and every\n * `node_modules/.bin` tool ship an extensionless POSIX shell script *beside*\n * their `.CMD` shim, in the same directory. Trying the empty extension first\n * matched that script, which is not executable by CreateProcess and is not a\n * `.cmd`, so the wrapper below was skipped and the spawn failed with ENOENT.\n * Everywhere else there are no extensions at all.\n */\nfunction extensions(\n env: Readonly<Record<string, string | undefined>>,\n platform: NodeJS.Platform,\n): string[] {\n if (platform !== \"win32\") {\n return [\"\"];\n }\n const declared = env.PATHEXT ?? \".COM;.EXE;.BAT;.CMD\";\n return [...declared.split(\";\").filter((extension) => extension.length > 0), \"\"];\n}\n\n/**\n * What the shell would have run, found the way the shell finds it: the name as\n * given if it carries a path, else each PATH directory, each with each\n * executable extension.\n *\n * `platform` is a parameter so the ordering above is testable on either kind of\n * machine — it is the whole behavior, and it differs by platform.\n */\nexport function findExecutable(\n executable: string,\n env: Readonly<Record<string, string | undefined>>,\n platform: NodeJS.Platform = process.platform,\n): string | undefined {\n const candidates = extensions(env, platform);\n const isFile = (path: string): boolean => existsSync(path) && statSync(path).isFile();\n\n if (executable.includes(\"/\") || executable.includes(\"\\\\\") || isAbsolute(executable)) {\n return candidates.map((extension) => executable + extension).find(isFile);\n }\n const path = env.PATH ?? env.Path ?? \"\";\n for (const directory of path.split(delimiter).filter((entry) => entry.length > 0)) {\n const hit = candidates.map((extension) => join(directory, executable + extension)).find(isFile);\n if (hit !== undefined) {\n return hit;\n }\n }\n return undefined;\n}\n\n/** The characters cmd.exe expands before the program ever sees them. */\nconst CMD_METACHARACTERS = /([()\\][%!^\"`<>&|;, *?])/g;\n\n/** The command's own path: cmd's metacharacters escaped, and no quotes to confuse it. */\nfunction escapeCommand(command: string): string {\n return command.replace(CMD_METACHARACTERS, \"^$1\");\n}\n\n/**\n * One argument, quoted so the child's runtime splits it exactly where penv was\n * given it, then escaped so cmd.exe passes those quotes through instead of\n * acting on them.\n */\nfunction escapeArgument(argument: string, doubleEscape: boolean): string {\n const quoted = `\"${argument.replace(/(\\\\*)\"/g, '$1$1\\\\\"').replace(/(\\\\*)$/, \"$1$1\")}\"`;\n const escaped = quoted.replace(CMD_METACHARACTERS, \"^$1\");\n return doubleEscape ? escaped.replace(CMD_METACHARACTERS, \"^$1\") : escaped;\n}\n"],"mappings":"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","names":["existsSync","join","PenvError","path","PenvError","existsSync","join"]}