@cencori/scan 0.4.3 → 0.4.5

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/cli.mjs CHANGED
@@ -4,7 +4,7 @@
4
4
  import { program } from "commander";
5
5
  import chalk from "chalk";
6
6
  import ora from "ora";
7
- import { confirm, password } from "@inquirer/prompts";
7
+ import { confirm, password, select } from "@inquirer/prompts";
8
8
 
9
9
  // src/scanner/index.ts
10
10
  import * as fs from "fs";
@@ -883,24 +883,6 @@ Generate a secure fix.`
883
883
  }
884
884
  return results;
885
885
  }
886
- async function applyFixes(fixes, fileContents) {
887
- for (const fix of fixes) {
888
- if (fix.fixedCode === fix.originalCode) {
889
- continue;
890
- }
891
- const content = fileContents.get(fix.issue.file);
892
- if (!content) {
893
- continue;
894
- }
895
- const newContent = content.replace(fix.originalCode, fix.fixedCode);
896
- if (newContent !== content) {
897
- const filePath = path2.resolve(fix.issue.file);
898
- fs2.writeFileSync(filePath, newContent, "utf-8");
899
- fix.applied = true;
900
- }
901
- }
902
- return fixes;
903
- }
904
886
 
905
887
  // src/telemetry.ts
906
888
  var TELEMETRY_URL = "https://api.cencori.com/v1/telemetry/scan";
@@ -1153,7 +1135,7 @@ No commits found in the specified period.
1153
1135
  // src/cli.ts
1154
1136
  import * as fs3 from "fs";
1155
1137
  import * as path3 from "path";
1156
- var VERSION = "0.4.2";
1138
+ var VERSION = "0.4.5";
1157
1139
  var scoreStyles = {
1158
1140
  A: { color: chalk.green },
1159
1141
  B: { color: chalk.blue },
@@ -1388,23 +1370,135 @@ async function handleAutoFix(result, targetPath) {
1388
1370
  fileContents
1389
1371
  );
1390
1372
  fixSpinner.succeed(`Generated ${fixes.length} fixes`);
1391
- const applySpinner = ora({
1392
- text: "Applying fixes...",
1393
- color: "cyan"
1394
- }).start();
1395
- const appliedFixes = await applyFixes(fixes, fileContents);
1396
- const appliedCount = appliedFixes.filter((f) => f.applied).length;
1397
- applySpinner.succeed(`Applied ${appliedCount}/${fixes.length} fixes`);
1398
1373
  console.log();
1399
- console.log(` ${chalk.bold("Applied fixes:")}`);
1400
- for (const fix of appliedFixes.filter((f) => f.applied)) {
1401
- console.log(chalk.green(` \u2714 ${fix.issue.file}:${fix.issue.line}`));
1402
- console.log(chalk.gray(` ${fix.explanation}`));
1374
+ const acceptedFixes = [];
1375
+ const skippedFixes = [];
1376
+ let applyAll = false;
1377
+ let skipRest = false;
1378
+ for (let i = 0; i < fixes.length; i++) {
1379
+ const fix = fixes[i];
1380
+ if (skipRest) {
1381
+ skippedFixes.push(fix);
1382
+ continue;
1383
+ }
1384
+ if (applyAll) {
1385
+ acceptedFixes.push(fix);
1386
+ continue;
1387
+ }
1388
+ console.log(chalk.cyan(` \u2500\u2500\u2500 Fix ${i + 1}/${fixes.length}: ${fix.issue.file}:${fix.issue.line} \u2500\u2500\u2500`));
1389
+ console.log(chalk.gray(` Issue: ${fix.issue.name} (${fix.issue.severity})`));
1390
+ console.log();
1391
+ const origLines = fix.originalCode.split("\n");
1392
+ console.log(chalk.red(" - Original:"));
1393
+ origLines.slice(0, 8).forEach((line) => console.log(chalk.red(` ${line}`)));
1394
+ if (origLines.length > 8) {
1395
+ console.log(chalk.gray(` ... (${origLines.length - 8} more lines)`));
1396
+ }
1397
+ console.log();
1398
+ const fixLines = fix.fixedCode.split("\n");
1399
+ console.log(chalk.green(" + Suggested fix:"));
1400
+ fixLines.slice(0, 8).forEach((line) => console.log(chalk.green(` ${line}`)));
1401
+ if (fixLines.length > 8) {
1402
+ console.log(chalk.gray(` ... (${fixLines.length - 8} more lines)`));
1403
+ }
1404
+ console.log();
1405
+ console.log(chalk.gray(` Explanation: ${fix.explanation}`));
1406
+ console.log();
1407
+ const action = await select({
1408
+ message: "Apply this fix?",
1409
+ choices: [
1410
+ { name: "Yes - apply this fix", value: "y" },
1411
+ { name: "No - skip this fix", value: "n" },
1412
+ { name: "All - apply all remaining fixes", value: "a" },
1413
+ { name: "Skip rest - save remaining to file", value: "s" },
1414
+ { name: "Quit - stop reviewing", value: "q" }
1415
+ ]
1416
+ });
1417
+ if (action === "y") {
1418
+ acceptedFixes.push(fix);
1419
+ console.log(chalk.green(" \u2714 Fix accepted"));
1420
+ } else if (action === "n") {
1421
+ skippedFixes.push(fix);
1422
+ console.log(chalk.yellow(" \u2298 Fix skipped"));
1423
+ } else if (action === "a") {
1424
+ applyAll = true;
1425
+ acceptedFixes.push(fix);
1426
+ for (let j = i + 1; j < fixes.length; j++) {
1427
+ acceptedFixes.push(fixes[j]);
1428
+ }
1429
+ console.log(chalk.green(` \u2714 Applying all ${fixes.length - i} remaining fixes`));
1430
+ break;
1431
+ } else if (action === "s") {
1432
+ skipRest = true;
1433
+ skippedFixes.push(fix);
1434
+ for (let j = i + 1; j < fixes.length; j++) {
1435
+ skippedFixes.push(fixes[j]);
1436
+ }
1437
+ console.log(chalk.yellow(` \u2298 Skipping ${fixes.length - i} remaining fixes`));
1438
+ break;
1439
+ } else if (action === "q") {
1440
+ skippedFixes.push(fix);
1441
+ for (let j = i + 1; j < fixes.length; j++) {
1442
+ skippedFixes.push(fixes[j]);
1443
+ }
1444
+ console.log(chalk.gray(" Stopped reviewing"));
1445
+ break;
1446
+ }
1447
+ console.log();
1448
+ }
1449
+ if (acceptedFixes.length > 0) {
1450
+ console.log();
1451
+ const applySpinner = ora({
1452
+ text: `Applying ${acceptedFixes.length} fixes...`,
1453
+ color: "cyan"
1454
+ }).start();
1455
+ let appliedCount = 0;
1456
+ for (const fix of acceptedFixes) {
1457
+ const content = fileContents.get(fix.issue.file);
1458
+ if (!content) continue;
1459
+ const newContent = content.replace(fix.originalCode, fix.fixedCode);
1460
+ if (newContent !== content) {
1461
+ const filePath = path3.resolve(targetPath, fix.issue.file);
1462
+ fs3.writeFileSync(filePath, newContent, "utf-8");
1463
+ fileContents.set(fix.issue.file, newContent);
1464
+ appliedCount++;
1465
+ }
1466
+ }
1467
+ applySpinner.succeed(`Applied ${appliedCount}/${acceptedFixes.length} fixes to your codebase`);
1468
+ }
1469
+ if (skippedFixes.length > 0) {
1470
+ const fixesFile = ".cencori-fixes.json";
1471
+ const fixesData = {
1472
+ generated_at: (/* @__PURE__ */ new Date()).toISOString(),
1473
+ total_fixes: skippedFixes.length,
1474
+ fixes: skippedFixes.map((f) => ({
1475
+ file: f.issue.file,
1476
+ line: f.issue.line,
1477
+ issue_type: f.issue.type,
1478
+ issue_name: f.issue.name,
1479
+ severity: f.issue.severity,
1480
+ original_code: f.originalCode,
1481
+ suggested_fix: f.fixedCode,
1482
+ explanation: f.explanation
1483
+ }))
1484
+ };
1485
+ fs3.writeFileSync(fixesFile, JSON.stringify(fixesData, null, 2));
1486
+ console.log();
1487
+ console.log(chalk.yellow(` ${skippedFixes.length} skipped fixes saved to ${chalk.bold(fixesFile)}`));
1488
+ }
1489
+ console.log();
1490
+ console.log(chalk.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1491
+ console.log();
1492
+ console.log(` ${chalk.bold("Summary:")}`);
1493
+ if (acceptedFixes.length > 0) {
1494
+ console.log(chalk.green(` \u2714 ${acceptedFixes.length} fixes applied`));
1495
+ }
1496
+ if (skippedFixes.length > 0) {
1497
+ console.log(chalk.yellow(` \u2298 ${skippedFixes.length} fixes skipped (saved to .cencori-fixes.json)`));
1403
1498
  }
1404
- const notApplied = appliedFixes.filter((f) => !f.applied);
1405
- if (notApplied.length > 0) {
1499
+ if (acceptedFixes.length > 0) {
1406
1500
  console.log();
1407
- console.log(` ${chalk.yellow(`${notApplied.length} issues require manual review`)}`);
1501
+ console.log(chalk.cyan(` Run ${chalk.bold("npx @cencori/scan")} again to verify your fixes!`));
1408
1502
  }
1409
1503
  console.log();
1410
1504
  } catch (error) {