@vibgrate/cli 2026.611.3 → 2026.615.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.
- package/dist/{baseline-AXQGF3QD.js → baseline-4E3WWG4W.js} +2 -2
- package/dist/{chunk-DMVLVXIP.js → chunk-Y3VTYTQR.js} +1 -1
- package/dist/{chunk-VP7PK4VN.js → chunk-ZDCFG3EB.js} +517 -153
- package/dist/cli.js +882 -4
- package/dist/hcs-worker.js +323 -12
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -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",
|
|
@@ -3991,7 +4208,7 @@ var KNOWN_FRAMEWORKS = {
|
|
|
3991
4208
|
"storybook": "Storybook",
|
|
3992
4209
|
"@storybook/react": "Storybook"
|
|
3993
4210
|
};
|
|
3994
|
-
async function scanNodeProjects(rootDir, npmCache, cache, projectScanTimeout) {
|
|
4211
|
+
async function scanNodeProjects(rootDir, npmCache, cache, projectScanTimeout, catalog = BUNDLED_RUNTIME_CATALOG) {
|
|
3995
4212
|
const packageJsonFiles = cache ? await cache.findPackageJsonFiles(rootDir) : await findPackageJsonFiles(rootDir);
|
|
3996
4213
|
const results = [];
|
|
3997
4214
|
const packageNameToPath = /* @__PURE__ */ new Map();
|
|
@@ -4055,7 +4272,7 @@ async function scanNodeProjects(rootDir, npmCache, cache, projectScanTimeout) {
|
|
|
4055
4272
|
}
|
|
4056
4273
|
const scannedProjects = await Promise.all(packageJsonFiles.map(async (pjPath) => projectSem.run(async () => {
|
|
4057
4274
|
try {
|
|
4058
|
-
const scanPromise = scanOnePackageJson(pjPath, rootDir, npmCache, cache);
|
|
4275
|
+
const scanPromise = scanOnePackageJson(pjPath, rootDir, npmCache, cache, catalog);
|
|
4059
4276
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
4060
4277
|
if (result.ok) {
|
|
4061
4278
|
return result.value;
|
|
@@ -4101,21 +4318,26 @@ async function scanNodeProjects(rootDir, npmCache, cache, projectScanTimeout) {
|
|
|
4101
4318
|
}
|
|
4102
4319
|
return results;
|
|
4103
4320
|
}
|
|
4104
|
-
async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache) {
|
|
4321
|
+
async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache, catalog) {
|
|
4105
4322
|
const pj = cache ? await cache.readJsonFile(packageJsonPath) : await readJsonFile(packageJsonPath);
|
|
4106
4323
|
const absProjectPath = path3.dirname(packageJsonPath);
|
|
4107
4324
|
const projectPath = path3.relative(rootDir, absProjectPath) || ".";
|
|
4108
4325
|
const nodeEngine = pj.engines?.node ?? void 0;
|
|
4109
4326
|
let runtimeLatest;
|
|
4110
4327
|
let runtimeMajorsBehind;
|
|
4328
|
+
let runtimeEol;
|
|
4329
|
+
let runtimeEolDate;
|
|
4111
4330
|
if (nodeEngine) {
|
|
4112
|
-
const
|
|
4331
|
+
const latest = latestLts(catalog, "nodejs");
|
|
4113
4332
|
const parsed = semver2.minVersion(nodeEngine);
|
|
4114
|
-
if (parsed) {
|
|
4333
|
+
if (latest && parsed) {
|
|
4115
4334
|
const currentMajor = semver2.major(parsed);
|
|
4116
|
-
runtimeLatest = `${
|
|
4117
|
-
runtimeMajorsBehind = Math.max(0,
|
|
4335
|
+
runtimeLatest = `${latest.major}.0.0`;
|
|
4336
|
+
runtimeMajorsBehind = Math.max(0, latest.major - currentMajor);
|
|
4118
4337
|
}
|
|
4338
|
+
runtimeEol = runtimeEolStatus(catalog, "node", nodeEngine);
|
|
4339
|
+
const cycle = extractCycle("node", nodeEngine);
|
|
4340
|
+
if (cycle) runtimeEolDate = eolDate(catalog, "nodejs", cycle);
|
|
4119
4341
|
}
|
|
4120
4342
|
const sections = [
|
|
4121
4343
|
{ name: "dependencies", deps: pj.dependencies },
|
|
@@ -4142,15 +4364,15 @@ async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache) {
|
|
|
4142
4364
|
const resolved = await Promise.all(metaPromises);
|
|
4143
4365
|
for (const { pkg: pkg2, section, spec, meta } of resolved) {
|
|
4144
4366
|
const resolvedVersion = meta.stableVersions.length > 0 ? semver2.maxSatisfying(meta.stableVersions, spec) ?? null : null;
|
|
4145
|
-
const
|
|
4367
|
+
const latestStable2 = meta.latestStableOverall;
|
|
4146
4368
|
let majorsBehind = null;
|
|
4147
4369
|
let drift = "unknown";
|
|
4148
|
-
if (resolvedVersion &&
|
|
4370
|
+
if (resolvedVersion && latestStable2) {
|
|
4149
4371
|
const currentMajor = semver2.major(resolvedVersion);
|
|
4150
|
-
const latestMajor = semver2.major(
|
|
4372
|
+
const latestMajor = semver2.major(latestStable2);
|
|
4151
4373
|
majorsBehind = latestMajor - currentMajor;
|
|
4152
4374
|
if (majorsBehind === 0) {
|
|
4153
|
-
drift = semver2.eq(resolvedVersion,
|
|
4375
|
+
drift = semver2.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
4154
4376
|
} else {
|
|
4155
4377
|
drift = "major-behind";
|
|
4156
4378
|
}
|
|
@@ -4160,14 +4382,14 @@ async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache) {
|
|
|
4160
4382
|
} else {
|
|
4161
4383
|
buckets.unknown++;
|
|
4162
4384
|
}
|
|
4163
|
-
const ageDays = ageDaysBetween(resolvedVersion,
|
|
4385
|
+
const ageDays = ageDaysBetween(resolvedVersion, latestStable2, meta.releaseDates);
|
|
4164
4386
|
const libyears = daysToLibyears(ageDays);
|
|
4165
4387
|
dependencies.push({
|
|
4166
4388
|
package: pkg2,
|
|
4167
4389
|
section,
|
|
4168
4390
|
currentSpec: spec,
|
|
4169
4391
|
resolvedVersion,
|
|
4170
|
-
latestStable,
|
|
4392
|
+
latestStable: latestStable2,
|
|
4171
4393
|
majorsBehind,
|
|
4172
4394
|
drift,
|
|
4173
4395
|
license: buildDependencyLicense(meta.license, "registry"),
|
|
@@ -4178,7 +4400,7 @@ async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache) {
|
|
|
4178
4400
|
frameworks.push({
|
|
4179
4401
|
name: KNOWN_FRAMEWORKS[pkg2],
|
|
4180
4402
|
currentVersion: resolvedVersion,
|
|
4181
|
-
latestVersion:
|
|
4403
|
+
latestVersion: latestStable2,
|
|
4182
4404
|
majorsBehind
|
|
4183
4405
|
});
|
|
4184
4406
|
}
|
|
@@ -4218,6 +4440,8 @@ async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache) {
|
|
|
4218
4440
|
runtime: nodeEngine,
|
|
4219
4441
|
runtimeLatest,
|
|
4220
4442
|
runtimeMajorsBehind,
|
|
4443
|
+
runtimeEol,
|
|
4444
|
+
runtimeEolDate,
|
|
4221
4445
|
frameworks,
|
|
4222
4446
|
dependencies,
|
|
4223
4447
|
dependencyAgeBuckets: buckets,
|
|
@@ -4442,7 +4666,6 @@ var KNOWN_DOTNET_FRAMEWORKS = {
|
|
|
4442
4666
|
// ── Real-time ──
|
|
4443
4667
|
"Microsoft.AspNetCore.SignalR.Client": "SignalR Client"
|
|
4444
4668
|
};
|
|
4445
|
-
var LATEST_DOTNET_MAJOR = 9;
|
|
4446
4669
|
function normalizePath(p) {
|
|
4447
4670
|
return p.replace(/\\/g, "/");
|
|
4448
4671
|
}
|
|
@@ -4506,7 +4729,7 @@ function parseDotnetProjectFile(xml, filePath) {
|
|
|
4506
4729
|
projectName: stripDotnetProjectExtension(filePath)
|
|
4507
4730
|
};
|
|
4508
4731
|
}
|
|
4509
|
-
async function scanDotnetProjects(rootDir, nugetCache, cache, projectScanTimeout) {
|
|
4732
|
+
async function scanDotnetProjects(rootDir, nugetCache, cache, projectScanTimeout, catalog = BUNDLED_RUNTIME_CATALOG) {
|
|
4510
4733
|
const projectFiles = cache ? await cache.findFiles(rootDir, isDotnetProjectFile) : await findFiles(rootDir, isDotnetProjectFile);
|
|
4511
4734
|
const slnFiles = cache ? await cache.findSolutionFiles(rootDir) : await findSolutionFiles(rootDir);
|
|
4512
4735
|
const slnProjectPaths = /* @__PURE__ */ new Set();
|
|
@@ -4530,7 +4753,7 @@ async function scanDotnetProjects(rootDir, nugetCache, cache, projectScanTimeout
|
|
|
4530
4753
|
const STUCK_TIMEOUT_MS = projectScanTimeout ?? cache?.projectScanTimeout ?? 18e4;
|
|
4531
4754
|
for (const csprojPath of allCsprojFiles) {
|
|
4532
4755
|
try {
|
|
4533
|
-
const scanPromise = scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache);
|
|
4756
|
+
const scanPromise = scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache, catalog);
|
|
4534
4757
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
4535
4758
|
if (result.ok) {
|
|
4536
4759
|
results.push(result.value);
|
|
@@ -4551,18 +4774,24 @@ async function scanDotnetProjects(rootDir, nugetCache, cache, projectScanTimeout
|
|
|
4551
4774
|
}
|
|
4552
4775
|
return results;
|
|
4553
4776
|
}
|
|
4554
|
-
async function scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache) {
|
|
4777
|
+
async function scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache, catalog) {
|
|
4555
4778
|
const xml = cache ? await cache.readTextFile(csprojPath) : await readTextFile(csprojPath);
|
|
4556
4779
|
const data = parseDotnetProjectFile(xml, csprojPath);
|
|
4557
4780
|
const csprojDir = path4.dirname(csprojPath);
|
|
4558
4781
|
const primaryTfm = data.targetFrameworks[0];
|
|
4782
|
+
const dotnetLatest = latestStable(catalog, "dotnet")?.major;
|
|
4559
4783
|
let runtimeMajorsBehind;
|
|
4784
|
+
let runtimeEol;
|
|
4785
|
+
let runtimeEolDate;
|
|
4560
4786
|
let targetFramework = primaryTfm;
|
|
4561
4787
|
if (primaryTfm) {
|
|
4562
4788
|
const major11 = parseTfmMajor(primaryTfm);
|
|
4563
|
-
if (major11 !== null) {
|
|
4564
|
-
runtimeMajorsBehind = Math.max(0,
|
|
4789
|
+
if (major11 !== null && dotnetLatest !== void 0) {
|
|
4790
|
+
runtimeMajorsBehind = Math.max(0, dotnetLatest - major11);
|
|
4565
4791
|
}
|
|
4792
|
+
runtimeEol = runtimeEolStatus(catalog, "dotnet", primaryTfm);
|
|
4793
|
+
const cycle = extractCycle("dotnet", primaryTfm);
|
|
4794
|
+
if (cycle) runtimeEolDate = eolDate(catalog, "dotnet", cycle);
|
|
4566
4795
|
}
|
|
4567
4796
|
const dependencies = [];
|
|
4568
4797
|
const bucketsMut = { current: 0, oneBehind: 0, twoPlusBehind: 0, unknown: 0 };
|
|
@@ -4574,15 +4803,15 @@ async function scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache)
|
|
|
4574
4803
|
const resolved = await Promise.all(metaPromises);
|
|
4575
4804
|
for (const { ref, meta } of resolved) {
|
|
4576
4805
|
const resolvedVersion = semver3.valid(ref.version) ? ref.version : null;
|
|
4577
|
-
const
|
|
4806
|
+
const latestStable2 = meta.latestStableOverall;
|
|
4578
4807
|
let majorsBehind = null;
|
|
4579
4808
|
let drift = "unknown";
|
|
4580
|
-
if (resolvedVersion &&
|
|
4809
|
+
if (resolvedVersion && latestStable2) {
|
|
4581
4810
|
const currentMajor = semver3.major(resolvedVersion);
|
|
4582
|
-
const latestMajor = semver3.major(
|
|
4811
|
+
const latestMajor = semver3.major(latestStable2);
|
|
4583
4812
|
majorsBehind = latestMajor - currentMajor;
|
|
4584
4813
|
if (majorsBehind === 0) {
|
|
4585
|
-
drift = semver3.eq(resolvedVersion,
|
|
4814
|
+
drift = semver3.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
4586
4815
|
} else if (majorsBehind > 0) {
|
|
4587
4816
|
drift = "major-behind";
|
|
4588
4817
|
} else {
|
|
@@ -4599,7 +4828,7 @@ async function scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache)
|
|
|
4599
4828
|
section: "dependencies",
|
|
4600
4829
|
currentSpec: ref.version,
|
|
4601
4830
|
resolvedVersion,
|
|
4602
|
-
latestStable,
|
|
4831
|
+
latestStable: latestStable2,
|
|
4603
4832
|
majorsBehind,
|
|
4604
4833
|
drift
|
|
4605
4834
|
});
|
|
@@ -4659,8 +4888,10 @@ async function scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache)
|
|
|
4659
4888
|
name: data.projectName,
|
|
4660
4889
|
targetFramework,
|
|
4661
4890
|
runtime: primaryTfm,
|
|
4662
|
-
runtimeLatest: `net${
|
|
4891
|
+
runtimeLatest: dotnetLatest !== void 0 ? `net${dotnetLatest}.0` : void 0,
|
|
4663
4892
|
runtimeMajorsBehind,
|
|
4893
|
+
runtimeEol,
|
|
4894
|
+
runtimeEolDate,
|
|
4664
4895
|
frameworks,
|
|
4665
4896
|
dependencies,
|
|
4666
4897
|
dependencyAgeBuckets: buckets,
|
|
@@ -4773,7 +5004,6 @@ var KNOWN_PYTHON_FRAMEWORKS = {
|
|
|
4773
5004
|
"opentelemetry-api": "OpenTelemetry",
|
|
4774
5005
|
"prometheus-client": "prometheus-client"
|
|
4775
5006
|
};
|
|
4776
|
-
var LATEST_PYTHON_MINOR = { major: 3, minor: 13 };
|
|
4777
5007
|
function parseRequirementLine(line) {
|
|
4778
5008
|
const trimmed = line.trim();
|
|
4779
5009
|
if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith("-")) return null;
|
|
@@ -4903,7 +5133,7 @@ var PYTHON_MANIFEST_FILES = /* @__PURE__ */ new Set([
|
|
|
4903
5133
|
"setup.cfg",
|
|
4904
5134
|
"Pipfile"
|
|
4905
5135
|
]);
|
|
4906
|
-
async function scanPythonProjects(rootDir, pypiCache, cache, projectScanTimeout) {
|
|
5136
|
+
async function scanPythonProjects(rootDir, pypiCache, cache, projectScanTimeout, catalog = BUNDLED_RUNTIME_CATALOG) {
|
|
4907
5137
|
const manifestFiles = cache ? await cache.findFiles(rootDir, (name) => PYTHON_MANIFEST_FILES.has(name) || /^requirements.*\.txt$/.test(name)) : await findPythonManifests(rootDir);
|
|
4908
5138
|
const projectDirs = /* @__PURE__ */ new Map();
|
|
4909
5139
|
for (const f of manifestFiles) {
|
|
@@ -4915,7 +5145,7 @@ async function scanPythonProjects(rootDir, pypiCache, cache, projectScanTimeout)
|
|
|
4915
5145
|
const STUCK_TIMEOUT_MS = projectScanTimeout ?? cache?.projectScanTimeout ?? 18e4;
|
|
4916
5146
|
for (const [dir, files] of projectDirs) {
|
|
4917
5147
|
try {
|
|
4918
|
-
const scanPromise = scanOnePythonProject(dir, files, rootDir, pypiCache, cache);
|
|
5148
|
+
const scanPromise = scanOnePythonProject(dir, files, rootDir, pypiCache, cache, catalog);
|
|
4919
5149
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
4920
5150
|
if (result.ok) {
|
|
4921
5151
|
results.push(result.value);
|
|
@@ -4938,7 +5168,7 @@ async function findPythonManifests(rootDir) {
|
|
|
4938
5168
|
const { findFiles: findFiles2 } = await import("./fs-PXXYZATK-EW5LCUA7.js");
|
|
4939
5169
|
return findFiles2(rootDir, (name) => PYTHON_MANIFEST_FILES.has(name) || /^requirements.*\.txt$/.test(name));
|
|
4940
5170
|
}
|
|
4941
|
-
async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cache) {
|
|
5171
|
+
async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cache, catalog) {
|
|
4942
5172
|
const relDir = path5.relative(rootDir, dir) || ".";
|
|
4943
5173
|
let projectName = path5.basename(dir === rootDir ? rootDir : dir);
|
|
4944
5174
|
let pythonVersion;
|
|
@@ -4972,18 +5202,26 @@ async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cach
|
|
|
4972
5202
|
}
|
|
4973
5203
|
let runtimeMajorsBehind;
|
|
4974
5204
|
let runtimeLatest;
|
|
5205
|
+
let runtimeEol;
|
|
5206
|
+
let runtimeEolDate;
|
|
4975
5207
|
if (pythonVersion) {
|
|
4976
5208
|
const verMatch = pythonVersion.match(/(\d+)\.(\d+)/);
|
|
4977
5209
|
if (verMatch) {
|
|
4978
5210
|
const reqMajor = parseInt(verMatch[1], 10);
|
|
4979
5211
|
const reqMinor = parseInt(verMatch[2], 10);
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
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}`;
|
|
4984
5220
|
}
|
|
4985
|
-
runtimeLatest = `${LATEST_PYTHON_MINOR.major}.${LATEST_PYTHON_MINOR.minor}`;
|
|
4986
5221
|
}
|
|
5222
|
+
runtimeEol = runtimeEolStatus(catalog, "python", pythonVersion);
|
|
5223
|
+
const cycle = extractCycle("python", pythonVersion);
|
|
5224
|
+
if (cycle) runtimeEolDate = eolDate(catalog, "python", cycle);
|
|
4987
5225
|
}
|
|
4988
5226
|
const dependencies = [];
|
|
4989
5227
|
const frameworks = [];
|
|
@@ -4997,15 +5235,15 @@ async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cach
|
|
|
4997
5235
|
for (const { dep, meta } of resolved) {
|
|
4998
5236
|
const pinnedVersion = extractPinnedVersion(dep.spec);
|
|
4999
5237
|
const resolvedVersion = pinnedVersion ? pep440ToSemver(pinnedVersion) : null;
|
|
5000
|
-
const
|
|
5238
|
+
const latestStable2 = meta.latestStableOverall;
|
|
5001
5239
|
let majorsBehind = null;
|
|
5002
5240
|
let drift = "unknown";
|
|
5003
|
-
if (resolvedVersion &&
|
|
5241
|
+
if (resolvedVersion && latestStable2) {
|
|
5004
5242
|
const currentMajor = semver4.major(resolvedVersion);
|
|
5005
|
-
const latestMajor = semver4.major(
|
|
5243
|
+
const latestMajor = semver4.major(latestStable2);
|
|
5006
5244
|
majorsBehind = latestMajor - currentMajor;
|
|
5007
5245
|
if (majorsBehind === 0) {
|
|
5008
|
-
drift = semver4.eq(resolvedVersion,
|
|
5246
|
+
drift = semver4.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
5009
5247
|
} else if (majorsBehind > 0) {
|
|
5010
5248
|
drift = "major-behind";
|
|
5011
5249
|
} else {
|
|
@@ -5022,7 +5260,7 @@ async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cach
|
|
|
5022
5260
|
section: "dependencies",
|
|
5023
5261
|
currentSpec: dep.spec || "*",
|
|
5024
5262
|
resolvedVersion,
|
|
5025
|
-
latestStable,
|
|
5263
|
+
latestStable: latestStable2,
|
|
5026
5264
|
majorsBehind,
|
|
5027
5265
|
drift
|
|
5028
5266
|
});
|
|
@@ -5030,7 +5268,7 @@ async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cach
|
|
|
5030
5268
|
frameworks.push({
|
|
5031
5269
|
name: KNOWN_PYTHON_FRAMEWORKS[dep.normalisedName],
|
|
5032
5270
|
currentVersion: resolvedVersion,
|
|
5033
|
-
latestVersion:
|
|
5271
|
+
latestVersion: latestStable2,
|
|
5034
5272
|
majorsBehind
|
|
5035
5273
|
});
|
|
5036
5274
|
}
|
|
@@ -5053,6 +5291,8 @@ async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cach
|
|
|
5053
5291
|
runtime: pythonVersion,
|
|
5054
5292
|
runtimeLatest,
|
|
5055
5293
|
runtimeMajorsBehind,
|
|
5294
|
+
runtimeEol,
|
|
5295
|
+
runtimeEolDate,
|
|
5056
5296
|
frameworks,
|
|
5057
5297
|
dependencies,
|
|
5058
5298
|
dependencyAgeBuckets: buckets,
|
|
@@ -5156,7 +5396,6 @@ var KNOWN_JAVA_FRAMEWORKS = {
|
|
|
5156
5396
|
"io.projectreactor:reactor-core": "Project Reactor",
|
|
5157
5397
|
"io.reactivex.rxjava3:rxjava": "RxJava 3"
|
|
5158
5398
|
};
|
|
5159
|
-
var LATEST_JAVA_LTS = 21;
|
|
5160
5399
|
function parsePom(xml, filePath) {
|
|
5161
5400
|
const parsed = parser2.parse(xml);
|
|
5162
5401
|
const project = parsed?.project;
|
|
@@ -5296,7 +5535,7 @@ function mavenToSemver(ver) {
|
|
|
5296
5535
|
return semver5.valid(v);
|
|
5297
5536
|
}
|
|
5298
5537
|
var JAVA_MANIFEST_FILES = /* @__PURE__ */ new Set(["pom.xml", "build.gradle", "build.gradle.kts"]);
|
|
5299
|
-
async function scanJavaProjects(rootDir, mavenCache, cache, projectScanTimeout) {
|
|
5538
|
+
async function scanJavaProjects(rootDir, mavenCache, cache, projectScanTimeout, catalog = BUNDLED_RUNTIME_CATALOG) {
|
|
5300
5539
|
const manifestFiles = cache ? await cache.findFiles(rootDir, (name) => JAVA_MANIFEST_FILES.has(name)) : await findJavaManifests(rootDir);
|
|
5301
5540
|
const projectDirs = /* @__PURE__ */ new Map();
|
|
5302
5541
|
for (const f of manifestFiles) {
|
|
@@ -5308,7 +5547,7 @@ async function scanJavaProjects(rootDir, mavenCache, cache, projectScanTimeout)
|
|
|
5308
5547
|
const STUCK_TIMEOUT_MS = projectScanTimeout ?? cache?.projectScanTimeout ?? 18e4;
|
|
5309
5548
|
for (const [dir, files] of projectDirs) {
|
|
5310
5549
|
try {
|
|
5311
|
-
const scanPromise = scanOneJavaProject(dir, files, rootDir, mavenCache, cache);
|
|
5550
|
+
const scanPromise = scanOneJavaProject(dir, files, rootDir, mavenCache, cache, catalog);
|
|
5312
5551
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
5313
5552
|
if (result.ok) {
|
|
5314
5553
|
results.push(result.value);
|
|
@@ -5335,7 +5574,7 @@ async function findJavaManifests(rootDir) {
|
|
|
5335
5574
|
const { findFiles: findFiles2 } = await import("./fs-PXXYZATK-EW5LCUA7.js");
|
|
5336
5575
|
return findFiles2(rootDir, (name) => JAVA_MANIFEST_FILES.has(name));
|
|
5337
5576
|
}
|
|
5338
|
-
async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache) {
|
|
5577
|
+
async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache, catalog) {
|
|
5339
5578
|
const relDir = path6.relative(rootDir, dir) || ".";
|
|
5340
5579
|
let projectName = path6.basename(dir === rootDir ? rootDir : dir);
|
|
5341
5580
|
let javaVersion;
|
|
@@ -5374,14 +5613,19 @@ async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache
|
|
|
5374
5613
|
}
|
|
5375
5614
|
}
|
|
5376
5615
|
let runtimeMajorsBehind;
|
|
5377
|
-
let
|
|
5616
|
+
let runtimeEol;
|
|
5617
|
+
let runtimeEolDate;
|
|
5618
|
+
const javaLts = latestLts(catalog, "java")?.major;
|
|
5619
|
+
const runtimeLatest = javaLts !== void 0 ? String(javaLts) : void 0;
|
|
5378
5620
|
if (javaVersion) {
|
|
5379
5621
|
const jvMatch = javaVersion.match(/^(1\.)?(\d+)/);
|
|
5380
5622
|
if (jvMatch) {
|
|
5381
5623
|
const major11 = jvMatch[1] ? parseInt(jvMatch[2], 10) : parseInt(jvMatch[2], 10);
|
|
5382
|
-
runtimeMajorsBehind = Math.max(0,
|
|
5383
|
-
runtimeLatest = String(LATEST_JAVA_LTS);
|
|
5624
|
+
if (javaLts !== void 0) runtimeMajorsBehind = Math.max(0, javaLts - major11);
|
|
5384
5625
|
}
|
|
5626
|
+
runtimeEol = runtimeEolStatus(catalog, "java", javaVersion);
|
|
5627
|
+
const cycle = extractCycle("java", javaVersion);
|
|
5628
|
+
if (cycle) runtimeEolDate = eolDate(catalog, "java", cycle);
|
|
5385
5629
|
}
|
|
5386
5630
|
const dependencies = [];
|
|
5387
5631
|
const frameworks = [];
|
|
@@ -5394,15 +5638,15 @@ async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache
|
|
|
5394
5638
|
const resolved = await Promise.all(metaPromises);
|
|
5395
5639
|
for (const { key, dep, meta } of resolved) {
|
|
5396
5640
|
const resolvedVersion = mavenToSemver(dep.version);
|
|
5397
|
-
const
|
|
5641
|
+
const latestStable2 = meta.latestStableOverall;
|
|
5398
5642
|
let majorsBehind = null;
|
|
5399
5643
|
let drift = "unknown";
|
|
5400
|
-
if (resolvedVersion &&
|
|
5644
|
+
if (resolvedVersion && latestStable2) {
|
|
5401
5645
|
const currentMajor = semver5.major(resolvedVersion);
|
|
5402
|
-
const latestMajor = semver5.major(
|
|
5646
|
+
const latestMajor = semver5.major(latestStable2);
|
|
5403
5647
|
majorsBehind = latestMajor - currentMajor;
|
|
5404
5648
|
if (majorsBehind === 0) {
|
|
5405
|
-
drift = semver5.eq(resolvedVersion,
|
|
5649
|
+
drift = semver5.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
5406
5650
|
} else if (majorsBehind > 0) {
|
|
5407
5651
|
drift = "major-behind";
|
|
5408
5652
|
} else {
|
|
@@ -5419,7 +5663,7 @@ async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache
|
|
|
5419
5663
|
section: "dependencies",
|
|
5420
5664
|
currentSpec: dep.version,
|
|
5421
5665
|
resolvedVersion,
|
|
5422
|
-
latestStable,
|
|
5666
|
+
latestStable: latestStable2,
|
|
5423
5667
|
majorsBehind,
|
|
5424
5668
|
drift
|
|
5425
5669
|
});
|
|
@@ -5427,7 +5671,7 @@ async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache
|
|
|
5427
5671
|
frameworks.push({
|
|
5428
5672
|
name: KNOWN_JAVA_FRAMEWORKS[key],
|
|
5429
5673
|
currentVersion: resolvedVersion,
|
|
5430
|
-
latestVersion:
|
|
5674
|
+
latestVersion: latestStable2,
|
|
5431
5675
|
majorsBehind
|
|
5432
5676
|
});
|
|
5433
5677
|
}
|
|
@@ -5448,8 +5692,10 @@ async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache
|
|
|
5448
5692
|
path: relDir,
|
|
5449
5693
|
name: projectName,
|
|
5450
5694
|
runtime: javaVersion ? `Java ${javaVersion}` : void 0,
|
|
5451
|
-
runtimeLatest
|
|
5695
|
+
runtimeLatest,
|
|
5452
5696
|
runtimeMajorsBehind,
|
|
5697
|
+
runtimeEol,
|
|
5698
|
+
runtimeEolDate,
|
|
5453
5699
|
targetFramework: javaVersion ? `Java ${javaVersion}` : void 0,
|
|
5454
5700
|
frameworks,
|
|
5455
5701
|
dependencies,
|
|
@@ -5575,7 +5821,6 @@ var KNOWN_RUBY_FRAMEWORKS = {
|
|
|
5575
5821
|
"dotenv": "dotenv",
|
|
5576
5822
|
"figaro": "Figaro"
|
|
5577
5823
|
};
|
|
5578
|
-
var LATEST_RUBY_MINOR = { major: 3, minor: 4 };
|
|
5579
5824
|
function parseGemfileLine(line) {
|
|
5580
5825
|
const trimmed = line.trim();
|
|
5581
5826
|
if (!trimmed || trimmed.startsWith("#")) return null;
|
|
@@ -5665,7 +5910,7 @@ var RUBY_MANIFEST_FILES = /* @__PURE__ */ new Set([
|
|
|
5665
5910
|
function isGemspec(name) {
|
|
5666
5911
|
return name.endsWith(".gemspec");
|
|
5667
5912
|
}
|
|
5668
|
-
async function scanRubyProjects(rootDir, rubygemsCache, cache, projectScanTimeout) {
|
|
5913
|
+
async function scanRubyProjects(rootDir, rubygemsCache, cache, projectScanTimeout, catalog = BUNDLED_RUNTIME_CATALOG) {
|
|
5669
5914
|
const manifestFiles = cache ? await cache.findFiles(rootDir, (name) => RUBY_MANIFEST_FILES.has(name) || isGemspec(name)) : await findRubyManifests(rootDir);
|
|
5670
5915
|
const projectDirs = /* @__PURE__ */ new Map();
|
|
5671
5916
|
for (const f of manifestFiles) {
|
|
@@ -5677,7 +5922,7 @@ async function scanRubyProjects(rootDir, rubygemsCache, cache, projectScanTimeou
|
|
|
5677
5922
|
const STUCK_TIMEOUT_MS = projectScanTimeout ?? cache?.projectScanTimeout ?? 18e4;
|
|
5678
5923
|
for (const [dir, files] of projectDirs) {
|
|
5679
5924
|
try {
|
|
5680
|
-
const scanPromise = scanOneRubyProject(dir, files, rootDir, rubygemsCache, cache);
|
|
5925
|
+
const scanPromise = scanOneRubyProject(dir, files, rootDir, rubygemsCache, cache, catalog);
|
|
5681
5926
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
5682
5927
|
if (result.ok) {
|
|
5683
5928
|
results.push(result.value);
|
|
@@ -5700,7 +5945,7 @@ async function findRubyManifests(rootDir) {
|
|
|
5700
5945
|
const { findFiles: findFiles2 } = await import("./fs-PXXYZATK-EW5LCUA7.js");
|
|
5701
5946
|
return findFiles2(rootDir, (name) => RUBY_MANIFEST_FILES.has(name) || isGemspec(name));
|
|
5702
5947
|
}
|
|
5703
|
-
async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, cache) {
|
|
5948
|
+
async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, cache, catalog) {
|
|
5704
5949
|
const relDir = path7.relative(rootDir, dir) || ".";
|
|
5705
5950
|
let projectName = path7.basename(dir === rootDir ? rootDir : dir);
|
|
5706
5951
|
let rubyVersion;
|
|
@@ -5724,18 +5969,26 @@ async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, ca
|
|
|
5724
5969
|
}
|
|
5725
5970
|
let runtimeMajorsBehind;
|
|
5726
5971
|
let runtimeLatest;
|
|
5972
|
+
let runtimeEol;
|
|
5973
|
+
let runtimeEolDate;
|
|
5727
5974
|
if (rubyVersion) {
|
|
5728
5975
|
const verMatch = rubyVersion.match(/(\d+)\.(\d+)/);
|
|
5729
5976
|
if (verMatch) {
|
|
5730
5977
|
const reqMajor = parseInt(verMatch[1], 10);
|
|
5731
5978
|
const reqMinor = parseInt(verMatch[2], 10);
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
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}`;
|
|
5736
5987
|
}
|
|
5737
|
-
runtimeLatest = `${LATEST_RUBY_MINOR.major}.${LATEST_RUBY_MINOR.minor}`;
|
|
5738
5988
|
}
|
|
5989
|
+
runtimeEol = runtimeEolStatus(catalog, "ruby", rubyVersion);
|
|
5990
|
+
const cycle = extractCycle("ruby", rubyVersion);
|
|
5991
|
+
if (cycle) runtimeEolDate = eolDate(catalog, "ruby", cycle);
|
|
5739
5992
|
}
|
|
5740
5993
|
const dependencies = [];
|
|
5741
5994
|
const frameworks = [];
|
|
@@ -5749,15 +6002,15 @@ async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, ca
|
|
|
5749
6002
|
for (const { dep, meta } of resolved) {
|
|
5750
6003
|
const rawVersion = extractGemVersion(dep.spec);
|
|
5751
6004
|
const resolvedVersion = rawVersion ? rubyVersionToSemver(rawVersion) : null;
|
|
5752
|
-
const
|
|
6005
|
+
const latestStable2 = meta.latestStableOverall;
|
|
5753
6006
|
let majorsBehind = null;
|
|
5754
6007
|
let drift = "unknown";
|
|
5755
|
-
if (resolvedVersion &&
|
|
6008
|
+
if (resolvedVersion && latestStable2) {
|
|
5756
6009
|
const currentMajor = semver6.major(resolvedVersion);
|
|
5757
|
-
const latestMajor = semver6.major(
|
|
6010
|
+
const latestMajor = semver6.major(latestStable2);
|
|
5758
6011
|
majorsBehind = latestMajor - currentMajor;
|
|
5759
6012
|
if (majorsBehind === 0) {
|
|
5760
|
-
drift = semver6.eq(resolvedVersion,
|
|
6013
|
+
drift = semver6.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
5761
6014
|
} else if (majorsBehind > 0) {
|
|
5762
6015
|
drift = "major-behind";
|
|
5763
6016
|
} else {
|
|
@@ -5775,7 +6028,7 @@ async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, ca
|
|
|
5775
6028
|
section,
|
|
5776
6029
|
currentSpec: dep.spec,
|
|
5777
6030
|
resolvedVersion,
|
|
5778
|
-
latestStable,
|
|
6031
|
+
latestStable: latestStable2,
|
|
5779
6032
|
majorsBehind,
|
|
5780
6033
|
drift
|
|
5781
6034
|
});
|
|
@@ -5783,7 +6036,7 @@ async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, ca
|
|
|
5783
6036
|
frameworks.push({
|
|
5784
6037
|
name: KNOWN_RUBY_FRAMEWORKS[dep.name],
|
|
5785
6038
|
currentVersion: resolvedVersion,
|
|
5786
|
-
latestVersion:
|
|
6039
|
+
latestVersion: latestStable2,
|
|
5787
6040
|
majorsBehind
|
|
5788
6041
|
});
|
|
5789
6042
|
}
|
|
@@ -5806,6 +6059,8 @@ async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, ca
|
|
|
5806
6059
|
runtime: rubyVersion,
|
|
5807
6060
|
runtimeLatest,
|
|
5808
6061
|
runtimeMajorsBehind,
|
|
6062
|
+
runtimeEol,
|
|
6063
|
+
runtimeEolDate,
|
|
5809
6064
|
frameworks,
|
|
5810
6065
|
dependencies,
|
|
5811
6066
|
dependencyAgeBuckets: buckets,
|
|
@@ -5963,15 +6218,15 @@ async function scanOneSwiftProject(dir, manifestFile, rootDir, swiftCache, cache
|
|
|
5963
6218
|
for (const { dep, meta } of resolved) {
|
|
5964
6219
|
const resolvedVersionStr = resolvedVersions.get(dep.name.toLowerCase()) ?? (dep.type === "exact" ? dep.version : null);
|
|
5965
6220
|
const resolvedVersion = resolvedVersionStr ? semver7.valid(semver7.clean(resolvedVersionStr)) : null;
|
|
5966
|
-
const
|
|
6221
|
+
const latestStable2 = meta.latestStableOverall;
|
|
5967
6222
|
let majorsBehind = null;
|
|
5968
6223
|
let drift = "unknown";
|
|
5969
|
-
if (resolvedVersion &&
|
|
6224
|
+
if (resolvedVersion && latestStable2) {
|
|
5970
6225
|
const currentMajor = semver7.major(resolvedVersion);
|
|
5971
|
-
const latestMajor = semver7.major(
|
|
6226
|
+
const latestMajor = semver7.major(latestStable2);
|
|
5972
6227
|
majorsBehind = latestMajor - currentMajor;
|
|
5973
6228
|
if (majorsBehind === 0) {
|
|
5974
|
-
drift = semver7.eq(resolvedVersion,
|
|
6229
|
+
drift = semver7.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
5975
6230
|
} else if (majorsBehind > 0) {
|
|
5976
6231
|
drift = "major-behind";
|
|
5977
6232
|
} else {
|
|
@@ -5988,7 +6243,7 @@ async function scanOneSwiftProject(dir, manifestFile, rootDir, swiftCache, cache
|
|
|
5988
6243
|
section: "dependencies",
|
|
5989
6244
|
currentSpec: dep.version,
|
|
5990
6245
|
resolvedVersion,
|
|
5991
|
-
latestStable,
|
|
6246
|
+
latestStable: latestStable2,
|
|
5992
6247
|
majorsBehind,
|
|
5993
6248
|
drift
|
|
5994
6249
|
});
|
|
@@ -5997,7 +6252,7 @@ async function scanOneSwiftProject(dir, manifestFile, rootDir, swiftCache, cache
|
|
|
5997
6252
|
frameworks.push({
|
|
5998
6253
|
name: KNOWN_SWIFT_FRAMEWORKS[lowerName],
|
|
5999
6254
|
currentVersion: resolvedVersion,
|
|
6000
|
-
latestVersion:
|
|
6255
|
+
latestVersion: latestStable2,
|
|
6001
6256
|
majorsBehind
|
|
6002
6257
|
});
|
|
6003
6258
|
}
|
|
@@ -6084,7 +6339,6 @@ var KNOWN_GO_FRAMEWORKS = {
|
|
|
6084
6339
|
"github.com/spf13/cast": "Cast",
|
|
6085
6340
|
"github.com/pkg/errors": "pkg/errors"
|
|
6086
6341
|
};
|
|
6087
|
-
var LATEST_GO_MINOR = { major: 1, minor: 23 };
|
|
6088
6342
|
function parseGoMod(content) {
|
|
6089
6343
|
const deps = [];
|
|
6090
6344
|
let goVersion;
|
|
@@ -6131,14 +6385,14 @@ function parseGoMod(content) {
|
|
|
6131
6385
|
var GO_MANIFEST_FILES = /* @__PURE__ */ new Set([
|
|
6132
6386
|
"go.mod"
|
|
6133
6387
|
]);
|
|
6134
|
-
async function scanGoProjects(rootDir, goCache, cache, projectScanTimeout) {
|
|
6388
|
+
async function scanGoProjects(rootDir, goCache, cache, projectScanTimeout, catalog = BUNDLED_RUNTIME_CATALOG) {
|
|
6135
6389
|
const manifestFiles = cache ? await cache.findFiles(rootDir, (name) => GO_MANIFEST_FILES.has(name)) : await findGoManifests(rootDir);
|
|
6136
6390
|
const results = [];
|
|
6137
6391
|
const STUCK_TIMEOUT_MS = projectScanTimeout ?? cache?.projectScanTimeout ?? 18e4;
|
|
6138
6392
|
for (const manifestFile of manifestFiles) {
|
|
6139
6393
|
const dir = path9.dirname(manifestFile);
|
|
6140
6394
|
try {
|
|
6141
|
-
const scanPromise = scanOneGoProject(dir, manifestFile, rootDir, goCache, cache);
|
|
6395
|
+
const scanPromise = scanOneGoProject(dir, manifestFile, rootDir, goCache, cache, catalog);
|
|
6142
6396
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
6143
6397
|
if (result.ok) {
|
|
6144
6398
|
results.push(result.value);
|
|
@@ -6161,7 +6415,7 @@ async function findGoManifests(rootDir) {
|
|
|
6161
6415
|
const { findFiles: findFiles2 } = await import("./fs-PXXYZATK-EW5LCUA7.js");
|
|
6162
6416
|
return findFiles2(rootDir, (name) => GO_MANIFEST_FILES.has(name));
|
|
6163
6417
|
}
|
|
6164
|
-
async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache) {
|
|
6418
|
+
async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache, catalog) {
|
|
6165
6419
|
const relDir = path9.relative(rootDir, dir) || ".";
|
|
6166
6420
|
const projectName = path9.basename(dir === rootDir ? rootDir : dir);
|
|
6167
6421
|
const content = cache ? await cache.readTextFile(manifestFile) : await readTextFile(manifestFile);
|
|
@@ -6169,18 +6423,26 @@ async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache) {
|
|
|
6169
6423
|
const directDeps = allDeps.filter((d) => !d.indirect);
|
|
6170
6424
|
let runtimeMajorsBehind;
|
|
6171
6425
|
let runtimeLatest;
|
|
6426
|
+
let runtimeEol;
|
|
6427
|
+
let runtimeEolDate;
|
|
6172
6428
|
if (goVersion) {
|
|
6173
6429
|
const verMatch = goVersion.match(/(\d+)\.(\d+)/);
|
|
6174
6430
|
if (verMatch) {
|
|
6175
6431
|
const reqMajor = parseInt(verMatch[1], 10);
|
|
6176
6432
|
const reqMinor = parseInt(verMatch[2], 10);
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
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}`;
|
|
6181
6441
|
}
|
|
6182
|
-
runtimeLatest = `${LATEST_GO_MINOR.major}.${LATEST_GO_MINOR.minor}`;
|
|
6183
6442
|
}
|
|
6443
|
+
runtimeEol = runtimeEolStatus(catalog, "go", goVersion);
|
|
6444
|
+
const cycle = extractCycle("go", goVersion);
|
|
6445
|
+
if (cycle) runtimeEolDate = eolDate(catalog, "go", cycle);
|
|
6184
6446
|
}
|
|
6185
6447
|
const dependencies = [];
|
|
6186
6448
|
const frameworks = [];
|
|
@@ -6192,15 +6454,15 @@ async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache) {
|
|
|
6192
6454
|
const resolved = await Promise.all(metaPromises);
|
|
6193
6455
|
for (const { dep, meta } of resolved) {
|
|
6194
6456
|
const resolvedVersion = semver8.valid(semver8.clean(dep.version));
|
|
6195
|
-
const
|
|
6457
|
+
const latestStable2 = meta.latestStableOverall;
|
|
6196
6458
|
let majorsBehind = null;
|
|
6197
6459
|
let drift = "unknown";
|
|
6198
|
-
if (resolvedVersion &&
|
|
6460
|
+
if (resolvedVersion && latestStable2) {
|
|
6199
6461
|
const currentMajor = semver8.major(resolvedVersion);
|
|
6200
|
-
const latestMajor = semver8.major(
|
|
6462
|
+
const latestMajor = semver8.major(latestStable2);
|
|
6201
6463
|
majorsBehind = latestMajor - currentMajor;
|
|
6202
6464
|
if (majorsBehind === 0) {
|
|
6203
|
-
drift = semver8.eq(resolvedVersion,
|
|
6465
|
+
drift = semver8.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
6204
6466
|
} else if (majorsBehind > 0) {
|
|
6205
6467
|
drift = "major-behind";
|
|
6206
6468
|
} else {
|
|
@@ -6217,7 +6479,7 @@ async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache) {
|
|
|
6217
6479
|
section: "dependencies",
|
|
6218
6480
|
currentSpec: dep.version,
|
|
6219
6481
|
resolvedVersion,
|
|
6220
|
-
latestStable,
|
|
6482
|
+
latestStable: latestStable2,
|
|
6221
6483
|
majorsBehind,
|
|
6222
6484
|
drift
|
|
6223
6485
|
});
|
|
@@ -6225,7 +6487,7 @@ async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache) {
|
|
|
6225
6487
|
frameworks.push({
|
|
6226
6488
|
name: KNOWN_GO_FRAMEWORKS[dep.path],
|
|
6227
6489
|
currentVersion: resolvedVersion,
|
|
6228
|
-
latestVersion:
|
|
6490
|
+
latestVersion: latestStable2,
|
|
6229
6491
|
majorsBehind
|
|
6230
6492
|
});
|
|
6231
6493
|
}
|
|
@@ -6248,6 +6510,8 @@ async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache) {
|
|
|
6248
6510
|
runtime: goVersion,
|
|
6249
6511
|
runtimeLatest,
|
|
6250
6512
|
runtimeMajorsBehind,
|
|
6513
|
+
runtimeEol,
|
|
6514
|
+
runtimeEolDate,
|
|
6251
6515
|
frameworks,
|
|
6252
6516
|
dependencies,
|
|
6253
6517
|
dependencyAgeBuckets: buckets,
|
|
@@ -6420,15 +6684,15 @@ async function scanOneRustProject(dir, manifestFile, rootDir, cargoCache, cache)
|
|
|
6420
6684
|
const resolved = await Promise.all(metaPromises);
|
|
6421
6685
|
for (const { dep, meta } of resolved) {
|
|
6422
6686
|
const resolvedVersion = semver9.valid(semver9.coerce(dep.version));
|
|
6423
|
-
const
|
|
6687
|
+
const latestStable2 = meta.latestStableOverall;
|
|
6424
6688
|
let majorsBehind = null;
|
|
6425
6689
|
let drift = "unknown";
|
|
6426
|
-
if (resolvedVersion &&
|
|
6690
|
+
if (resolvedVersion && latestStable2) {
|
|
6427
6691
|
const currentMajor = semver9.major(resolvedVersion);
|
|
6428
|
-
const latestMajor = semver9.major(
|
|
6692
|
+
const latestMajor = semver9.major(latestStable2);
|
|
6429
6693
|
majorsBehind = latestMajor - currentMajor;
|
|
6430
6694
|
if (majorsBehind === 0) {
|
|
6431
|
-
drift = semver9.eq(resolvedVersion,
|
|
6695
|
+
drift = semver9.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
6432
6696
|
} else if (majorsBehind > 0) {
|
|
6433
6697
|
drift = "major-behind";
|
|
6434
6698
|
} else {
|
|
@@ -6446,7 +6710,7 @@ async function scanOneRustProject(dir, manifestFile, rootDir, cargoCache, cache)
|
|
|
6446
6710
|
section,
|
|
6447
6711
|
currentSpec: dep.version,
|
|
6448
6712
|
resolvedVersion,
|
|
6449
|
-
latestStable,
|
|
6713
|
+
latestStable: latestStable2,
|
|
6450
6714
|
majorsBehind,
|
|
6451
6715
|
drift
|
|
6452
6716
|
});
|
|
@@ -6454,7 +6718,7 @@ async function scanOneRustProject(dir, manifestFile, rootDir, cargoCache, cache)
|
|
|
6454
6718
|
frameworks.push({
|
|
6455
6719
|
name: KNOWN_RUST_FRAMEWORKS[dep.name],
|
|
6456
6720
|
currentVersion: resolvedVersion,
|
|
6457
|
-
latestVersion:
|
|
6721
|
+
latestVersion: latestStable2,
|
|
6458
6722
|
majorsBehind
|
|
6459
6723
|
});
|
|
6460
6724
|
}
|
|
@@ -6660,15 +6924,15 @@ async function scanOnePhpProject(dir, manifestFile, rootDir, composerCache, cach
|
|
|
6660
6924
|
for (const { dep, meta } of resolved) {
|
|
6661
6925
|
const resolvedVersionStr = resolvedVersions.get(dep.name);
|
|
6662
6926
|
const resolvedVersion = resolvedVersionStr ? semver10.valid(semver10.clean(resolvedVersionStr)) : null;
|
|
6663
|
-
const
|
|
6927
|
+
const latestStable2 = meta.latestStableOverall;
|
|
6664
6928
|
let majorsBehind = null;
|
|
6665
6929
|
let drift = "unknown";
|
|
6666
|
-
if (resolvedVersion &&
|
|
6930
|
+
if (resolvedVersion && latestStable2) {
|
|
6667
6931
|
const currentMajor = semver10.major(resolvedVersion);
|
|
6668
|
-
const latestMajor = semver10.major(
|
|
6932
|
+
const latestMajor = semver10.major(latestStable2);
|
|
6669
6933
|
majorsBehind = latestMajor - currentMajor;
|
|
6670
6934
|
if (majorsBehind === 0) {
|
|
6671
|
-
drift = semver10.eq(resolvedVersion,
|
|
6935
|
+
drift = semver10.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
6672
6936
|
} else if (majorsBehind > 0) {
|
|
6673
6937
|
drift = "major-behind";
|
|
6674
6938
|
} else {
|
|
@@ -6686,7 +6950,7 @@ async function scanOnePhpProject(dir, manifestFile, rootDir, composerCache, cach
|
|
|
6686
6950
|
section,
|
|
6687
6951
|
currentSpec: dep.version,
|
|
6688
6952
|
resolvedVersion,
|
|
6689
|
-
latestStable,
|
|
6953
|
+
latestStable: latestStable2,
|
|
6690
6954
|
majorsBehind,
|
|
6691
6955
|
drift
|
|
6692
6956
|
});
|
|
@@ -6694,7 +6958,7 @@ async function scanOnePhpProject(dir, manifestFile, rootDir, composerCache, cach
|
|
|
6694
6958
|
frameworks.push({
|
|
6695
6959
|
name: KNOWN_PHP_FRAMEWORKS[dep.name],
|
|
6696
6960
|
currentVersion: resolvedVersion,
|
|
6697
|
-
latestVersion:
|
|
6961
|
+
latestVersion: latestStable2,
|
|
6698
6962
|
majorsBehind
|
|
6699
6963
|
});
|
|
6700
6964
|
}
|
|
@@ -6926,15 +7190,15 @@ async function scanOneDartProject(dir, manifestFile, rootDir, pubCache, cache) {
|
|
|
6926
7190
|
for (const { dep, meta } of resolved) {
|
|
6927
7191
|
const resolvedVersionStr = resolvedVersions.get(dep.name);
|
|
6928
7192
|
const resolvedVersion = resolvedVersionStr ? semver11.valid(semver11.clean(resolvedVersionStr)) : null;
|
|
6929
|
-
const
|
|
7193
|
+
const latestStable2 = meta.latestStableOverall;
|
|
6930
7194
|
let majorsBehind = null;
|
|
6931
7195
|
let drift = "unknown";
|
|
6932
|
-
if (resolvedVersion &&
|
|
7196
|
+
if (resolvedVersion && latestStable2) {
|
|
6933
7197
|
const currentMajor = semver11.major(resolvedVersion);
|
|
6934
|
-
const latestMajor = semver11.major(
|
|
7198
|
+
const latestMajor = semver11.major(latestStable2);
|
|
6935
7199
|
majorsBehind = latestMajor - currentMajor;
|
|
6936
7200
|
if (majorsBehind === 0) {
|
|
6937
|
-
drift = semver11.eq(resolvedVersion,
|
|
7201
|
+
drift = semver11.eq(resolvedVersion, latestStable2) ? "current" : "minor-behind";
|
|
6938
7202
|
} else if (majorsBehind > 0) {
|
|
6939
7203
|
drift = "major-behind";
|
|
6940
7204
|
} else {
|
|
@@ -6952,7 +7216,7 @@ async function scanOneDartProject(dir, manifestFile, rootDir, pubCache, cache) {
|
|
|
6952
7216
|
section,
|
|
6953
7217
|
currentSpec: dep.version,
|
|
6954
7218
|
resolvedVersion,
|
|
6955
|
-
latestStable,
|
|
7219
|
+
latestStable: latestStable2,
|
|
6956
7220
|
majorsBehind,
|
|
6957
7221
|
drift
|
|
6958
7222
|
});
|
|
@@ -6960,7 +7224,7 @@ async function scanOneDartProject(dir, manifestFile, rootDir, pubCache, cache) {
|
|
|
6960
7224
|
frameworks.push({
|
|
6961
7225
|
name: KNOWN_DART_FRAMEWORKS[dep.name],
|
|
6962
7226
|
currentVersion: resolvedVersion,
|
|
6963
|
-
latestVersion:
|
|
7227
|
+
latestVersion: latestStable2,
|
|
6964
7228
|
majorsBehind
|
|
6965
7229
|
});
|
|
6966
7230
|
}
|
|
@@ -13414,6 +13678,96 @@ async function computeTreeMetadataHash(rootDir, options) {
|
|
|
13414
13678
|
}
|
|
13415
13679
|
return digest.digest("hex");
|
|
13416
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
|
+
};
|
|
13417
13771
|
var ProgressTrace = class _ProgressTrace {
|
|
13418
13772
|
constructor(outPath) {
|
|
13419
13773
|
this.outPath = outPath;
|
|
@@ -13424,8 +13778,8 @@ var ProgressTrace = class _ProgressTrace {
|
|
|
13424
13778
|
flushed = false;
|
|
13425
13779
|
/** Returns a trace when VIBGRATE_TRACE_EVENTS is set, else null. */
|
|
13426
13780
|
static fromEnv() {
|
|
13427
|
-
const
|
|
13428
|
-
return
|
|
13781
|
+
const path35 = process.env.VIBGRATE_TRACE_EVENTS;
|
|
13782
|
+
return path35 ? new _ProgressTrace(path35) : null;
|
|
13429
13783
|
}
|
|
13430
13784
|
record(op, data = {}) {
|
|
13431
13785
|
if (this.flushed) return;
|
|
@@ -13942,7 +14296,7 @@ var ScanProgress = class {
|
|
|
13942
14296
|
var HISTORY_FILENAME = "scan_history.json";
|
|
13943
14297
|
var MAX_RECORDS = 10;
|
|
13944
14298
|
async function loadScanHistory(rootDir) {
|
|
13945
|
-
const filePath =
|
|
14299
|
+
const filePath = path33.join(rootDir, ".vibgrate", HISTORY_FILENAME);
|
|
13946
14300
|
try {
|
|
13947
14301
|
const txt = await fs7.readFile(filePath, "utf8");
|
|
13948
14302
|
const data = JSON.parse(txt);
|
|
@@ -13955,8 +14309,8 @@ async function loadScanHistory(rootDir) {
|
|
|
13955
14309
|
}
|
|
13956
14310
|
}
|
|
13957
14311
|
async function saveScanHistory(rootDir, record2) {
|
|
13958
|
-
const dir =
|
|
13959
|
-
const filePath =
|
|
14312
|
+
const dir = path33.join(rootDir, ".vibgrate");
|
|
14313
|
+
const filePath = path33.join(dir, HISTORY_FILENAME);
|
|
13960
14314
|
let history;
|
|
13961
14315
|
const existing = await loadScanHistory(rootDir);
|
|
13962
14316
|
if (existing) {
|
|
@@ -14024,18 +14378,18 @@ async function discoverSolutions(rootDir, fileCache) {
|
|
|
14024
14378
|
for (const solutionFile of solutionFiles) {
|
|
14025
14379
|
try {
|
|
14026
14380
|
const content = await fileCache.readTextFile(solutionFile);
|
|
14027
|
-
const dir =
|
|
14028
|
-
const rootBasename =
|
|
14029
|
-
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("/");
|
|
14030
14384
|
const projectPaths = /* @__PURE__ */ new Set();
|
|
14031
14385
|
const projectRegex = /Project\("[^"]*"\)\s*=\s*"([^"]*)",\s*"([^"]+\.(?:cs|vb)proj)"/g;
|
|
14032
14386
|
let match;
|
|
14033
14387
|
while ((match = projectRegex.exec(content)) !== null) {
|
|
14034
14388
|
const projectRelative = match[2];
|
|
14035
|
-
const absProjectPath =
|
|
14036
|
-
projectPaths.add(
|
|
14389
|
+
const absProjectPath = path34.resolve(dir, projectRelative.replace(/\\/g, "/"));
|
|
14390
|
+
projectPaths.add(path34.relative(rootDir, absProjectPath).replace(/\\/g, "/"));
|
|
14037
14391
|
}
|
|
14038
|
-
const solutionName =
|
|
14392
|
+
const solutionName = path34.basename(solutionFile, path34.extname(solutionFile));
|
|
14039
14393
|
parsed.push({
|
|
14040
14394
|
path: relSolutionPath,
|
|
14041
14395
|
name: solutionName,
|
|
@@ -14143,6 +14497,9 @@ async function runScan(rootDir, opts) {
|
|
|
14143
14497
|
].join("\n");
|
|
14144
14498
|
throw new Error(msg);
|
|
14145
14499
|
}
|
|
14500
|
+
const runtimeClient = new RuntimeCatalogClient({ offline: offlineMode, manifest: packageManifest });
|
|
14501
|
+
const resolvedRuntimeCatalog = await runtimeClient.resolve();
|
|
14502
|
+
const runtimeCatalog = resolvedRuntimeCatalog.catalog;
|
|
14146
14503
|
const treeCountPromise = quickTreeCount(rootDir, excludePatterns);
|
|
14147
14504
|
progress.startStep("discovery");
|
|
14148
14505
|
const treeCount = await treeCountPromise;
|
|
@@ -14168,7 +14525,7 @@ async function runScan(rootDir, opts) {
|
|
|
14168
14525
|
progress.updateStats({ treeSummary: indexedTreeCount });
|
|
14169
14526
|
}
|
|
14170
14527
|
progress.completeStep("walk", `${treeCount.totalFiles.toLocaleString()} files indexed`);
|
|
14171
|
-
const nodeProjects = await scanNodeProjects(rootDir, npmCache, fileCache, projectScanTimeoutMs);
|
|
14528
|
+
const nodeProjects = await scanNodeProjects(rootDir, npmCache, fileCache, projectScanTimeoutMs, runtimeCatalog);
|
|
14172
14529
|
if (nodeProjects.length > 0) {
|
|
14173
14530
|
progress.insertStepBefore("drift", { id: "node", label: "Found Node projects", weight: 4 });
|
|
14174
14531
|
progress.startStep("node");
|
|
@@ -14180,7 +14537,7 @@ async function runScan(rootDir, opts) {
|
|
|
14180
14537
|
progress.addProjects(nodeProjects.length);
|
|
14181
14538
|
progress.completeStep("node", `${nodeProjects.length} project${nodeProjects.length !== 1 ? "s" : ""}`, nodeProjects.length);
|
|
14182
14539
|
}
|
|
14183
|
-
const dotnetProjects = await scanDotnetProjects(rootDir, nugetCache, fileCache, projectScanTimeoutMs);
|
|
14540
|
+
const dotnetProjects = await scanDotnetProjects(rootDir, nugetCache, fileCache, projectScanTimeoutMs, runtimeCatalog);
|
|
14184
14541
|
if (dotnetProjects.length > 0) {
|
|
14185
14542
|
progress.insertStepBefore("drift", { id: "dotnet", label: "Found .NET projects", weight: 2 });
|
|
14186
14543
|
progress.startStep("dotnet");
|
|
@@ -14192,7 +14549,7 @@ async function runScan(rootDir, opts) {
|
|
|
14192
14549
|
progress.addProjects(dotnetProjects.length);
|
|
14193
14550
|
progress.completeStep("dotnet", `${dotnetProjects.length} project${dotnetProjects.length !== 1 ? "s" : ""}`, dotnetProjects.length);
|
|
14194
14551
|
}
|
|
14195
|
-
const pythonProjects = await scanPythonProjects(rootDir, pypiCache, fileCache, projectScanTimeoutMs);
|
|
14552
|
+
const pythonProjects = await scanPythonProjects(rootDir, pypiCache, fileCache, projectScanTimeoutMs, runtimeCatalog);
|
|
14196
14553
|
if (pythonProjects.length > 0) {
|
|
14197
14554
|
progress.insertStepBefore("drift", { id: "python", label: "Found Python projects", weight: 3 });
|
|
14198
14555
|
progress.startStep("python");
|
|
@@ -14204,7 +14561,7 @@ async function runScan(rootDir, opts) {
|
|
|
14204
14561
|
progress.addProjects(pythonProjects.length);
|
|
14205
14562
|
progress.completeStep("python", `${pythonProjects.length} project${pythonProjects.length !== 1 ? "s" : ""}`, pythonProjects.length);
|
|
14206
14563
|
}
|
|
14207
|
-
const javaProjects = await scanJavaProjects(rootDir, mavenCache, fileCache, projectScanTimeoutMs);
|
|
14564
|
+
const javaProjects = await scanJavaProjects(rootDir, mavenCache, fileCache, projectScanTimeoutMs, runtimeCatalog);
|
|
14208
14565
|
if (javaProjects.length > 0) {
|
|
14209
14566
|
progress.insertStepBefore("drift", { id: "java", label: "Found Java projects", weight: 3 });
|
|
14210
14567
|
progress.startStep("java");
|
|
@@ -14216,7 +14573,7 @@ async function runScan(rootDir, opts) {
|
|
|
14216
14573
|
progress.addProjects(javaProjects.length);
|
|
14217
14574
|
progress.completeStep("java", `${javaProjects.length} project${javaProjects.length !== 1 ? "s" : ""}`, javaProjects.length);
|
|
14218
14575
|
}
|
|
14219
|
-
const rubyProjects = await scanRubyProjects(rootDir, rubygemsCache, fileCache, projectScanTimeoutMs);
|
|
14576
|
+
const rubyProjects = await scanRubyProjects(rootDir, rubygemsCache, fileCache, projectScanTimeoutMs, runtimeCatalog);
|
|
14220
14577
|
if (rubyProjects.length > 0) {
|
|
14221
14578
|
progress.insertStepBefore("drift", { id: "ruby", label: "Found Ruby projects", weight: 2 });
|
|
14222
14579
|
progress.startStep("ruby");
|
|
@@ -14240,7 +14597,7 @@ async function runScan(rootDir, opts) {
|
|
|
14240
14597
|
progress.addProjects(swiftProjects.length);
|
|
14241
14598
|
progress.completeStep("swift", `${swiftProjects.length} project${swiftProjects.length !== 1 ? "s" : ""}`, swiftProjects.length);
|
|
14242
14599
|
}
|
|
14243
|
-
const goProjects = await scanGoProjects(rootDir, goCache, fileCache, projectScanTimeoutMs);
|
|
14600
|
+
const goProjects = await scanGoProjects(rootDir, goCache, fileCache, projectScanTimeoutMs, runtimeCatalog);
|
|
14244
14601
|
if (goProjects.length > 0) {
|
|
14245
14602
|
progress.insertStepBefore("drift", { id: "go", label: "Found Go projects", weight: 2 });
|
|
14246
14603
|
progress.startStep("go");
|
|
@@ -14379,7 +14736,7 @@ async function runScan(rootDir, opts) {
|
|
|
14379
14736
|
for (const project of allProjects) {
|
|
14380
14737
|
project.drift = computeDriftScore([project]);
|
|
14381
14738
|
project.projectId = computeProjectId(project.path, project.name, workspaceId);
|
|
14382
|
-
const absProjectDir =
|
|
14739
|
+
const absProjectDir = path34.resolve(rootDir, project.path);
|
|
14383
14740
|
try {
|
|
14384
14741
|
const source = await fileCache.sourceMetricsUnder(rootDir, absProjectDir);
|
|
14385
14742
|
if (project.fileCount === void 0) project.fileCount = source.fileCount;
|
|
@@ -14393,7 +14750,7 @@ async function runScan(rootDir, opts) {
|
|
|
14393
14750
|
dependencyCount: project.dependencyCount
|
|
14394
14751
|
});
|
|
14395
14752
|
}
|
|
14396
|
-
const solutionsManifestPath =
|
|
14753
|
+
const solutionsManifestPath = path34.join(rootDir, ".vibgrate", "solutions.json");
|
|
14397
14754
|
const persistedSolutionIds = /* @__PURE__ */ new Map();
|
|
14398
14755
|
if (await pathExists(solutionsManifestPath)) {
|
|
14399
14756
|
try {
|
|
@@ -14415,7 +14772,7 @@ async function runScan(rootDir, opts) {
|
|
|
14415
14772
|
const projectsByPath = new Map(allProjects.map((project) => [project.path, project]));
|
|
14416
14773
|
for (const solution of solutions) {
|
|
14417
14774
|
const includedProjects = solution.projectPaths.map((projectPath) => {
|
|
14418
|
-
return projectsByPath.get(projectPath) ?? projectsByPath.get(
|
|
14775
|
+
return projectsByPath.get(projectPath) ?? projectsByPath.get(path34.dirname(projectPath).replace(/\\/g, "/"));
|
|
14419
14776
|
}).filter((project) => Boolean(project));
|
|
14420
14777
|
solution.drift = includedProjects.length > 0 ? computeDriftScore(includedProjects) : void 0;
|
|
14421
14778
|
for (const project of includedProjects) {
|
|
@@ -14630,7 +14987,7 @@ async function runScan(rootDir, opts) {
|
|
|
14630
14987
|
const summary = [`${up.topEvidence.length} evidence`, ...up.capped ? ["capped"] : []].join(" \xB7 ");
|
|
14631
14988
|
progress.completeStep("uipurpose", summary, up.topEvidence.length);
|
|
14632
14989
|
await Promise.all(allProjects.map(async (project) => {
|
|
14633
|
-
const projectDir =
|
|
14990
|
+
const projectDir = path34.join(rootDir, project.path);
|
|
14634
14991
|
const projectResult = await scanUiPurpose(projectDir, fileCache, 150);
|
|
14635
14992
|
if (projectResult.topEvidence.length > 0) {
|
|
14636
14993
|
project.uiPurpose = compactUiPurpose(projectResult);
|
|
@@ -14638,7 +14995,7 @@ async function runScan(rootDir, opts) {
|
|
|
14638
14995
|
}));
|
|
14639
14996
|
}
|
|
14640
14997
|
await Promise.all(allProjects.map(async (project) => {
|
|
14641
|
-
const projectAbsPath =
|
|
14998
|
+
const projectAbsPath = path34.join(rootDir, project.path);
|
|
14642
14999
|
const favicon = await findProjectFavicon(projectAbsPath);
|
|
14643
15000
|
if (favicon) project.faviconBase64 = favicon;
|
|
14644
15001
|
}));
|
|
@@ -14663,7 +15020,7 @@ async function runScan(rootDir, opts) {
|
|
|
14663
15020
|
project.architecture = await scanProjectArchitecture(rootDir, project, fileCache);
|
|
14664
15021
|
}));
|
|
14665
15022
|
for (const solution of solutions) {
|
|
14666
|
-
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));
|
|
14667
15024
|
const memberArchResults = memberProjects.map((p) => p.architecture).filter((a) => Boolean(a));
|
|
14668
15025
|
if (memberArchResults.length > 0) {
|
|
14669
15026
|
solution.architecture = aggregateSolutionArchitecture(memberArchResults);
|
|
@@ -14676,6 +15033,13 @@ async function runScan(rootDir, opts) {
|
|
|
14676
15033
|
);
|
|
14677
15034
|
}
|
|
14678
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
|
+
};
|
|
14679
15043
|
progress.startStep("drift");
|
|
14680
15044
|
const drift = computeDriftScore(allProjects);
|
|
14681
15045
|
progress.completeStep("drift", `${drift.score}/100 \u2014 ${drift.riskLevel} risk`);
|
|
@@ -14747,7 +15111,7 @@ async function runScan(rootDir, opts) {
|
|
|
14747
15111
|
schemaVersion: "1.0",
|
|
14748
15112
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14749
15113
|
vibgrateVersion,
|
|
14750
|
-
rootPath:
|
|
15114
|
+
rootPath: path34.basename(rootDir),
|
|
14751
15115
|
...vcs.type !== "unknown" ? { vcs } : {},
|
|
14752
15116
|
repository,
|
|
14753
15117
|
projects: allProjects,
|
|
@@ -14762,7 +15126,7 @@ async function runScan(rootDir, opts) {
|
|
|
14762
15126
|
billing: summarizeBilling(allProjects)
|
|
14763
15127
|
};
|
|
14764
15128
|
if (opts.baseline) {
|
|
14765
|
-
const baselinePath =
|
|
15129
|
+
const baselinePath = path34.resolve(opts.baseline);
|
|
14766
15130
|
if (await pathExists(baselinePath)) {
|
|
14767
15131
|
try {
|
|
14768
15132
|
const baseline = await readJsonFile(baselinePath);
|
|
@@ -14774,10 +15138,10 @@ async function runScan(rootDir, opts) {
|
|
|
14774
15138
|
}
|
|
14775
15139
|
}
|
|
14776
15140
|
if (!opts.noLocalArtifacts && !maxPrivacyMode) {
|
|
14777
|
-
const vibgrateDir =
|
|
15141
|
+
const vibgrateDir = path34.join(rootDir, ".vibgrate");
|
|
14778
15142
|
await ensureDir(vibgrateDir);
|
|
14779
|
-
await writeJsonFile(
|
|
14780
|
-
await writeJsonFile(
|
|
15143
|
+
await writeJsonFile(path34.join(vibgrateDir, "scan_result.json"), artifact);
|
|
15144
|
+
await writeJsonFile(path34.join(vibgrateDir, "solutions.json"), {
|
|
14781
15145
|
scannedAt: artifact.timestamp,
|
|
14782
15146
|
solutions: solutions.map((solution) => ({
|
|
14783
15147
|
solutionId: solution.solutionId,
|
|
@@ -14816,15 +15180,15 @@ async function runScan(rootDir, opts) {
|
|
|
14816
15180
|
}
|
|
14817
15181
|
}
|
|
14818
15182
|
if (Object.keys(projectScores).length > 0) {
|
|
14819
|
-
const vibgrateDir =
|
|
15183
|
+
const vibgrateDir = path34.join(rootDir, ".vibgrate");
|
|
14820
15184
|
await ensureDir(vibgrateDir);
|
|
14821
|
-
await writeJsonFile(
|
|
15185
|
+
await writeJsonFile(path34.join(vibgrateDir, "project_scores.json"), projectScores);
|
|
14822
15186
|
}
|
|
14823
15187
|
}
|
|
14824
15188
|
if (opts.format === "json") {
|
|
14825
15189
|
const jsonStr = JSON.stringify(artifact, null, 2);
|
|
14826
15190
|
if (opts.out) {
|
|
14827
|
-
await writeTextFile(
|
|
15191
|
+
await writeTextFile(path34.resolve(opts.out), jsonStr);
|
|
14828
15192
|
console.log(chalk3.green("\u2714") + ` JSON written to ${opts.out}`);
|
|
14829
15193
|
} else {
|
|
14830
15194
|
console.log(jsonStr);
|
|
@@ -14833,7 +15197,7 @@ async function runScan(rootDir, opts) {
|
|
|
14833
15197
|
const sarif = formatSarif(artifact);
|
|
14834
15198
|
const sarifStr = JSON.stringify(sarif, null, 2);
|
|
14835
15199
|
if (opts.out) {
|
|
14836
|
-
await writeTextFile(
|
|
15200
|
+
await writeTextFile(path34.resolve(opts.out), sarifStr);
|
|
14837
15201
|
console.log(chalk3.green("\u2714") + ` SARIF written to ${opts.out}`);
|
|
14838
15202
|
} else {
|
|
14839
15203
|
console.log(sarifStr);
|
|
@@ -14842,13 +15206,13 @@ async function runScan(rootDir, opts) {
|
|
|
14842
15206
|
const markdown = formatMarkdown(artifact);
|
|
14843
15207
|
console.log(markdown);
|
|
14844
15208
|
if (opts.out) {
|
|
14845
|
-
await writeTextFile(
|
|
15209
|
+
await writeTextFile(path34.resolve(opts.out), markdown);
|
|
14846
15210
|
}
|
|
14847
15211
|
} else {
|
|
14848
15212
|
const text = formatText(artifact);
|
|
14849
15213
|
console.log(text);
|
|
14850
15214
|
if (opts.out) {
|
|
14851
|
-
await writeTextFile(
|
|
15215
|
+
await writeTextFile(path34.resolve(opts.out), text);
|
|
14852
15216
|
}
|
|
14853
15217
|
}
|
|
14854
15218
|
return artifact;
|
|
@@ -14856,7 +15220,7 @@ async function runScan(rootDir, opts) {
|
|
|
14856
15220
|
async function buildRepositoryInfo(rootDir, remoteUrl, ciSystems) {
|
|
14857
15221
|
const name = await resolveRepositoryName(rootDir);
|
|
14858
15222
|
let version;
|
|
14859
|
-
const packageJsonPath =
|
|
15223
|
+
const packageJsonPath = path34.join(rootDir, "package.json");
|
|
14860
15224
|
if (await pathExists(packageJsonPath)) {
|
|
14861
15225
|
try {
|
|
14862
15226
|
const packageJson = await readJsonFile(packageJsonPath);
|