@tractorcow/beefup 0.0.0 → 1.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.
Files changed (165) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +108 -0
  3. package/dist/__tests__/with-safe-chain-stubs.d.ts +5 -0
  4. package/dist/__tests__/with-safe-chain-stubs.js +25 -0
  5. package/dist/__tests__/with-safe-chain-stubs.js.map +1 -0
  6. package/dist/bin.d.ts +2 -0
  7. package/dist/bin.js +6 -0
  8. package/dist/bin.js.map +1 -0
  9. package/dist/cli/args.d.ts +18 -0
  10. package/dist/cli/args.js +88 -0
  11. package/dist/cli/args.js.map +1 -0
  12. package/dist/cli/main.d.ts +4 -0
  13. package/dist/cli/main.js +81 -0
  14. package/dist/cli/main.js.map +1 -0
  15. package/dist/commands/accept.d.ts +16 -0
  16. package/dist/commands/accept.js +47 -0
  17. package/dist/commands/accept.js.map +1 -0
  18. package/dist/commands/report.d.ts +19 -0
  19. package/dist/commands/report.js +151 -0
  20. package/dist/commands/report.js.map +1 -0
  21. package/dist/commands/stage.d.ts +16 -0
  22. package/dist/commands/stage.js +60 -0
  23. package/dist/commands/stage.js.map +1 -0
  24. package/dist/config/load.d.ts +6 -0
  25. package/dist/config/load.js +103 -0
  26. package/dist/config/load.js.map +1 -0
  27. package/dist/config/types.d.ts +75 -0
  28. package/dist/config/types.js +68 -0
  29. package/dist/config/types.js.map +1 -0
  30. package/dist/diff/diff.d.ts +21 -0
  31. package/dist/diff/diff.js +132 -0
  32. package/dist/diff/diff.js.map +1 -0
  33. package/dist/diff/group.d.ts +5 -0
  34. package/dist/diff/group.js +24 -0
  35. package/dist/diff/group.js.map +1 -0
  36. package/dist/diff/types.d.ts +37 -0
  37. package/dist/diff/types.js +7 -0
  38. package/dist/diff/types.js.map +1 -0
  39. package/dist/errors.d.ts +10 -0
  40. package/dist/errors.js +15 -0
  41. package/dist/errors.js.map +1 -0
  42. package/dist/fsutil.d.ts +20 -0
  43. package/dist/fsutil.js +43 -0
  44. package/dist/fsutil.js.map +1 -0
  45. package/dist/lockfile/locked.d.ts +9 -0
  46. package/dist/lockfile/locked.js +15 -0
  47. package/dist/lockfile/locked.js.map +1 -0
  48. package/dist/lockfile/npm.d.ts +15 -0
  49. package/dist/lockfile/npm.js +152 -0
  50. package/dist/lockfile/npm.js.map +1 -0
  51. package/dist/lockfile/pnpm.d.ts +27 -0
  52. package/dist/lockfile/pnpm.js +155 -0
  53. package/dist/lockfile/pnpm.js.map +1 -0
  54. package/dist/lockfile/resolve.d.ts +10 -0
  55. package/dist/lockfile/resolve.js +20 -0
  56. package/dist/lockfile/resolve.js.map +1 -0
  57. package/dist/lockfile/types.d.ts +49 -0
  58. package/dist/lockfile/types.js +2 -0
  59. package/dist/lockfile/types.js.map +1 -0
  60. package/dist/pm/cve-lite-bin.d.ts +5 -0
  61. package/dist/pm/cve-lite-bin.js +36 -0
  62. package/dist/pm/cve-lite-bin.js.map +1 -0
  63. package/dist/pm/install.d.ts +24 -0
  64. package/dist/pm/install.js +30 -0
  65. package/dist/pm/install.js.map +1 -0
  66. package/dist/pm/runner.d.ts +17 -0
  67. package/dist/pm/runner.js +27 -0
  68. package/dist/pm/runner.js.map +1 -0
  69. package/dist/pm/safe-chain.d.ts +17 -0
  70. package/dist/pm/safe-chain.js +65 -0
  71. package/dist/pm/safe-chain.js.map +1 -0
  72. package/dist/pm/update.d.ts +16 -0
  73. package/dist/pm/update.js +25 -0
  74. package/dist/pm/update.js.map +1 -0
  75. package/dist/policy/alignment.d.ts +13 -0
  76. package/dist/policy/alignment.js +171 -0
  77. package/dist/policy/alignment.js.map +1 -0
  78. package/dist/policy/evaluate.d.ts +19 -0
  79. package/dist/policy/evaluate.js +75 -0
  80. package/dist/policy/evaluate.js.map +1 -0
  81. package/dist/policy/overrides.d.ts +42 -0
  82. package/dist/policy/overrides.js +358 -0
  83. package/dist/policy/overrides.js.map +1 -0
  84. package/dist/policy/ranges.d.ts +13 -0
  85. package/dist/policy/ranges.js +58 -0
  86. package/dist/policy/ranges.js.map +1 -0
  87. package/dist/project/collect.d.ts +15 -0
  88. package/dist/project/collect.js +60 -0
  89. package/dist/project/collect.js.map +1 -0
  90. package/dist/project/detect.d.ts +5 -0
  91. package/dist/project/detect.js +76 -0
  92. package/dist/project/detect.js.map +1 -0
  93. package/dist/project/direct-deps.d.ts +7 -0
  94. package/dist/project/direct-deps.js +28 -0
  95. package/dist/project/direct-deps.js.map +1 -0
  96. package/dist/project/package-json.d.ts +20 -0
  97. package/dist/project/package-json.js +6 -0
  98. package/dist/project/package-json.js.map +1 -0
  99. package/dist/project/paths.d.ts +31 -0
  100. package/dist/project/paths.js +45 -0
  101. package/dist/project/paths.js.map +1 -0
  102. package/dist/project/types.d.ts +13 -0
  103. package/dist/project/types.js +6 -0
  104. package/dist/project/types.js.map +1 -0
  105. package/dist/project/workspace.d.ts +14 -0
  106. package/dist/project/workspace.js +80 -0
  107. package/dist/project/workspace.js.map +1 -0
  108. package/dist/report/ansi.d.ts +31 -0
  109. package/dist/report/ansi.js +59 -0
  110. package/dist/report/ansi.js.map +1 -0
  111. package/dist/report/html.d.ts +6 -0
  112. package/dist/report/html.js +260 -0
  113. package/dist/report/html.js.map +1 -0
  114. package/dist/report/markdown.d.ts +6 -0
  115. package/dist/report/markdown.js +234 -0
  116. package/dist/report/markdown.js.map +1 -0
  117. package/dist/report/shared.d.ts +25 -0
  118. package/dist/report/shared.js +32 -0
  119. package/dist/report/shared.js.map +1 -0
  120. package/dist/report/text.d.ts +10 -0
  121. package/dist/report/text.js +156 -0
  122. package/dist/report/text.js.map +1 -0
  123. package/dist/report/types.d.ts +20 -0
  124. package/dist/report/types.js +2 -0
  125. package/dist/report/types.js.map +1 -0
  126. package/dist/rewrite/constraints.d.ts +20 -0
  127. package/dist/rewrite/constraints.js +64 -0
  128. package/dist/rewrite/constraints.js.map +1 -0
  129. package/dist/rewrite/repin.d.ts +8 -0
  130. package/dist/rewrite/repin.js +28 -0
  131. package/dist/rewrite/repin.js.map +1 -0
  132. package/dist/rewrite/workspace.d.ts +14 -0
  133. package/dist/rewrite/workspace.js +40 -0
  134. package/dist/rewrite/workspace.js.map +1 -0
  135. package/dist/security/classify.d.ts +48 -0
  136. package/dist/security/classify.js +86 -0
  137. package/dist/security/classify.js.map +1 -0
  138. package/dist/security/cve-lite.d.ts +7 -0
  139. package/dist/security/cve-lite.js +78 -0
  140. package/dist/security/cve-lite.js.map +1 -0
  141. package/dist/security/npm-audit.d.ts +10 -0
  142. package/dist/security/npm-audit.js +65 -0
  143. package/dist/security/npm-audit.js.map +1 -0
  144. package/dist/security/refs.d.ts +63 -0
  145. package/dist/security/refs.js +218 -0
  146. package/dist/security/refs.js.map +1 -0
  147. package/dist/security/scan.d.ts +13 -0
  148. package/dist/security/scan.js +32 -0
  149. package/dist/security/scan.js.map +1 -0
  150. package/dist/strategy/git.d.ts +16 -0
  151. package/dist/strategy/git.js +92 -0
  152. package/dist/strategy/git.js.map +1 -0
  153. package/dist/strategy/index.d.ts +7 -0
  154. package/dist/strategy/index.js +13 -0
  155. package/dist/strategy/index.js.map +1 -0
  156. package/dist/strategy/inplace.d.ts +30 -0
  157. package/dist/strategy/inplace.js +77 -0
  158. package/dist/strategy/inplace.js.map +1 -0
  159. package/dist/strategy/types.d.ts +13 -0
  160. package/dist/strategy/types.js +2 -0
  161. package/dist/strategy/types.js.map +1 -0
  162. package/dist/strategy/worktree.d.ts +26 -0
  163. package/dist/strategy/worktree.js +74 -0
  164. package/dist/strategy/worktree.js.map +1 -0
  165. package/package.json +60 -4
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2025 Damian Mooyman
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # @tractorcow/beefup
2
+
3
+ CLI for **staged, pinned, audited** npm/pnpm dependency upgrades. A proposed upgrade is written to `.beefup/staged` for review; nothing is applied to the live project until a later accept step.
4
+
5
+ ## Prerequisites
6
+
7
+ - Node.js 22+
8
+ - [pnpm](https://pnpm.io/) 11.22.0 (see `packageManager` in `package.json`) or npm 12+
9
+ - Git
10
+ - [Aikido Safe Chain](https://github.com/AikidoSec/safe-chain) wrapping the package manager
11
+
12
+ Beefup **will not run** unless Safe Chain is enabled. It looks for `aikido-pnpm` / `aikido-npm`, or `safe-chain`, on `PATH`. That keeps lockfile updates and security scans behind Safe Chain’s malware checks and minimum package age.
13
+
14
+ ### Install Safe Chain
15
+
16
+ Unix / macOS / Linux (pinned release + installer checksum):
17
+
18
+ ```sh
19
+ curl -fsSL https://github.com/AikidoSec/safe-chain/releases/download/1.5.15/install-safe-chain.sh -o /tmp/install-safe-chain.sh \
20
+ && echo "de0565e3d6346407a604e84e639e95fea8758748063da2216bbfdca5feda5dd2 /tmp/install-safe-chain.sh" | sha256sum -c - \
21
+ && sh /tmp/install-safe-chain.sh \
22
+ && rm /tmp/install-safe-chain.sh
23
+ ```
24
+
25
+ On macOS without `sha256sum`, use `shasum -a 256 -c -` instead of `sha256sum -c -`.
26
+
27
+ Then **restart your shell** and verify:
28
+
29
+ ```sh
30
+ pnpm safe-chain-verify
31
+ # or: npm safe-chain-verify
32
+ ```
33
+
34
+ You should see `OK: Safe-chain works!`.
35
+
36
+ If `pnpm` is already installed, check that its global bin directory is on `PATH`:
37
+
38
+ ```sh
39
+ pnpm bin -g
40
+ ```
41
+
42
+ If that command reports the directory is missing from `PATH`, run `pnpm setup` and restart the shell.
43
+
44
+ ## Install
45
+
46
+ ```sh
47
+ pnpm add --global @tractorcow/beefup
48
+ # or: npm install --global @tractorcow/beefup
49
+ ```
50
+
51
+ Confirm:
52
+
53
+ ```sh
54
+ beefup --version
55
+ beefup --help
56
+ ```
57
+
58
+ ### From a git checkout (development)
59
+
60
+ ```sh
61
+ git clone git@github.com:tractorcow/beefup.git
62
+ cd beefup
63
+ pnpm install --frozen-lockfile
64
+ pnpm run build
65
+ pnpm add --global .
66
+ ```
67
+
68
+ Or from the repo root: `make install && make install-global`.
69
+
70
+ ## Update
71
+
72
+ ```sh
73
+ pnpm add --global @tractorcow/beefup@latest
74
+ # or: npm install --global @tractorcow/beefup@latest
75
+ ```
76
+
77
+ From a git checkout:
78
+
79
+ ```sh
80
+ cd /path/to/beefup
81
+ git pull
82
+ pnpm install --frozen-lockfile
83
+ pnpm run build
84
+ pnpm add --global .
85
+ ```
86
+
87
+ Or: `git pull && make install && make install-global`.
88
+
89
+ ## Uninstall
90
+
91
+ ```sh
92
+ pnpm remove --global @tractorcow/beefup
93
+ # or: npm uninstall --global @tractorcow/beefup
94
+ ```
95
+
96
+ Or: `make uninstall-global`.
97
+
98
+ ## Usage
99
+
100
+ See [docs/index.md](docs/index.md), [staging](docs/stage.md), and [accept](docs/accept.md).
101
+
102
+ ```sh
103
+ beefup stage
104
+ beefup stage --mode latest --strategy inplace
105
+ beefup stage --format html
106
+ beefup report
107
+ beefup accept
108
+ ```
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Puts stub `aikido-pnpm` / `aikido-npm` binaries on PATH for the duration of `fn`.
3
+ * Production code only needs `which` to succeed; ProcessRunner mocks handle execution.
4
+ */
5
+ export declare function withSafeChainStubs<T>(fn: () => Promise<T>): Promise<T>;
@@ -0,0 +1,25 @@
1
+ import { chmod, mkdtemp, rm, writeFile } from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ /**
5
+ * Puts stub `aikido-pnpm` / `aikido-npm` binaries on PATH for the duration of `fn`.
6
+ * Production code only needs `which` to succeed; ProcessRunner mocks handle execution.
7
+ */
8
+ export async function withSafeChainStubs(fn) {
9
+ const dir = await mkdtemp(path.join(os.tmpdir(), "beefup-sc-stub-"));
10
+ const previous = process.env.PATH;
11
+ try {
12
+ for (const name of ["aikido-pnpm", "aikido-npm", "safe-chain"]) {
13
+ const stub = path.join(dir, name);
14
+ await writeFile(stub, "#!/bin/sh\nexit 0\n", "utf8");
15
+ await chmod(stub, 0o755);
16
+ }
17
+ process.env.PATH = `${dir}${path.delimiter}${previous ?? ""}`;
18
+ return await fn();
19
+ }
20
+ finally {
21
+ process.env.PATH = previous;
22
+ await rm(dir, { recursive: true, force: true });
23
+ }
24
+ }
25
+ //# sourceMappingURL=with-safe-chain-stubs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with-safe-chain-stubs.js","sourceRoot":"","sources":["../../src/__tests__/with-safe-chain-stubs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAI,EAAoB;IAC9D,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACrE,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAClC,IAAI,CAAC;QACH,KAAK,MAAM,IAAI,IAAI,CAAC,aAAa,EAAE,YAAY,EAAE,YAAY,CAAU,EAAE,CAAC;YACxE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAClC,MAAM,SAAS,CAAC,IAAI,EAAE,qBAAqB,EAAE,MAAM,CAAC,CAAC;YACrD,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,GAAG,QAAQ,IAAI,EAAE,EAAE,CAAC;QAC9D,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC;QAC5B,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;AACH,CAAC"}
package/dist/bin.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/bin.js ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import { main } from "./cli/main.js";
3
+ main().then((code) => {
4
+ process.exit(code);
5
+ });
6
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;IACnB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { type ReportFormat, type StageStrategyName, type UpgradeMode } from "../config/types.js";
2
+ export interface CliArgs {
3
+ command?: string;
4
+ mode?: UpgradeMode;
5
+ strategy?: StageStrategyName;
6
+ dir?: string;
7
+ format: ReportFormat;
8
+ help: boolean;
9
+ version: boolean;
10
+ }
11
+ /**
12
+ * Parses process argv into typed CLI options for stage, report, and accept.
13
+ */
14
+ export declare function parseCliArgs(argv: string[]): CliArgs;
15
+ /**
16
+ * Returns the CLI usage help text printed for `--help` or missing commands.
17
+ */
18
+ export declare function showHelp(): string;
@@ -0,0 +1,88 @@
1
+ import { CliCommands, isReportFormat, isStageStrategy, isUpgradeMode, ReportFormats, StageStrategies, UpgradeModes, } from "../config/types.js";
2
+ import { BeefupError } from "../errors.js";
3
+ /**
4
+ * Parses process argv into typed CLI options for stage, report, and accept.
5
+ */
6
+ export function parseCliArgs(argv) {
7
+ const args = {
8
+ format: ReportFormats.Color,
9
+ help: false,
10
+ version: false,
11
+ };
12
+ for (let i = 2; i < argv.length; i += 1) {
13
+ const arg = argv[i];
14
+ if (arg === "--help" || arg === "-h") {
15
+ args.help = true;
16
+ }
17
+ else if (arg === "--version" || arg === "-v") {
18
+ args.version = true;
19
+ }
20
+ else if (arg === "--mode") {
21
+ const value = argv[i + 1];
22
+ i += 1;
23
+ if (!isUpgradeMode(value)) {
24
+ throw new BeefupError(`invalid --mode ${value}; use same-major or latest`);
25
+ }
26
+ args.mode = value;
27
+ }
28
+ else if (arg === "--strategy") {
29
+ const value = argv[i + 1];
30
+ i += 1;
31
+ if (!isStageStrategy(value)) {
32
+ throw new BeefupError(`invalid --strategy ${value}; use worktree or inplace`);
33
+ }
34
+ args.strategy = value;
35
+ }
36
+ else if (arg === "--dir") {
37
+ args.dir = argv[i + 1];
38
+ i += 1;
39
+ }
40
+ else if (arg === "--format") {
41
+ const value = argv[i + 1];
42
+ i += 1;
43
+ if (!isReportFormat(value)) {
44
+ throw new BeefupError(`invalid --format ${value}; use ${Object.values(ReportFormats).join(", ")}`);
45
+ }
46
+ args.format = value;
47
+ }
48
+ else if (!arg.startsWith("-") && !args.command) {
49
+ args.command = arg;
50
+ }
51
+ else {
52
+ throw new BeefupError(`unknown argument: ${arg}`);
53
+ }
54
+ }
55
+ return args;
56
+ }
57
+ /**
58
+ * Returns the CLI usage help text printed for `--help` or missing commands.
59
+ */
60
+ export function showHelp() {
61
+ return `beefup - staged, pinned, audited dependency upgrades
62
+
63
+ USAGE:
64
+ beefup <command> [OPTIONS]
65
+
66
+ COMMANDS:
67
+ ${CliCommands.Stage} Propose an upgrade into .beefup/staged and write a report
68
+ ${CliCommands.Report} Regenerate the report for an existing staged upgrade
69
+ ${CliCommands.Accept} Apply the staged upgrade to the live project and install from the lockfile
70
+
71
+ OPTIONS:
72
+ --mode ${UpgradeModes.SameMajor}|${UpgradeModes.Latest} Upgrade mode (default: ${UpgradeModes.SameMajor}, or project config)
73
+ --strategy ${StageStrategies.Worktree}|${StageStrategies.Inplace} Isolation strategy for ${CliCommands.Stage} (default: ${StageStrategies.Worktree})
74
+ --dir <path> Project directory (default: cwd)
75
+ --format ${Object.values(ReportFormats).join("|")} Report format printed to stdout (default: ${ReportFormats.Color})
76
+ -h, --help Show this help
77
+ -v, --version Show version
78
+
79
+ EXAMPLES:
80
+ beefup ${CliCommands.Stage}
81
+ beefup ${CliCommands.Stage} --mode ${UpgradeModes.Latest} --strategy ${StageStrategies.Inplace}
82
+ beefup ${CliCommands.Stage} --format ${ReportFormats.Html}
83
+ beefup ${CliCommands.Report}
84
+ beefup ${CliCommands.Report} --format ${ReportFormats.Json}
85
+ beefup ${CliCommands.Accept}
86
+ `;
87
+ }
88
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * CLI entrypoint: parses argv, runs stage, report, or accept, and returns a process exit code.
3
+ */
4
+ export declare function main(argv?: string[]): Promise<number>;
@@ -0,0 +1,81 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { runAccept } from "../commands/accept.js";
5
+ import { printReport, runReport } from "../commands/report.js";
6
+ import { runStage } from "../commands/stage.js";
7
+ import { CliCommands, StageStrategies, } from "../config/types.js";
8
+ import { BeefupError } from "../errors.js";
9
+ import { parseCliArgs, showHelp } from "./args.js";
10
+ /**
11
+ * Reads the package version from the nearest package.json for `--version`.
12
+ */
13
+ async function readVersion() {
14
+ const pkgPath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../package.json");
15
+ const pkg = JSON.parse(await readFile(pkgPath, "utf8"));
16
+ return pkg.version ?? "0.0.0";
17
+ }
18
+ /**
19
+ * Writes a stage/report result to stdout and warns if new CVEs were introduced.
20
+ */
21
+ function emitReport(report, format) {
22
+ process.stdout.write(printReport(report, format));
23
+ if (report.security.introduced.length > 0) {
24
+ console.error(`warning: ${report.security.introduced.length} CVE(s) introduced; review .beefup/staged before accept`);
25
+ }
26
+ }
27
+ /**
28
+ * CLI entrypoint: parses argv, runs stage, report, or accept, and returns a process exit code.
29
+ */
30
+ export async function main(argv = process.argv) {
31
+ try {
32
+ const args = parseCliArgs(argv);
33
+ if (args.version) {
34
+ console.log(await readVersion());
35
+ return 0;
36
+ }
37
+ if (args.help || !args.command) {
38
+ console.log(showHelp());
39
+ return 0;
40
+ }
41
+ const projectRoot = args.dir ?? process.cwd();
42
+ if (args.command === CliCommands.Stage) {
43
+ const report = await runStage({
44
+ projectRoot,
45
+ mode: args.mode,
46
+ strategy: args.strategy ?? StageStrategies.Worktree,
47
+ format: args.format,
48
+ });
49
+ emitReport(report, args.format);
50
+ return 0;
51
+ }
52
+ if (args.command === CliCommands.Report) {
53
+ const report = await runReport({
54
+ projectRoot,
55
+ mode: args.mode,
56
+ strategy: args.strategy,
57
+ format: args.format,
58
+ });
59
+ emitReport(report, args.format);
60
+ return 0;
61
+ }
62
+ if (args.command === CliCommands.Accept) {
63
+ const result = await runAccept({ projectRoot });
64
+ process.stdout.write(`Accepted staged upgrade. Applied ${result.copied.join(", ")} and installed from the frozen lockfile (${result.packageManager}).\n`);
65
+ for (const warning of result.warnings) {
66
+ console.error(`warning: ${warning}`);
67
+ }
68
+ return 0;
69
+ }
70
+ throw new BeefupError(`unknown command: ${args.command}`);
71
+ }
72
+ catch (error) {
73
+ if (error instanceof BeefupError) {
74
+ console.error(`error: ${error.message}`);
75
+ return error.exitCode;
76
+ }
77
+ console.error(`error: ${error instanceof Error ? error.message : String(error)}`);
78
+ return 1;
79
+ }
80
+ }
81
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type ProcessRunner } from "../pm/runner.js";
2
+ import { type PackageManager } from "../project/types.js";
3
+ export interface AcceptOptions {
4
+ projectRoot: string;
5
+ runner?: ProcessRunner;
6
+ }
7
+ export interface AcceptResult {
8
+ packageManager: PackageManager;
9
+ copied: string[];
10
+ warnings: string[];
11
+ }
12
+ /**
13
+ * Applies `.beefup/staged` manifests and lockfile to the live project, then
14
+ * installs from that reviewed lockfile via Safe Chain (`npm ci` / frozen pnpm).
15
+ */
16
+ export declare function runAccept(options: AcceptOptions): Promise<AcceptResult>;
@@ -0,0 +1,47 @@
1
+ import path from "node:path";
2
+ import { loadConfig } from "../config/load.js";
3
+ import { CliCommands } from "../config/types.js";
4
+ import { BeefupError } from "../errors.js";
5
+ import { pathExists } from "../fsutil.js";
6
+ import { installFromLockfile } from "../pm/install.js";
7
+ import { defaultProcessRunner } from "../pm/runner.js";
8
+ import { assertNpmVersion, resolveProtectedPm } from "../pm/safe-chain.js";
9
+ import { assertPolicy, evaluatePolicy } from "../policy/evaluate.js";
10
+ import { applyStagedOutputs, requireStagedUpgrade } from "../project/collect.js";
11
+ import { detectProject } from "../project/detect.js";
12
+ import { inProgressPath } from "../project/paths.js";
13
+ import { PackageManagers } from "../project/types.js";
14
+ /**
15
+ * Applies `.beefup/staged` manifests and lockfile to the live project, then
16
+ * installs from that reviewed lockfile via Safe Chain (`npm ci` / frozen pnpm).
17
+ */
18
+ export async function runAccept(options) {
19
+ const projectRoot = path.resolve(options.projectRoot);
20
+ const runner = options.runner ?? defaultProcessRunner;
21
+ const project = await detectProject(projectRoot);
22
+ const staged = await requireStagedUpgrade(projectRoot, project.lockfileName);
23
+ const inProgress = inProgressPath(projectRoot);
24
+ if (await pathExists(inProgress)) {
25
+ throw new BeefupError(`cannot accept while an in-place ${CliCommands.Stage} is in progress (${path.relative(projectRoot, inProgress) || inProgress}); run beefup ${CliCommands.Stage} to restore the live tree first`);
26
+ }
27
+ const protectedPm = await resolveProtectedPm(project.packageManager);
28
+ if (project.packageManager === PackageManagers.Npm) {
29
+ await assertNpmVersion(protectedPm);
30
+ }
31
+ const config = await loadConfig(projectRoot);
32
+ const policy = await evaluatePolicy(staged, project.packageManager, project.lockfileName, config);
33
+ assertPolicy(policy);
34
+ const copied = await applyStagedOutputs(projectRoot, project.lockfileName);
35
+ await installFromLockfile({
36
+ pm: protectedPm,
37
+ packageManager: project.packageManager,
38
+ cwd: projectRoot,
39
+ runner,
40
+ });
41
+ return {
42
+ packageManager: project.packageManager,
43
+ copied,
44
+ warnings: policy.warnings,
45
+ };
46
+ }
47
+ //# sourceMappingURL=accept.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accept.js","sourceRoot":"","sources":["../../src/commands/accept.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAsB,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAuB,MAAM,qBAAqB,CAAC;AAa3E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAsB;IACpD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,oBAAoB,CAAC;IACtD,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAE7E,MAAM,UAAU,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,MAAM,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,WAAW,CACnB,mCAAmC,WAAW,CAAC,KAAK,oBAAoB,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,IAAI,UAAU,iBAAiB,WAAW,CAAC,KAAK,iCAAiC,CAChM,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACrE,IAAI,OAAO,CAAC,cAAc,KAAK,eAAe,CAAC,GAAG,EAAE,CAAC;QACnD,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,MAAM,cAAc,CACjC,MAAM,EACN,OAAO,CAAC,cAAc,EACtB,OAAO,CAAC,YAAY,EACpB,MAAM,CACP,CAAC;IACF,YAAY,CAAC,MAAM,CAAC,CAAC;IAErB,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,WAAW,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC3E,MAAM,mBAAmB,CAAC;QACxB,EAAE,EAAE,WAAW;QACf,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,GAAG,EAAE,WAAW;QAChB,MAAM;KACP,CAAC,CAAC;IAEH,OAAO;QACL,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,MAAM;QACN,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type ReportFormat, type StageStrategyName, type UpgradeMode } from "../config/types.js";
2
+ import { type ProcessRunner } from "../pm/runner.js";
3
+ import type { StageReport } from "../report/types.js";
4
+ export interface ReportOptions {
5
+ projectRoot: string;
6
+ mode?: UpgradeMode;
7
+ strategy?: StageStrategyName;
8
+ format: ReportFormat;
9
+ runner?: ProcessRunner;
10
+ }
11
+ /**
12
+ * Regenerates the upgrade report for an existing `.beefup/staged` proposal.
13
+ * Writes HTML and JSON under `.beefup/report`.
14
+ */
15
+ export declare function runReport(options: ReportOptions): Promise<StageReport>;
16
+ /**
17
+ * Formats a stage report for stdout as color, text, markdown, JSON, or HTML.
18
+ */
19
+ export declare function printReport(report: StageReport, format: ReportFormat): string;
@@ -0,0 +1,151 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { loadConfig } from "../config/load.js";
5
+ import { isStageStrategy, isUpgradeMode, ReportFormats, StageStrategies, } from "../config/types.js";
6
+ import { annotatePackageChanges, diffResolutions } from "../diff/diff.js";
7
+ import { pathExists, readJsonFile } from "../fsutil.js";
8
+ import { resolveLockfile } from "../lockfile/resolve.js";
9
+ import { defaultProcessRunner } from "../pm/runner.js";
10
+ import { assertNpmVersion, resolveProtectedPm } from "../pm/safe-chain.js";
11
+ import { assertPolicy, evaluatePolicy } from "../policy/evaluate.js";
12
+ import { requireStagedUpgrade } from "../project/collect.js";
13
+ import { detectProject } from "../project/detect.js";
14
+ import { collectDirectDependencyNames } from "../project/direct-deps.js";
15
+ import { reportDir, ReportFileNames } from "../project/paths.js";
16
+ import { PackageManagers } from "../project/types.js";
17
+ import { ansiColorEnabled } from "../report/ansi.js";
18
+ import { renderHtml } from "../report/html.js";
19
+ import { renderMarkdown } from "../report/markdown.js";
20
+ import { renderText } from "../report/text.js";
21
+ import { classifyFindings } from "../security/classify.js";
22
+ import { scanProject } from "../security/scan.js";
23
+ /**
24
+ * Regenerates the upgrade report for an existing `.beefup/staged` proposal.
25
+ * Writes HTML and JSON under `.beefup/report`.
26
+ */
27
+ export async function runReport(options) {
28
+ const projectRoot = path.resolve(options.projectRoot);
29
+ const runner = options.runner ?? defaultProcessRunner;
30
+ const project = await detectProject(projectRoot);
31
+ const staged = await requireStagedUpgrade(projectRoot, project.lockfileName);
32
+ const reports = reportDir(projectRoot);
33
+ const stagedLock = path.join(staged, project.lockfileName);
34
+ const previous = await readPreviousReport(reports);
35
+ const config = await loadConfig(projectRoot, options.mode ?? parseUpgradeMode(previous?.mode));
36
+ const strategy = options.strategy ??
37
+ parseStrategy(previous?.strategy) ??
38
+ StageStrategies.Worktree;
39
+ const protectedPm = await resolveProtectedPm(project.packageManager);
40
+ if (project.packageManager === PackageManagers.Npm) {
41
+ await assertNpmVersion(protectedPm);
42
+ }
43
+ const before = await resolveLockfile(project.lockfilePath, project.packageManager);
44
+ const after = await resolveLockfile(stagedLock, project.packageManager);
45
+ const { directNames, optionalDeclaredNames } = await collectDirectDependencyNames(projectRoot);
46
+ const diff = annotatePackageChanges(diffResolutions(before, after), {
47
+ directNames,
48
+ optionalDeclaredNames,
49
+ before,
50
+ after,
51
+ });
52
+ const policy = await evaluatePolicy(staged, project.packageManager, project.lockfileName, config);
53
+ const beforeFindings = await scanProject({
54
+ root: projectRoot,
55
+ packageManager: project.packageManager,
56
+ pmBin: protectedPm.bin,
57
+ prefixArgs: protectedPm.prefixArgs,
58
+ runner,
59
+ });
60
+ const afterFindings = await scanProject({
61
+ root: staged,
62
+ packageManager: project.packageManager,
63
+ pmBin: protectedPm.bin,
64
+ prefixArgs: protectedPm.prefixArgs,
65
+ runner,
66
+ });
67
+ const security = classifyFindings(beforeFindings, afterFindings);
68
+ const report = {
69
+ mode: config.mode,
70
+ strategy,
71
+ packageManager: project.packageManager,
72
+ generatedAt: new Date().toISOString(),
73
+ beefupVersion: await readBeefupVersion(),
74
+ diff,
75
+ ranges: policy.ranges,
76
+ overrides: policy.overrides,
77
+ alignment: policy.alignment,
78
+ security,
79
+ warnings: policy.warnings,
80
+ };
81
+ await mkdir(reports, { recursive: true });
82
+ await writeFile(path.join(reports, ReportFileNames.Html), renderHtml(report), "utf8");
83
+ await writeFile(path.join(reports, ReportFileNames.Json), `${JSON.stringify(report, null, 2)}\n`, "utf8");
84
+ assertPolicy(policy);
85
+ return report;
86
+ }
87
+ /**
88
+ * Formats a stage report for stdout as color, text, markdown, JSON, or HTML.
89
+ */
90
+ export function printReport(report, format) {
91
+ if (format === ReportFormats.Json) {
92
+ return `${JSON.stringify(report, null, 2)}\n`;
93
+ }
94
+ if (format === ReportFormats.Markdown) {
95
+ return renderMarkdown(report);
96
+ }
97
+ if (format === ReportFormats.Html) {
98
+ return renderHtml(report);
99
+ }
100
+ if (format === ReportFormats.Color) {
101
+ return renderText(report, { color: ansiColorEnabled() });
102
+ }
103
+ return renderText(report);
104
+ }
105
+ /**
106
+ * Loads the previous report.json if present, otherwise returns undefined.
107
+ */
108
+ async function readPreviousReport(reports) {
109
+ const reportPath = path.join(reports, ReportFileNames.Json);
110
+ if (!(await pathExists(reportPath))) {
111
+ return undefined;
112
+ }
113
+ try {
114
+ return await readJsonFile(reportPath);
115
+ }
116
+ catch {
117
+ return undefined;
118
+ }
119
+ }
120
+ /**
121
+ * Parses a stored upgrade mode string into a typed mode, or undefined if unknown.
122
+ */
123
+ function parseUpgradeMode(value) {
124
+ if (isUpgradeMode(value)) {
125
+ return value;
126
+ }
127
+ return undefined;
128
+ }
129
+ /**
130
+ * Parses a stored strategy string into a typed strategy, or undefined if unknown.
131
+ */
132
+ function parseStrategy(value) {
133
+ if (isStageStrategy(value)) {
134
+ return value;
135
+ }
136
+ return undefined;
137
+ }
138
+ /**
139
+ * Reads this package's version from beefup's own package.json.
140
+ */
141
+ async function readBeefupVersion() {
142
+ const pkgPath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../package.json");
143
+ try {
144
+ const pkg = JSON.parse(await readFile(pkgPath, "utf8"));
145
+ return pkg.version ?? "0.0.0";
146
+ }
147
+ catch {
148
+ return "0.0.0";
149
+ }
150
+ }
151
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/commands/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { ReportFormat, StageStrategyName, UpgradeMode } from "../config/types.js";
2
+ import { type ProcessRunner } from "../pm/runner.js";
3
+ import type { StageReport } from "../report/types.js";
4
+ export interface StageOptions {
5
+ projectRoot: string;
6
+ mode?: UpgradeMode;
7
+ strategy: StageStrategyName;
8
+ format: ReportFormat;
9
+ runner?: ProcessRunner;
10
+ }
11
+ /**
12
+ * Stages a dependency upgrade into `.beefup/staged`, then regenerates the report.
13
+ * Uses the selected isolation strategy and restores the workspace on exit or signal.
14
+ */
15
+ export declare function runStage(options: StageOptions): Promise<StageReport>;
16
+ export { printReport } from "./report.js";