@vibgrate/cli 2026.611.2 → 2026.613.1
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.
|
@@ -1717,6 +1717,195 @@ var require_fxp = __commonJS({
|
|
|
1717
1717
|
}
|
|
1718
1718
|
});
|
|
1719
1719
|
|
|
1720
|
+
// ../vibgrate-core/dist/chunk-KML6OTXK.js
|
|
1721
|
+
function productForType(type) {
|
|
1722
|
+
switch (type) {
|
|
1723
|
+
case "node":
|
|
1724
|
+
return "nodejs";
|
|
1725
|
+
case "python":
|
|
1726
|
+
return "python";
|
|
1727
|
+
case "dotnet":
|
|
1728
|
+
return "dotnet";
|
|
1729
|
+
case "java":
|
|
1730
|
+
return "java";
|
|
1731
|
+
case "php":
|
|
1732
|
+
return "php";
|
|
1733
|
+
case "ruby":
|
|
1734
|
+
return "ruby";
|
|
1735
|
+
case "go":
|
|
1736
|
+
return "go";
|
|
1737
|
+
default:
|
|
1738
|
+
return null;
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
function extractCycle(type, runtime) {
|
|
1742
|
+
if (!runtime) return null;
|
|
1743
|
+
switch (type) {
|
|
1744
|
+
case "python":
|
|
1745
|
+
case "php":
|
|
1746
|
+
case "ruby":
|
|
1747
|
+
case "go": {
|
|
1748
|
+
const m = runtime.match(/(\d+)\.(\d+)/);
|
|
1749
|
+
return m ? `${m[1]}.${m[2]}` : null;
|
|
1750
|
+
}
|
|
1751
|
+
case "dotnet": {
|
|
1752
|
+
const m = runtime.match(/(\d+)\.(\d+)/) ?? runtime.match(/(\d+)/);
|
|
1753
|
+
if (!m) return null;
|
|
1754
|
+
return m[2] !== void 0 ? `${m[1]}.${m[2]}` : `${m[1]}.0`;
|
|
1755
|
+
}
|
|
1756
|
+
case "node": {
|
|
1757
|
+
const m = runtime.match(/(\d+)/);
|
|
1758
|
+
return m ? m[1] : null;
|
|
1759
|
+
}
|
|
1760
|
+
case "java": {
|
|
1761
|
+
const legacy = runtime.match(/1\.(\d+)/);
|
|
1762
|
+
if (legacy) return legacy[1];
|
|
1763
|
+
const m = runtime.match(/(\d+)/);
|
|
1764
|
+
return m ? m[1] : null;
|
|
1765
|
+
}
|
|
1766
|
+
default:
|
|
1767
|
+
return null;
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
function cycleEolStatus(cycle, cycles, now = Date.now()) {
|
|
1771
|
+
const entry = cycles.find((c) => String(c.cycle) === cycle);
|
|
1772
|
+
if (!entry) return null;
|
|
1773
|
+
if (typeof entry.eol === "boolean") return entry.eol;
|
|
1774
|
+
const eolMs = Date.parse(entry.eol);
|
|
1775
|
+
if (Number.isNaN(eolMs)) return null;
|
|
1776
|
+
return eolMs <= now;
|
|
1777
|
+
}
|
|
1778
|
+
function parseCycle(cycle) {
|
|
1779
|
+
const m = String(cycle).match(/^(\d+)(?:\.(\d+))?/);
|
|
1780
|
+
if (!m) return null;
|
|
1781
|
+
return { major: parseInt(m[1], 10), minor: m[2] ? parseInt(m[2], 10) : 0 };
|
|
1782
|
+
}
|
|
1783
|
+
function rank(v) {
|
|
1784
|
+
return v.major * 1e3 + v.minor;
|
|
1785
|
+
}
|
|
1786
|
+
function isReleased(cycle, now) {
|
|
1787
|
+
if (typeof cycle.releaseDate !== "string") return true;
|
|
1788
|
+
const ts3 = Date.parse(cycle.releaseDate);
|
|
1789
|
+
return Number.isNaN(ts3) ? true : ts3 <= now;
|
|
1790
|
+
}
|
|
1791
|
+
function isLts(cycle, now) {
|
|
1792
|
+
if (cycle.lts === true) return true;
|
|
1793
|
+
if (typeof cycle.lts === "string") {
|
|
1794
|
+
const ts3 = Date.parse(cycle.lts);
|
|
1795
|
+
return !Number.isNaN(ts3) && ts3 <= now;
|
|
1796
|
+
}
|
|
1797
|
+
return false;
|
|
1798
|
+
}
|
|
1799
|
+
function cyclesFor(catalog, product) {
|
|
1800
|
+
return catalog.products[product]?.cycles ?? [];
|
|
1801
|
+
}
|
|
1802
|
+
function latestStable(catalog, product, now = Date.now()) {
|
|
1803
|
+
let best = null;
|
|
1804
|
+
for (const cycle of cyclesFor(catalog, product)) {
|
|
1805
|
+
if (!isReleased(cycle, now)) continue;
|
|
1806
|
+
const v = parseCycle(cycle.cycle);
|
|
1807
|
+
if (v && (!best || rank(v) > rank(best))) best = v;
|
|
1808
|
+
}
|
|
1809
|
+
return best;
|
|
1810
|
+
}
|
|
1811
|
+
function latestLts(catalog, product, now = Date.now()) {
|
|
1812
|
+
let best = null;
|
|
1813
|
+
for (const cycle of cyclesFor(catalog, product)) {
|
|
1814
|
+
if (!isReleased(cycle, now) || !isLts(cycle, now)) continue;
|
|
1815
|
+
const v = parseCycle(cycle.cycle);
|
|
1816
|
+
if (v && (!best || rank(v) > rank(best))) best = v;
|
|
1817
|
+
}
|
|
1818
|
+
return best;
|
|
1819
|
+
}
|
|
1820
|
+
function eolDate(catalog, product, cycle) {
|
|
1821
|
+
const entry = cyclesFor(catalog, product).find((c) => String(c.cycle) === cycle);
|
|
1822
|
+
return entry && typeof entry.eol === "string" ? entry.eol : void 0;
|
|
1823
|
+
}
|
|
1824
|
+
function runtimeEolStatus(catalog, type, runtime, now = Date.now()) {
|
|
1825
|
+
const product = productForType(type);
|
|
1826
|
+
if (!product) return null;
|
|
1827
|
+
const cycle = extractCycle(type, runtime);
|
|
1828
|
+
if (!cycle) return null;
|
|
1829
|
+
return cycleEolStatus(cycle, cyclesFor(catalog, product), now);
|
|
1830
|
+
}
|
|
1831
|
+
var BUNDLED_RUNTIME_CATALOG = {
|
|
1832
|
+
generatedAt: "2026-06-01",
|
|
1833
|
+
source: "endoflife.date",
|
|
1834
|
+
products: {
|
|
1835
|
+
nodejs: {
|
|
1836
|
+
product: "nodejs",
|
|
1837
|
+
cycles: [
|
|
1838
|
+
{ cycle: "24", releaseDate: "2025-05-06", lts: "2025-10-28", eol: "2028-04-30" },
|
|
1839
|
+
{ cycle: "23", releaseDate: "2024-10-16", lts: false, eol: "2025-06-01" },
|
|
1840
|
+
{ cycle: "22", releaseDate: "2024-04-24", lts: "2024-10-29", eol: "2027-04-30" },
|
|
1841
|
+
{ cycle: "20", releaseDate: "2023-04-18", lts: "2023-10-24", eol: "2026-04-30" },
|
|
1842
|
+
{ cycle: "18", releaseDate: "2022-04-19", lts: "2022-10-25", eol: "2025-04-30" }
|
|
1843
|
+
]
|
|
1844
|
+
},
|
|
1845
|
+
python: {
|
|
1846
|
+
product: "python",
|
|
1847
|
+
cycles: [
|
|
1848
|
+
{ cycle: "3.14", releaseDate: "2025-10-07", eol: "2030-10-01" },
|
|
1849
|
+
{ cycle: "3.13", releaseDate: "2024-10-07", eol: "2029-10-01" },
|
|
1850
|
+
{ cycle: "3.12", releaseDate: "2023-10-02", eol: "2028-10-01" },
|
|
1851
|
+
{ cycle: "3.11", releaseDate: "2022-10-24", eol: "2027-10-01" },
|
|
1852
|
+
{ cycle: "3.10", releaseDate: "2021-10-04", eol: "2026-10-01" },
|
|
1853
|
+
{ cycle: "3.9", releaseDate: "2020-10-05", eol: "2025-10-01" },
|
|
1854
|
+
{ cycle: "3.8", releaseDate: "2019-10-14", eol: "2024-10-07" }
|
|
1855
|
+
]
|
|
1856
|
+
},
|
|
1857
|
+
dotnet: {
|
|
1858
|
+
product: "dotnet",
|
|
1859
|
+
cycles: [
|
|
1860
|
+
{ cycle: "10.0", releaseDate: "2025-11-11", lts: true, eol: "2028-11-10" },
|
|
1861
|
+
{ cycle: "9.0", releaseDate: "2024-11-12", lts: false, eol: "2026-05-12" },
|
|
1862
|
+
{ cycle: "8.0", releaseDate: "2023-11-14", lts: true, eol: "2026-11-10" },
|
|
1863
|
+
{ cycle: "7.0", releaseDate: "2022-11-08", lts: false, eol: "2024-05-14" },
|
|
1864
|
+
{ cycle: "6.0", releaseDate: "2021-11-08", lts: true, eol: "2024-11-12" }
|
|
1865
|
+
]
|
|
1866
|
+
},
|
|
1867
|
+
java: {
|
|
1868
|
+
product: "java",
|
|
1869
|
+
cycles: [
|
|
1870
|
+
{ cycle: "25", releaseDate: "2025-09-16", lts: true, eol: "2033-09-01" },
|
|
1871
|
+
{ cycle: "21", releaseDate: "2023-09-19", lts: true, eol: "2031-09-01" },
|
|
1872
|
+
{ cycle: "17", releaseDate: "2021-09-14", lts: true, eol: "2029-09-01" },
|
|
1873
|
+
{ cycle: "11", releaseDate: "2018-09-25", lts: true, eol: "2026-09-01" },
|
|
1874
|
+
{ cycle: "8", releaseDate: "2014-03-18", lts: true, eol: "2030-12-01" }
|
|
1875
|
+
]
|
|
1876
|
+
},
|
|
1877
|
+
php: {
|
|
1878
|
+
product: "php",
|
|
1879
|
+
cycles: [
|
|
1880
|
+
{ cycle: "8.4", releaseDate: "2024-11-21", eol: "2028-12-31" },
|
|
1881
|
+
{ cycle: "8.3", releaseDate: "2023-11-23", eol: "2027-12-31" },
|
|
1882
|
+
{ cycle: "8.2", releaseDate: "2022-12-08", eol: "2026-12-31" },
|
|
1883
|
+
{ cycle: "8.1", releaseDate: "2021-11-25", eol: "2025-12-31" },
|
|
1884
|
+
{ cycle: "8.0", releaseDate: "2020-11-26", eol: "2023-11-26" }
|
|
1885
|
+
]
|
|
1886
|
+
},
|
|
1887
|
+
ruby: {
|
|
1888
|
+
product: "ruby",
|
|
1889
|
+
cycles: [
|
|
1890
|
+
{ cycle: "3.5", releaseDate: "2025-12-25", eol: "2029-03-31" },
|
|
1891
|
+
{ cycle: "3.4", releaseDate: "2024-12-25", eol: "2028-03-31" },
|
|
1892
|
+
{ cycle: "3.3", releaseDate: "2023-12-25", eol: "2027-03-31" },
|
|
1893
|
+
{ cycle: "3.2", releaseDate: "2022-12-25", eol: "2026-03-31" },
|
|
1894
|
+
{ cycle: "3.1", releaseDate: "2021-12-25", eol: "2025-03-31" }
|
|
1895
|
+
]
|
|
1896
|
+
},
|
|
1897
|
+
go: {
|
|
1898
|
+
product: "go",
|
|
1899
|
+
cycles: [
|
|
1900
|
+
{ cycle: "1.25", releaseDate: "2025-08-13", eol: false },
|
|
1901
|
+
{ cycle: "1.24", releaseDate: "2025-02-11", eol: false },
|
|
1902
|
+
{ cycle: "1.23", releaseDate: "2024-08-13", eol: true },
|
|
1903
|
+
{ cycle: "1.22", releaseDate: "2024-02-06", eol: true }
|
|
1904
|
+
]
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
};
|
|
1908
|
+
|
|
1720
1909
|
// ../vibgrate-core/dist/index.js
|
|
1721
1910
|
var semver2 = __toESM(require_semver(), 1);
|
|
1722
1911
|
var semver = __toESM(require_semver(), 1);
|
|
@@ -1799,13 +1988,16 @@ import * as path30 from "path";
|
|
|
1799
1988
|
import * as crypto2 from "crypto";
|
|
1800
1989
|
import * as fs6 from "fs/promises";
|
|
1801
1990
|
import * as path31 from "path";
|
|
1802
|
-
import * as
|
|
1991
|
+
import * as path34 from "path";
|
|
1803
1992
|
import chalk3 from "chalk";
|
|
1993
|
+
import * as os4 from "os";
|
|
1994
|
+
import * as path32 from "path";
|
|
1995
|
+
import { readFile as readFile4, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
1804
1996
|
import chalk2 from "chalk";
|
|
1805
1997
|
import { writeFileSync, mkdirSync } from "fs";
|
|
1806
1998
|
import { dirname as dirname182, basename as basename192 } from "path";
|
|
1807
1999
|
import * as fs7 from "fs/promises";
|
|
1808
|
-
import * as
|
|
2000
|
+
import * as path33 from "path";
|
|
1809
2001
|
var CONFIG_FILES = [
|
|
1810
2002
|
"vibgrate.config.ts",
|
|
1811
2003
|
"vibgrate.config.js",
|
|
@@ -1999,10 +2191,10 @@ async function appendExcludePatterns(rootDir, newPatterns) {
|
|
|
1999
2191
|
}
|
|
2000
2192
|
var MS_PER_DAY = 864e5;
|
|
2001
2193
|
var DAYS_PER_YEAR = 365.25;
|
|
2002
|
-
function ageDaysBetween(resolvedVersion,
|
|
2003
|
-
if (!resolvedVersion || !
|
|
2194
|
+
function ageDaysBetween(resolvedVersion, latestStable2, releaseDates) {
|
|
2195
|
+
if (!resolvedVersion || !latestStable2 || !releaseDates) return null;
|
|
2004
2196
|
const resolvedIso = releaseDates[resolvedVersion];
|
|
2005
|
-
const latestIso = releaseDates[
|
|
2197
|
+
const latestIso = releaseDates[latestStable2];
|
|
2006
2198
|
if (!resolvedIso || !latestIso) return null;
|
|
2007
2199
|
const resolvedMs = Date.parse(resolvedIso);
|
|
2008
2200
|
const latestMs = Date.parse(latestIso);
|
|
@@ -2089,11 +2281,29 @@ function dependencyScore(projects) {
|
|
|
2089
2281
|
const twoPct = totalTwo / total;
|
|
2090
2282
|
return clamp(Math.round(currentPct * 100 - onePct * 10 - twoPct * 40), 0, 100);
|
|
2091
2283
|
}
|
|
2284
|
+
var MONTH_MS = 1e3 * 60 * 60 * 24 * 30;
|
|
2092
2285
|
function eolScore(projects) {
|
|
2093
|
-
const hasRuntimeData = projects.some(
|
|
2286
|
+
const hasRuntimeData = projects.some(
|
|
2287
|
+
(p) => p.runtimeMajorsBehind !== void 0 || p.runtimeEol !== void 0 && p.runtimeEol !== null
|
|
2288
|
+
);
|
|
2094
2289
|
if (!hasRuntimeData) return null;
|
|
2095
2290
|
let score = 100;
|
|
2291
|
+
const now = Date.now();
|
|
2096
2292
|
for (const p of projects) {
|
|
2293
|
+
if (p.runtimeEol === true) {
|
|
2294
|
+
score = Math.min(score, 0);
|
|
2295
|
+
continue;
|
|
2296
|
+
}
|
|
2297
|
+
if (p.runtimeEol === false) {
|
|
2298
|
+
if (p.runtimeEolDate) {
|
|
2299
|
+
const remaining = Date.parse(p.runtimeEolDate) - now;
|
|
2300
|
+
if (!Number.isNaN(remaining)) {
|
|
2301
|
+
if (remaining <= 6 * MONTH_MS) score = Math.min(score, 40);
|
|
2302
|
+
else if (remaining <= 12 * MONTH_MS) score = Math.min(score, 75);
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
continue;
|
|
2306
|
+
}
|
|
2097
2307
|
if (p.type === "node" && p.runtimeMajorsBehind !== void 0) {
|
|
2098
2308
|
if (p.runtimeMajorsBehind >= 3) score = Math.min(score, 0);
|
|
2099
2309
|
else if (p.runtimeMajorsBehind >= 2) score = Math.min(score, 30);
|
|
@@ -2201,8 +2411,16 @@ function generateFindings(projects, config) {
|
|
|
2201
2411
|
};
|
|
2202
2412
|
const findings = [];
|
|
2203
2413
|
for (const project of projects) {
|
|
2204
|
-
|
|
2205
|
-
|
|
2414
|
+
const runtimeLabel = project.type === "node" ? "Node.js" : project.type === "dotnet" ? ".NET" : project.type === "python" ? "Python" : project.type === "java" ? "Java" : project.type;
|
|
2415
|
+
if (project.runtimeEol === true) {
|
|
2416
|
+
const when = project.runtimeEolDate ? ` on ${project.runtimeEolDate}` : "";
|
|
2417
|
+
findings.push({
|
|
2418
|
+
ruleId: "vibgrate/runtime-eol",
|
|
2419
|
+
level: "error",
|
|
2420
|
+
message: `${runtimeLabel} runtime "${project.runtime}" reached end-of-life${when} (latest: ${project.runtimeLatest}).`,
|
|
2421
|
+
location: project.path
|
|
2422
|
+
});
|
|
2423
|
+
} else if (project.runtimeMajorsBehind !== void 0 && project.runtimeMajorsBehind >= 3) {
|
|
2206
2424
|
findings.push({
|
|
2207
2425
|
ruleId: "vibgrate/runtime-eol",
|
|
2208
2426
|
level: "error",
|
|
@@ -2210,7 +2428,6 @@ function generateFindings(projects, config) {
|
|
|
2210
2428
|
location: project.path
|
|
2211
2429
|
});
|
|
2212
2430
|
} else if (project.runtimeMajorsBehind !== void 0 && project.runtimeMajorsBehind >= 2) {
|
|
2213
|
-
const runtimeLabel = project.type === "node" ? "Node.js" : project.type === "dotnet" ? ".NET" : project.type === "python" ? "Python" : project.type === "java" ? "Java" : project.type;
|
|
2214
2431
|
findings.push({
|
|
2215
2432
|
ruleId: "vibgrate/runtime-lag",
|
|
2216
2433
|
level: "warning",
|
|
@@ -2342,11 +2559,6 @@ function summarizeBilling(projects) {
|
|
|
2342
2559
|
function formatText(artifact) {
|
|
2343
2560
|
const lines = [];
|
|
2344
2561
|
lines.push("");
|
|
2345
|
-
lines.push(chalk.cyan(" \u256D\u2500\u2500\u2500\u256E") + chalk.greenBright("\u279C"));
|
|
2346
|
-
lines.push(chalk.cyan(" \u256D\u2524") + chalk.greenBright("\u25C9 \u25C9") + chalk.cyan("\u251C\u256E") + " " + chalk.bold.white("V I B G R A T E"));
|
|
2347
|
-
lines.push(chalk.cyan(" \u2570\u2524") + chalk.dim("\u2500\u2500\u2500") + chalk.cyan("\u251C\u256F") + " " + chalk.dim(`Drift Intelligence Engine v${artifact.vibgrateVersion ?? "unknown"}`));
|
|
2348
|
-
lines.push(chalk.cyan(" \u2570\u2500\u2500\u2500\u256F"));
|
|
2349
|
-
lines.push("");
|
|
2350
2562
|
lines.push(chalk.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
|
|
2351
2563
|
lines.push(chalk.bold.cyan("\u2551 Vibgrate Drift Report \u2551"));
|
|
2352
2564
|
lines.push(chalk.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
|
|
@@ -3996,7 +4208,7 @@ var KNOWN_FRAMEWORKS = {
|
|
|
3996
4208
|
"storybook": "Storybook",
|
|
3997
4209
|
"@storybook/react": "Storybook"
|
|
3998
4210
|
};
|
|
3999
|
-
async function scanNodeProjects(rootDir, npmCache, cache, projectScanTimeout) {
|
|
4211
|
+
async function scanNodeProjects(rootDir, npmCache, cache, projectScanTimeout, catalog = BUNDLED_RUNTIME_CATALOG) {
|
|
4000
4212
|
const packageJsonFiles = cache ? await cache.findPackageJsonFiles(rootDir) : await findPackageJsonFiles(rootDir);
|
|
4001
4213
|
const results = [];
|
|
4002
4214
|
const packageNameToPath = /* @__PURE__ */ new Map();
|
|
@@ -4060,7 +4272,7 @@ async function scanNodeProjects(rootDir, npmCache, cache, projectScanTimeout) {
|
|
|
4060
4272
|
}
|
|
4061
4273
|
const scannedProjects = await Promise.all(packageJsonFiles.map(async (pjPath) => projectSem.run(async () => {
|
|
4062
4274
|
try {
|
|
4063
|
-
const scanPromise = scanOnePackageJson(pjPath, rootDir, npmCache, cache);
|
|
4275
|
+
const scanPromise = scanOnePackageJson(pjPath, rootDir, npmCache, cache, catalog);
|
|
4064
4276
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
4065
4277
|
if (result.ok) {
|
|
4066
4278
|
return result.value;
|
|
@@ -4106,21 +4318,26 @@ async function scanNodeProjects(rootDir, npmCache, cache, projectScanTimeout) {
|
|
|
4106
4318
|
}
|
|
4107
4319
|
return results;
|
|
4108
4320
|
}
|
|
4109
|
-
async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache) {
|
|
4321
|
+
async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache, catalog) {
|
|
4110
4322
|
const pj = cache ? await cache.readJsonFile(packageJsonPath) : await readJsonFile(packageJsonPath);
|
|
4111
4323
|
const absProjectPath = path3.dirname(packageJsonPath);
|
|
4112
4324
|
const projectPath = path3.relative(rootDir, absProjectPath) || ".";
|
|
4113
4325
|
const nodeEngine = pj.engines?.node ?? void 0;
|
|
4114
4326
|
let runtimeLatest;
|
|
4115
4327
|
let runtimeMajorsBehind;
|
|
4328
|
+
let runtimeEol;
|
|
4329
|
+
let runtimeEolDate;
|
|
4116
4330
|
if (nodeEngine) {
|
|
4117
|
-
const
|
|
4331
|
+
const latest = latestLts(catalog, "nodejs");
|
|
4118
4332
|
const parsed = semver2.minVersion(nodeEngine);
|
|
4119
|
-
if (parsed) {
|
|
4333
|
+
if (latest && parsed) {
|
|
4120
4334
|
const currentMajor = semver2.major(parsed);
|
|
4121
|
-
runtimeLatest = `${
|
|
4122
|
-
runtimeMajorsBehind = Math.max(0,
|
|
4335
|
+
runtimeLatest = `${latest.major}.0.0`;
|
|
4336
|
+
runtimeMajorsBehind = Math.max(0, latest.major - currentMajor);
|
|
4123
4337
|
}
|
|
4338
|
+
runtimeEol = runtimeEolStatus(catalog, "node", nodeEngine);
|
|
4339
|
+
const cycle = extractCycle("node", nodeEngine);
|
|
4340
|
+
if (cycle) runtimeEolDate = eolDate(catalog, "nodejs", cycle);
|
|
4124
4341
|
}
|
|
4125
4342
|
const sections = [
|
|
4126
4343
|
{ name: "dependencies", deps: pj.dependencies },
|
|
@@ -4147,15 +4364,15 @@ async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache) {
|
|
|
4147
4364
|
const resolved = await Promise.all(metaPromises);
|
|
4148
4365
|
for (const { pkg: pkg2, section, spec, meta } of resolved) {
|
|
4149
4366
|
const resolvedVersion = meta.stableVersions.length > 0 ? semver2.maxSatisfying(meta.stableVersions, spec) ?? null : null;
|
|
4150
|
-
const
|
|
4367
|
+
const latestStable2 = meta.latestStableOverall;
|
|
4151
4368
|
let majorsBehind = null;
|
|
4152
4369
|
let drift = "unknown";
|
|
4153
|
-
if (resolvedVersion &&
|
|
4370
|
+
if (resolvedVersion && latestStable2) {
|
|
4154
4371
|
const currentMajor = semver2.major(resolvedVersion);
|
|
4155
|
-
const latestMajor = semver2.major(
|
|
4372
|
+
const latestMajor = semver2.major(latestStable2);
|
|
4156
4373
|
majorsBehind = latestMajor - currentMajor;
|
|
4157
4374
|
if (majorsBehind === 0) {
|
|
4158
|
-
drift = semver2.eq(resolvedVersion,
|
|
4375
|
+
drift = semver2.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
4159
4376
|
} else {
|
|
4160
4377
|
drift = "major-behind";
|
|
4161
4378
|
}
|
|
@@ -4165,14 +4382,14 @@ async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache) {
|
|
|
4165
4382
|
} else {
|
|
4166
4383
|
buckets.unknown++;
|
|
4167
4384
|
}
|
|
4168
|
-
const ageDays = ageDaysBetween(resolvedVersion,
|
|
4385
|
+
const ageDays = ageDaysBetween(resolvedVersion, latestStable2, meta.releaseDates);
|
|
4169
4386
|
const libyears = daysToLibyears(ageDays);
|
|
4170
4387
|
dependencies.push({
|
|
4171
4388
|
package: pkg2,
|
|
4172
4389
|
section,
|
|
4173
4390
|
currentSpec: spec,
|
|
4174
4391
|
resolvedVersion,
|
|
4175
|
-
latestStable,
|
|
4392
|
+
latestStable: latestStable2,
|
|
4176
4393
|
majorsBehind,
|
|
4177
4394
|
drift,
|
|
4178
4395
|
license: buildDependencyLicense(meta.license, "registry"),
|
|
@@ -4183,7 +4400,7 @@ async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache) {
|
|
|
4183
4400
|
frameworks.push({
|
|
4184
4401
|
name: KNOWN_FRAMEWORKS[pkg2],
|
|
4185
4402
|
currentVersion: resolvedVersion,
|
|
4186
|
-
latestVersion:
|
|
4403
|
+
latestVersion: latestStable2,
|
|
4187
4404
|
majorsBehind
|
|
4188
4405
|
});
|
|
4189
4406
|
}
|
|
@@ -4223,6 +4440,8 @@ async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache) {
|
|
|
4223
4440
|
runtime: nodeEngine,
|
|
4224
4441
|
runtimeLatest,
|
|
4225
4442
|
runtimeMajorsBehind,
|
|
4443
|
+
runtimeEol,
|
|
4444
|
+
runtimeEolDate,
|
|
4226
4445
|
frameworks,
|
|
4227
4446
|
dependencies,
|
|
4228
4447
|
dependencyAgeBuckets: buckets,
|
|
@@ -4447,7 +4666,6 @@ var KNOWN_DOTNET_FRAMEWORKS = {
|
|
|
4447
4666
|
// ── Real-time ──
|
|
4448
4667
|
"Microsoft.AspNetCore.SignalR.Client": "SignalR Client"
|
|
4449
4668
|
};
|
|
4450
|
-
var LATEST_DOTNET_MAJOR = 9;
|
|
4451
4669
|
function normalizePath(p) {
|
|
4452
4670
|
return p.replace(/\\/g, "/");
|
|
4453
4671
|
}
|
|
@@ -4511,7 +4729,7 @@ function parseDotnetProjectFile(xml, filePath) {
|
|
|
4511
4729
|
projectName: stripDotnetProjectExtension(filePath)
|
|
4512
4730
|
};
|
|
4513
4731
|
}
|
|
4514
|
-
async function scanDotnetProjects(rootDir, nugetCache, cache, projectScanTimeout) {
|
|
4732
|
+
async function scanDotnetProjects(rootDir, nugetCache, cache, projectScanTimeout, catalog = BUNDLED_RUNTIME_CATALOG) {
|
|
4515
4733
|
const projectFiles = cache ? await cache.findFiles(rootDir, isDotnetProjectFile) : await findFiles(rootDir, isDotnetProjectFile);
|
|
4516
4734
|
const slnFiles = cache ? await cache.findSolutionFiles(rootDir) : await findSolutionFiles(rootDir);
|
|
4517
4735
|
const slnProjectPaths = /* @__PURE__ */ new Set();
|
|
@@ -4535,7 +4753,7 @@ async function scanDotnetProjects(rootDir, nugetCache, cache, projectScanTimeout
|
|
|
4535
4753
|
const STUCK_TIMEOUT_MS = projectScanTimeout ?? cache?.projectScanTimeout ?? 18e4;
|
|
4536
4754
|
for (const csprojPath of allCsprojFiles) {
|
|
4537
4755
|
try {
|
|
4538
|
-
const scanPromise = scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache);
|
|
4756
|
+
const scanPromise = scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache, catalog);
|
|
4539
4757
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
4540
4758
|
if (result.ok) {
|
|
4541
4759
|
results.push(result.value);
|
|
@@ -4556,18 +4774,24 @@ async function scanDotnetProjects(rootDir, nugetCache, cache, projectScanTimeout
|
|
|
4556
4774
|
}
|
|
4557
4775
|
return results;
|
|
4558
4776
|
}
|
|
4559
|
-
async function scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache) {
|
|
4777
|
+
async function scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache, catalog) {
|
|
4560
4778
|
const xml = cache ? await cache.readTextFile(csprojPath) : await readTextFile(csprojPath);
|
|
4561
4779
|
const data = parseDotnetProjectFile(xml, csprojPath);
|
|
4562
4780
|
const csprojDir = path4.dirname(csprojPath);
|
|
4563
4781
|
const primaryTfm = data.targetFrameworks[0];
|
|
4782
|
+
const dotnetLatest = latestStable(catalog, "dotnet")?.major;
|
|
4564
4783
|
let runtimeMajorsBehind;
|
|
4784
|
+
let runtimeEol;
|
|
4785
|
+
let runtimeEolDate;
|
|
4565
4786
|
let targetFramework = primaryTfm;
|
|
4566
4787
|
if (primaryTfm) {
|
|
4567
4788
|
const major11 = parseTfmMajor(primaryTfm);
|
|
4568
|
-
if (major11 !== null) {
|
|
4569
|
-
runtimeMajorsBehind = Math.max(0,
|
|
4789
|
+
if (major11 !== null && dotnetLatest !== void 0) {
|
|
4790
|
+
runtimeMajorsBehind = Math.max(0, dotnetLatest - major11);
|
|
4570
4791
|
}
|
|
4792
|
+
runtimeEol = runtimeEolStatus(catalog, "dotnet", primaryTfm);
|
|
4793
|
+
const cycle = extractCycle("dotnet", primaryTfm);
|
|
4794
|
+
if (cycle) runtimeEolDate = eolDate(catalog, "dotnet", cycle);
|
|
4571
4795
|
}
|
|
4572
4796
|
const dependencies = [];
|
|
4573
4797
|
const bucketsMut = { current: 0, oneBehind: 0, twoPlusBehind: 0, unknown: 0 };
|
|
@@ -4579,15 +4803,15 @@ async function scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache)
|
|
|
4579
4803
|
const resolved = await Promise.all(metaPromises);
|
|
4580
4804
|
for (const { ref, meta } of resolved) {
|
|
4581
4805
|
const resolvedVersion = semver3.valid(ref.version) ? ref.version : null;
|
|
4582
|
-
const
|
|
4806
|
+
const latestStable2 = meta.latestStableOverall;
|
|
4583
4807
|
let majorsBehind = null;
|
|
4584
4808
|
let drift = "unknown";
|
|
4585
|
-
if (resolvedVersion &&
|
|
4809
|
+
if (resolvedVersion && latestStable2) {
|
|
4586
4810
|
const currentMajor = semver3.major(resolvedVersion);
|
|
4587
|
-
const latestMajor = semver3.major(
|
|
4811
|
+
const latestMajor = semver3.major(latestStable2);
|
|
4588
4812
|
majorsBehind = latestMajor - currentMajor;
|
|
4589
4813
|
if (majorsBehind === 0) {
|
|
4590
|
-
drift = semver3.eq(resolvedVersion,
|
|
4814
|
+
drift = semver3.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
4591
4815
|
} else if (majorsBehind > 0) {
|
|
4592
4816
|
drift = "major-behind";
|
|
4593
4817
|
} else {
|
|
@@ -4604,7 +4828,7 @@ async function scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache)
|
|
|
4604
4828
|
section: "dependencies",
|
|
4605
4829
|
currentSpec: ref.version,
|
|
4606
4830
|
resolvedVersion,
|
|
4607
|
-
latestStable,
|
|
4831
|
+
latestStable: latestStable2,
|
|
4608
4832
|
majorsBehind,
|
|
4609
4833
|
drift
|
|
4610
4834
|
});
|
|
@@ -4664,8 +4888,10 @@ async function scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache)
|
|
|
4664
4888
|
name: data.projectName,
|
|
4665
4889
|
targetFramework,
|
|
4666
4890
|
runtime: primaryTfm,
|
|
4667
|
-
runtimeLatest: `net${
|
|
4891
|
+
runtimeLatest: dotnetLatest !== void 0 ? `net${dotnetLatest}.0` : void 0,
|
|
4668
4892
|
runtimeMajorsBehind,
|
|
4893
|
+
runtimeEol,
|
|
4894
|
+
runtimeEolDate,
|
|
4669
4895
|
frameworks,
|
|
4670
4896
|
dependencies,
|
|
4671
4897
|
dependencyAgeBuckets: buckets,
|
|
@@ -4778,7 +5004,6 @@ var KNOWN_PYTHON_FRAMEWORKS = {
|
|
|
4778
5004
|
"opentelemetry-api": "OpenTelemetry",
|
|
4779
5005
|
"prometheus-client": "prometheus-client"
|
|
4780
5006
|
};
|
|
4781
|
-
var LATEST_PYTHON_MINOR = { major: 3, minor: 13 };
|
|
4782
5007
|
function parseRequirementLine(line) {
|
|
4783
5008
|
const trimmed = line.trim();
|
|
4784
5009
|
if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith("-")) return null;
|
|
@@ -4908,7 +5133,7 @@ var PYTHON_MANIFEST_FILES = /* @__PURE__ */ new Set([
|
|
|
4908
5133
|
"setup.cfg",
|
|
4909
5134
|
"Pipfile"
|
|
4910
5135
|
]);
|
|
4911
|
-
async function scanPythonProjects(rootDir, pypiCache, cache, projectScanTimeout) {
|
|
5136
|
+
async function scanPythonProjects(rootDir, pypiCache, cache, projectScanTimeout, catalog = BUNDLED_RUNTIME_CATALOG) {
|
|
4912
5137
|
const manifestFiles = cache ? await cache.findFiles(rootDir, (name) => PYTHON_MANIFEST_FILES.has(name) || /^requirements.*\.txt$/.test(name)) : await findPythonManifests(rootDir);
|
|
4913
5138
|
const projectDirs = /* @__PURE__ */ new Map();
|
|
4914
5139
|
for (const f of manifestFiles) {
|
|
@@ -4920,7 +5145,7 @@ async function scanPythonProjects(rootDir, pypiCache, cache, projectScanTimeout)
|
|
|
4920
5145
|
const STUCK_TIMEOUT_MS = projectScanTimeout ?? cache?.projectScanTimeout ?? 18e4;
|
|
4921
5146
|
for (const [dir, files] of projectDirs) {
|
|
4922
5147
|
try {
|
|
4923
|
-
const scanPromise = scanOnePythonProject(dir, files, rootDir, pypiCache, cache);
|
|
5148
|
+
const scanPromise = scanOnePythonProject(dir, files, rootDir, pypiCache, cache, catalog);
|
|
4924
5149
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
4925
5150
|
if (result.ok) {
|
|
4926
5151
|
results.push(result.value);
|
|
@@ -4943,7 +5168,7 @@ async function findPythonManifests(rootDir) {
|
|
|
4943
5168
|
const { findFiles: findFiles2 } = await import("./fs-PXXYZATK-EW5LCUA7.js");
|
|
4944
5169
|
return findFiles2(rootDir, (name) => PYTHON_MANIFEST_FILES.has(name) || /^requirements.*\.txt$/.test(name));
|
|
4945
5170
|
}
|
|
4946
|
-
async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cache) {
|
|
5171
|
+
async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cache, catalog) {
|
|
4947
5172
|
const relDir = path5.relative(rootDir, dir) || ".";
|
|
4948
5173
|
let projectName = path5.basename(dir === rootDir ? rootDir : dir);
|
|
4949
5174
|
let pythonVersion;
|
|
@@ -4977,18 +5202,26 @@ async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cach
|
|
|
4977
5202
|
}
|
|
4978
5203
|
let runtimeMajorsBehind;
|
|
4979
5204
|
let runtimeLatest;
|
|
5205
|
+
let runtimeEol;
|
|
5206
|
+
let runtimeEolDate;
|
|
4980
5207
|
if (pythonVersion) {
|
|
4981
5208
|
const verMatch = pythonVersion.match(/(\d+)\.(\d+)/);
|
|
4982
5209
|
if (verMatch) {
|
|
4983
5210
|
const reqMajor = parseInt(verMatch[1], 10);
|
|
4984
5211
|
const reqMinor = parseInt(verMatch[2], 10);
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
5212
|
+
const LATEST_PYTHON_MINOR = latestStable(catalog, "python");
|
|
5213
|
+
if (LATEST_PYTHON_MINOR) {
|
|
5214
|
+
if (reqMajor === LATEST_PYTHON_MINOR.major) {
|
|
5215
|
+
runtimeMajorsBehind = Math.max(0, LATEST_PYTHON_MINOR.minor - reqMinor);
|
|
5216
|
+
} else if (reqMajor < LATEST_PYTHON_MINOR.major) {
|
|
5217
|
+
runtimeMajorsBehind = LATEST_PYTHON_MINOR.minor + (LATEST_PYTHON_MINOR.major - reqMajor) * 10;
|
|
5218
|
+
}
|
|
5219
|
+
runtimeLatest = `${LATEST_PYTHON_MINOR.major}.${LATEST_PYTHON_MINOR.minor}`;
|
|
4989
5220
|
}
|
|
4990
|
-
runtimeLatest = `${LATEST_PYTHON_MINOR.major}.${LATEST_PYTHON_MINOR.minor}`;
|
|
4991
5221
|
}
|
|
5222
|
+
runtimeEol = runtimeEolStatus(catalog, "python", pythonVersion);
|
|
5223
|
+
const cycle = extractCycle("python", pythonVersion);
|
|
5224
|
+
if (cycle) runtimeEolDate = eolDate(catalog, "python", cycle);
|
|
4992
5225
|
}
|
|
4993
5226
|
const dependencies = [];
|
|
4994
5227
|
const frameworks = [];
|
|
@@ -5002,15 +5235,15 @@ async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cach
|
|
|
5002
5235
|
for (const { dep, meta } of resolved) {
|
|
5003
5236
|
const pinnedVersion = extractPinnedVersion(dep.spec);
|
|
5004
5237
|
const resolvedVersion = pinnedVersion ? pep440ToSemver(pinnedVersion) : null;
|
|
5005
|
-
const
|
|
5238
|
+
const latestStable2 = meta.latestStableOverall;
|
|
5006
5239
|
let majorsBehind = null;
|
|
5007
5240
|
let drift = "unknown";
|
|
5008
|
-
if (resolvedVersion &&
|
|
5241
|
+
if (resolvedVersion && latestStable2) {
|
|
5009
5242
|
const currentMajor = semver4.major(resolvedVersion);
|
|
5010
|
-
const latestMajor = semver4.major(
|
|
5243
|
+
const latestMajor = semver4.major(latestStable2);
|
|
5011
5244
|
majorsBehind = latestMajor - currentMajor;
|
|
5012
5245
|
if (majorsBehind === 0) {
|
|
5013
|
-
drift = semver4.eq(resolvedVersion,
|
|
5246
|
+
drift = semver4.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
5014
5247
|
} else if (majorsBehind > 0) {
|
|
5015
5248
|
drift = "major-behind";
|
|
5016
5249
|
} else {
|
|
@@ -5027,7 +5260,7 @@ async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cach
|
|
|
5027
5260
|
section: "dependencies",
|
|
5028
5261
|
currentSpec: dep.spec || "*",
|
|
5029
5262
|
resolvedVersion,
|
|
5030
|
-
latestStable,
|
|
5263
|
+
latestStable: latestStable2,
|
|
5031
5264
|
majorsBehind,
|
|
5032
5265
|
drift
|
|
5033
5266
|
});
|
|
@@ -5035,7 +5268,7 @@ async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cach
|
|
|
5035
5268
|
frameworks.push({
|
|
5036
5269
|
name: KNOWN_PYTHON_FRAMEWORKS[dep.normalisedName],
|
|
5037
5270
|
currentVersion: resolvedVersion,
|
|
5038
|
-
latestVersion:
|
|
5271
|
+
latestVersion: latestStable2,
|
|
5039
5272
|
majorsBehind
|
|
5040
5273
|
});
|
|
5041
5274
|
}
|
|
@@ -5058,6 +5291,8 @@ async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cach
|
|
|
5058
5291
|
runtime: pythonVersion,
|
|
5059
5292
|
runtimeLatest,
|
|
5060
5293
|
runtimeMajorsBehind,
|
|
5294
|
+
runtimeEol,
|
|
5295
|
+
runtimeEolDate,
|
|
5061
5296
|
frameworks,
|
|
5062
5297
|
dependencies,
|
|
5063
5298
|
dependencyAgeBuckets: buckets,
|
|
@@ -5161,7 +5396,6 @@ var KNOWN_JAVA_FRAMEWORKS = {
|
|
|
5161
5396
|
"io.projectreactor:reactor-core": "Project Reactor",
|
|
5162
5397
|
"io.reactivex.rxjava3:rxjava": "RxJava 3"
|
|
5163
5398
|
};
|
|
5164
|
-
var LATEST_JAVA_LTS = 21;
|
|
5165
5399
|
function parsePom(xml, filePath) {
|
|
5166
5400
|
const parsed = parser2.parse(xml);
|
|
5167
5401
|
const project = parsed?.project;
|
|
@@ -5301,7 +5535,7 @@ function mavenToSemver(ver) {
|
|
|
5301
5535
|
return semver5.valid(v);
|
|
5302
5536
|
}
|
|
5303
5537
|
var JAVA_MANIFEST_FILES = /* @__PURE__ */ new Set(["pom.xml", "build.gradle", "build.gradle.kts"]);
|
|
5304
|
-
async function scanJavaProjects(rootDir, mavenCache, cache, projectScanTimeout) {
|
|
5538
|
+
async function scanJavaProjects(rootDir, mavenCache, cache, projectScanTimeout, catalog = BUNDLED_RUNTIME_CATALOG) {
|
|
5305
5539
|
const manifestFiles = cache ? await cache.findFiles(rootDir, (name) => JAVA_MANIFEST_FILES.has(name)) : await findJavaManifests(rootDir);
|
|
5306
5540
|
const projectDirs = /* @__PURE__ */ new Map();
|
|
5307
5541
|
for (const f of manifestFiles) {
|
|
@@ -5313,7 +5547,7 @@ async function scanJavaProjects(rootDir, mavenCache, cache, projectScanTimeout)
|
|
|
5313
5547
|
const STUCK_TIMEOUT_MS = projectScanTimeout ?? cache?.projectScanTimeout ?? 18e4;
|
|
5314
5548
|
for (const [dir, files] of projectDirs) {
|
|
5315
5549
|
try {
|
|
5316
|
-
const scanPromise = scanOneJavaProject(dir, files, rootDir, mavenCache, cache);
|
|
5550
|
+
const scanPromise = scanOneJavaProject(dir, files, rootDir, mavenCache, cache, catalog);
|
|
5317
5551
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
5318
5552
|
if (result.ok) {
|
|
5319
5553
|
results.push(result.value);
|
|
@@ -5340,7 +5574,7 @@ async function findJavaManifests(rootDir) {
|
|
|
5340
5574
|
const { findFiles: findFiles2 } = await import("./fs-PXXYZATK-EW5LCUA7.js");
|
|
5341
5575
|
return findFiles2(rootDir, (name) => JAVA_MANIFEST_FILES.has(name));
|
|
5342
5576
|
}
|
|
5343
|
-
async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache) {
|
|
5577
|
+
async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache, catalog) {
|
|
5344
5578
|
const relDir = path6.relative(rootDir, dir) || ".";
|
|
5345
5579
|
let projectName = path6.basename(dir === rootDir ? rootDir : dir);
|
|
5346
5580
|
let javaVersion;
|
|
@@ -5379,14 +5613,19 @@ async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache
|
|
|
5379
5613
|
}
|
|
5380
5614
|
}
|
|
5381
5615
|
let runtimeMajorsBehind;
|
|
5382
|
-
let
|
|
5616
|
+
let runtimeEol;
|
|
5617
|
+
let runtimeEolDate;
|
|
5618
|
+
const javaLts = latestLts(catalog, "java")?.major;
|
|
5619
|
+
const runtimeLatest = javaLts !== void 0 ? String(javaLts) : void 0;
|
|
5383
5620
|
if (javaVersion) {
|
|
5384
5621
|
const jvMatch = javaVersion.match(/^(1\.)?(\d+)/);
|
|
5385
5622
|
if (jvMatch) {
|
|
5386
5623
|
const major11 = jvMatch[1] ? parseInt(jvMatch[2], 10) : parseInt(jvMatch[2], 10);
|
|
5387
|
-
runtimeMajorsBehind = Math.max(0,
|
|
5388
|
-
runtimeLatest = String(LATEST_JAVA_LTS);
|
|
5624
|
+
if (javaLts !== void 0) runtimeMajorsBehind = Math.max(0, javaLts - major11);
|
|
5389
5625
|
}
|
|
5626
|
+
runtimeEol = runtimeEolStatus(catalog, "java", javaVersion);
|
|
5627
|
+
const cycle = extractCycle("java", javaVersion);
|
|
5628
|
+
if (cycle) runtimeEolDate = eolDate(catalog, "java", cycle);
|
|
5390
5629
|
}
|
|
5391
5630
|
const dependencies = [];
|
|
5392
5631
|
const frameworks = [];
|
|
@@ -5399,15 +5638,15 @@ async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache
|
|
|
5399
5638
|
const resolved = await Promise.all(metaPromises);
|
|
5400
5639
|
for (const { key, dep, meta } of resolved) {
|
|
5401
5640
|
const resolvedVersion = mavenToSemver(dep.version);
|
|
5402
|
-
const
|
|
5641
|
+
const latestStable2 = meta.latestStableOverall;
|
|
5403
5642
|
let majorsBehind = null;
|
|
5404
5643
|
let drift = "unknown";
|
|
5405
|
-
if (resolvedVersion &&
|
|
5644
|
+
if (resolvedVersion && latestStable2) {
|
|
5406
5645
|
const currentMajor = semver5.major(resolvedVersion);
|
|
5407
|
-
const latestMajor = semver5.major(
|
|
5646
|
+
const latestMajor = semver5.major(latestStable2);
|
|
5408
5647
|
majorsBehind = latestMajor - currentMajor;
|
|
5409
5648
|
if (majorsBehind === 0) {
|
|
5410
|
-
drift = semver5.eq(resolvedVersion,
|
|
5649
|
+
drift = semver5.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
5411
5650
|
} else if (majorsBehind > 0) {
|
|
5412
5651
|
drift = "major-behind";
|
|
5413
5652
|
} else {
|
|
@@ -5424,7 +5663,7 @@ async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache
|
|
|
5424
5663
|
section: "dependencies",
|
|
5425
5664
|
currentSpec: dep.version,
|
|
5426
5665
|
resolvedVersion,
|
|
5427
|
-
latestStable,
|
|
5666
|
+
latestStable: latestStable2,
|
|
5428
5667
|
majorsBehind,
|
|
5429
5668
|
drift
|
|
5430
5669
|
});
|
|
@@ -5432,7 +5671,7 @@ async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache
|
|
|
5432
5671
|
frameworks.push({
|
|
5433
5672
|
name: KNOWN_JAVA_FRAMEWORKS[key],
|
|
5434
5673
|
currentVersion: resolvedVersion,
|
|
5435
|
-
latestVersion:
|
|
5674
|
+
latestVersion: latestStable2,
|
|
5436
5675
|
majorsBehind
|
|
5437
5676
|
});
|
|
5438
5677
|
}
|
|
@@ -5453,8 +5692,10 @@ async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache
|
|
|
5453
5692
|
path: relDir,
|
|
5454
5693
|
name: projectName,
|
|
5455
5694
|
runtime: javaVersion ? `Java ${javaVersion}` : void 0,
|
|
5456
|
-
runtimeLatest
|
|
5695
|
+
runtimeLatest,
|
|
5457
5696
|
runtimeMajorsBehind,
|
|
5697
|
+
runtimeEol,
|
|
5698
|
+
runtimeEolDate,
|
|
5458
5699
|
targetFramework: javaVersion ? `Java ${javaVersion}` : void 0,
|
|
5459
5700
|
frameworks,
|
|
5460
5701
|
dependencies,
|
|
@@ -5580,7 +5821,6 @@ var KNOWN_RUBY_FRAMEWORKS = {
|
|
|
5580
5821
|
"dotenv": "dotenv",
|
|
5581
5822
|
"figaro": "Figaro"
|
|
5582
5823
|
};
|
|
5583
|
-
var LATEST_RUBY_MINOR = { major: 3, minor: 4 };
|
|
5584
5824
|
function parseGemfileLine(line) {
|
|
5585
5825
|
const trimmed = line.trim();
|
|
5586
5826
|
if (!trimmed || trimmed.startsWith("#")) return null;
|
|
@@ -5670,7 +5910,7 @@ var RUBY_MANIFEST_FILES = /* @__PURE__ */ new Set([
|
|
|
5670
5910
|
function isGemspec(name) {
|
|
5671
5911
|
return name.endsWith(".gemspec");
|
|
5672
5912
|
}
|
|
5673
|
-
async function scanRubyProjects(rootDir, rubygemsCache, cache, projectScanTimeout) {
|
|
5913
|
+
async function scanRubyProjects(rootDir, rubygemsCache, cache, projectScanTimeout, catalog = BUNDLED_RUNTIME_CATALOG) {
|
|
5674
5914
|
const manifestFiles = cache ? await cache.findFiles(rootDir, (name) => RUBY_MANIFEST_FILES.has(name) || isGemspec(name)) : await findRubyManifests(rootDir);
|
|
5675
5915
|
const projectDirs = /* @__PURE__ */ new Map();
|
|
5676
5916
|
for (const f of manifestFiles) {
|
|
@@ -5682,7 +5922,7 @@ async function scanRubyProjects(rootDir, rubygemsCache, cache, projectScanTimeou
|
|
|
5682
5922
|
const STUCK_TIMEOUT_MS = projectScanTimeout ?? cache?.projectScanTimeout ?? 18e4;
|
|
5683
5923
|
for (const [dir, files] of projectDirs) {
|
|
5684
5924
|
try {
|
|
5685
|
-
const scanPromise = scanOneRubyProject(dir, files, rootDir, rubygemsCache, cache);
|
|
5925
|
+
const scanPromise = scanOneRubyProject(dir, files, rootDir, rubygemsCache, cache, catalog);
|
|
5686
5926
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
5687
5927
|
if (result.ok) {
|
|
5688
5928
|
results.push(result.value);
|
|
@@ -5705,7 +5945,7 @@ async function findRubyManifests(rootDir) {
|
|
|
5705
5945
|
const { findFiles: findFiles2 } = await import("./fs-PXXYZATK-EW5LCUA7.js");
|
|
5706
5946
|
return findFiles2(rootDir, (name) => RUBY_MANIFEST_FILES.has(name) || isGemspec(name));
|
|
5707
5947
|
}
|
|
5708
|
-
async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, cache) {
|
|
5948
|
+
async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, cache, catalog) {
|
|
5709
5949
|
const relDir = path7.relative(rootDir, dir) || ".";
|
|
5710
5950
|
let projectName = path7.basename(dir === rootDir ? rootDir : dir);
|
|
5711
5951
|
let rubyVersion;
|
|
@@ -5729,18 +5969,26 @@ async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, ca
|
|
|
5729
5969
|
}
|
|
5730
5970
|
let runtimeMajorsBehind;
|
|
5731
5971
|
let runtimeLatest;
|
|
5972
|
+
let runtimeEol;
|
|
5973
|
+
let runtimeEolDate;
|
|
5732
5974
|
if (rubyVersion) {
|
|
5733
5975
|
const verMatch = rubyVersion.match(/(\d+)\.(\d+)/);
|
|
5734
5976
|
if (verMatch) {
|
|
5735
5977
|
const reqMajor = parseInt(verMatch[1], 10);
|
|
5736
5978
|
const reqMinor = parseInt(verMatch[2], 10);
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5979
|
+
const LATEST_RUBY_MINOR = latestStable(catalog, "ruby");
|
|
5980
|
+
if (LATEST_RUBY_MINOR) {
|
|
5981
|
+
if (reqMajor === LATEST_RUBY_MINOR.major) {
|
|
5982
|
+
runtimeMajorsBehind = Math.max(0, LATEST_RUBY_MINOR.minor - reqMinor);
|
|
5983
|
+
} else if (reqMajor < LATEST_RUBY_MINOR.major) {
|
|
5984
|
+
runtimeMajorsBehind = LATEST_RUBY_MINOR.minor + (LATEST_RUBY_MINOR.major - reqMajor) * 10;
|
|
5985
|
+
}
|
|
5986
|
+
runtimeLatest = `${LATEST_RUBY_MINOR.major}.${LATEST_RUBY_MINOR.minor}`;
|
|
5741
5987
|
}
|
|
5742
|
-
runtimeLatest = `${LATEST_RUBY_MINOR.major}.${LATEST_RUBY_MINOR.minor}`;
|
|
5743
5988
|
}
|
|
5989
|
+
runtimeEol = runtimeEolStatus(catalog, "ruby", rubyVersion);
|
|
5990
|
+
const cycle = extractCycle("ruby", rubyVersion);
|
|
5991
|
+
if (cycle) runtimeEolDate = eolDate(catalog, "ruby", cycle);
|
|
5744
5992
|
}
|
|
5745
5993
|
const dependencies = [];
|
|
5746
5994
|
const frameworks = [];
|
|
@@ -5754,15 +6002,15 @@ async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, ca
|
|
|
5754
6002
|
for (const { dep, meta } of resolved) {
|
|
5755
6003
|
const rawVersion = extractGemVersion(dep.spec);
|
|
5756
6004
|
const resolvedVersion = rawVersion ? rubyVersionToSemver(rawVersion) : null;
|
|
5757
|
-
const
|
|
6005
|
+
const latestStable2 = meta.latestStableOverall;
|
|
5758
6006
|
let majorsBehind = null;
|
|
5759
6007
|
let drift = "unknown";
|
|
5760
|
-
if (resolvedVersion &&
|
|
6008
|
+
if (resolvedVersion && latestStable2) {
|
|
5761
6009
|
const currentMajor = semver6.major(resolvedVersion);
|
|
5762
|
-
const latestMajor = semver6.major(
|
|
6010
|
+
const latestMajor = semver6.major(latestStable2);
|
|
5763
6011
|
majorsBehind = latestMajor - currentMajor;
|
|
5764
6012
|
if (majorsBehind === 0) {
|
|
5765
|
-
drift = semver6.eq(resolvedVersion,
|
|
6013
|
+
drift = semver6.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
5766
6014
|
} else if (majorsBehind > 0) {
|
|
5767
6015
|
drift = "major-behind";
|
|
5768
6016
|
} else {
|
|
@@ -5780,7 +6028,7 @@ async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, ca
|
|
|
5780
6028
|
section,
|
|
5781
6029
|
currentSpec: dep.spec,
|
|
5782
6030
|
resolvedVersion,
|
|
5783
|
-
latestStable,
|
|
6031
|
+
latestStable: latestStable2,
|
|
5784
6032
|
majorsBehind,
|
|
5785
6033
|
drift
|
|
5786
6034
|
});
|
|
@@ -5788,7 +6036,7 @@ async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, ca
|
|
|
5788
6036
|
frameworks.push({
|
|
5789
6037
|
name: KNOWN_RUBY_FRAMEWORKS[dep.name],
|
|
5790
6038
|
currentVersion: resolvedVersion,
|
|
5791
|
-
latestVersion:
|
|
6039
|
+
latestVersion: latestStable2,
|
|
5792
6040
|
majorsBehind
|
|
5793
6041
|
});
|
|
5794
6042
|
}
|
|
@@ -5811,6 +6059,8 @@ async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, ca
|
|
|
5811
6059
|
runtime: rubyVersion,
|
|
5812
6060
|
runtimeLatest,
|
|
5813
6061
|
runtimeMajorsBehind,
|
|
6062
|
+
runtimeEol,
|
|
6063
|
+
runtimeEolDate,
|
|
5814
6064
|
frameworks,
|
|
5815
6065
|
dependencies,
|
|
5816
6066
|
dependencyAgeBuckets: buckets,
|
|
@@ -5968,15 +6218,15 @@ async function scanOneSwiftProject(dir, manifestFile, rootDir, swiftCache, cache
|
|
|
5968
6218
|
for (const { dep, meta } of resolved) {
|
|
5969
6219
|
const resolvedVersionStr = resolvedVersions.get(dep.name.toLowerCase()) ?? (dep.type === "exact" ? dep.version : null);
|
|
5970
6220
|
const resolvedVersion = resolvedVersionStr ? semver7.valid(semver7.clean(resolvedVersionStr)) : null;
|
|
5971
|
-
const
|
|
6221
|
+
const latestStable2 = meta.latestStableOverall;
|
|
5972
6222
|
let majorsBehind = null;
|
|
5973
6223
|
let drift = "unknown";
|
|
5974
|
-
if (resolvedVersion &&
|
|
6224
|
+
if (resolvedVersion && latestStable2) {
|
|
5975
6225
|
const currentMajor = semver7.major(resolvedVersion);
|
|
5976
|
-
const latestMajor = semver7.major(
|
|
6226
|
+
const latestMajor = semver7.major(latestStable2);
|
|
5977
6227
|
majorsBehind = latestMajor - currentMajor;
|
|
5978
6228
|
if (majorsBehind === 0) {
|
|
5979
|
-
drift = semver7.eq(resolvedVersion,
|
|
6229
|
+
drift = semver7.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
5980
6230
|
} else if (majorsBehind > 0) {
|
|
5981
6231
|
drift = "major-behind";
|
|
5982
6232
|
} else {
|
|
@@ -5993,7 +6243,7 @@ async function scanOneSwiftProject(dir, manifestFile, rootDir, swiftCache, cache
|
|
|
5993
6243
|
section: "dependencies",
|
|
5994
6244
|
currentSpec: dep.version,
|
|
5995
6245
|
resolvedVersion,
|
|
5996
|
-
latestStable,
|
|
6246
|
+
latestStable: latestStable2,
|
|
5997
6247
|
majorsBehind,
|
|
5998
6248
|
drift
|
|
5999
6249
|
});
|
|
@@ -6002,7 +6252,7 @@ async function scanOneSwiftProject(dir, manifestFile, rootDir, swiftCache, cache
|
|
|
6002
6252
|
frameworks.push({
|
|
6003
6253
|
name: KNOWN_SWIFT_FRAMEWORKS[lowerName],
|
|
6004
6254
|
currentVersion: resolvedVersion,
|
|
6005
|
-
latestVersion:
|
|
6255
|
+
latestVersion: latestStable2,
|
|
6006
6256
|
majorsBehind
|
|
6007
6257
|
});
|
|
6008
6258
|
}
|
|
@@ -6089,7 +6339,6 @@ var KNOWN_GO_FRAMEWORKS = {
|
|
|
6089
6339
|
"github.com/spf13/cast": "Cast",
|
|
6090
6340
|
"github.com/pkg/errors": "pkg/errors"
|
|
6091
6341
|
};
|
|
6092
|
-
var LATEST_GO_MINOR = { major: 1, minor: 23 };
|
|
6093
6342
|
function parseGoMod(content) {
|
|
6094
6343
|
const deps = [];
|
|
6095
6344
|
let goVersion;
|
|
@@ -6136,14 +6385,14 @@ function parseGoMod(content) {
|
|
|
6136
6385
|
var GO_MANIFEST_FILES = /* @__PURE__ */ new Set([
|
|
6137
6386
|
"go.mod"
|
|
6138
6387
|
]);
|
|
6139
|
-
async function scanGoProjects(rootDir, goCache, cache, projectScanTimeout) {
|
|
6388
|
+
async function scanGoProjects(rootDir, goCache, cache, projectScanTimeout, catalog = BUNDLED_RUNTIME_CATALOG) {
|
|
6140
6389
|
const manifestFiles = cache ? await cache.findFiles(rootDir, (name) => GO_MANIFEST_FILES.has(name)) : await findGoManifests(rootDir);
|
|
6141
6390
|
const results = [];
|
|
6142
6391
|
const STUCK_TIMEOUT_MS = projectScanTimeout ?? cache?.projectScanTimeout ?? 18e4;
|
|
6143
6392
|
for (const manifestFile of manifestFiles) {
|
|
6144
6393
|
const dir = path9.dirname(manifestFile);
|
|
6145
6394
|
try {
|
|
6146
|
-
const scanPromise = scanOneGoProject(dir, manifestFile, rootDir, goCache, cache);
|
|
6395
|
+
const scanPromise = scanOneGoProject(dir, manifestFile, rootDir, goCache, cache, catalog);
|
|
6147
6396
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
6148
6397
|
if (result.ok) {
|
|
6149
6398
|
results.push(result.value);
|
|
@@ -6166,7 +6415,7 @@ async function findGoManifests(rootDir) {
|
|
|
6166
6415
|
const { findFiles: findFiles2 } = await import("./fs-PXXYZATK-EW5LCUA7.js");
|
|
6167
6416
|
return findFiles2(rootDir, (name) => GO_MANIFEST_FILES.has(name));
|
|
6168
6417
|
}
|
|
6169
|
-
async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache) {
|
|
6418
|
+
async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache, catalog) {
|
|
6170
6419
|
const relDir = path9.relative(rootDir, dir) || ".";
|
|
6171
6420
|
const projectName = path9.basename(dir === rootDir ? rootDir : dir);
|
|
6172
6421
|
const content = cache ? await cache.readTextFile(manifestFile) : await readTextFile(manifestFile);
|
|
@@ -6174,18 +6423,26 @@ async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache) {
|
|
|
6174
6423
|
const directDeps = allDeps.filter((d) => !d.indirect);
|
|
6175
6424
|
let runtimeMajorsBehind;
|
|
6176
6425
|
let runtimeLatest;
|
|
6426
|
+
let runtimeEol;
|
|
6427
|
+
let runtimeEolDate;
|
|
6177
6428
|
if (goVersion) {
|
|
6178
6429
|
const verMatch = goVersion.match(/(\d+)\.(\d+)/);
|
|
6179
6430
|
if (verMatch) {
|
|
6180
6431
|
const reqMajor = parseInt(verMatch[1], 10);
|
|
6181
6432
|
const reqMinor = parseInt(verMatch[2], 10);
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6433
|
+
const LATEST_GO_MINOR = latestStable(catalog, "go");
|
|
6434
|
+
if (LATEST_GO_MINOR) {
|
|
6435
|
+
if (reqMajor === LATEST_GO_MINOR.major) {
|
|
6436
|
+
runtimeMajorsBehind = Math.max(0, LATEST_GO_MINOR.minor - reqMinor);
|
|
6437
|
+
} else if (reqMajor < LATEST_GO_MINOR.major) {
|
|
6438
|
+
runtimeMajorsBehind = LATEST_GO_MINOR.minor + (LATEST_GO_MINOR.major - reqMajor) * 100;
|
|
6439
|
+
}
|
|
6440
|
+
runtimeLatest = `${LATEST_GO_MINOR.major}.${LATEST_GO_MINOR.minor}`;
|
|
6186
6441
|
}
|
|
6187
|
-
runtimeLatest = `${LATEST_GO_MINOR.major}.${LATEST_GO_MINOR.minor}`;
|
|
6188
6442
|
}
|
|
6443
|
+
runtimeEol = runtimeEolStatus(catalog, "go", goVersion);
|
|
6444
|
+
const cycle = extractCycle("go", goVersion);
|
|
6445
|
+
if (cycle) runtimeEolDate = eolDate(catalog, "go", cycle);
|
|
6189
6446
|
}
|
|
6190
6447
|
const dependencies = [];
|
|
6191
6448
|
const frameworks = [];
|
|
@@ -6197,15 +6454,15 @@ async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache) {
|
|
|
6197
6454
|
const resolved = await Promise.all(metaPromises);
|
|
6198
6455
|
for (const { dep, meta } of resolved) {
|
|
6199
6456
|
const resolvedVersion = semver8.valid(semver8.clean(dep.version));
|
|
6200
|
-
const
|
|
6457
|
+
const latestStable2 = meta.latestStableOverall;
|
|
6201
6458
|
let majorsBehind = null;
|
|
6202
6459
|
let drift = "unknown";
|
|
6203
|
-
if (resolvedVersion &&
|
|
6460
|
+
if (resolvedVersion && latestStable2) {
|
|
6204
6461
|
const currentMajor = semver8.major(resolvedVersion);
|
|
6205
|
-
const latestMajor = semver8.major(
|
|
6462
|
+
const latestMajor = semver8.major(latestStable2);
|
|
6206
6463
|
majorsBehind = latestMajor - currentMajor;
|
|
6207
6464
|
if (majorsBehind === 0) {
|
|
6208
|
-
drift = semver8.eq(resolvedVersion,
|
|
6465
|
+
drift = semver8.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
6209
6466
|
} else if (majorsBehind > 0) {
|
|
6210
6467
|
drift = "major-behind";
|
|
6211
6468
|
} else {
|
|
@@ -6222,7 +6479,7 @@ async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache) {
|
|
|
6222
6479
|
section: "dependencies",
|
|
6223
6480
|
currentSpec: dep.version,
|
|
6224
6481
|
resolvedVersion,
|
|
6225
|
-
latestStable,
|
|
6482
|
+
latestStable: latestStable2,
|
|
6226
6483
|
majorsBehind,
|
|
6227
6484
|
drift
|
|
6228
6485
|
});
|
|
@@ -6230,7 +6487,7 @@ async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache) {
|
|
|
6230
6487
|
frameworks.push({
|
|
6231
6488
|
name: KNOWN_GO_FRAMEWORKS[dep.path],
|
|
6232
6489
|
currentVersion: resolvedVersion,
|
|
6233
|
-
latestVersion:
|
|
6490
|
+
latestVersion: latestStable2,
|
|
6234
6491
|
majorsBehind
|
|
6235
6492
|
});
|
|
6236
6493
|
}
|
|
@@ -6253,6 +6510,8 @@ async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache) {
|
|
|
6253
6510
|
runtime: goVersion,
|
|
6254
6511
|
runtimeLatest,
|
|
6255
6512
|
runtimeMajorsBehind,
|
|
6513
|
+
runtimeEol,
|
|
6514
|
+
runtimeEolDate,
|
|
6256
6515
|
frameworks,
|
|
6257
6516
|
dependencies,
|
|
6258
6517
|
dependencyAgeBuckets: buckets,
|
|
@@ -6425,15 +6684,15 @@ async function scanOneRustProject(dir, manifestFile, rootDir, cargoCache, cache)
|
|
|
6425
6684
|
const resolved = await Promise.all(metaPromises);
|
|
6426
6685
|
for (const { dep, meta } of resolved) {
|
|
6427
6686
|
const resolvedVersion = semver9.valid(semver9.coerce(dep.version));
|
|
6428
|
-
const
|
|
6687
|
+
const latestStable2 = meta.latestStableOverall;
|
|
6429
6688
|
let majorsBehind = null;
|
|
6430
6689
|
let drift = "unknown";
|
|
6431
|
-
if (resolvedVersion &&
|
|
6690
|
+
if (resolvedVersion && latestStable2) {
|
|
6432
6691
|
const currentMajor = semver9.major(resolvedVersion);
|
|
6433
|
-
const latestMajor = semver9.major(
|
|
6692
|
+
const latestMajor = semver9.major(latestStable2);
|
|
6434
6693
|
majorsBehind = latestMajor - currentMajor;
|
|
6435
6694
|
if (majorsBehind === 0) {
|
|
6436
|
-
drift = semver9.eq(resolvedVersion,
|
|
6695
|
+
drift = semver9.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
6437
6696
|
} else if (majorsBehind > 0) {
|
|
6438
6697
|
drift = "major-behind";
|
|
6439
6698
|
} else {
|
|
@@ -6451,7 +6710,7 @@ async function scanOneRustProject(dir, manifestFile, rootDir, cargoCache, cache)
|
|
|
6451
6710
|
section,
|
|
6452
6711
|
currentSpec: dep.version,
|
|
6453
6712
|
resolvedVersion,
|
|
6454
|
-
latestStable,
|
|
6713
|
+
latestStable: latestStable2,
|
|
6455
6714
|
majorsBehind,
|
|
6456
6715
|
drift
|
|
6457
6716
|
});
|
|
@@ -6459,7 +6718,7 @@ async function scanOneRustProject(dir, manifestFile, rootDir, cargoCache, cache)
|
|
|
6459
6718
|
frameworks.push({
|
|
6460
6719
|
name: KNOWN_RUST_FRAMEWORKS[dep.name],
|
|
6461
6720
|
currentVersion: resolvedVersion,
|
|
6462
|
-
latestVersion:
|
|
6721
|
+
latestVersion: latestStable2,
|
|
6463
6722
|
majorsBehind
|
|
6464
6723
|
});
|
|
6465
6724
|
}
|
|
@@ -6665,15 +6924,15 @@ async function scanOnePhpProject(dir, manifestFile, rootDir, composerCache, cach
|
|
|
6665
6924
|
for (const { dep, meta } of resolved) {
|
|
6666
6925
|
const resolvedVersionStr = resolvedVersions.get(dep.name);
|
|
6667
6926
|
const resolvedVersion = resolvedVersionStr ? semver10.valid(semver10.clean(resolvedVersionStr)) : null;
|
|
6668
|
-
const
|
|
6927
|
+
const latestStable2 = meta.latestStableOverall;
|
|
6669
6928
|
let majorsBehind = null;
|
|
6670
6929
|
let drift = "unknown";
|
|
6671
|
-
if (resolvedVersion &&
|
|
6930
|
+
if (resolvedVersion && latestStable2) {
|
|
6672
6931
|
const currentMajor = semver10.major(resolvedVersion);
|
|
6673
|
-
const latestMajor = semver10.major(
|
|
6932
|
+
const latestMajor = semver10.major(latestStable2);
|
|
6674
6933
|
majorsBehind = latestMajor - currentMajor;
|
|
6675
6934
|
if (majorsBehind === 0) {
|
|
6676
|
-
drift = semver10.eq(resolvedVersion,
|
|
6935
|
+
drift = semver10.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
6677
6936
|
} else if (majorsBehind > 0) {
|
|
6678
6937
|
drift = "major-behind";
|
|
6679
6938
|
} else {
|
|
@@ -6691,7 +6950,7 @@ async function scanOnePhpProject(dir, manifestFile, rootDir, composerCache, cach
|
|
|
6691
6950
|
section,
|
|
6692
6951
|
currentSpec: dep.version,
|
|
6693
6952
|
resolvedVersion,
|
|
6694
|
-
latestStable,
|
|
6953
|
+
latestStable: latestStable2,
|
|
6695
6954
|
majorsBehind,
|
|
6696
6955
|
drift
|
|
6697
6956
|
});
|
|
@@ -6699,7 +6958,7 @@ async function scanOnePhpProject(dir, manifestFile, rootDir, composerCache, cach
|
|
|
6699
6958
|
frameworks.push({
|
|
6700
6959
|
name: KNOWN_PHP_FRAMEWORKS[dep.name],
|
|
6701
6960
|
currentVersion: resolvedVersion,
|
|
6702
|
-
latestVersion:
|
|
6961
|
+
latestVersion: latestStable2,
|
|
6703
6962
|
majorsBehind
|
|
6704
6963
|
});
|
|
6705
6964
|
}
|
|
@@ -6931,15 +7190,15 @@ async function scanOneDartProject(dir, manifestFile, rootDir, pubCache, cache) {
|
|
|
6931
7190
|
for (const { dep, meta } of resolved) {
|
|
6932
7191
|
const resolvedVersionStr = resolvedVersions.get(dep.name);
|
|
6933
7192
|
const resolvedVersion = resolvedVersionStr ? semver11.valid(semver11.clean(resolvedVersionStr)) : null;
|
|
6934
|
-
const
|
|
7193
|
+
const latestStable2 = meta.latestStableOverall;
|
|
6935
7194
|
let majorsBehind = null;
|
|
6936
7195
|
let drift = "unknown";
|
|
6937
|
-
if (resolvedVersion &&
|
|
7196
|
+
if (resolvedVersion && latestStable2) {
|
|
6938
7197
|
const currentMajor = semver11.major(resolvedVersion);
|
|
6939
|
-
const latestMajor = semver11.major(
|
|
7198
|
+
const latestMajor = semver11.major(latestStable2);
|
|
6940
7199
|
majorsBehind = latestMajor - currentMajor;
|
|
6941
7200
|
if (majorsBehind === 0) {
|
|
6942
|
-
drift = semver11.eq(resolvedVersion,
|
|
7201
|
+
drift = semver11.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
6943
7202
|
} else if (majorsBehind > 0) {
|
|
6944
7203
|
drift = "major-behind";
|
|
6945
7204
|
} else {
|
|
@@ -6957,7 +7216,7 @@ async function scanOneDartProject(dir, manifestFile, rootDir, pubCache, cache) {
|
|
|
6957
7216
|
section,
|
|
6958
7217
|
currentSpec: dep.version,
|
|
6959
7218
|
resolvedVersion,
|
|
6960
|
-
latestStable,
|
|
7219
|
+
latestStable: latestStable2,
|
|
6961
7220
|
majorsBehind,
|
|
6962
7221
|
drift
|
|
6963
7222
|
});
|
|
@@ -6965,7 +7224,7 @@ async function scanOneDartProject(dir, manifestFile, rootDir, pubCache, cache) {
|
|
|
6965
7224
|
frameworks.push({
|
|
6966
7225
|
name: KNOWN_DART_FRAMEWORKS[dep.name],
|
|
6967
7226
|
currentVersion: resolvedVersion,
|
|
6968
|
-
latestVersion:
|
|
7227
|
+
latestVersion: latestStable2,
|
|
6969
7228
|
majorsBehind
|
|
6970
7229
|
});
|
|
6971
7230
|
}
|
|
@@ -13419,6 +13678,96 @@ async function computeTreeMetadataHash(rootDir, options) {
|
|
|
13419
13678
|
}
|
|
13420
13679
|
return digest.digest("hex");
|
|
13421
13680
|
}
|
|
13681
|
+
var DEFAULT_API_BASE = "https://api.vibgrate.com";
|
|
13682
|
+
var CACHE_TTL_MS = 1e3 * 60 * 60 * 24;
|
|
13683
|
+
var FETCH_TIMEOUT_MS = 5e3;
|
|
13684
|
+
function isRuntimeCatalog(value) {
|
|
13685
|
+
return !!value && typeof value === "object" && typeof value.generatedAt === "string" && typeof value.products === "object" && value.products !== null;
|
|
13686
|
+
}
|
|
13687
|
+
var RuntimeCatalogClient = class {
|
|
13688
|
+
apiBase;
|
|
13689
|
+
offline;
|
|
13690
|
+
manifest;
|
|
13691
|
+
cacheDir;
|
|
13692
|
+
fetchImpl;
|
|
13693
|
+
resolution = null;
|
|
13694
|
+
constructor(opts = {}) {
|
|
13695
|
+
this.apiBase = (opts.apiBase ?? process.env.VIBGRATE_API_BASE ?? DEFAULT_API_BASE).replace(/\/+$/, "");
|
|
13696
|
+
this.offline = opts.offline ?? false;
|
|
13697
|
+
this.manifest = opts.manifest;
|
|
13698
|
+
this.cacheDir = opts.cacheDir ?? path32.join(os4.homedir(), ".vibgrate", "cache");
|
|
13699
|
+
this.fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
13700
|
+
}
|
|
13701
|
+
/** Resolve the catalog once; concurrent/repeat calls share the result. */
|
|
13702
|
+
resolve() {
|
|
13703
|
+
if (!this.resolution) this.resolution = this.doResolve();
|
|
13704
|
+
return this.resolution;
|
|
13705
|
+
}
|
|
13706
|
+
get cacheFile() {
|
|
13707
|
+
return path32.join(this.cacheDir, "runtimes.json");
|
|
13708
|
+
}
|
|
13709
|
+
async doResolve() {
|
|
13710
|
+
let staleCache;
|
|
13711
|
+
if (!this.offline) {
|
|
13712
|
+
const envelope = await this.readCache();
|
|
13713
|
+
if (envelope) {
|
|
13714
|
+
const fresh = Date.now() - Date.parse(envelope.fetchedAt) < CACHE_TTL_MS;
|
|
13715
|
+
if (fresh) return { catalog: envelope.catalog, source: "cache" };
|
|
13716
|
+
staleCache = envelope.catalog;
|
|
13717
|
+
}
|
|
13718
|
+
const fetched = await this.fetchFromApi();
|
|
13719
|
+
if (fetched) {
|
|
13720
|
+
await this.writeCache(fetched);
|
|
13721
|
+
return { catalog: fetched, source: "api" };
|
|
13722
|
+
}
|
|
13723
|
+
}
|
|
13724
|
+
const manifestCatalog = this.manifest?.runtimes;
|
|
13725
|
+
if (isRuntimeCatalog(manifestCatalog)) {
|
|
13726
|
+
return { catalog: manifestCatalog, source: "manifest" };
|
|
13727
|
+
}
|
|
13728
|
+
if (staleCache && Date.parse(staleCache.generatedAt) > Date.parse(BUNDLED_RUNTIME_CATALOG.generatedAt)) {
|
|
13729
|
+
return { catalog: staleCache, source: "cache" };
|
|
13730
|
+
}
|
|
13731
|
+
return { catalog: BUNDLED_RUNTIME_CATALOG, source: "bundled" };
|
|
13732
|
+
}
|
|
13733
|
+
async fetchFromApi() {
|
|
13734
|
+
if (!this.fetchImpl) return null;
|
|
13735
|
+
const controller = new AbortController();
|
|
13736
|
+
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
13737
|
+
try {
|
|
13738
|
+
const res = await this.fetchImpl(`${this.apiBase}/v1/reference/runtimes`, {
|
|
13739
|
+
signal: controller.signal,
|
|
13740
|
+
headers: { Accept: "application/json" }
|
|
13741
|
+
});
|
|
13742
|
+
if (!res.ok) return null;
|
|
13743
|
+
const data = await res.json();
|
|
13744
|
+
return isRuntimeCatalog(data) ? data : null;
|
|
13745
|
+
} catch {
|
|
13746
|
+
return null;
|
|
13747
|
+
} finally {
|
|
13748
|
+
clearTimeout(timer);
|
|
13749
|
+
}
|
|
13750
|
+
}
|
|
13751
|
+
async readCache() {
|
|
13752
|
+
try {
|
|
13753
|
+
const text = await readFile4(this.cacheFile, "utf8");
|
|
13754
|
+
const parsed = JSON.parse(text);
|
|
13755
|
+
if (parsed && typeof parsed.fetchedAt === "string" && isRuntimeCatalog(parsed.catalog)) {
|
|
13756
|
+
return parsed;
|
|
13757
|
+
}
|
|
13758
|
+
} catch {
|
|
13759
|
+
}
|
|
13760
|
+
return null;
|
|
13761
|
+
}
|
|
13762
|
+
async writeCache(catalog) {
|
|
13763
|
+
try {
|
|
13764
|
+
await mkdir3(this.cacheDir, { recursive: true });
|
|
13765
|
+
const envelope = { fetchedAt: (/* @__PURE__ */ new Date()).toISOString(), catalog };
|
|
13766
|
+
await writeFile3(this.cacheFile, JSON.stringify(envelope), "utf8");
|
|
13767
|
+
} catch {
|
|
13768
|
+
}
|
|
13769
|
+
}
|
|
13770
|
+
};
|
|
13422
13771
|
var ProgressTrace = class _ProgressTrace {
|
|
13423
13772
|
constructor(outPath) {
|
|
13424
13773
|
this.outPath = outPath;
|
|
@@ -13429,8 +13778,8 @@ var ProgressTrace = class _ProgressTrace {
|
|
|
13429
13778
|
flushed = false;
|
|
13430
13779
|
/** Returns a trace when VIBGRATE_TRACE_EVENTS is set, else null. */
|
|
13431
13780
|
static fromEnv() {
|
|
13432
|
-
const
|
|
13433
|
-
return
|
|
13781
|
+
const path35 = process.env.VIBGRATE_TRACE_EVENTS;
|
|
13782
|
+
return path35 ? new _ProgressTrace(path35) : null;
|
|
13434
13783
|
}
|
|
13435
13784
|
record(op, data = {}) {
|
|
13436
13785
|
if (this.flushed) return;
|
|
@@ -13947,7 +14296,7 @@ var ScanProgress = class {
|
|
|
13947
14296
|
var HISTORY_FILENAME = "scan_history.json";
|
|
13948
14297
|
var MAX_RECORDS = 10;
|
|
13949
14298
|
async function loadScanHistory(rootDir) {
|
|
13950
|
-
const filePath =
|
|
14299
|
+
const filePath = path33.join(rootDir, ".vibgrate", HISTORY_FILENAME);
|
|
13951
14300
|
try {
|
|
13952
14301
|
const txt = await fs7.readFile(filePath, "utf8");
|
|
13953
14302
|
const data = JSON.parse(txt);
|
|
@@ -13960,8 +14309,8 @@ async function loadScanHistory(rootDir) {
|
|
|
13960
14309
|
}
|
|
13961
14310
|
}
|
|
13962
14311
|
async function saveScanHistory(rootDir, record2) {
|
|
13963
|
-
const dir =
|
|
13964
|
-
const filePath =
|
|
14312
|
+
const dir = path33.join(rootDir, ".vibgrate");
|
|
14313
|
+
const filePath = path33.join(dir, HISTORY_FILENAME);
|
|
13965
14314
|
let history;
|
|
13966
14315
|
const existing = await loadScanHistory(rootDir);
|
|
13967
14316
|
if (existing) {
|
|
@@ -14029,18 +14378,18 @@ async function discoverSolutions(rootDir, fileCache) {
|
|
|
14029
14378
|
for (const solutionFile of solutionFiles) {
|
|
14030
14379
|
try {
|
|
14031
14380
|
const content = await fileCache.readTextFile(solutionFile);
|
|
14032
|
-
const dir =
|
|
14033
|
-
const rootBasename =
|
|
14034
|
-
const relSolutionPath = [rootBasename,
|
|
14381
|
+
const dir = path34.dirname(solutionFile);
|
|
14382
|
+
const rootBasename = path34.basename(rootDir);
|
|
14383
|
+
const relSolutionPath = [rootBasename, path34.relative(rootDir, solutionFile).replace(/\\/g, "/")].join("/");
|
|
14035
14384
|
const projectPaths = /* @__PURE__ */ new Set();
|
|
14036
14385
|
const projectRegex = /Project\("[^"]*"\)\s*=\s*"([^"]*)",\s*"([^"]+\.(?:cs|vb)proj)"/g;
|
|
14037
14386
|
let match;
|
|
14038
14387
|
while ((match = projectRegex.exec(content)) !== null) {
|
|
14039
14388
|
const projectRelative = match[2];
|
|
14040
|
-
const absProjectPath =
|
|
14041
|
-
projectPaths.add(
|
|
14389
|
+
const absProjectPath = path34.resolve(dir, projectRelative.replace(/\\/g, "/"));
|
|
14390
|
+
projectPaths.add(path34.relative(rootDir, absProjectPath).replace(/\\/g, "/"));
|
|
14042
14391
|
}
|
|
14043
|
-
const solutionName =
|
|
14392
|
+
const solutionName = path34.basename(solutionFile, path34.extname(solutionFile));
|
|
14044
14393
|
parsed.push({
|
|
14045
14394
|
path: relSolutionPath,
|
|
14046
14395
|
name: solutionName,
|
|
@@ -14148,6 +14497,9 @@ async function runScan(rootDir, opts) {
|
|
|
14148
14497
|
].join("\n");
|
|
14149
14498
|
throw new Error(msg);
|
|
14150
14499
|
}
|
|
14500
|
+
const runtimeClient = new RuntimeCatalogClient({ offline: offlineMode, manifest: packageManifest });
|
|
14501
|
+
const resolvedRuntimeCatalog = await runtimeClient.resolve();
|
|
14502
|
+
const runtimeCatalog = resolvedRuntimeCatalog.catalog;
|
|
14151
14503
|
const treeCountPromise = quickTreeCount(rootDir, excludePatterns);
|
|
14152
14504
|
progress.startStep("discovery");
|
|
14153
14505
|
const treeCount = await treeCountPromise;
|
|
@@ -14173,7 +14525,7 @@ async function runScan(rootDir, opts) {
|
|
|
14173
14525
|
progress.updateStats({ treeSummary: indexedTreeCount });
|
|
14174
14526
|
}
|
|
14175
14527
|
progress.completeStep("walk", `${treeCount.totalFiles.toLocaleString()} files indexed`);
|
|
14176
|
-
const nodeProjects = await scanNodeProjects(rootDir, npmCache, fileCache, projectScanTimeoutMs);
|
|
14528
|
+
const nodeProjects = await scanNodeProjects(rootDir, npmCache, fileCache, projectScanTimeoutMs, runtimeCatalog);
|
|
14177
14529
|
if (nodeProjects.length > 0) {
|
|
14178
14530
|
progress.insertStepBefore("drift", { id: "node", label: "Found Node projects", weight: 4 });
|
|
14179
14531
|
progress.startStep("node");
|
|
@@ -14185,7 +14537,7 @@ async function runScan(rootDir, opts) {
|
|
|
14185
14537
|
progress.addProjects(nodeProjects.length);
|
|
14186
14538
|
progress.completeStep("node", `${nodeProjects.length} project${nodeProjects.length !== 1 ? "s" : ""}`, nodeProjects.length);
|
|
14187
14539
|
}
|
|
14188
|
-
const dotnetProjects = await scanDotnetProjects(rootDir, nugetCache, fileCache, projectScanTimeoutMs);
|
|
14540
|
+
const dotnetProjects = await scanDotnetProjects(rootDir, nugetCache, fileCache, projectScanTimeoutMs, runtimeCatalog);
|
|
14189
14541
|
if (dotnetProjects.length > 0) {
|
|
14190
14542
|
progress.insertStepBefore("drift", { id: "dotnet", label: "Found .NET projects", weight: 2 });
|
|
14191
14543
|
progress.startStep("dotnet");
|
|
@@ -14197,7 +14549,7 @@ async function runScan(rootDir, opts) {
|
|
|
14197
14549
|
progress.addProjects(dotnetProjects.length);
|
|
14198
14550
|
progress.completeStep("dotnet", `${dotnetProjects.length} project${dotnetProjects.length !== 1 ? "s" : ""}`, dotnetProjects.length);
|
|
14199
14551
|
}
|
|
14200
|
-
const pythonProjects = await scanPythonProjects(rootDir, pypiCache, fileCache, projectScanTimeoutMs);
|
|
14552
|
+
const pythonProjects = await scanPythonProjects(rootDir, pypiCache, fileCache, projectScanTimeoutMs, runtimeCatalog);
|
|
14201
14553
|
if (pythonProjects.length > 0) {
|
|
14202
14554
|
progress.insertStepBefore("drift", { id: "python", label: "Found Python projects", weight: 3 });
|
|
14203
14555
|
progress.startStep("python");
|
|
@@ -14209,7 +14561,7 @@ async function runScan(rootDir, opts) {
|
|
|
14209
14561
|
progress.addProjects(pythonProjects.length);
|
|
14210
14562
|
progress.completeStep("python", `${pythonProjects.length} project${pythonProjects.length !== 1 ? "s" : ""}`, pythonProjects.length);
|
|
14211
14563
|
}
|
|
14212
|
-
const javaProjects = await scanJavaProjects(rootDir, mavenCache, fileCache, projectScanTimeoutMs);
|
|
14564
|
+
const javaProjects = await scanJavaProjects(rootDir, mavenCache, fileCache, projectScanTimeoutMs, runtimeCatalog);
|
|
14213
14565
|
if (javaProjects.length > 0) {
|
|
14214
14566
|
progress.insertStepBefore("drift", { id: "java", label: "Found Java projects", weight: 3 });
|
|
14215
14567
|
progress.startStep("java");
|
|
@@ -14221,7 +14573,7 @@ async function runScan(rootDir, opts) {
|
|
|
14221
14573
|
progress.addProjects(javaProjects.length);
|
|
14222
14574
|
progress.completeStep("java", `${javaProjects.length} project${javaProjects.length !== 1 ? "s" : ""}`, javaProjects.length);
|
|
14223
14575
|
}
|
|
14224
|
-
const rubyProjects = await scanRubyProjects(rootDir, rubygemsCache, fileCache, projectScanTimeoutMs);
|
|
14576
|
+
const rubyProjects = await scanRubyProjects(rootDir, rubygemsCache, fileCache, projectScanTimeoutMs, runtimeCatalog);
|
|
14225
14577
|
if (rubyProjects.length > 0) {
|
|
14226
14578
|
progress.insertStepBefore("drift", { id: "ruby", label: "Found Ruby projects", weight: 2 });
|
|
14227
14579
|
progress.startStep("ruby");
|
|
@@ -14245,7 +14597,7 @@ async function runScan(rootDir, opts) {
|
|
|
14245
14597
|
progress.addProjects(swiftProjects.length);
|
|
14246
14598
|
progress.completeStep("swift", `${swiftProjects.length} project${swiftProjects.length !== 1 ? "s" : ""}`, swiftProjects.length);
|
|
14247
14599
|
}
|
|
14248
|
-
const goProjects = await scanGoProjects(rootDir, goCache, fileCache, projectScanTimeoutMs);
|
|
14600
|
+
const goProjects = await scanGoProjects(rootDir, goCache, fileCache, projectScanTimeoutMs, runtimeCatalog);
|
|
14249
14601
|
if (goProjects.length > 0) {
|
|
14250
14602
|
progress.insertStepBefore("drift", { id: "go", label: "Found Go projects", weight: 2 });
|
|
14251
14603
|
progress.startStep("go");
|
|
@@ -14384,7 +14736,7 @@ async function runScan(rootDir, opts) {
|
|
|
14384
14736
|
for (const project of allProjects) {
|
|
14385
14737
|
project.drift = computeDriftScore([project]);
|
|
14386
14738
|
project.projectId = computeProjectId(project.path, project.name, workspaceId);
|
|
14387
|
-
const absProjectDir =
|
|
14739
|
+
const absProjectDir = path34.resolve(rootDir, project.path);
|
|
14388
14740
|
try {
|
|
14389
14741
|
const source = await fileCache.sourceMetricsUnder(rootDir, absProjectDir);
|
|
14390
14742
|
if (project.fileCount === void 0) project.fileCount = source.fileCount;
|
|
@@ -14398,7 +14750,7 @@ async function runScan(rootDir, opts) {
|
|
|
14398
14750
|
dependencyCount: project.dependencyCount
|
|
14399
14751
|
});
|
|
14400
14752
|
}
|
|
14401
|
-
const solutionsManifestPath =
|
|
14753
|
+
const solutionsManifestPath = path34.join(rootDir, ".vibgrate", "solutions.json");
|
|
14402
14754
|
const persistedSolutionIds = /* @__PURE__ */ new Map();
|
|
14403
14755
|
if (await pathExists(solutionsManifestPath)) {
|
|
14404
14756
|
try {
|
|
@@ -14420,7 +14772,7 @@ async function runScan(rootDir, opts) {
|
|
|
14420
14772
|
const projectsByPath = new Map(allProjects.map((project) => [project.path, project]));
|
|
14421
14773
|
for (const solution of solutions) {
|
|
14422
14774
|
const includedProjects = solution.projectPaths.map((projectPath) => {
|
|
14423
|
-
return projectsByPath.get(projectPath) ?? projectsByPath.get(
|
|
14775
|
+
return projectsByPath.get(projectPath) ?? projectsByPath.get(path34.dirname(projectPath).replace(/\\/g, "/"));
|
|
14424
14776
|
}).filter((project) => Boolean(project));
|
|
14425
14777
|
solution.drift = includedProjects.length > 0 ? computeDriftScore(includedProjects) : void 0;
|
|
14426
14778
|
for (const project of includedProjects) {
|
|
@@ -14635,7 +14987,7 @@ async function runScan(rootDir, opts) {
|
|
|
14635
14987
|
const summary = [`${up.topEvidence.length} evidence`, ...up.capped ? ["capped"] : []].join(" \xB7 ");
|
|
14636
14988
|
progress.completeStep("uipurpose", summary, up.topEvidence.length);
|
|
14637
14989
|
await Promise.all(allProjects.map(async (project) => {
|
|
14638
|
-
const projectDir =
|
|
14990
|
+
const projectDir = path34.join(rootDir, project.path);
|
|
14639
14991
|
const projectResult = await scanUiPurpose(projectDir, fileCache, 150);
|
|
14640
14992
|
if (projectResult.topEvidence.length > 0) {
|
|
14641
14993
|
project.uiPurpose = compactUiPurpose(projectResult);
|
|
@@ -14643,7 +14995,7 @@ async function runScan(rootDir, opts) {
|
|
|
14643
14995
|
}));
|
|
14644
14996
|
}
|
|
14645
14997
|
await Promise.all(allProjects.map(async (project) => {
|
|
14646
|
-
const projectAbsPath =
|
|
14998
|
+
const projectAbsPath = path34.join(rootDir, project.path);
|
|
14647
14999
|
const favicon = await findProjectFavicon(projectAbsPath);
|
|
14648
15000
|
if (favicon) project.faviconBase64 = favicon;
|
|
14649
15001
|
}));
|
|
@@ -14668,7 +15020,7 @@ async function runScan(rootDir, opts) {
|
|
|
14668
15020
|
project.architecture = await scanProjectArchitecture(rootDir, project, fileCache);
|
|
14669
15021
|
}));
|
|
14670
15022
|
for (const solution of solutions) {
|
|
14671
|
-
const memberProjects = solution.projectPaths.map((pp) => projectsByPath.get(pp) ?? projectsByPath.get(
|
|
15023
|
+
const memberProjects = solution.projectPaths.map((pp) => projectsByPath.get(pp) ?? projectsByPath.get(path34.dirname(pp).replace(/\\/g, "/"))).filter((p) => Boolean(p));
|
|
14672
15024
|
const memberArchResults = memberProjects.map((p) => p.architecture).filter((a) => Boolean(a));
|
|
14673
15025
|
if (memberArchResults.length > 0) {
|
|
14674
15026
|
solution.architecture = aggregateSolutionArchitecture(memberArchResults);
|
|
@@ -14681,6 +15033,13 @@ async function runScan(rootDir, opts) {
|
|
|
14681
15033
|
);
|
|
14682
15034
|
}
|
|
14683
15035
|
}
|
|
15036
|
+
const catalogAgeDays = (Date.now() - Date.parse(runtimeCatalog.generatedAt)) / (1e3 * 60 * 60 * 24);
|
|
15037
|
+
const runtimeCatalogStale = Number.isFinite(catalogAgeDays) && catalogAgeDays > 30;
|
|
15038
|
+
extended.runtimeCatalogInfo = {
|
|
15039
|
+
generatedAt: runtimeCatalog.generatedAt,
|
|
15040
|
+
source: resolvedRuntimeCatalog.source,
|
|
15041
|
+
stale: runtimeCatalogStale
|
|
15042
|
+
};
|
|
14684
15043
|
progress.startStep("drift");
|
|
14685
15044
|
const drift = computeDriftScore(allProjects);
|
|
14686
15045
|
progress.completeStep("drift", `${drift.score}/100 \u2014 ${drift.riskLevel} risk`);
|
|
@@ -14752,7 +15111,7 @@ async function runScan(rootDir, opts) {
|
|
|
14752
15111
|
schemaVersion: "1.0",
|
|
14753
15112
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14754
15113
|
vibgrateVersion,
|
|
14755
|
-
rootPath:
|
|
15114
|
+
rootPath: path34.basename(rootDir),
|
|
14756
15115
|
...vcs.type !== "unknown" ? { vcs } : {},
|
|
14757
15116
|
repository,
|
|
14758
15117
|
projects: allProjects,
|
|
@@ -14767,7 +15126,7 @@ async function runScan(rootDir, opts) {
|
|
|
14767
15126
|
billing: summarizeBilling(allProjects)
|
|
14768
15127
|
};
|
|
14769
15128
|
if (opts.baseline) {
|
|
14770
|
-
const baselinePath =
|
|
15129
|
+
const baselinePath = path34.resolve(opts.baseline);
|
|
14771
15130
|
if (await pathExists(baselinePath)) {
|
|
14772
15131
|
try {
|
|
14773
15132
|
const baseline = await readJsonFile(baselinePath);
|
|
@@ -14779,10 +15138,10 @@ async function runScan(rootDir, opts) {
|
|
|
14779
15138
|
}
|
|
14780
15139
|
}
|
|
14781
15140
|
if (!opts.noLocalArtifacts && !maxPrivacyMode) {
|
|
14782
|
-
const vibgrateDir =
|
|
15141
|
+
const vibgrateDir = path34.join(rootDir, ".vibgrate");
|
|
14783
15142
|
await ensureDir(vibgrateDir);
|
|
14784
|
-
await writeJsonFile(
|
|
14785
|
-
await writeJsonFile(
|
|
15143
|
+
await writeJsonFile(path34.join(vibgrateDir, "scan_result.json"), artifact);
|
|
15144
|
+
await writeJsonFile(path34.join(vibgrateDir, "solutions.json"), {
|
|
14786
15145
|
scannedAt: artifact.timestamp,
|
|
14787
15146
|
solutions: solutions.map((solution) => ({
|
|
14788
15147
|
solutionId: solution.solutionId,
|
|
@@ -14821,15 +15180,15 @@ async function runScan(rootDir, opts) {
|
|
|
14821
15180
|
}
|
|
14822
15181
|
}
|
|
14823
15182
|
if (Object.keys(projectScores).length > 0) {
|
|
14824
|
-
const vibgrateDir =
|
|
15183
|
+
const vibgrateDir = path34.join(rootDir, ".vibgrate");
|
|
14825
15184
|
await ensureDir(vibgrateDir);
|
|
14826
|
-
await writeJsonFile(
|
|
15185
|
+
await writeJsonFile(path34.join(vibgrateDir, "project_scores.json"), projectScores);
|
|
14827
15186
|
}
|
|
14828
15187
|
}
|
|
14829
15188
|
if (opts.format === "json") {
|
|
14830
15189
|
const jsonStr = JSON.stringify(artifact, null, 2);
|
|
14831
15190
|
if (opts.out) {
|
|
14832
|
-
await writeTextFile(
|
|
15191
|
+
await writeTextFile(path34.resolve(opts.out), jsonStr);
|
|
14833
15192
|
console.log(chalk3.green("\u2714") + ` JSON written to ${opts.out}`);
|
|
14834
15193
|
} else {
|
|
14835
15194
|
console.log(jsonStr);
|
|
@@ -14838,7 +15197,7 @@ async function runScan(rootDir, opts) {
|
|
|
14838
15197
|
const sarif = formatSarif(artifact);
|
|
14839
15198
|
const sarifStr = JSON.stringify(sarif, null, 2);
|
|
14840
15199
|
if (opts.out) {
|
|
14841
|
-
await writeTextFile(
|
|
15200
|
+
await writeTextFile(path34.resolve(opts.out), sarifStr);
|
|
14842
15201
|
console.log(chalk3.green("\u2714") + ` SARIF written to ${opts.out}`);
|
|
14843
15202
|
} else {
|
|
14844
15203
|
console.log(sarifStr);
|
|
@@ -14847,13 +15206,13 @@ async function runScan(rootDir, opts) {
|
|
|
14847
15206
|
const markdown = formatMarkdown(artifact);
|
|
14848
15207
|
console.log(markdown);
|
|
14849
15208
|
if (opts.out) {
|
|
14850
|
-
await writeTextFile(
|
|
15209
|
+
await writeTextFile(path34.resolve(opts.out), markdown);
|
|
14851
15210
|
}
|
|
14852
15211
|
} else {
|
|
14853
15212
|
const text = formatText(artifact);
|
|
14854
15213
|
console.log(text);
|
|
14855
15214
|
if (opts.out) {
|
|
14856
|
-
await writeTextFile(
|
|
15215
|
+
await writeTextFile(path34.resolve(opts.out), text);
|
|
14857
15216
|
}
|
|
14858
15217
|
}
|
|
14859
15218
|
return artifact;
|
|
@@ -14861,7 +15220,7 @@ async function runScan(rootDir, opts) {
|
|
|
14861
15220
|
async function buildRepositoryInfo(rootDir, remoteUrl, ciSystems) {
|
|
14862
15221
|
const name = await resolveRepositoryName(rootDir);
|
|
14863
15222
|
let version;
|
|
14864
|
-
const packageJsonPath =
|
|
15223
|
+
const packageJsonPath = path34.join(rootDir, "package.json");
|
|
14865
15224
|
if (await pathExists(packageJsonPath)) {
|
|
14866
15225
|
try {
|
|
14867
15226
|
const packageJson = await readJsonFile(packageJsonPath);
|