greenbump 0.4.0 → 0.6.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 (78) hide show
  1. package/README.md +673 -66
  2. package/README.zh-CN.md +525 -100
  3. package/dist/agent/fixer.js +161 -12
  4. package/dist/agent/fixer.js.map +1 -1
  5. package/dist/agent/fixer.test.js +410 -0
  6. package/dist/agent/fixer.test.js.map +1 -0
  7. package/dist/cli/interactive.js +81 -0
  8. package/dist/cli/interactive.js.map +1 -0
  9. package/dist/cli.js +53 -0
  10. package/dist/cli.js.map +1 -1
  11. package/dist/engine/analyzers/changelog-parser.js +121 -0
  12. package/dist/engine/analyzers/changelog-parser.js.map +1 -0
  13. package/dist/engine/batch.test.js +59 -0
  14. package/dist/engine/batch.test.js.map +1 -0
  15. package/dist/engine/cache/manager.js +165 -0
  16. package/dist/engine/cache/manager.js.map +1 -0
  17. package/dist/engine/cache/manager.test.js +75 -0
  18. package/dist/engine/cache/manager.test.js.map +1 -0
  19. package/dist/engine/checks.test.js +92 -0
  20. package/dist/engine/checks.test.js.map +1 -0
  21. package/dist/engine/context/optimizer.js +189 -0
  22. package/dist/engine/context/optimizer.js.map +1 -0
  23. package/dist/engine/context/optimizer.test.js +81 -0
  24. package/dist/engine/context/optimizer.test.js.map +1 -0
  25. package/dist/engine/ecosystems/parsers.test.js +255 -0
  26. package/dist/engine/ecosystems/parsers.test.js.map +1 -0
  27. package/dist/engine/fixer/patterns.js +356 -0
  28. package/dist/engine/fixer/patterns.js.map +1 -0
  29. package/dist/engine/fixer/patterns.test.js +124 -0
  30. package/dist/engine/fixer/patterns.test.js.map +1 -0
  31. package/dist/engine/git.js +1 -0
  32. package/dist/engine/git.js.map +1 -1
  33. package/dist/engine/git.test.js +111 -0
  34. package/dist/engine/git.test.js.map +1 -0
  35. package/dist/engine/perf/metrics.js +171 -0
  36. package/dist/engine/perf/metrics.js.map +1 -0
  37. package/dist/engine/perf/regression.js +115 -0
  38. package/dist/engine/perf/regression.js.map +1 -0
  39. package/dist/engine/run.js +93 -2
  40. package/dist/engine/run.js.map +1 -1
  41. package/dist/engine/run.test.js +47 -0
  42. package/dist/engine/run.test.js.map +1 -0
  43. package/dist/engine/sandbox/docker-manager.js +215 -0
  44. package/dist/engine/sandbox/docker-manager.js.map +1 -0
  45. package/dist/engine/sandbox/orchestrator.js +107 -0
  46. package/dist/engine/sandbox/orchestrator.js.map +1 -0
  47. package/dist/engine/sandbox/service-detector.js +147 -0
  48. package/dist/engine/sandbox/service-detector.js.map +1 -0
  49. package/dist/engine/sandbox/template-generator.js +241 -0
  50. package/dist/engine/sandbox/template-generator.js.map +1 -0
  51. package/dist/engine/verifiers/ast-analyzer.js +212 -0
  52. package/dist/engine/verifiers/ast-analyzer.js.map +1 -0
  53. package/dist/engine/verifiers/ast-analyzer.test.js +96 -0
  54. package/dist/engine/verifiers/ast-analyzer.test.js.map +1 -0
  55. package/dist/engine/workspace.test.js +95 -0
  56. package/dist/engine/workspace.test.js.map +1 -0
  57. package/dist/exitcode.test.js +62 -0
  58. package/dist/exitcode.test.js.map +1 -0
  59. package/dist/format.js +15 -0
  60. package/dist/format.js.map +1 -1
  61. package/dist/report.test.js +56 -0
  62. package/dist/report.test.js.map +1 -0
  63. package/package.json +7 -4
  64. package/CHANGELOG.md +0 -93
  65. package/CONTRIBUTING.md +0 -52
  66. package/SECURITY.md +0 -38
  67. package/action-dist/index.cjs +0 -19935
  68. package/action.yml +0 -76
  69. package/competitive-analysis.md +0 -304
  70. package/examples/greenbump.yml +0 -37
  71. package/examples/legacy-repo/package.json +0 -12
  72. package/examples/legacy-repo/test.js +0 -17
  73. package/examples/multi-file-repo/models/todo.js +0 -8
  74. package/examples/multi-file-repo/models/user.js +0 -11
  75. package/examples/multi-file-repo/package.json +0 -12
  76. package/examples/multi-file-repo/services/session.js +0 -9
  77. package/examples/multi-file-repo/test.js +0 -19
  78. package/optimization-roadmap.md +0 -772
