securesync
Version:
Intelligent dependency security scanner with auto-fix
34 lines (29 loc) • 23.4 kB
JavaScript
import{Command as Ke}from"commander";import{Command as oe}from"commander";import{readFile as O}from"fs/promises";import{join as F}from"path";import{existsSync as R}from"fs";async function k(n,e={}){let t=await Q(n),r=await X(n),o=Z(t,r,e.includeDevDependencies??!1),i=await ne(n,o),l=e.enhanceWithOSV?await te(i):i,a=e.analyzeReachability?await re(l,n):l,c={critical:a.filter(f=>f.severity==="critical").length,high:a.filter(f=>f.severity==="high").length,moderate:a.filter(f=>f.severity==="moderate").length,low:a.filter(f=>f.severity==="low").length};return{vulnerabilities:a,totalPackages:o.packages.length,scannedAt:new Date,dependencies:o,summary:c}}async function Q(n){let e=F(n,"package.json");if(!R(e))throw new Error(`package.json not found at ${e}`);let t=await O(e,"utf-8");return JSON.parse(t)}async function X(n){let e=F(n,"package-lock.json");if(!R(e))throw new Error(`package-lock.json not found at ${e}. Please run 'npm install' first.`);let t=await O(e,"utf-8");return JSON.parse(t)}function Z(n,e,t){let r=[],o=new Map,i=n.dependencies||{},l=t?n.devDependencies||{}:{};for(let[a]of Object.entries(i)){let c=e.packages?.[`node_modules/${a}`];c&&(o.set(a,{name:a,version:c.version,resolved:c.resolved||"",dependencies:S(e,c)}),r.push({name:a,version:c.version,isDevDependency:!1,isDirect:!0}))}for(let[a]of Object.entries(l)){let c=e.packages?.[`node_modules/${a}`];c&&(o.set(a,{name:a,version:c.version,resolved:c.resolved||"",dependencies:S(e,c)}),r.push({name:a,version:c.version,isDevDependency:!0,isDirect:!0}))}return ee(o,r),{name:n.name,version:n.version,dependencies:o,packages:r}}function S(n,e){if(!e.dependencies)return;let t=new Map;for(let[r]of Object.entries(e.dependencies)){let o=n.packages?.[`node_modules/${r}`];o&&t.set(r,{name:r,version:o.version,resolved:o.resolved||"",dependencies:S(n,o)})}return t.size>0?t:void 0}function ee(n,e){let t=new Set(e.map(o=>`${o.name}@${o.version}`));function r(o,i){if(o)for(let[l,a]of o){let c=`${l}@${a.version}`;t.has(c)||(t.add(c),e.push({name:l,version:a.version,isDevDependency:i,isDirect:!1})),r(a.dependencies,i)}}for(let[,o]of n)r(o.dependencies,!1)}async function ne(n,e){let t=[];try{return t}catch(r){return console.error("Error querying npm audit:",r),t}}async function te(n){return n}async function re(n,e){return n}import g from"chalk";import ie from"ora";var x=class{spinner=null;startSpinner(e){this.spinner=ie(e).start()}stopSpinner(e=!0,t){this.spinner&&(e?this.spinner.succeed(t):this.spinner.fail(t),this.spinner=null)}updateSpinner(e){this.spinner&&(this.spinner.text=e)}success(e){console.log(g.green("\u2713")+" "+e)}error(e){console.log(g.red("\u2717")+" "+e)}warning(e){console.log(g.yellow("\u26A0")+" "+e)}info(e){console.log(g.blue("\u2139")+" "+e)}header(e){console.log(`
`+g.bold.underline(e)+`
`)}section(e){console.log(`
`+g.bold(e))}printScanResults(e){if(this.header("Security Scan Results"),console.log(g.bold("Summary:")),console.log(` Total packages scanned: ${e.totalPackages}`),console.log(` Vulnerabilities found: ${e.vulnerabilities.length}`),console.log(` Scanned at: ${e.scannedAt.toLocaleString()}
`),e.summary&&(console.log(g.bold("Severity Breakdown:")),e.summary.critical>0&&console.log(` ${g.red("Critical")}: ${e.summary.critical}`),e.summary.high>0&&console.log(` ${g.red("High")}: ${e.summary.high}`),e.summary.moderate>0&&console.log(` ${g.yellow("Moderate")}: ${e.summary.moderate}`),e.summary.low>0&&console.log(` ${g.blue("Low")}: ${e.summary.low}`),console.log()),e.vulnerabilities.length>0){this.section("Vulnerabilities:");for(let t of e.vulnerabilities)this.printVulnerability(t)}else this.success("No vulnerabilities found!")}printVulnerability(e){let r=this.getSeverityColor(e.severity)(e.severity.toUpperCase());console.log(`
${g.bold(e.id)} [${r}]`),console.log(` Package: ${g.cyan(e.package)}@${e.version}`),console.log(` Description: ${e.description}`),e.patched&&e.patched.length>0&&console.log(` Patched in: ${g.green(e.patched.join(", "))}`),e.path&&e.path.length>0&&console.log(` Path: ${e.path.join(" > ")}`),e.cvss&&console.log(` CVSS Score: ${e.cvss}`)}printBreakingChanges(e){if(this.header(`Breaking Change Analysis: ${e.packageName}`),console.log(` From: ${g.cyan(e.fromVersion)}`),console.log(` To: ${g.cyan(e.toVersion)}`),console.log(` Risk Level: ${this.getRiskColor(e.riskLevel)(e.riskLevel.toUpperCase())}`),console.log(` Breaking Changes: ${e.hasBreakingChanges?g.red("YES"):g.green("NO")}`),console.log(` Changes Found: ${e.changes.length}
`),e.changes.length>0){this.section("Changes:");for(let t of e.changes){let r=t.type==="breaking"?g.red:g.green;console.log(`
${r(t.type.toUpperCase())}: ${t.symbol}`),console.log(` Category: ${t.category}`),t.before&&console.log(` Before: ${g.gray(t.before)}`),t.after&&console.log(` After: ${g.gray(t.after)}`),t.migration&&console.log(` Migration: ${g.cyan(t.migration)}`),console.log(` Confidence: ${Math.round(t.confidence*100)}%`)}}}printAlternatives(e){if(this.header("Alternative Packages"),e.length===0){this.warning("No suitable alternatives found.");return}for(let t=0;t<e.length;t++){let r=e[t];console.log(`
${g.bold(`${t+1}. ${r.name}`)} (Score: ${r.score}/100)`),console.log(` ${r.description}`),console.log(` Downloads: ${this.formatNumber(r.downloads)}/week`),console.log(` Last publish: ${this.formatDate(r.lastPublish)}`),console.log(` Stars: ${this.formatNumber(r.stars)}`),console.log(` Vulnerabilities: ${r.vulnerabilities===0?g.green("0"):g.red(r.vulnerabilities)}`),console.log(` API Compatibility: ${r.compatibility}%`),console.log(` Migration Effort: ${this.getMigrationColor(r.migrationEffort)(r.migrationEffort.toUpperCase())}`)}}getSeverityColor(e){switch(e.toLowerCase()){case"critical":case"high":return g.red;case"moderate":return g.yellow;case"low":return g.blue;default:return g.gray}}getRiskColor(e){switch(e.toLowerCase()){case"high":return g.red;case"medium":return g.yellow;case"low":return g.green;default:return g.gray}}getMigrationColor(e){switch(e.toLowerCase()){case"low":return g.green;case"medium":return g.yellow;case"high":return g.red;default:return g.gray}}formatNumber(e){return e>=1e6?(e/1e6).toFixed(1)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":e.toString()}formatDate(e){let r=new Date().getTime()-e.getTime(),o=Math.floor(r/(1e3*60*60*24));if(o===0)return"today";if(o===1)return"yesterday";if(o<30)return`${o} days ago`;if(o<365){let i=Math.floor(o/30);return`${i} month${i>1?"s":""} ago`}else{let i=Math.floor(o/365);return`${i} year${i>1?"s":""} ago`}}},s=new x;function B(){let n=new oe("scan");return n.description("Scan project for security vulnerabilities").argument("[path]","Project path to scan",process.cwd()).option("-d, --dev","Include dev dependencies",!1).option("-r, --reachability","Analyze vulnerability reachability",!1).option("--enhance","Enhance with additional vulnerability databases",!1).option("--fail-on <severity>","Exit with error code if vulnerabilities of severity or higher found","").option("--json","Output results as JSON",!1).action(async(e,t)=>{try{s.startSpinner("Scanning dependencies...");let r=await k(e,{projectPath:e,includeDevDependencies:t.dev,analyzeReachability:t.reachability,enhanceWithOSV:t.enhance});if(s.stopSpinner(!0,"Scan complete"),t.json?console.log(JSON.stringify(r,null,2)):s.printScanResults(r),t.failOn){let o=["low","moderate","high","critical"],i=o.indexOf(t.failOn.toLowerCase());i===-1&&(s.error(`Invalid severity level: ${t.failOn}`),process.exit(1)),r.vulnerabilities.some(a=>o.indexOf(a.severity)>=i)&&(s.error(`Found vulnerabilities with severity ${t.failOn} or higher`),process.exit(1))}}catch(r){s.stopSpinner(!1,"Scan failed"),s.error(r.message),process.exit(1)}}),n}import{Command as pe}from"commander";import{compare as ae,diff as se,valid as z}from"semver";function $(n,e){if(!z(n)||!z(e))throw new Error(`Invalid semver versions: ${n} or ${e}`);let t=ae(n,e),r=se(n,e);return{fromVersion:n,toVersion:e,diffType:r,isUpgrade:t<0,isDowngrade:t>0,expectedBreakingChanges:r==="major"||r==="premajor"}}function N(n){return n.expectedBreakingChanges?!0:n.isUpgrade&&n.diffType!==null}async function P(n){let e=[],t=/^##?\s*\[?(\d+\.\d+\.\d+[^\]]*)\]?.*$/gm,r=[...n.matchAll(t)];for(let o=0;o<r.length;o++){let i=r[o],l=i[1],a=i.index+i[0].length,c=o<r.length-1?r[o+1].index:n.length,f=n.slice(a,c);e.push({version:l,date:ce(i[0]),changes:le(f)})}return e}function ce(n){let e=/\d{4}-\d{2}-\d{2}/,t=n.match(e);return t?t[0]:void 0}function le(n){let e={breaking:[],features:[],fixes:[],other:[]},t=n.split(`
`),r="other";for(let o of t){let i=o.trim();if(/^###?\s*(breaking|breaking changes)/i.test(i)){r="breaking";continue}else if(/^###?\s*(features?|added)/i.test(i)){r="features";continue}else if(/^###?\s*(fix(es)?|bug\s*fix(es)?)/i.test(i)){r="fixes";continue}if(/^[-*]\s/.test(i)){let l=i.replace(/^[-*]\s/,"").trim();l&&e[r].push(l)}}return e}function E(n,e){let t=new Map,r=n.find(o=>o.version===e);if(!r)return t;for(let o of r.changes.breaking){let i=ge(o);i&&t.set(i.from,i.to)}return t}function ge(n){let e=/replace\s+`?(\w+)`?\s+with\s+`?(\w+)`?/i,t=/use\s+`?(\w+)`?\s+instead\s+of\s+`?(\w+)`?/i,r=n.match(e);return r?{from:r[1],to:r[2]}:(r=n.match(t),r?{from:r[2],to:r[1]}:null)}function L(n,e){let t=[],r=new Map(n.map(i=>[i.name,i])),o=new Map(e.map(i=>[i.name,i]));for(let[i,l]of r){if(!l.exported)continue;let a=o.get(i);a?a.signature!==l.signature&&t.push({type:"breaking",category:"signature",symbol:i,before:l.signature,after:a.signature,confidence:.9,source:"typescript"}):t.push({type:"breaking",category:"removed",symbol:i,before:l.signature,after:"",confidence:1,source:"typescript"})}for(let[i,l]of o)l.exported&&(r.has(i)||t.push({type:"feature",category:"signature",symbol:i,before:"",after:l.signature,confidence:1,source:"typescript"}));return t}async function A(n){return[]}function J(n,e){return n.map(t=>{if(t.category==="removed"||t.category==="renamed"){let r=e.get(t.symbol);if(r)return{...t,migration:`Replace \`${t.symbol}\` with \`${r}\``,confidence:Math.min(t.confidence+.1,1)}}return t})}async function b(n,e,t){let r=$(e,t);if(!N(r))return{packageName:n,fromVersion:e,toVersion:t,changes:[],hasBreakingChanges:!1,riskLevel:"low",analyzedAt:new Date};let o=await V(n,e),i=await V(n,t),l=await A(o),a=await A(i),c=L(l,a),f=await fe(i),u=f?await P(f):[],d=E(u,t),m=J(c,d),p=u.find(v=>v.version===t);if(p)for(let v of p.changes.breaking)m.some(Y=>Y.symbol===v)||m.push({type:"breaking",category:"behavior",symbol:v,before:"",after:"",confidence:.7,source:"changelog"});let y=ue(m,r.expectedBreakingChanges);return{packageName:n,fromVersion:e,toVersion:t,changes:m,hasBreakingChanges:m.some(v=>v.type==="breaking"),riskLevel:y,analyzedAt:new Date}}async function V(n,e){return`/tmp/securesync-cache/${n}@${e}`}async function fe(n){return null}function ue(n,e){let t=n.filter(r=>r.type==="breaking");return t.length===0?"low":t.length>5||!e?"high":"medium"}function _(){let n=new pe("analyze");return n.description("Analyze breaking changes for a package update").argument("<package>","Package name").argument("<from-version>","Current version").argument("<to-version>","Target version").option("--json","Output results as JSON",!1).action(async(e,t,r,o)=>{try{s.startSpinner(`Analyzing breaking changes for ${e}...`);let i=await b(e,t,r);s.stopSpinner(!0,"Analysis complete"),o.json?console.log(JSON.stringify(i,null,2)):s.printBreakingChanges(i),i.hasBreakingChanges&&process.exit(1)}catch(i){s.stopSpinner(!1,"Analysis failed"),s.error(i.message),process.exit(1)}}),n}import{Command as Pe}from"commander";async function D(n,e){let t=0,r=de(n.downloads);t+=r*.3;let o=me(n.lastPublish);t+=o*.25;let i=await ye(n.name);t+=i*.25;let l=await he(n);return t+=l*.2,Math.min(100,Math.round(t))}function de(n){return n>=1e6?100:n>=1e5?75+(n-1e5)/9e5*25:n>=1e4?50+(n-1e4)/9e4*25:n>=1e3?25+(n-1e3)/9e3*25:n/1e3*25}function me(n){let e=we(n);return e<30?100:e<90?80+(90-e)/60*20:e<180?60+(180-e)/90*20:e<365?40+(365-e)/185*20:e<730?20+(730-e)/365*20:Math.max(0,20-(e-730)/365*20)}async function ye(n){return 100}async function he(n){let e=0;return n.description&&n.description.length>20&&(e+=20),n.repository&&(e+=20),n.homepage&&(e+=15),n.keywords&&n.keywords.length>=3&&(e+=15),n.license&&(e+=15),e}function we(n){let t=new Date().getTime()-n.getTime();return Math.floor(t/(1e3*60*60*24))}async function M(n,e={}){let t=await ve(n),r=await be({keywords:t,exclude:[n]});return(await Promise.all(r.map(async i=>{let l=await D(i,n),a=await Ce(i,n),c=Se(a,l);return{name:i.name,description:i.description,downloads:i.downloads,lastPublish:i.lastPublish,stars:0,issues:0,maintainers:0,vulnerabilities:0,compatibility:a,migrationEffort:c,score:l}}))).filter(i=>xe(i,e)).sort((i,l)=>l.score-i.score).slice(0,10)}async function ve(n){try{return(await ke(n)).keywords||[]}catch{return n.split("-").filter(e=>e.length>2)}}async function be(n){return[]}async function ke(n){return{name:n,description:"",version:"1.0.0",downloads:0,lastPublish:new Date,keywords:[]}}async function Ce(n,e){return 50}function Se(n,e){return n>=80?"low":n>=50?"medium":"high"}function xe(n,e){return!(e.minDownloads&&n.downloads<e.minDownloads||e.maxAge&&$e(n.lastPublish)>e.maxAge||e.minStars&&n.stars<e.minStars||e.zeroVulnerabilities&&n.vulnerabilities>0||e.minCompatibility&&n.compatibility<e.minCompatibility)}function $e(n){let t=new Date().getTime()-n.getTime();return Math.floor(t/(1e3*60*60*24))}function U(){let n=new Pe("alternatives");return n.description("Find alternative packages").argument("<package>","Package name to find alternatives for").option("--min-downloads <number>","Minimum weekly downloads",parseInt).option("--max-age <days>","Maximum days since last publish",parseInt).option("--min-stars <number>","Minimum GitHub stars",parseInt).option("--zero-vulns","Only show packages with zero vulnerabilities",!1).option("--min-compat <number>","Minimum API compatibility score (0-100)",parseInt).option("--json","Output results as JSON",!1).action(async(e,t)=>{try{s.startSpinner(`Finding alternatives for ${e}...`);let r=await M(e,{minDownloads:t.minDownloads,maxAge:t.maxAge,minStars:t.minStars,zeroVulnerabilities:t.zeroVulns,minCompatibility:t.minCompat});s.stopSpinner(!0,`Found ${r.length} alternative(s)`),t.json?console.log(JSON.stringify(r,null,2)):s.printAlternatives(r)}catch(r){s.stopSpinner(!1,"Search failed"),s.error(r.message),process.exit(1)}}),n}import{Command as _e}from"commander";import{readFile as Ae}from"fs/promises";import{parse as De}from"@babel/parser";import Me from"@babel/traverse";import G from"@babel/generator";async function C(n,e,t){let r=[],o=await Te(n,e);for(let i of o){let l=await Ae(i,"utf-8"),a;try{a=De(l,{sourceType:"module",plugins:["typescript","jsx"]})}catch(u){console.warn(`Failed to parse ${i}:`,u);continue}let c=[],f=t.filter(u=>u.type==="breaking");Me(a,{CallExpression(u){let d=u.node.callee,m=je(d,f);if(m){let p=G(u.node),y=Ie(u.node,m);y&&c.push({line:u.node.loc?.start.line||0,column:u.node.loc?.start.column||0,old:p.code,new:y})}},ImportDeclaration(u){if(u.node.source.value===e){for(let d of u.node.specifiers)if(d.type==="ImportSpecifier"){let m=d.imported.type==="Identifier"?d.imported.name:"",p=f.find(y=>y.symbol===m&&y.category==="renamed");if(p&&p.migration){let y=G(d);c.push({line:d.loc?.start.line||0,column:d.loc?.start.column||0,old:y.code,new:p.migration})}}}}}),c.length>0&&r.push({file:i,changes:c,script:Oe(i,c),safe:Fe(c,f)})}return r}async function Te(n,e){return[]}function je(n,e){return n.type==="Identifier"?e.find(t=>t.symbol===n.name)||null:n.type==="MemberExpression"&&n.property.type==="Identifier"&&e.find(t=>t.symbol===n.property.name)||null}function Ie(n,e){return e.migration?e.migration:(e.category==="signature",null)}function Oe(n,e){let t=`// Migration script for ${n}
`;t+=`import { readFile, writeFile } from 'fs/promises';
`,t+=`async function migrate() {
`,t+=` const content = await readFile('${n}', 'utf-8');
`,t+=` let updated = content;
`;for(let r of e)t+=` // Line ${r.line}: ${r.old} -> ${r.new}
`,t+=` updated = updated.replace(
`,t+=` ${JSON.stringify(r.old)},
`,t+=` ${JSON.stringify(r.new)}
`,t+=` );
`;return t+=` await writeFile('${n}', updated, 'utf-8');
`,t+=` console.log('Migration completed for ${n}');
`,t+=`}
`,t+=`migrate().catch(console.error);
`,t}function Fe(n,e){return!(n.length>5||e.some(o=>o.confidence<.8)||n.some(o=>!o.new||o.new===o.old))}import{exec as Re}from"child_process";import{promisify as Be}from"util";import{readFile as ze}from"fs/promises";import{join as h}from"path";var j=Be(Re);async function I(n,e,t,r,o={}){let i=o.runTests??!0,l=o.createBackup??!0;if(i){let a=await T(n);if(!a.passed)return{success:!1,reason:"Tests failing before update - please fix existing test failures first",failedTests:a.failedTests}}l&&await Le(n);try{if(await Je(n,e,t),o.autoApply&&r.length>0)for(let a of r)(a.safe||o.interactive===!1)&&await Ve(a);if(i){let a=await T(n);if(!a.passed)return await H(n),{success:!1,reason:"Tests failed after update",failedTests:a.failedTests,migrations:r,rolledBack:!0}}return{success:!0,migrations:r}}catch(a){throw l&&await H(n),a}}async function T(n){let e=Date.now();try{let t=await Ne(n);if(!t)return{passed:!0,output:"No test command found, skipping tests",duration:Date.now()-e};let{stdout:r}=await j(t,{cwd:n,env:{...process.env,CI:"true"}});return{passed:!0,output:r,duration:Date.now()-e,exitCode:0}}catch(t){return{passed:!1,output:t.stderr||t.stdout||t.message,duration:Date.now()-e,failedTests:Ee(t.stderr||t.stdout||""),exitCode:t.code}}}async function Ne(n){try{let e=h(n,"package.json"),t=await ze(e,"utf-8");return JSON.parse(t).scripts?.test||null}catch{return null}}function Ee(n){let e=[],t=[/FAIL\s+(.+)/g,/✖\s+(.+)/g,/×\s+(.+)/g,/ERROR\s+(.+)/g];for(let r of t){let o=n.matchAll(r);for(let i of o)i[1]&&!e.includes(i[1])&&e.push(i[1].trim())}return e}async function Le(n){let{copyFile:e}=await import("fs/promises");try{await e(h(n,"package.json"),h(n,"package.json.backup")),await e(h(n,"package-lock.json"),h(n,"package-lock.json.backup"))}catch(t){console.warn("Failed to create backup files:",t)}}async function Je(n,e,t){await j(`npm install ${e}@${t}`,{cwd:n})}async function Ve(n){let{readFile:e,writeFile:t}=await import("fs/promises");try{let r=await e(n.file,"utf-8");for(let o of n.changes)r=r.replace(o.old,o.new);await t(n.file,r,"utf-8")}catch(r){throw console.error(`Failed to apply migration to ${n.file}:`,r),r}}async function H(n){let{copyFile:e,unlink:t}=await import("fs/promises");try{await e(h(n,"package.json.backup"),h(n,"package.json")),await e(h(n,"package-lock.json.backup"),h(n,"package-lock.json")),await j("npm install",{cwd:n}),await t(h(n,"package.json.backup")),await t(h(n,"package-lock.json.backup"))}catch(r){throw console.error("Failed to rollback changes:",r),r}}import Ue from"inquirer";function q(){let n=new _e("fix");return n.description("Auto-fix vulnerabilities").argument("[path]","Project path",process.cwd()).option("--auto","Automatically apply fixes without prompts",!1).option("--no-test","Skip running tests",!1).option("--max-severity <level>","Only fix vulnerabilities up to this severity","critical").option("--breaking-changes <action>","How to handle breaking changes (skip, warn, allow)","warn").action(async(e,t)=>{try{s.startSpinner("Scanning for vulnerabilities...");let r=await k(e,{projectPath:e,includeDevDependencies:!1});if(s.stopSpinner(!0,`Found ${r.vulnerabilities.length} vulnerabilities`),r.vulnerabilities.length===0){s.success("No vulnerabilities to fix!");return}let o=["low","moderate","high","critical"],i=o.indexOf(t.maxSeverity.toLowerCase()),l=r.vulnerabilities.filter(c=>o.indexOf(c.severity)>=i);s.info(`Found ${l.length} vulnerabilities matching severity criteria`);let a=new Map;for(let c of l)a.has(c.package)||a.set(c.package,{current:c.version,patched:c.patched});for(let[c,f]of a){let u=f.patched[0];if(!u){s.warning(`No patched version available for ${c}`);continue}s.section(`Processing ${c}@${f.current} -> ${u}`),s.startSpinner("Analyzing breaking changes...");let d=await b(c,f.current,u);if(s.stopSpinner(!0,"Analysis complete"),d.hasBreakingChanges){if(t.breakingChanges==="skip"){s.warning(`Skipping ${c} due to breaking changes`);continue}else if(t.breakingChanges==="warn"&&!t.auto){let{proceed:y}=await Ue.prompt([{type:"confirm",name:"proceed",message:`${c} has breaking changes. Continue?`,default:!1}]);if(!y){s.info(`Skipping ${c}`);continue}}}s.startSpinner("Generating migration scripts...");let m=await C(e,c,d.changes);s.stopSpinner(!0,`Generated ${m.length} migration(s)`),s.startSpinner("Applying update...");let p=await I(e,c,u,m,{autoApply:t.auto,runTests:t.test,createBackup:!0});if(p.success)s.stopSpinner(!0,`Successfully updated ${c}`);else{if(s.stopSpinner(!1,`Failed to update ${c}`),s.error(p.reason||"Unknown error"),p.failedTests){s.error("Failed tests:");for(let y of p.failedTests)console.log(` - ${y}`)}p.rolledBack&&s.info("Changes have been rolled back")}}s.success("Fix process complete!")}catch(r){s.error(r.message),process.exit(1)}}),n}import{Command as Ge}from"commander";import{writeFile as He}from"fs/promises";import{join as K}from"path";function W(){let n=new Ge("migrate");return n.description("Generate migration scripts for a package update").argument("<package>","Package name").argument("<to-version>","Target version").option("-p, --path <path>","Project path",process.cwd()).option("--from <version>","Current version (auto-detected if not provided)").option("--output <path>","Output directory for migration scripts","./migrations").option("--json","Output as JSON",!1).action(async(e,t,r)=>{try{let o=r.from;o||(s.startSpinner("Detecting current version..."),o=await qe(r.path,e),s.stopSpinner(!0,`Current version: ${o}`)),s.startSpinner("Analyzing breaking changes...");let i=await b(e,o,t);s.stopSpinner(!0,"Analysis complete"),s.startSpinner("Generating migration scripts...");let l=await C(r.path,e,i.changes);if(s.stopSpinner(!0,`Generated ${l.length} migration(s)`),r.json){console.log(JSON.stringify({analysis:i,migrations:l},null,2));return}if(l.length>0){s.section("Migration Scripts:");for(let a=0;a<l.length;a++){let c=l[a],f=`${a+1}-${e.replace("/","-")}-${t}.js`,u=K(r.output,f);await He(u,c.script,"utf-8"),s.success(`Saved: ${u}`),console.log(`
File: ${c.file}`),console.log(` Changes: ${c.changes.length}`),console.log(` Safe to auto-apply: ${c.safe?"Yes":"No"}`)}s.info(`
Migration scripts saved to ${r.output}`)}else s.warning("No migration scripts needed");i.hasBreakingChanges&&s.printBreakingChanges(i)}catch(o){s.error(o.message),process.exit(1)}}),n}async function qe(n,e){let{readFile:t}=await import("fs/promises"),r=K(n,"package.json");try{let o=await t(r,"utf-8"),i=JSON.parse(o),l=i.dependencies?.[e]||i.devDependencies?.[e];if(!l)throw new Error(`Package ${e} not found in dependencies`);return l.replace(/^[\^~>=<]/,"")}catch(o){throw new Error(`Failed to detect current version: ${o.message}`)}}var w=new Ke;w.name("securesync").description("Intelligent dependency security scanner with auto-fix").version("1.0.0");w.addCommand(B());w.addCommand(q());w.addCommand(_());w.addCommand(U());w.addCommand(W());w.parse(process.argv);
//# sourceMappingURL=cli.mjs.map