@visulima/vis 1.0.0-alpha.11 → 1.0.0-alpha.13
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/CHANGELOG.md +101 -0
- package/LICENSE.md +559 -186
- package/README.md +18 -0
- package/dist/bin.js +1 -9
- package/dist/config/index.d.ts +477 -556
- package/dist/config/index.js +1 -2
- package/dist/generate/index.js +1 -3
- package/dist/packem_chunks/applyDefaults.js +2 -336
- package/dist/packem_chunks/bin.js +234 -9552
- package/dist/packem_chunks/doctor-probe.js +2 -112
- package/dist/packem_chunks/fix.js +11 -234
- package/dist/packem_chunks/handler.js +1 -99
- package/dist/packem_chunks/handler10.js +2 -53
- package/dist/packem_chunks/handler11.js +1 -32
- package/dist/packem_chunks/handler12.js +5 -100
- package/dist/packem_chunks/handler13.js +1 -25
- package/dist/packem_chunks/handler14.js +18 -916
- package/dist/packem_chunks/handler15.js +15 -201
- package/dist/packem_chunks/handler16.js +1 -124
- package/dist/packem_chunks/handler17.js +1 -13
- package/dist/packem_chunks/handler18.js +1 -106
- package/dist/packem_chunks/handler19.js +1 -19
- package/dist/packem_chunks/handler2.js +2 -75
- package/dist/packem_chunks/handler20.js +5 -29
- package/dist/packem_chunks/handler21.js +1 -222
- package/dist/packem_chunks/handler22.js +1 -237
- package/dist/packem_chunks/handler23.js +5 -101
- package/dist/packem_chunks/handler24.js +1 -110
- package/dist/packem_chunks/handler25.js +3 -402
- package/dist/packem_chunks/handler26.js +1 -13
- package/dist/packem_chunks/handler27.js +1 -63
- package/dist/packem_chunks/handler28.js +7 -34
- package/dist/packem_chunks/handler29.js +21 -456
- package/dist/packem_chunks/handler3.js +4 -95
- package/dist/packem_chunks/handler30.js +3 -170
- package/dist/packem_chunks/handler31.js +1 -530
- package/dist/packem_chunks/handler32.js +2 -214
- package/dist/packem_chunks/handler33.js +25 -119
- package/dist/packem_chunks/handler34.js +2 -630
- package/dist/packem_chunks/handler35.js +3 -283
- package/dist/packem_chunks/handler36.js +22 -542
- package/dist/packem_chunks/handler37.js +410 -744
- package/dist/packem_chunks/handler38.js +22 -989
- package/dist/packem_chunks/handler39.js +22 -574
- package/dist/packem_chunks/handler4.js +2 -90
- package/dist/packem_chunks/handler40.js +22 -1685
- package/dist/packem_chunks/handler41.js +6 -1088
- package/dist/packem_chunks/handler42.js +5 -797
- package/dist/packem_chunks/handler43.js +10 -2658
- package/dist/packem_chunks/handler44.js +51 -3784
- package/dist/packem_chunks/handler45.js +25 -2574
- package/dist/packem_chunks/handler46.js +3 -3769
- package/dist/packem_chunks/handler47.js +21 -1485
- package/dist/packem_chunks/handler48.js +42 -0
- package/dist/packem_chunks/handler5.js +8 -174
- package/dist/packem_chunks/handler6.js +1 -95
- package/dist/packem_chunks/handler7.js +1 -115
- package/dist/packem_chunks/handler8.js +1 -12
- package/dist/packem_chunks/handler9.js +1 -29
- package/dist/packem_chunks/heal-accept.js +10 -522
- package/dist/packem_chunks/heal.js +14 -673
- package/dist/packem_chunks/index.js +7 -873
- package/dist/packem_chunks/loader.js +1 -23
- package/dist/packem_chunks/tar.js +3 -0
- package/dist/packem_shared/ai-analysis-hm8d2W7z.js +67 -0
- package/dist/packem_shared/ai-cache-DoiF80AR.js +1 -0
- package/dist/packem_shared/ai-fix-nn4zOE95.js +43 -0
- package/dist/packem_shared/cache-directory-CwHlJhgx.js +1 -0
- package/dist/packem_shared/dependency-scan-COr5n63B.js +2 -0
- package/dist/packem_shared/docker-D6OGr5_S.js +2 -0
- package/dist/packem_shared/failure-log-iUVLf6ts.js +2 -0
- package/dist/packem_shared/flakiness-D9wf0t56.js +1 -0
- package/dist/packem_shared/giget-CcEy_Elm.js +2 -0
- package/dist/packem_shared/index-DH-5hsrC.js +1 -0
- package/dist/packem_shared/otel-DxDUPJJH.js +6 -0
- package/dist/packem_shared/otelPlugin-CQq6poq8.js +1 -0
- package/dist/packem_shared/registry-CkubDdiY.js +2 -0
- package/dist/packem_shared/run-summary-utils-BfBvjzhY.js +1 -0
- package/dist/packem_shared/runtime-check-BXZ43CBW.js +1 -0
- package/dist/packem_shared/selectors-BylODRiM.js +3 -0
- package/dist/packem_shared/symbols-CQmER5MT.js +1 -0
- package/dist/packem_shared/toolchain-BgBOUHII.js +5 -0
- package/dist/packem_shared/typosquats-CcZl99B1.js +1 -0
- package/dist/packem_shared/use-measured-height-DjYgUOKk.js +1 -0
- package/dist/packem_shared/utils-DrNg0XTR.js +1 -0
- package/dist/packem_shared/verify-Baj5mFJ7.js +1 -0
- package/dist/packem_shared/vis-update-app-D1jl0UZZ.js +1 -0
- package/dist/packem_shared/xxh3-DrAUNq4n.js +1 -0
- package/index.js +556 -727
- package/package.json +19 -29
- package/schemas/project.schema.json +739 -297
- package/schemas/vis-config.schema.json +3365 -384
- package/templates/buildkite-ci/template.yml +20 -20
- package/dist/packem_shared/VisUpdateApp-D-Yz_wvg.js +0 -1316
- package/dist/packem_shared/_commonjsHelpers-BqLXS_qQ.js +0 -5
- package/dist/packem_shared/ai-analysis-CHeB1joD.js +0 -367
- package/dist/packem_shared/ai-cache-Be_jexe4.js +0 -142
- package/dist/packem_shared/ai-fix-B9iQVcD2.js +0 -379
- package/dist/packem_shared/cache-directory-2qvs4goY.js +0 -98
- package/dist/packem_shared/catalog-BJTtyi-O.js +0 -1371
- package/dist/packem_shared/dependency-scan-A0KSklpG.js +0 -188
- package/dist/packem_shared/docker-2iZzc280.js +0 -181
- package/dist/packem_shared/failure-log-Cz3Z4SKL.js +0 -100
- package/dist/packem_shared/flakiness-goTxXuCX.js +0 -180
- package/dist/packem_shared/otel-DCvqCTz_.js +0 -158
- package/dist/packem_shared/otelPlugin-DFaLDvJf.js +0 -3
- package/dist/packem_shared/registry-CbqXI0rc.js +0 -272
- package/dist/packem_shared/run-summary-utils-PVMl4aIh.js +0 -130
- package/dist/packem_shared/runtime-check-Cobi3p6l.js +0 -127
- package/dist/packem_shared/selectors-SM69TfqC.js +0 -194
- package/dist/packem_shared/symbols-Ta7g2nU-.js +0 -14
- package/dist/packem_shared/toolchain-BdZd9eBi.js +0 -975
- package/dist/packem_shared/typosquats-C-bCh3PX.js +0 -1210
- package/dist/packem_shared/use-measured-height-CNP0vT4M.js +0 -20
- package/dist/packem_shared/utils-CthVdBPS.js +0 -40
- package/dist/packem_shared/xxh3-Ck8mXNg1.js +0 -239
|
@@ -1,458 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
var re=Object.defineProperty;var V=(t,n)=>re(t,"name",{value:n,configurable:!0});import{dim as b,yellow as Y,cyan as Z,magenta as _,red as ee}from"@visulima/colorize";import{isAccessibleSync as G,readFileSync as B,writeFileSync as Q}from"@visulima/fs";import{readYamlSync as se}from"@visulima/fs/yaml";import{join as H}from"@visulima/path";import{r as oe,R as ae,A as ce,p as a,V as le,b as de,U as ue,t as ge,F as W}from"./bin.js";import{l as fe,f as pe,s as he}from"../packem_shared/dependency-scan-COr5n63B.js";var ve=Object.defineProperty,S=V((t,n)=>ve(t,"name",{value:n,configurable:!0}),"o");const L=S(t=>Array.isArray(t)?t.filter(n=>typeof n=="string"):[],"toStringArray"),K=S((t,n)=>{for(const r of n)if(r===t||r.endsWith("*")&&t.startsWith(r.slice(0,-1)))return!0;return!1},"matchesGlobList"),te=S(t=>{const n=H(t,"pnpm-workspace.yaml");if(!G(n))return{excludedPackages:[],ignoredAdvisories:[]};try{const r=se(n);return{excludedPackages:[],ignoredAdvisories:[...L(r?.auditConfig?.ignoreCves),...L(r?.auditConfig?.ignoreGhsas)]}}catch{return{excludedPackages:[],ignoredAdvisories:[]}}},"readPnpmAuditExclusions"),ne=S(t=>{const n=H(t,".yarnrc.yml");if(!G(n))return{excludedPackages:[],ignoredAdvisories:[]};try{const r=se(n);return{excludedPackages:L(r?.npmAuditExcludePackages),ignoredAdvisories:L(r?.npmAuditIgnoreAdvisories)}}catch{return{excludedPackages:[],ignoredAdvisories:[]}}},"readYarnAuditExclusions"),me=S((t,n)=>{switch(n){case"pnpm":return te(t);case"yarn":return ne(t);default:return{excludedPackages:[],ignoredAdvisories:[]}}},"readNativeAuditExclusions"),X=S((t,n,r)=>{if(K(t,n.ignoredAdvisories))return!0;if(r){for(const l of r)if(K(l,n.ignoredAdvisories))return!0}return!1},"isAdvisoryExcluded"),$e=S((t,n)=>K(t,n.excludedPackages),"isPackageExcluded"),ke=S((t,n,r)=>{if(r.length===0)return["No advisory IDs to sync."];const l=[];switch(t){case"bun":{l.push(`bun has no audit config file. Use CLI flags: bun audit ${r.map(f=>`--ignore ${f}`).join(" ")}`);break}case"npm":{l.push("npm has no native audit exclusion config. vis accepted risks are the only layer.");break}case"pnpm":{const f=H(n,"pnpm-workspace.yaml");if(!G(f)){l.push("pnpm-workspace.yaml not found. Cannot sync.");break}const h=te(n),k=new Set(h.ignoredAdvisories.filter(c=>c.startsWith("CVE-"))),m=new Set(h.ignoredAdvisories.filter(c=>c.startsWith("GHSA-"))),y=r.filter(c=>c.startsWith("CVE-")),$=r.filter(c=>c.startsWith("GHSA-")),p=[...new Set([...k,...y])],d=[...new Set([...m,...$])],v=y.filter(c=>!k.has(c)).length,w=$.filter(c=>!m.has(c)).length;if(v===0&&w===0){l.push("All advisory IDs already present in pnpm-workspace.yaml.");break}let g=B(f);if(p.length>0){const c=` ignoreCves:
|
|
2
|
+
${p.map(x=>` - ${x}`).join(`
|
|
3
|
+
`)}
|
|
4
|
+
`;/auditConfig:/.test(g)?g=/ignoreCves:/.test(g)?g.replace(/ignoreCves:\s*\n(?:\s+-\s+(?:\S.*|[\t\v\f \u00A0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF])\n)*/,c):g.replace(/auditConfig:\s*\n/,`auditConfig:
|
|
5
|
+
${c}`):g=`${g.trimEnd()}
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
auditConfig:
|
|
8
|
+
${c}`,v>0&&l.push(`Added ${String(v)} new CVE${v===1?"":"s"} to pnpm-workspace.yaml (${String(p.length)} total)`)}if(d.length>0){const c=` ignoreGhsas:
|
|
9
|
+
${d.map(x=>` - ${x}`).join(`
|
|
10
|
+
`)}
|
|
11
|
+
`;/auditConfig:/.test(g)&&(g=/ignoreGhsas:/.test(g)?g.replace(/ignoreGhsas:\s*\n(?:\s+-\s+(?:\S.*|[\t\v\f \u00A0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF])\n)*/,c):g.replace(/(auditConfig:[\s\S]*?)(\n\S|\n?$)/m,`$1${c}$2`)),w>0&&l.push(`Added ${String(w)} new GHSA${w===1?"":"s"} to pnpm-workspace.yaml (${String(d.length)} total)`)}Q(f,g);break}case"yarn":{const f=H(n,".yarnrc.yml");if(!G(f)){l.push(".yarnrc.yml not found. Cannot sync.");break}const h=ne(n),k=new Set(h.ignoredAdvisories),m=[...new Set([...k,...r])],y=r.filter(d=>!k.has(d)).length;if(y===0){l.push("All advisory IDs already present in .yarnrc.yml.");break}let $=B(f);const p=`npmAuditIgnoreAdvisories:
|
|
12
|
+
${m.map(d=>` - "${d}"`).join(`
|
|
13
|
+
`)}
|
|
14
|
+
`;$=/npmAuditIgnoreAdvisories:/.test($)?$.replace(/npmAuditIgnoreAdvisories:\s*\n(?:\s+-\s+(?:\S.*|[\t\v\f \u00A0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF])\n)*/,p):`${$.trimEnd()}
|
|
4
15
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return __cjs_getProcess.getBuiltinModule(module);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
// Fallback to createRequire
|
|
17
|
-
return __cjs_require(module);
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const {
|
|
21
|
-
createInterface
|
|
22
|
-
} = __cjs_getBuiltinModule("node:readline");
|
|
23
|
-
import { green, dim, red, yellow } from '@visulima/colorize';
|
|
24
|
-
import { readJsonSync, writeJsonSync } from '@visulima/fs';
|
|
25
|
-
import { findPackageManagerSync } from '@visulima/package';
|
|
26
|
-
import { join } from '@visulima/path';
|
|
27
|
-
import { coerce } from 'semver';
|
|
28
|
-
import { r as resolveInstaller, F as runAdd, a as buildSocketOptions, p as pail, f as fetchSocketReports, d as discoverWorkspace, x as runInstall, t as findAcceptedRisk, G as formatReportSummary, H as scoreLabel, I as formatAcceptedRiskSnippet, J as getFullPackageName, j as scoreColor, D as DEFAULT_LOW_SCORE_THRESHOLD } from './bin.js';
|
|
29
|
-
import { r as runTyposquatCheck } from '../packem_shared/typosquats-C-bCh3PX.js';
|
|
30
|
-
import { r as readCatalogs } from '../packem_shared/catalog-BJTtyi-O.js';
|
|
31
|
-
import { p as parsePackageArgument, t as toStringArray } from '../packem_shared/utils-CthVdBPS.js';
|
|
32
|
-
|
|
33
|
-
const buildCatalogRef = (catalogName) => catalogName === "default" ? "catalog:" : `catalog:${catalogName}`;
|
|
34
|
-
const labelForCatalog = (catalogName) => catalogName === "default" ? "default catalog" : `catalog "${catalogName}"`;
|
|
35
|
-
const resolveFromCatalogs = (name, catalogs) => {
|
|
36
|
-
const matchedCatalogs = [];
|
|
37
|
-
for (const [key, deps] of catalogs) {
|
|
38
|
-
if (key.includes(":")) {
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
if (deps.has(name)) {
|
|
42
|
-
matchedCatalogs.push(key);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
if (matchedCatalogs.length === 0) {
|
|
46
|
-
return void 0;
|
|
47
|
-
}
|
|
48
|
-
if (matchedCatalogs.length === 1) {
|
|
49
|
-
const [only] = matchedCatalogs;
|
|
50
|
-
return { source: labelForCatalog(only), spec: buildCatalogRef(only) };
|
|
51
|
-
}
|
|
52
|
-
const preferred = matchedCatalogs.find((c) => c === "default") ?? matchedCatalogs[0];
|
|
53
|
-
const others = matchedCatalogs.filter((c) => c !== preferred);
|
|
54
|
-
return {
|
|
55
|
-
candidates: [...matchedCatalogs],
|
|
56
|
-
conflict: true,
|
|
57
|
-
source: `${labelForCatalog(preferred)} (also in: ${others.map(labelForCatalog).join(", ")})`,
|
|
58
|
-
spec: buildCatalogRef(preferred)
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
const resolveFromSiblings = (name, catalogs) => {
|
|
62
|
-
const tally = /* @__PURE__ */ new Map();
|
|
63
|
-
for (const [key, deps] of catalogs) {
|
|
64
|
-
if (!key.includes(":")) {
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
const range = deps.get(name);
|
|
68
|
-
if (range !== void 0) {
|
|
69
|
-
tally.set(range, (tally.get(range) ?? 0) + 1);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
if (tally.size === 0) {
|
|
73
|
-
return void 0;
|
|
74
|
-
}
|
|
75
|
-
const entries = [...tally.entries()];
|
|
76
|
-
const total = entries.reduce((a, [, count]) => a + count, 0);
|
|
77
|
-
if (entries.length === 1) {
|
|
78
|
-
const [[range]] = entries;
|
|
79
|
-
return {
|
|
80
|
-
source: `siblings (${String(total)} pkg${total === 1 ? "" : "s"} on ${range})`,
|
|
81
|
-
spec: range
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
const sorted = [...entries].sort((a, b) => b[1] - a[1]);
|
|
85
|
-
const [chosen, chosenCount] = sorted[0];
|
|
86
|
-
const others = sorted.slice(1).map(([range, count]) => `${range} (×${String(count)})`);
|
|
87
|
-
return {
|
|
88
|
-
candidates: sorted.map(([range]) => range),
|
|
89
|
-
conflict: true,
|
|
90
|
-
source: `siblings (most common: ${chosen} ×${String(chosenCount)}; conflicts: ${others.join(", ")})`,
|
|
91
|
-
spec: chosen
|
|
92
|
-
};
|
|
93
|
-
};
|
|
94
|
-
const conformToCatalog = (name, catalogs) => {
|
|
95
|
-
const fromCatalog = resolveFromCatalogs(name, catalogs);
|
|
96
|
-
if (fromCatalog) {
|
|
97
|
-
return fromCatalog;
|
|
98
|
-
}
|
|
99
|
-
return resolveFromSiblings(name, catalogs);
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const resolveLatestVersions = async (packageNames, timeoutMs = 1e4) => {
|
|
103
|
-
const results = /* @__PURE__ */ new Map();
|
|
104
|
-
const controller = new AbortController();
|
|
105
|
-
const timeout = setTimeout(() => {
|
|
106
|
-
controller.abort();
|
|
107
|
-
}, timeoutMs);
|
|
108
|
-
try {
|
|
109
|
-
const fetches = packageNames.map(async (name) => {
|
|
110
|
-
try {
|
|
111
|
-
const response = await fetch(`https://registry.npmjs.org/${name}/latest`, {
|
|
112
|
-
headers: { Accept: "application/json" },
|
|
113
|
-
signal: controller.signal
|
|
114
|
-
});
|
|
115
|
-
if (response.ok) {
|
|
116
|
-
const data = await response.json();
|
|
117
|
-
if (data.version) {
|
|
118
|
-
results.set(name, data.version);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
} catch {
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
await Promise.all(fetches);
|
|
125
|
-
} finally {
|
|
126
|
-
clearTimeout(timeout);
|
|
127
|
-
}
|
|
128
|
-
return results;
|
|
129
|
-
};
|
|
130
|
-
const displaySecurityReports = (reports, minimumScore, acceptedRisks) => {
|
|
131
|
-
const lowScorePackages = [];
|
|
132
|
-
for (const report of reports.values()) {
|
|
133
|
-
const { overall } = report.score;
|
|
134
|
-
const color = scoreColor(overall);
|
|
135
|
-
const pct = `${String(Math.round(overall * 100))}%`;
|
|
136
|
-
const alertCount = report.alerts.length;
|
|
137
|
-
const fullName = getFullPackageName(report);
|
|
138
|
-
const accepted = findAcceptedRisk(fullName, report.version, acceptedRisks);
|
|
139
|
-
const colorFunction = color === "red" ? red : color === "yellow" ? yellow : green;
|
|
140
|
-
if (accepted) {
|
|
141
|
-
pail.info(` ${colorFunction(pct)} ${formatReportSummary(report)} ${dim(`[accepted: ${accepted.reason}]`)}`);
|
|
142
|
-
} else {
|
|
143
|
-
pail.info(` ${colorFunction(pct)} ${formatReportSummary(report)}`);
|
|
144
|
-
}
|
|
145
|
-
if (alertCount > 0) {
|
|
146
|
-
const critHigh = report.alerts.filter((a) => a.severity === "critical" || a.severity === "high").length;
|
|
147
|
-
if (critHigh > 0) {
|
|
148
|
-
pail.warn(` ${String(critHigh)} critical/high alert${critHigh === 1 ? "" : "s"}`);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
if (overall < minimumScore && !accepted) {
|
|
152
|
-
lowScorePackages.push(report);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return lowScorePackages;
|
|
156
|
-
};
|
|
157
|
-
const confirmLowScorePackages = async (lowScorePackages, minimumScore) => {
|
|
158
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
159
|
-
const ask = (question) => new Promise((resolve) => {
|
|
160
|
-
rl.question(question, (answer2) => {
|
|
161
|
-
resolve(answer2.trim());
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
const pct = String(Math.round(minimumScore * 100));
|
|
165
|
-
pail.warn("");
|
|
166
|
-
pail.warn(`${String(lowScorePackages.length)} package${lowScorePackages.length === 1 ? "" : "s"} scored below the minimum threshold (${pct}%):`);
|
|
167
|
-
for (const report of lowScorePackages) {
|
|
168
|
-
const name = getFullPackageName(report);
|
|
169
|
-
const score = `${String(Math.round(report.score.overall * 100))}%`;
|
|
170
|
-
pail.warn(` • ${name}@${report.version} — score: ${score} (${scoreLabel(report.score.overall)})`);
|
|
171
|
-
}
|
|
172
|
-
pail.warn("");
|
|
173
|
-
const answer = await ask("Continue adding these packages? [y/N] ");
|
|
174
|
-
if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
|
|
175
|
-
rl.close();
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
const rememberAnswer = await ask("Remember this decision? (prints config snippet) [y/N] ");
|
|
179
|
-
rl.close();
|
|
180
|
-
if (rememberAnswer.toLowerCase() === "y" || rememberAnswer.toLowerCase() === "yes") {
|
|
181
|
-
pail.notice("");
|
|
182
|
-
pail.notice("Add the following to security.socket.acceptedRisks in vis.config.ts:");
|
|
183
|
-
pail.notice("");
|
|
184
|
-
for (const report of lowScorePackages) {
|
|
185
|
-
const fullName = getFullPackageName(report);
|
|
186
|
-
const snippet = formatAcceptedRiskSnippet(fullName, report.version, report.score.overall, "Reviewed and accepted");
|
|
187
|
-
pail.notice(snippet);
|
|
188
|
-
}
|
|
189
|
-
pail.notice("");
|
|
190
|
-
}
|
|
191
|
-
return true;
|
|
192
|
-
};
|
|
193
|
-
const runSocketPreCheck = async (packages, socketOptions, minimumScore, acceptedRisks) => {
|
|
194
|
-
const parsed = packages.map(parsePackageArgument);
|
|
195
|
-
const coercedSpecs = /* @__PURE__ */ new Map();
|
|
196
|
-
for (const p of parsed) {
|
|
197
|
-
if (p.versionSpec) {
|
|
198
|
-
const coerced = coerce(p.versionSpec);
|
|
199
|
-
if (coerced) {
|
|
200
|
-
coercedSpecs.set(p.name, coerced.version);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
const needsResolution = parsed.filter((p) => !coercedSpecs.has(p.name)).map((p) => p.name);
|
|
205
|
-
const resolvedVersions = needsResolution.length > 0 ? await resolveLatestVersions(needsResolution) : /* @__PURE__ */ new Map();
|
|
206
|
-
const lookupPackages = [];
|
|
207
|
-
for (const p of parsed) {
|
|
208
|
-
const version = coercedSpecs.get(p.name) ?? resolvedVersions.get(p.name);
|
|
209
|
-
if (version) {
|
|
210
|
-
lookupPackages.push({ name: p.name, version });
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
if (lookupPackages.length === 0) {
|
|
214
|
-
return true;
|
|
215
|
-
}
|
|
216
|
-
pail.info("");
|
|
217
|
-
pail.info("Socket.dev security check:");
|
|
218
|
-
const reports = await fetchSocketReports(lookupPackages, socketOptions);
|
|
219
|
-
if (reports.size === 0) {
|
|
220
|
-
pail.info(" Could not fetch security data. Proceeding.");
|
|
221
|
-
return true;
|
|
222
|
-
}
|
|
223
|
-
const lowScorePackages = displaySecurityReports(reports, minimumScore, acceptedRisks);
|
|
224
|
-
if (lowScorePackages.length === 0) {
|
|
225
|
-
pail.info("");
|
|
226
|
-
return true;
|
|
227
|
-
}
|
|
228
|
-
if (!process.stdin.isTTY) {
|
|
229
|
-
pail.warn(
|
|
230
|
-
`Aborting: ${String(lowScorePackages.length)} package${lowScorePackages.length === 1 ? "" : "s"} below minimum score. Use --no-socket-check to skip.`
|
|
231
|
-
);
|
|
232
|
-
return false;
|
|
233
|
-
}
|
|
234
|
-
return confirmLowScorePackages(lowScorePackages, minimumScore);
|
|
235
|
-
};
|
|
236
|
-
const SIBLING_SECTIONS = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];
|
|
237
|
-
const pickDepSection = (options) => {
|
|
238
|
-
if (options.savePeer) {
|
|
239
|
-
return "peerDependencies";
|
|
240
|
-
}
|
|
241
|
-
if (options.saveOptional) {
|
|
242
|
-
return "optionalDependencies";
|
|
243
|
-
}
|
|
244
|
-
if (options.saveDev) {
|
|
245
|
-
return "devDependencies";
|
|
246
|
-
}
|
|
247
|
-
return "dependencies";
|
|
248
|
-
};
|
|
249
|
-
const applyExactPrefix = (spec, exact) => {
|
|
250
|
-
if (spec.startsWith("catalog:")) {
|
|
251
|
-
return spec;
|
|
252
|
-
}
|
|
253
|
-
if (!exact) {
|
|
254
|
-
return spec;
|
|
255
|
-
}
|
|
256
|
-
return spec.replace(/^[\^~]/, "");
|
|
257
|
-
};
|
|
258
|
-
const planConformedSpecs = async (packages, catalogs) => {
|
|
259
|
-
const slots = [];
|
|
260
|
-
for (const argument of packages) {
|
|
261
|
-
const { name, versionSpec } = parsePackageArgument(argument);
|
|
262
|
-
if (!name) {
|
|
263
|
-
continue;
|
|
264
|
-
}
|
|
265
|
-
if (versionSpec !== void 0) {
|
|
266
|
-
slots.push({ explicit: versionSpec, name });
|
|
267
|
-
continue;
|
|
268
|
-
}
|
|
269
|
-
const conformed = conformToCatalog(name, catalogs);
|
|
270
|
-
if (conformed) {
|
|
271
|
-
if (conformed.conflict) {
|
|
272
|
-
pail.warn(`${name}: ambiguous constraint — picking ${conformed.spec} (${conformed.source}). Pass ${name}@<version> to override.`);
|
|
273
|
-
}
|
|
274
|
-
slots.push({ entry: { name, source: conformed.source, spec: conformed.spec }, kind: "resolved", name });
|
|
275
|
-
continue;
|
|
276
|
-
}
|
|
277
|
-
slots.push({ kind: "missing", name });
|
|
278
|
-
}
|
|
279
|
-
const missingNames = slots.filter((s) => "kind" in s && s.kind === "missing").map((s) => s.name);
|
|
280
|
-
const latest = missingNames.length > 0 ? await resolveLatestVersions(missingNames) : /* @__PURE__ */ new Map();
|
|
281
|
-
return slots.map((slot) => {
|
|
282
|
-
if ("explicit" in slot) {
|
|
283
|
-
return { name: slot.name, source: "explicit", spec: slot.explicit };
|
|
284
|
-
}
|
|
285
|
-
if (slot.kind === "resolved") {
|
|
286
|
-
return slot.entry;
|
|
287
|
-
}
|
|
288
|
-
const version = latest.get(slot.name);
|
|
289
|
-
if (version === void 0) {
|
|
290
|
-
throw new Error(`--to: cannot resolve a version for "${slot.name}" (not in any catalog or sibling, and registry lookup failed). Pass ${slot.name}@<version> explicitly.`);
|
|
291
|
-
}
|
|
292
|
-
const spec = `^${version}`;
|
|
293
|
-
pail.info(`${slot.name}: no existing constraint — using registry latest (${spec}). Add to a catalog to share this version across workspace packages.`);
|
|
294
|
-
return { name: slot.name, source: "registry latest", spec };
|
|
295
|
-
});
|
|
296
|
-
};
|
|
297
|
-
const applyPlannedSpecsToPackageJson = (pkgJson, planned, section, exact) => {
|
|
298
|
-
for (const { name, spec } of planned) {
|
|
299
|
-
const finalSpec = applyExactPrefix(spec, exact);
|
|
300
|
-
for (const otherSection of SIBLING_SECTIONS) {
|
|
301
|
-
if (otherSection === section) {
|
|
302
|
-
continue;
|
|
303
|
-
}
|
|
304
|
-
const block2 = pkgJson[otherSection];
|
|
305
|
-
if (block2?.[name] !== void 0) {
|
|
306
|
-
delete block2[name];
|
|
307
|
-
if (Object.keys(block2).length === 0) {
|
|
308
|
-
delete pkgJson[otherSection];
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
let block = pkgJson[section];
|
|
313
|
-
if (block === void 0) {
|
|
314
|
-
block = {};
|
|
315
|
-
pkgJson[section] = block;
|
|
316
|
-
}
|
|
317
|
-
block[name] = finalSpec;
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
const applyConformedAdd = async ({
|
|
321
|
-
ignoreScripts,
|
|
322
|
-
logger,
|
|
323
|
-
options,
|
|
324
|
-
packages,
|
|
325
|
-
pm,
|
|
326
|
-
target,
|
|
327
|
-
visConfig,
|
|
328
|
-
workspaceRoot
|
|
329
|
-
}) => {
|
|
330
|
-
const { workspace } = discoverWorkspace(workspaceRoot, visConfig ?? {});
|
|
331
|
-
const project = workspace.projects[target];
|
|
332
|
-
if (!project) {
|
|
333
|
-
const available = Object.keys(workspace.projects).sort();
|
|
334
|
-
throw new Error(
|
|
335
|
-
`--to: workspace package "${target}" not found. Available: ${available.length > 0 ? available.slice(0, 10).join(", ") : "(none)"}${available.length > 10 ? `, ... (${String(available.length - 10)} more)` : ""}.`
|
|
336
|
-
);
|
|
337
|
-
}
|
|
338
|
-
const targetPkgPath = join(workspaceRoot, project.root, "package.json");
|
|
339
|
-
const { packageManager } = findPackageManagerSync(workspaceRoot);
|
|
340
|
-
const catalogs = readCatalogs(workspaceRoot, packageManager);
|
|
341
|
-
const section = pickDepSection(options);
|
|
342
|
-
const exact = options.exact ?? false;
|
|
343
|
-
const planned = await planConformedSpecs(packages, catalogs);
|
|
344
|
-
if (planned.length === 0) {
|
|
345
|
-
return 0;
|
|
346
|
-
}
|
|
347
|
-
const pkgJson = readJsonSync(targetPkgPath);
|
|
348
|
-
applyPlannedSpecsToPackageJson(pkgJson, planned, section, exact);
|
|
349
|
-
writeJsonSync(targetPkgPath, pkgJson, { detectIndent: true, overwrite: true });
|
|
350
|
-
for (const entry of planned) {
|
|
351
|
-
const finalSpec = applyExactPrefix(entry.spec, exact);
|
|
352
|
-
pail.info(`${green("+")} ${entry.name}@${finalSpec} → ${target}/${section} (${dim(entry.source)})`);
|
|
353
|
-
}
|
|
354
|
-
return runInstall(
|
|
355
|
-
pm,
|
|
356
|
-
{
|
|
357
|
-
dev: false,
|
|
358
|
-
filter: [],
|
|
359
|
-
force: false,
|
|
360
|
-
frozenLockfile: false,
|
|
361
|
-
ignoreScripts,
|
|
362
|
-
lockfileOnly: false,
|
|
363
|
-
noOptional: false,
|
|
364
|
-
offline: false,
|
|
365
|
-
prod: false,
|
|
366
|
-
recursive: false,
|
|
367
|
-
silent: false,
|
|
368
|
-
workspaceRoot: false
|
|
369
|
-
},
|
|
370
|
-
workspaceRoot,
|
|
371
|
-
logger
|
|
372
|
-
);
|
|
373
|
-
};
|
|
374
|
-
const execute = async ({ argument, logger, options, visConfig, workspaceRoot: wsRoot }) => {
|
|
375
|
-
let packages = argument;
|
|
376
|
-
if (!packages || packages.length === 0) {
|
|
377
|
-
throw new Error("No packages specified. Usage: vis add <packages...>");
|
|
378
|
-
}
|
|
379
|
-
if (!options.noTyposquatCheck) {
|
|
380
|
-
const parsed = packages.map((p) => parsePackageArgument(p));
|
|
381
|
-
const result = await runTyposquatCheck(
|
|
382
|
-
parsed.map((p) => p.name),
|
|
383
|
-
visConfig?.security?.typosquatAllowlist
|
|
384
|
-
);
|
|
385
|
-
if (!result.ok) {
|
|
386
|
-
process.exitCode = 1;
|
|
387
|
-
return;
|
|
388
|
-
}
|
|
389
|
-
packages = parsed.map((p, i) => {
|
|
390
|
-
const corrected = result.packages[i];
|
|
391
|
-
if (corrected !== p.name) {
|
|
392
|
-
return p.versionSpec ? `${corrected}@${p.versionSpec}` : corrected ?? "";
|
|
393
|
-
}
|
|
394
|
-
return packages[i] ?? "";
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
if (!options.noSocketCheck) {
|
|
398
|
-
const socketOptions = buildSocketOptions(visConfig?.security?.socket);
|
|
399
|
-
if (socketOptions) {
|
|
400
|
-
const minimumScore = socketOptions.minimumScore ?? DEFAULT_LOW_SCORE_THRESHOLD;
|
|
401
|
-
const shouldContinue = await runSocketPreCheck(packages, socketOptions, minimumScore, visConfig?.security?.socket?.acceptedRisks);
|
|
402
|
-
if (!shouldContinue) {
|
|
403
|
-
process.exitCode = 1;
|
|
404
|
-
return;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
const cwd = process.cwd();
|
|
409
|
-
const pm = resolveInstaller(wsRoot ?? cwd, { configBackend: visConfig?.install?.backend });
|
|
410
|
-
const ignoreScripts = !options.runScripts;
|
|
411
|
-
if (options.to) {
|
|
412
|
-
if (options.global || options.workspaceRoot) {
|
|
413
|
-
throw new Error("--to is incompatible with --global / --workspace-root.");
|
|
414
|
-
}
|
|
415
|
-
if (options.filter && toStringArray(options.filter).length > 0) {
|
|
416
|
-
throw new Error("--to and --filter are mutually exclusive — --to already targets one package.");
|
|
417
|
-
}
|
|
418
|
-
if (!wsRoot) {
|
|
419
|
-
throw new Error("--to requires a monorepo workspace. Run from inside a pnpm/bun/yarn/npm workspace.");
|
|
420
|
-
}
|
|
421
|
-
const code2 = await applyConformedAdd({
|
|
422
|
-
ignoreScripts,
|
|
423
|
-
logger,
|
|
424
|
-
options,
|
|
425
|
-
packages,
|
|
426
|
-
pm,
|
|
427
|
-
target: options.to,
|
|
428
|
-
visConfig,
|
|
429
|
-
workspaceRoot: wsRoot
|
|
430
|
-
});
|
|
431
|
-
if (code2 !== 0) {
|
|
432
|
-
process.exitCode = code2;
|
|
433
|
-
}
|
|
434
|
-
return;
|
|
435
|
-
}
|
|
436
|
-
const code = runAdd(
|
|
437
|
-
pm,
|
|
438
|
-
{
|
|
439
|
-
exact: options.exact || false,
|
|
440
|
-
filter: toStringArray(options.filter),
|
|
441
|
-
global: options.global || false,
|
|
442
|
-
optional: options.saveOptional || false,
|
|
443
|
-
packages,
|
|
444
|
-
peer: options.savePeer || false,
|
|
445
|
-
saveDev: options.saveDev || false,
|
|
446
|
-
workspace: options.workspace || false,
|
|
447
|
-
workspaceRoot: options.workspaceRoot || false
|
|
448
|
-
},
|
|
449
|
-
cwd,
|
|
450
|
-
logger,
|
|
451
|
-
{ ignoreScripts }
|
|
452
|
-
);
|
|
453
|
-
if (code !== 0) {
|
|
454
|
-
process.exitCode = code;
|
|
455
|
-
}
|
|
456
|
-
};
|
|
457
|
-
|
|
458
|
-
export { execute as default };
|
|
16
|
+
${p}`,Q(f,$),l.push(`Synced ${String(y)} advisor${y===1?"y":"ies"} to .yarnrc.yml (${String(m.length)} total)`);break}default:l.push(`Unknown package manager: ${t}`)}return l},"syncAcceptedRisksToNativeConfig");var ye=Object.defineProperty,R=V((t,n)=>ye(t,"name",{value:n,configurable:!0}),"m");const U={CRITICAL:0,HIGH:1,LOW:3,MODERATE:2,UNKNOWN:4},Ae={critical:ee,high:_,low:Z,medium:Y},j=R((t,n)=>{const r=U[n.toUpperCase()]??U.MODERATE??2;return(U[t.toUpperCase()]??4)<=r},"severityPassesFilter"),Se={CRITICAL:ee,HIGH:_,LOW:Z,MODERATE:Y,UNKNOWN:b},we=R((t,n,r,l)=>{const f=Se[r.severity]??b,h=l?` ${b("[acknowledged]")}`:"",k=r.fixedVersions??[],m=k.length>0?` (fix: ${k.join(", ")})`:"";return` ${f(r.severity)} ${r.id} — ${t}@${n}${h}
|
|
17
|
+
${r.summary}${m}`},"formatVulnLine"),Ce=R((t,n)=>{const r=oe(t),l=`${String(Math.round(t.score.overall*100))}%`,f=n?` ${b("[acknowledged]")}`:"",h=t.alerts.length>0?`, ${String(t.alerts.length)} alert${t.alerts.length===1?"":"s"}`:"";return` ${l} ${r}@${t.version} (${ae(t.score.overall)}${h})${f}`},"formatSocketLine"),Re=R(async(t,n,r,l)=>{const f=n.severity??"low",h=n.format==="json"||!!n.json,k=!!n.fix,m=!!n.showAccepted,y=r?.security?.socket,$=y?.acceptedRisks,p=ce(t),d=me(t,p.name);(d.ignoredAdvisories.length>0||d.excludedPackages.length>0)&&a.info(`Loaded ${String(d.ignoredAdvisories.length)} ignored advisor${d.ignoredAdvisories.length===1?"y":"ies"} and ${String(d.excludedPackages.length)} excluded package${d.excludedPackages.length===1?"":"s"} from ${p.name} config.`);const v=fe(t,p.name);if(v.length===0){a.info(`No ${p.name} lockfile entries found. Run ${p.name} install first.`);return}h||a.info(`Scanning ${String(v.length)} installed packages…`);const w=v.map(e=>({name:e.name,version:e.version})),g=le(y),c=pe(t,p.name),x=[{id:"vulnerabilities",label:"Known vulnerabilities (OSV)"},...g?[{id:"socket",label:"Socket.dev supply-chain reports"}]:[]],C=he(x,{live:!h}),ie=Date.now(),E=R(e=>{const s=Date.now()-e;return s>=1e3?`${(s/1e3).toFixed(1)}s`:`${String(Math.round(s))}ms`},"fmtElapsed");let q,J;try{const e=Date.now(),s=Date.now();C.start("vulnerabilities"),g&&C.start("socket"),[q,J]=await Promise.all([de(w).then(i=>{let o=0;for(const u of i.values())o+=u.length;return C.finish("vulnerabilities",o>0?"warn":"ok",o>0?`${String(o)} found · ${E(e)}`:`none found · ${E(e)}`),i}).catch(i=>{const o=i instanceof Error?i.message:String(i);return C.finish("vulnerabilities","error",o),new Map}),g?ue(w,g).then(i=>{let o=0,u=0;for(const D of i.values())o+=D.alerts.length,D.score.overall<W&&(u+=1);const O=o+u;return C.finish("socket",O>0?"warn":"ok",O>0?`${String(o)} alert${o===1?"":"s"}, ${String(u)} low-score · ${E(s)}`:`clean · ${E(s)}`),i}).catch(i=>{const o=i instanceof Error?i.message:String(i);return C.finish("socket","error",o),new Map}):Promise.resolve(new Map)])}finally{C.stop()}h||a.info(b(`Scan completed in ${E(ie)}`));const M=[];for(const e of v){if($e(e.name,d))continue;const s=q.get(e.name)??[],i=J.get(`${e.name}@${e.version}`),o=ge(e.name,e.version,$),u=s.length>0,O=i?i.score.overall<W:!1,D=i?i.alerts.length>0:!1;(u||O||D)&&M.push({acceptedRisk:o,name:e.name,socketReport:i,version:e.version,vulnerabilities:s})}const A=M.filter(e=>{const s=e.vulnerabilities.some(u=>j(u.severity,f)),i=e.socketReport?.alerts.some(u=>j(u.severity==="medium"?"MODERATE":u.severity.toUpperCase(),f)),o=e.socketReport&&e.socketReport.score.overall<W;return s||i||o});if(h){const e={duplicates:c.map(s=>({name:s.name,versionCount:s.versions.length,versions:s.versions})),packages:v.length,results:A.map(s=>({acceptedRisk:s.acceptedRisk??null,name:s.name,socketAlerts:s.socketReport?.alerts??[],socketScore:s.socketReport?.score.overall??null,version:s.version,vulnerabilities:s.vulnerabilities})),summary:{accepted:A.filter(s=>s.acceptedRisk).length,duplicatePackages:c.length,issues:A.filter(s=>!s.acceptedRisk).length,total:A.length}};process.stdout.write(`${JSON.stringify(e,void 0,2)}
|
|
18
|
+
`),n.exitCode&&e.summary.issues>0&&(process.exitCode=1);return}if(A.length===0){a.success(`No security issues found across ${String(v.length)} packages.`);return}const I={CRITICAL:[],HIGH:[],LOW:[],MODERATE:[]};for(const e of A)for(const s of e.vulnerabilities)if(j(s.severity,f)){const i=s.severity==="UNKNOWN"?"LOW":s.severity;I[i]?.push({entry:e,vuln:s})}let F=0,T=0;for(const e of["CRITICAL","HIGH","MODERATE","LOW"]){const s=I[e];if(!(!s||s.length===0)){a.info(`
|
|
19
|
+
── ${e} (${String(s.length)}) ──`);for(const{entry:i,vuln:o}of s){const u=!!i.acceptedRisk||X(o.id,d,o.aliases);u&&(T++,!m)||(F++,a.info(we(i.name,i.version,o,u)),k&&(o.fixedVersions??[]).length>0&&a.notice(` Fix: update to ${o.fixedVersions.at(-1)}`))}}}const P=A.filter(e=>e.socketReport&&(e.socketReport.score.overall<W||e.socketReport.alerts.length>0));if(P.length>0){a.info(`
|
|
20
|
+
── Socket.dev Supply Chain (${String(P.length)}) ──`);for(const e of P){if(!e.socketReport)continue;const s=!!e.acceptedRisk;if(!(s&&!m)){a.info(Ce(e.socketReport,s));for(const i of e.socketReport.alerts){const o=Ae[i.severity]??b;a.info(` ${o(`[${i.severity.toUpperCase()}]`)} ${i.type} — ${i.category}`)}}}}if(c.length>0){a.info(`
|
|
21
|
+
── Duplicate Dependencies (${String(c.length)}) ──`);for(const e of c){const s=e.versions.join(", ");a.info(` ${e.name} — ${String(e.versions.length)} versions: ${Y(s)}`)}}const N=R(e=>!!e.acceptedRisk||e.vulnerabilities.length>0&&e.vulnerabilities.every(s=>X(s.id,d,s.aliases)),"isEntryExcluded"),z=A.filter(e=>!N(e)).length;if(a.info(""),a.info("─ Audit Summary"),a.info(` ${String(v.length)} packages scanned`),d.ignoredAdvisories.length>0&&a.info(` ${String(d.ignoredAdvisories.length)} ${p.name} audit exclusion${d.ignoredAdvisories.length===1?"":"s"} applied`),F>0){const e=I.CRITICAL?.filter(i=>!N(i.entry)).length??0,s=I.HIGH?.filter(i=>!N(i.entry)).length??0;a.error(` ${String(F)} vulnerabilit${F===1?"y":"ies"} found`),e>0&&a.error(` ${String(e)} critical`),s>0&&a.warn(` ${String(s)} high`)}else a.success(" No vulnerabilities found");if(P.length>0){const e=P.filter(s=>!N(s)).length;a.warn(` ${String(e)} package${e===1?"":"s"} with Socket.dev supply chain issues`)}if(c.length>0&&(a.warn(` ${String(c.length)} package${c.length===1?"":"s"} with duplicate versions`),a.notice(" Run 'vis dedupe' or your package manager's dedupe command to reduce duplicates.")),T>0&&(a.info(` ${String(T)} acknowledged (accepted risks)`),m||a.notice(" Use --show-accepted to see acknowledged issues.")),z===0&&a.success(`
|
|
22
|
+
All issues are acknowledged. No action required.`),n.sync&&$){const e=new Set;for(const i of M)if(i.acceptedRisk){for(const o of i.vulnerabilities)if((o.id.startsWith("CVE-")||o.id.startsWith("GHSA-"))&&e.add(o.id),o.aliases)for(const u of o.aliases)(u.startsWith("CVE-")||u.startsWith("GHSA-"))&&e.add(u)}const s=[...e];if(s.length>0){a.info("");const i=ke(p.name,t,s);for(const o of i)a.success(` ${o}`)}else a.info(`
|
|
23
|
+
No advisory IDs to sync to native PM config.`)}n.exitCode&&z>0&&(process.exitCode=1)},"executeAudit"),Oe=R(async({logger:t,options:n,visConfig:r,workspaceRoot:l})=>{if(!l)throw new Error("Could not determine workspace root. Run this command inside a monorepo.");await Re(l,n,r,t)},"execute");export{Oe as default};
|
|
@@ -1,95 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const VERSION_PREFIX_REGEX = /^[\^~>=<]+/;
|
|
7
|
-
const execute = async ({ argument, logger, options, visConfig, workspaceRoot: wsRoot }) => {
|
|
8
|
-
if (!wsRoot) {
|
|
9
|
-
throw new Error("Could not determine workspace root. Run this command inside a monorepo.");
|
|
10
|
-
}
|
|
11
|
-
const positionalArguments = argument;
|
|
12
|
-
const packageName = positionalArguments[0];
|
|
13
|
-
if (!packageName) {
|
|
14
|
-
throw new Error("Package name is required. Usage: vis analyze <package> [version]");
|
|
15
|
-
}
|
|
16
|
-
const targetVersionArgument = positionalArguments[1];
|
|
17
|
-
const { packageManager } = findPackageManagerSync(wsRoot);
|
|
18
|
-
let currentRange;
|
|
19
|
-
let catalogName = "default";
|
|
20
|
-
const catalogs = readCatalogs(wsRoot, packageManager);
|
|
21
|
-
for (const [name, deps] of catalogs) {
|
|
22
|
-
const range = deps.get(packageName);
|
|
23
|
-
if (range) {
|
|
24
|
-
currentRange = range;
|
|
25
|
-
catalogName = name;
|
|
26
|
-
break;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
if (!currentRange) {
|
|
30
|
-
throw new Error(`Package "${packageName}" not found in any catalog or package.json. Make sure it exists in your workspace dependencies.`);
|
|
31
|
-
}
|
|
32
|
-
let targetVersion;
|
|
33
|
-
if (targetVersionArgument) {
|
|
34
|
-
targetVersion = targetVersionArgument;
|
|
35
|
-
} else {
|
|
36
|
-
logger.info(`Fetching latest version for ${packageName}...
|
|
37
|
-
`);
|
|
38
|
-
const info = await fetchPackageVersions(packageName);
|
|
39
|
-
if (!info.latest) {
|
|
40
|
-
throw new Error(`Could not determine latest version for "${packageName}".`);
|
|
41
|
-
}
|
|
42
|
-
targetVersion = info.latest;
|
|
43
|
-
}
|
|
44
|
-
const current = parseVersion(currentRange);
|
|
45
|
-
const target = parseVersion(targetVersion);
|
|
46
|
-
if (!current || !target) {
|
|
47
|
-
throw new Error(`Could not parse versions: current="${currentRange}", target="${targetVersion}".`);
|
|
48
|
-
}
|
|
49
|
-
const updateType = getUpdateType(current, target);
|
|
50
|
-
if (updateType === "none") {
|
|
51
|
-
logger.info(`${packageName} is already at ${targetVersion}. Nothing to analyze.`);
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
const prefix = extractPrefix(currentRange);
|
|
55
|
-
const entry = {
|
|
56
|
-
catalogName,
|
|
57
|
-
currentRange,
|
|
58
|
-
newRange: `${prefix}${targetVersion}`,
|
|
59
|
-
packageName,
|
|
60
|
-
targetVersion,
|
|
61
|
-
updateType
|
|
62
|
-
};
|
|
63
|
-
const analysisType = validateAnalysisType(options.aiType ?? "impact");
|
|
64
|
-
if (analysisType === "security" || options.security) {
|
|
65
|
-
logger.info("Checking for known vulnerabilities...\n");
|
|
66
|
-
const version = currentRange.replace(VERSION_PREFIX_REGEX, "");
|
|
67
|
-
const vulnMap = await fetchVulnerabilities([{ name: packageName, version }]);
|
|
68
|
-
const vulns = vulnMap.get(packageName);
|
|
69
|
-
if (vulns && vulns.length > 0) {
|
|
70
|
-
entry.vulnerabilities = vulns;
|
|
71
|
-
}
|
|
72
|
-
const socketOptions = buildSocketOptions(visConfig?.security?.socket);
|
|
73
|
-
if (socketOptions) {
|
|
74
|
-
const reports = await fetchSocketReports([{ name: packageName, version }], socketOptions);
|
|
75
|
-
const report = reports.get(`${packageName}@${version}`);
|
|
76
|
-
if (report) {
|
|
77
|
-
entry.socketReport = {
|
|
78
|
-
alerts: report.alerts,
|
|
79
|
-
license: report.license,
|
|
80
|
-
score: report.score
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
const result = await runAiAnalysis([entry], logger, visConfig?.ai, analysisType);
|
|
86
|
-
const format = options.format ?? "table";
|
|
87
|
-
if (format === "json") {
|
|
88
|
-
process.stdout.write(`${JSON.stringify(result, void 0, 2)}
|
|
89
|
-
`);
|
|
90
|
-
} else {
|
|
91
|
-
logger.info(formatAiAnalysis(result));
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
export { execute as default };
|
|
1
|
+
var x=Object.defineProperty;var h=(n,t)=>x(n,"name",{value:t,configurable:!0});import{findPackageManagerSync as N}from"@visulima/package";import{H as P,e as U,Z as j}from"../packem_shared/ai-analysis-hm8d2W7z.js";import{g as M,a as O,E as b,i as T,L as z,b as S,V,U as q}from"./bin.js";var A=Object.defineProperty,F=h((n,t)=>A(n,"name",{value:t,configurable:!0}),"x");const H=/^[\^~>=<]+/,B=F(async({argument:n,logger:t,options:f,visConfig:u,workspaceRoot:g})=>{if(!g)throw new Error("Could not determine workspace root. Run this command inside a monorepo.");const p=n,e=p[0];if(!e)throw new Error("Package name is required. Usage: vis analyze <package> [version]");const m=p[1],{packageManager:E}=N(g);let o,w="default";const C=M(g,E);for(const[a,i]of C){const s=i.get(e);if(s){o=s,w=a;break}}if(!o)throw new Error(`Package "${e}" not found in any catalog or package.json. Make sure it exists in your workspace dependencies.`);let r;if(m)r=m;else{t.info(`Fetching latest version for ${e}...
|
|
2
|
+
`);const a=await O(e);if(!a.latest)throw new Error(`Could not determine latest version for "${e}".`);r=a.latest}const d=b(o),k=b(r);if(!d||!k)throw new Error(`Could not parse versions: current="${o}", target="${r}".`);const y=T(d,k);if(y==="none"){t.info(`${e} is already at ${r}. Nothing to analyze.`);return}const R=z(o),l={catalogName:w,currentRange:o,newRange:`${R}${r}`,packageName:e,targetVersion:r,updateType:y},v=P(f.aiType??"impact");if(v==="security"||f.security){t.info(`Checking for known vulnerabilities...
|
|
3
|
+
`);const a=o.replace(H,""),i=(await S([{name:e,version:a}])).get(e);i&&i.length>0&&(l.vulnerabilities=i);const s=V(u?.security?.socket);if(s){const c=(await q([{name:e,version:a}],s)).get(`${e}@${a}`);c&&(l.socketReport={alerts:c.alerts,license:c.license,score:c.score})}}const $=await U([l],t,u?.ai,v);(f.format??"table")==="json"?process.stdout.write(`${JSON.stringify($,void 0,2)}
|
|
4
|
+
`):t.info(j($))},"execute");export{B as default};
|