@@ -0,0 +1,189 @@
1
+ import { readFile, readdir, stat } from "node:fs/promises";
2
+ import { join, relative } from "node:path";
3
+ /**
4
+ * Context optimizer: shrink what we send to the LLM.
5
+ *
6
+ * Two strategies:
7
+ * 1. Trim the failure output — keep error lines, drop passing-test noise,
8
+ * stack frames in node_modules, and repeated warnings.
9
+ * 2. Identify candidate files — parse the error output for file paths so the
10
+ * fix agent gets pointed at the right files immediately instead of
11
+ * exploring (every exploration round costs input tokens).
12
+ */
13
+ const NOISE_PATTERNS = [
14
+ /^\s*at .*node_modules.*$/, // stack frames inside dependencies
15
+ /^\s*at .*internal\//, // node internal frames
16
+ /npm warn/i,
17
+ /deprecated.*\(https?:\/\//i,
18
+ /^\s*✓/, // passing test lines
19
+ /^\s*PASS /,
20
+ /Test Suites:.*passed/i,
21
+ /Tests:.*passed/i,
22
+ ];
23
+ const MAX_FAILURE_CHARS = 4_000;
24
+ const MAX_FILE_LINE = 300;
25
+ /**
26
+ * Compress failure output: keep the informative parts (errors, file refs,
27
+ * first stack frame per error), drop the rest. Preserves the error's
28
+ * "signature" — the part that determines what the fix should be.
29
+ */
30
+ export function trimFailureOutput(output) {
31
+ const lines = output.split("\n");
32
+ const kept = [];
33
+ let seenErrors = 0;
34
+ for (const line of lines) {
35
+ if (NOISE_PATTERNS.some((p) => p.test(line)))
36
+ continue;
37
+ const isError = /error|fail|✗|✘|cannot|not a function|not defined|TypeError|ReferenceError|SyntaxError/i.test(line);
38
+ if (isError)
39
+ seenErrors++;
40
+ // After the first couple of errors, stack-trace lines become noise
41
+ const isStackFrame = /^\s*at\s/.test(line);
42
+ if (isStackFrame && seenErrors > 2)
43
+ continue;
44
+ kept.push(line.length > MAX_FILE_LINE ? line.slice(0, MAX_FILE_LINE) + "…" : line);
45
+ if (kept.join("\n").length > MAX_FAILURE_CHARS)
46
+ break;
47
+ }
48
+ let result = kept.join("\n");
49
+ if (output.length > result.length) {
50
+ result += `\n… (trimmed ${output.length - result.length} chars of passing/noisy output)`;
51
+ }
52
+ return result;
53
+ }
54
+ /**
55
+ * Extract file paths referenced by the failure output — these are the
56
+ * files most likely to need edits. Returned as project-relative paths,
57
+ * deduplicated, existing files only.
58
+ */
59
+ export async function extractCandidateFiles(failureOutput, cwd) {
60
+ const found = new Set();
61
+ // Match path:line:col references (TS/JS errors), stack frames, webpack errors
62
+ const patterns = [
63
+ /([^\s():]+\.(?:ts|tsx|js|jsx|mjs|cjs|vue|svelte)):\d+:\d+/g,
64
+ /at\s+(?:\w+\s+)?\(([^():\s]+\.(?:ts|tsx|js|jsx|mjs|cjs)):\d+:\d+\)/g,
65
+ /at\s+([^():\s]+\.(?:ts|tsx|js|jsx|mjs|cjs)):\d+:\d+/g,
66
+ /ERROR in ([^\s]+\.(?:ts|tsx|js|jsx|vue|svelte))/g,
67
+ ];
68
+ for (const pattern of patterns) {
69
+ let m;
70
+ while ((m = pattern.exec(failureOutput)) !== null) {
71
+ const p = normalizePath(m[1], cwd);
72
+ if (p)
73
+ found.add(p);
74
+ }
75
+ }
76
+ // Verify the files actually exist in the project
77
+ const existing = [];
78
+ for (const f of found) {
79
+ try {
80
+ const s = await stat(join(cwd, f));
81
+ if (s.isFile() && s.size < 200_000)
82
+ existing.push(f);
83
+ }
84
+ catch {
85
+ // not a real project file — skip
86
+ }
87
+ }
88
+ return existing.slice(0, 20); // cap to avoid flooding the context
89
+ }
90
+ /**
91
+ * Find test files related to candidate source files, so the agent can
92
+ * see expectations without searching.
93
+ */
94
+ export async function findRelatedTests(candidateFiles, cwd) {
95
+ const tests = new Set();
96
+ for (const f of candidateFiles) {
97
+ // src/foo.ts → src/foo.test.ts, tests/foo.test.ts, __tests__/foo.test.ts
98
+ const base = f.replace(/\.(ts|tsx|js|jsx|mjs|cjs|vue|svelte)$/, "");
99
+ const candidates = [
100
+ `${base}.test.ts`, `${base}.test.tsx`, `${base}.test.js`, `${base}.test.jsx`,
101
+ `${base}.spec.ts`, `${base}.spec.tsx`, `${base}.spec.js`, `${base}.spec.jsx`,
102
+ ];
103
+ for (const c of candidates) {
104
+ try {
105
+ await stat(join(cwd, c));
106
+ tests.add(c);
107
+ }
108
+ catch { /* doesn't exist */ }
109
+ }
110
+ }
111
+ return [...tests].slice(0, 10);
112
+ }
113
+ /**
114
+ * Read candidate files (truncated) to include as upfront context.
115
+ * Returns a map of path → content.
116
+ */
117
+ export async function readCandidateContents(files, cwd, maxCharsPerFile = 8_000) {
118
+ const out = new Map();
119
+ for (const f of files) {
120
+ try {
121
+ let content = await readFile(join(cwd, f), "utf8");
122
+ if (content.length > maxCharsPerFile) {
123
+ content = content.slice(0, maxCharsPerFile) + "\n… (file truncated)";
124
+ }
125
+ out.set(f, content);
126
+ }
127
+ catch {
128
+ // unreadable — skip
129
+ }
130
+ }
131
+ return out;
132
+ }
133
+ /** Estimate token count for a string (~4 chars/token for code+prose mix). */
134
+ export function estimateTokens(text) {
135
+ return Math.ceil(text.length / 4);
136
+ }
137
+ /** Build the "files likely involved" hint block for the fix prompt. */
138
+ export function buildCandidateHint(candidateFiles, relatedTests) {
139
+ if (candidateFiles.length === 0 && relatedTests.length === 0)
140
+ return "";
141
+ const parts = ["\n\nFiles referenced by the failure output (start here):"];
142
+ for (const f of candidateFiles)
143
+ parts.push(`- ${f}`);
144
+ if (relatedTests.length > 0) {
145
+ parts.push("\nRelated test files:");
146
+ for (const t of relatedTests)
147
+ parts.push(`- ${t}`);
148
+ }
149
+ return parts.join("\n");
150
+ }
151
+ function normalizePath(p, cwd) {
152
+ // Strip common prefixes to get a project-relative path
153
+ let cleaned = p
154
+ .replace(/^file:\/\//, "")
155
+ .replace(/\\/g, "/");
156
+ if (cleaned.startsWith(cwd)) {
157
+ cleaned = relative(cwd, cleaned);
158
+ }
159
+ // Drop absolute paths that aren't under cwd
160
+ if (cleaned.startsWith("/"))
161
+ return null;
162
+ // Drop anything escaping the project
163
+ if (cleaned.startsWith(".."))
164
+ return null;
165
+ // Drop node_modules references — we don't fix dependency internals
166
+ if (cleaned.includes("node_modules/"))
167
+ return null;
168
+ return cleaned;
169
+ }
170
+ /**
171
+ * Scan the project root for the most likely source dirs, so the candidate
172
+ * search can stay focused (cheap heuristic, avoids walking node_modules).
173
+ */
174
+ export async function guessSourceDirs(cwd) {
175
+ const candidates = ["src", "lib", "app", "packages", "source", "test", "tests", "__tests__"];
176
+ const found = [];
177
+ try {
178
+ const entries = await readdir(cwd, { withFileTypes: true });
179
+ for (const e of entries) {
180
+ if (e.isDirectory() && candidates.includes(e.name))
181
+ found.push(e.name);
182
+ }
183
+ }
184
+ catch {
185
+ // unreadable root — return empty
186
+ }
187
+ return found.length > 0 ? found : ["."];
188
+ }
189
+ //# sourceMappingURL=optimizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optimizer.js","sourceRoot":"","sources":["../../../src/engine/context/optimizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtemp, writeFile, rm, mkdir } from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { trimFailureOutput, extractCandidateFiles, estimateTokens, buildCandidateHint, } from "./optimizer.js";
7
+ test("trimFailureOutput: drops passing-test noise, keeps errors", () => {
8
+ const output = [
9
+ " ✓ renders header",
10
+ " ✓ renders footer",
11
+ " ✗ renders body",
12
+ "TypeError: ReactDOM.render is not a function",
13
+ " at render (src/index.tsx:5:3)",
14
+ " at Object.<anonymous> (node_modules/react-dom/cjs/index.js:12:1)",
15
+ "Tests: 2 passed, 1 failed",
16
+ ].join("\n");
17
+ const trimmed = trimFailureOutput(output);
18
+ assert.ok(trimmed.includes("ReactDOM.render is not a function"));
19
+ assert.ok(!trimmed.includes("✓ renders header"));
20
+ assert.ok(!trimmed.includes("node_modules"));
21
+ assert.ok(!trimmed.includes("Tests: 2 passed"));
22
+ });
23
+ test("trimFailureOutput: caps total size", () => {
24
+ const huge = "error line\n".repeat(5000);
25
+ const trimmed = trimFailureOutput(huge);
26
+ assert.ok(trimmed.length < 5000);
27
+ });
28
+ test("extractCandidateFiles: pulls project-relative paths from TS errors", async () => {
29
+ const dir = await mkdtemp(join(tmpdir(), "greenbump-ctx-"));
30
+ await mkdir(join(dir, "src"), { recursive: true });
31
+ await writeFile(join(dir, "src", "index.tsx"), "content", "utf8");
32
+ try {
33
+ const files = await extractCandidateFiles("src/index.tsx:5:3 - error TS2339: Property 'render' does not exist", dir);
34
+ assert.deepEqual(files, ["src/index.tsx"]);
35
+ }
36
+ finally {
37
+ await rm(dir, { recursive: true, force: true });
38
+ }
39
+ });
40
+ test("extractCandidateFiles: ignores node_modules and absolute paths outside project", async () => {
41
+ const dir = await mkdtemp(join(tmpdir(), "greenbump-ctx-"));
42
+ await mkdir(join(dir, "src"), { recursive: true });
43
+ await writeFile(join(dir, "src", "index.tsx"), "content", "utf8");
44
+ try {
45
+ const files = await extractCandidateFiles([
46
+ "at render (/project/node_modules/react-dom/index.js:5:3)",
47
+ "at render (/totally/other/place/file.ts:1:1)",
48
+ "src/index.tsx:5:3 - error TS2339",
49
+ ].join("\n"), dir);
50
+ assert.deepEqual(files, ["src/index.tsx"]);
51
+ }
52
+ finally {
53
+ await rm(dir, { recursive: true, force: true });
54
+ }
55
+ });
56
+ test("extractCandidateFiles: only returns files that exist", async () => {
57
+ const dir = await mkdtemp(join(tmpdir(), "greenbump-ctx-"));
58
+ await mkdir(join(dir, "src"), { recursive: true });
59
+ await writeFile(join(dir, "src", "real.tsx"), "content", "utf8");
60
+ try {
61
+ const files = await extractCandidateFiles(["src/real.tsx:1:1 - error", "src/imaginary.tsx:2:2 - error"].join("\n"), dir);
62
+ assert.deepEqual(files, ["src/real.tsx"]);
63
+ }
64
+ finally {
65
+ await rm(dir, { recursive: true, force: true });
66
+ }
67
+ });
68
+ test("estimateTokens: roughly 4 chars per token", () => {
69
+ assert.equal(estimateTokens(""), 0);
70
+ assert.equal(estimateTokens("abcd"), 1);
71
+ assert.equal(estimateTokens("a".repeat(100)), 25);
72
+ });
73
+ test("buildCandidateHint: empty when no candidates", () => {
74
+ assert.equal(buildCandidateHint([], []), "");
75
+ });
76
+ test("buildCandidateHint: lists files and tests", () => {
77
+ const hint = buildCandidateHint(["src/index.tsx"], ["src/index.test.tsx"]);
78
+ assert.ok(hint.includes("src/index.tsx"));
79
+ assert.ok(hint.includes("src/index.test.tsx"));
80
+ });
81
+ //# sourceMappingURL=optimizer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optimizer.test.js","sourceRoot":"","sources":["../../../src/engine/context/optimizer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,255 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { parseYarnOutdated } from "./yarn.js";
4
+ import { parseGoListOutdated } from "./go.js";
5
+ import { parseComposerOutdated } from "./composer.js";
6
+ import { parsePubOutdated } from "./pub.js";
7
+ import { parseNugetOutdated } from "./nuget.js";
8
+ import { parseCargoToml } from "./cargo.js";
9
+ import { parsePomXml } from "./maven.js";
10
+ import { parseGradleBuildFile } from "./gradle.js";
11
+ import { parseBundlerOutdated } from "./bundler.js";
12
+ import { parsePoetryOutdated } from "./poetry.js";
13
+ import { parseCocoapodsOutdated } from "./cocoapods.js";
14
+ import { parseMixOutdated } from "./mix.js";
15
+ import { parseConanfileTxt } from "./conan.js";
16
+ import { parseNpmOutdated } from "./npm.js";
17
+ import { parsePnpmOutdated } from "./pnpm.js";
18
+ import { parsePipOutdated } from "./pip.js";
19
+ import { parseUvOutdated } from "./uv.js";
20
+ import { parsePipenvOutdated } from "./pipenv.js";
21
+ import { parseElmDirectDeps } from "./elm.js";
22
+ import { parsePackageResolved, parsePackageSwiftDeps } from "./swiftpm.js";
23
+ test("yarn: parses the ndjson table row, skips non-table lines", () => {
24
+ const stdout = [
25
+ JSON.stringify({ type: "info", data: "unrelated" }),
26
+ JSON.stringify({
27
+ type: "table",
28
+ data: {
29
+ head: ["Package", "Current", "Wanted", "Latest", "Package Type", "URL"],
30
+ body: [
31
+ ["lodash", "4.17.20", "4.17.21", "4.17.21", "dependencies", ""],
32
+ ["left-pad", "1.0.0", "1.0.0", "1.0.0", "dependencies", ""],
33
+ ],
34
+ },
35
+ }),
36
+ ].join("\n");
37
+ const result = parseYarnOutdated(stdout);
38
+ assert.deepEqual(result, [{ name: "lodash", current: "4.17.20", wanted: "", latest: "4.17.21" }]);
39
+ });
40
+ test("go: parses ndjson module stream, skips main/indirect/no-update", () => {
41
+ const stdout = [
42
+ JSON.stringify({ Path: "example.com/app", Main: true }),
43
+ JSON.stringify({ Path: "example.com/indirect", Version: "v1.0.0", Indirect: true, Update: { Version: "v1.1.0" } }),
44
+ JSON.stringify({ Path: "example.com/nodiff", Version: "v1.0.0", Update: { Version: "v1.0.0" } }),
45
+ JSON.stringify({ Path: "example.com/direct", Version: "v1.0.0", Update: { Version: "v1.2.0" } }),
46
+ ].join("\n");
47
+ const result = parseGoListOutdated(stdout);
48
+ assert.deepEqual(result, [{ name: "example.com/direct", current: "v1.0.0", wanted: "", latest: "v1.2.0" }]);
49
+ });
50
+ test("composer: parses `composer outdated --format json`", () => {
51
+ const stdout = JSON.stringify({
52
+ installed: [
53
+ { name: "monolog/monolog", version: "2.0.0", latest: "3.5.0" },
54
+ { name: "psr/log", version: "1.1.4", latest: "1.1.4" },
55
+ ],
56
+ });
57
+ const result = parseComposerOutdated(stdout);
58
+ assert.deepEqual(result, [{ name: "monolog/monolog", current: "2.0.0", wanted: "", latest: "3.5.0" }]);
59
+ });
60
+ test("pub: parses `dart pub outdated --json`", () => {
61
+ const stdout = JSON.stringify({
62
+ packages: [
63
+ { package: "http", current: { version: "0.13.0" }, latest: { version: "1.2.0" } },
64
+ { package: "path", current: { version: "1.8.0" }, latest: { version: "1.8.0" } },
65
+ ],
66
+ });
67
+ const result = parsePubOutdated(stdout);
68
+ assert.deepEqual(result, [{ name: "http", current: "0.13.0", wanted: "", latest: "1.2.0" }]);
69
+ });
70
+ test("nuget: parses `dotnet list package --outdated` table", () => {
71
+ const stdout = [
72
+ "Project 'App' has the following updates to its packages",
73
+ " [net8.0]:",
74
+ " Top-level Package Requested Resolved Latest",
75
+ " > Newtonsoft.Json 13.0.1 13.0.1 13.0.3",
76
+ ].join("\n");
77
+ const result = parseNugetOutdated(stdout);
78
+ assert.deepEqual(result, [{ name: "Newtonsoft.Json", current: "13.0.1", wanted: "13.0.1", latest: "13.0.3" }]);
79
+ });
80
+ test("cargo: parses [dependencies] section of Cargo.toml", () => {
81
+ const raw = [
82
+ "[package]",
83
+ 'name = "app"',
84
+ "",
85
+ "[dependencies]",
86
+ 'serde = "1.0"',
87
+ 'tokio = "^1.28"',
88
+ "",
89
+ "[dev-dependencies]",
90
+ 'criterion = "0.5"',
91
+ ].join("\n");
92
+ const result = parseCargoToml(raw);
93
+ assert.deepEqual([...result.entries()], [["serde", "1.0"], ["tokio", "1.28"]]);
94
+ });
95
+ test("maven: parses <dependency> blocks from pom.xml", () => {
96
+ const raw = `<project>
97
+ <dependencies>
98
+ <dependency>
99
+ <groupId>org.apache.commons</groupId>
100
+ <artifactId>commons-lang3</artifactId>
101
+ <version>3.12.0</version>
102
+ </dependency>
103
+ </dependencies>
104
+ </project>`;
105
+ const result = parsePomXml(raw);
106
+ assert.deepEqual(result, [{ name: "org.apache.commons:commons-lang3", version: "3.12.0" }]);
107
+ });
108
+ test("gradle: parses implementation(...) dependency declarations", () => {
109
+ const raw = `dependencies {
110
+ implementation("com.google.guava:guava:31.1-jre")
111
+ testImplementation 'junit:junit:4.13.2'
112
+ }`;
113
+ const result = parseGradleBuildFile(raw);
114
+ assert.deepEqual(result, [
115
+ { group: "com.google.guava", artifact: "guava", version: "31.1-jre" },
116
+ { group: "junit", artifact: "junit", version: "4.13.2" },
117
+ ]);
118
+ });
119
+ test("bundler: parses `bundle outdated` gem lines", () => {
120
+ const stdout = [
121
+ "Fetching gem metadata...",
122
+ "Gem Current Latest Requested Groups",
123
+ "* rails (newest 7.1.2, installed 7.0.4, requested ~> 7.0) in groups \"default\"",
124
+ "* rake (newest 13.1.0, installed 13.1.0)",
125
+ ].join("\n");
126
+ const result = parseBundlerOutdated(stdout);
127
+ assert.deepEqual(result, [{ name: "rails", current: "7.0.4", wanted: "", latest: "7.1.2" }]);
128
+ });
129
+ test("poetry: parses `poetry show -o` plain-text table", () => {
130
+ const stdout = ["requests 2.28.0 2.31.0 HTTP library", "click 8.1.3 8.1.3 CLI toolkit"].join("\n");
131
+ const result = parsePoetryOutdated(stdout);
132
+ assert.deepEqual(result, [{ name: "requests", current: "2.28.0", wanted: "", latest: "2.31.0" }]);
133
+ });
134
+ test("cocoapods: parses `pod outdated` list lines, using the (latest version) suffix", () => {
135
+ // The value after "->" is only what the Podfile's constraint resolves
136
+ // to (often == current for an exact pin, as with AFNetworking below) —
137
+ // the true latest is only in the "(latest version X)" suffix.
138
+ const stdout = [
139
+ "The following pod updates are available:",
140
+ "- AFNetworking 3.2.1 -> 3.2.1 (latest version 4.0.1)",
141
+ "- Alamofire 5.6.0 -> 5.6.0 (latest version 5.6.0)",
142
+ ].join("\n");
143
+ const result = parseCocoapodsOutdated(stdout);
144
+ assert.deepEqual(result, [{ name: "AFNetworking", current: "3.2.1", wanted: "", latest: "4.0.1" }]);
145
+ });
146
+ test("mix: parses `mix hex.outdated` table rows, including the Only column", () => {
147
+ // Real `mix hex.outdated` output always has the "Only" column; it's blank
148
+ // for deps with no `only:` restriction (e.g. jason below).
149
+ const stdout = [
150
+ "Dependency Only Current Latest Status ",
151
+ "ex_doc dev 0.29.0 0.40.3 Update not possible ",
152
+ "jason 1.2.0 1.4.5 Update not possible ",
153
+ "",
154
+ "Run `mix hex.outdated APP` to see requirements for a specific dependency.",
155
+ ].join("\n");
156
+ const result = parseMixOutdated(stdout);
157
+ assert.deepEqual(result, [
158
+ { name: "ex_doc", current: "0.29.0", wanted: "", latest: "0.40.3" },
159
+ { name: "jason", current: "1.2.0", wanted: "", latest: "1.4.5" },
160
+ ]);
161
+ });
162
+ test("conan: parses [requires] section of conanfile.txt", () => {
163
+ const raw = ["[requires]", "zlib/1.2.13", "boost/1.83.0", "", "[generators]", "CMakeDeps"].join("\n");
164
+ const result = parseConanfileTxt(raw);
165
+ assert.deepEqual(result, [
166
+ { name: "zlib", version: "1.2.13" },
167
+ { name: "boost", version: "1.83.0" },
168
+ ]);
169
+ });
170
+ test("npm: parses `npm outdated --json` output, dropping entries already at latest", () => {
171
+ const data = {
172
+ lodash: { current: "4.17.20", latest: "4.17.21" },
173
+ axios: { current: "1.3.0", latest: "1.3.0" },
174
+ };
175
+ const result = parseNpmOutdated(data);
176
+ assert.deepEqual(result, [{ name: "lodash", current: "4.17.20", wanted: "", latest: "4.17.21" }]);
177
+ });
178
+ test("npm: null data (non-JSON stdout) yields empty result", () => {
179
+ assert.deepEqual(parseNpmOutdated(null), []);
180
+ });
181
+ test("pnpm: parses `pnpm outdated --format json`, tolerating missing current/latest", () => {
182
+ const data = {
183
+ lodash: { current: "4.17.20", latest: "4.17.21" },
184
+ // pnpm can omit fields for workspace-linked packages; guard against undefined.
185
+ weird: {},
186
+ };
187
+ const result = parsePnpmOutdated(data);
188
+ assert.deepEqual(result, [{ name: "lodash", current: "4.17.20", wanted: "", latest: "4.17.21" }]);
189
+ });
190
+ test("pnpm: null data yields empty result", () => {
191
+ assert.deepEqual(parsePnpmOutdated(null), []);
192
+ });
193
+ test("pip: parses `pip list --outdated --format json`", () => {
194
+ const data = [
195
+ { name: "requests", version: "2.28.0", latest_version: "2.31.0" },
196
+ { name: "flask", version: "2.0.0", latest_version: "2.3.3" },
197
+ ];
198
+ const result = parsePipOutdated(data);
199
+ assert.deepEqual(result, [
200
+ { name: "requests", current: "2.28.0", wanted: "", latest: "2.31.0" },
201
+ { name: "flask", current: "2.0.0", wanted: "", latest: "2.3.3" },
202
+ ]);
203
+ });
204
+ test("pip: null data yields empty result", () => {
205
+ assert.deepEqual(parsePipOutdated(null), []);
206
+ });
207
+ test("uv: parses `uv pip list --outdated --format json` (same shape as pip)", () => {
208
+ const data = [{ name: "requests", version: "2.28.0", latest_version: "2.31.0" }];
209
+ const result = parseUvOutdated(data);
210
+ assert.deepEqual(result, [{ name: "requests", current: "2.28.0", wanted: "", latest: "2.31.0" }]);
211
+ });
212
+ test("uv: null data yields empty result", () => {
213
+ assert.deepEqual(parseUvOutdated(null), []);
214
+ });
215
+ test("pipenv: parses `pipenv run pip list --outdated --format json`", () => {
216
+ const data = [{ name: "django", version: "4.0.0", latest_version: "4.2.5" }];
217
+ const result = parsePipenvOutdated(data);
218
+ assert.deepEqual(result, [{ name: "django", current: "4.0.0", wanted: "", latest: "4.2.5" }]);
219
+ });
220
+ test("pipenv: null data yields empty result", () => {
221
+ assert.deepEqual(parsePipenvOutdated(null), []);
222
+ });
223
+ test("elm: extracts direct dependencies from elm.json, ignoring indirect deps", () => {
224
+ const json = {
225
+ dependencies: {
226
+ direct: { "elm/core": "1.0.5", "elm/json": "1.1.3" },
227
+ indirect: { "elm/bytes": "1.0.8" },
228
+ },
229
+ };
230
+ assert.deepEqual(parseElmDirectDeps(json), { "elm/core": "1.0.5", "elm/json": "1.1.3" });
231
+ });
232
+ test("elm: missing dependencies field yields empty object", () => {
233
+ assert.deepEqual(parseElmDirectDeps({}), {});
234
+ });
235
+ test("swiftpm: parses Package.resolved pins into a name-to-version map", () => {
236
+ const raw = JSON.stringify({
237
+ pins: [
238
+ { identity: "swift-log", state: { version: "1.5.3" } },
239
+ { identity: "no-version-pin", state: {} },
240
+ ],
241
+ });
242
+ assert.deepEqual(parsePackageResolved(raw), { "swift-log": "1.5.3" });
243
+ });
244
+ test("swiftpm: extracts .package(url:, from:) declarations and joins with resolved versions", () => {
245
+ const manifest = [
246
+ ".package(url: \"https://github.com/apple/swift-log.git\", from: \"1.4.0\")",
247
+ ".package(url: \"https://github.com/apple/swift-nio.git\", from: \"2.0.0\")",
248
+ ].join("\n");
249
+ const resolved = { "swift-log": "1.5.3" }; // swift-nio has no resolved pin (e.g. not yet fetched)
250
+ const result = parsePackageSwiftDeps(manifest, resolved);
251
+ assert.deepEqual(result, [
252
+ { name: "swift-log", current: "1.5.3", url: "https://github.com/apple/swift-log.git" },
253
+ ]);
254
+ });
255
+ //# sourceMappingURL=parsers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsers.test.js","sourceRoot":"","sources":["../../../src/engine/ecosystems/parsers.test.ts"],"names":[],"mappings":"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"}