@valbuild/init 0.69.1 → 0.71.0

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.
@@ -492,7 +492,7 @@ function transformNextAppRouterValProvider(fileInfo, api, options) {
492
492
 
493
493
  var packageJson = {
494
494
  name: "@valbuild/init",
495
- version: "0.69.1",
495
+ version: "0.71.0",
496
496
  description: "Initialize a new val.build project",
497
497
  exports: {
498
498
  "./main": {
@@ -591,6 +591,15 @@ function info(message) {
591
591
  console.log(message);
592
592
  }
593
593
 
594
+ function addEslintPluginToEslintMjs(fileInfo, api, options) {
595
+ if (!options.configImportPath) {
596
+ throw new Error("configImportPath is required");
597
+ }
598
+ var root = api.jscodeshift(fileInfo.source);
599
+ root.findVariableDeclarators("eslintConfig").find(j.ArrayExpression).find(j.SpreadElement).find(j.CallExpression).find(j.Literal).at(-1).insertAfter(j.literal("plugin:@valbuild/recommended"));
600
+ return root.toSource();
601
+ }
602
+
594
603
  var MIN_VAL_VERSION = packageJson.version;
595
604
  var MIN_NEXT_VERSION = "13.4.0";
596
605
  var maxResetLength = 0;
@@ -727,6 +736,16 @@ var analyze = /*#__PURE__*/function () {
727
736
  analysis.isValEslintRulesConfigured = analysis.eslintRcJsText.includes("plugin:@valbuild/recommended");
728
737
  }
729
738
  }
739
+ analysis.eslintRcMjsPath = files.find(function (file) {
740
+ return file.endsWith("eslint.config.mjs");
741
+ });
742
+ if (analysis.eslintRcMjsPath) {
743
+ analysis.eslintRcMjsText = fs.readFileSync(analysis.eslintRcMjsPath, "utf8");
744
+ if (analysis.eslintRcMjsText) {
745
+ // TODO: Evaluate and extract config?
746
+ analysis.isValEslintRulesConfigured = analysis.eslintRcMjsText.includes("@valbuild");
747
+ }
748
+ }
730
749
  analysis.eslintRcJsonPath = files.find(function (file) {
731
750
  return file.endsWith(".eslintrc.json");
732
751
  }) || files.find(function (file) {
@@ -764,15 +783,15 @@ var analyze = /*#__PURE__*/function () {
764
783
  analysis.appRouterPath = path.dirname(appRouterLayoutPath);
765
784
  analysis.srcDir = path.dirname(analysis.appRouterPath);
766
785
  }
767
- _context.prev = 34;
786
+ _context.prev = 36;
768
787
  git = simpleGit(root);
769
- _context.next = 38;
788
+ _context.next = 40;
770
789
  return git.status([]);
771
- case 38:
790
+ case 40:
772
791
  gitStatus = _context.sent;
773
- _context.next = 41;
792
+ _context.next = 43;
774
793
  return git.remote(["-v"]);
775
- case 41:
794
+ case 43:
776
795
  gitRemoteOrigin = _context.sent;
777
796
  analysis.hasGit = true;
778
797
  analysis.isGitHub = gitRemoteOrigin ? !!gitRemoteOrigin.includes("github.com") : false;
@@ -788,21 +807,21 @@ var analyze = /*#__PURE__*/function () {
788
807
  repo: repo
789
808
  };
790
809
  }
791
- _context.next = 50;
810
+ _context.next = 52;
792
811
  break;
793
- case 48:
794
- _context.prev = 48;
795
- _context.t1 = _context["catch"](34);
796
812
  case 50:
813
+ _context.prev = 50;
814
+ _context.t1 = _context["catch"](36);
815
+ case 52:
797
816
  gitIgnorePath = path.join(root, ".gitignore");
798
817
  analysis.gitIgnorePath = gitIgnorePath;
799
818
  analysis.gitIgnoreFile = fs.readFileSync(gitIgnorePath, "utf-8");
800
819
  return _context.abrupt("return", analysis);
801
- case 54:
820
+ case 56:
802
821
  case "end":
803
822
  return _context.stop();
804
823
  }
805
- }, _callee, null, [[8, 19], [34, 48]]);
824
+ }, _callee, null, [[8, 19], [36, 50]]);
806
825
  }));
807
826
  return function analyze(_x, _x2) {
808
827
  return _ref2.apply(this, arguments);
@@ -850,8 +869,13 @@ function _plan() {
850
869
  _answer9,
851
870
  currentEslintRc,
852
871
  parsedEslint,
872
+ _res,
873
+ _diff,
874
+ _s,
853
875
  _answer10,
854
876
  _answer11,
877
+ _answer12,
878
+ _answer13,
855
879
  vscodeDir,
856
880
  settingsPath,
857
881
  currentSettings,
@@ -1418,7 +1442,7 @@ function _plan() {
1418
1442
  warn(NO_PATCH_WARNING);
1419
1443
  }
1420
1444
  if (!analysis.valEslintVersion) {
1421
- _context3.next = 246;
1445
+ _context3.next = 279;
1422
1446
  break;
1423
1447
  }
1424
1448
  if (!analysis.isValEslintRulesConfigured) {
@@ -1426,53 +1450,58 @@ function _plan() {
1426
1450
  break;
1427
1451
  }
1428
1452
  warn(" @valbuild/eslint-plugin rules: already configured");
1429
- _context3.next = 246;
1453
+ _context3.next = 279;
1430
1454
  break;
1431
1455
  case 220:
1432
1456
  if (!analysis.eslintRcJsPath) {
1433
- _context3.next = 224;
1457
+ _context3.next = 225;
1434
1458
  break;
1435
1459
  }
1436
- warn('Cannot patch eslint: found .eslintrc.js but can only patch JSON files (at the moment).\nAdd the following to your eslint config:\n\n "extends": ["plugin:@valbuild/recommended"]\n');
1437
- _context3.next = 246;
1460
+ _context3.next = 223;
1461
+ return confirm({
1462
+ message: ' Cannot patch eslint: found .eslintrc.js but can only patch JSON files (at the moment).\nAdd the following to your eslint config:\n\n "extends": ["plugin:@valbuild/recommended"]\n\n',
1463
+ "default": true
1464
+ });
1465
+ case 223:
1466
+ _context3.next = 279;
1438
1467
  break;
1439
- case 224:
1468
+ case 225:
1440
1469
  if (!analysis.eslintRcJsonPath) {
1441
- _context3.next = 245;
1470
+ _context3.next = 246;
1442
1471
  break;
1443
1472
  }
1444
1473
  if (defaultAnswers) {
1445
- _context3.next = 231;
1474
+ _context3.next = 232;
1446
1475
  break;
1447
1476
  }
1448
- _context3.next = 228;
1477
+ _context3.next = 229;
1449
1478
  return confirm({
1450
1479
  message: "Patch eslintrc.json to use the recommended Val eslint rules?",
1451
1480
  "default": true
1452
1481
  });
1453
- case 228:
1482
+ case 229:
1454
1483
  _context3.t9 = _context3.sent;
1455
- _context3.next = 232;
1484
+ _context3.next = 233;
1456
1485
  break;
1457
- case 231:
1458
- _context3.t9 = true;
1459
1486
  case 232:
1487
+ _context3.t9 = true;
1488
+ case 233:
1460
1489
  _answer9 = _context3.t9;
1461
1490
  if (!_answer9) {
1462
- _context3.next = 243;
1491
+ _context3.next = 244;
1463
1492
  break;
1464
1493
  }
1465
1494
  currentEslintRc = fs.readFileSync(analysis.eslintRcJsonPath, "utf-8");
1466
1495
  parsedEslint = JSON.parse(currentEslintRc);
1467
1496
  if (!(_typeof(parsedEslint) !== "object")) {
1468
- _context3.next = 239;
1497
+ _context3.next = 240;
1469
1498
  break;
1470
1499
  }
1471
1500
  error("Could not patch eslint: ".concat(analysis.eslintRcJsonPath, " was not an object"));
1472
1501
  return _context3.abrupt("return", {
1473
1502
  abort: true
1474
1503
  });
1475
- case 239:
1504
+ case 240:
1476
1505
  if (typeof parsedEslint["extends"] === "string") {
1477
1506
  parsedEslint["extends"] = [parsedEslint["extends"]];
1478
1507
  }
@@ -1482,34 +1511,124 @@ function _plan() {
1482
1511
  path: analysis.eslintRcJsonPath,
1483
1512
  source: JSON.stringify(parsedEslint, null, 2) + "\n"
1484
1513
  };
1485
- case 243:
1486
- _context3.next = 246;
1514
+ case 244:
1515
+ _context3.next = 279;
1487
1516
  break;
1488
- case 245:
1489
- warn("Cannot patch eslint: failed to find eslint config file");
1490
1517
  case 246:
1491
- if (!analysis.gitIgnorePath) {
1492
- _context3.next = 258;
1518
+ if (!analysis.eslintRcMjsPath) {
1519
+ _context3.next = 278;
1520
+ break;
1521
+ }
1522
+ if (!analysis.eslintRcMjsText) {
1523
+ _context3.next = 275;
1493
1524
  break;
1494
1525
  }
1526
+ _res = addEslintPluginToEslintMjs({
1527
+ path: analysis.eslintRcMjsPath,
1528
+ source: analysis.eslintRcMjsText
1529
+ }, {
1530
+ j: j,
1531
+ jscodeshift: j.withParser("tsx"),
1532
+ stats: function stats() {},
1533
+ report: function report() {}
1534
+ }, {
1535
+ configImportPath: path.relative(path.dirname(analysis.eslintRcMjsPath), valConfigPath).replace(".js", "").replace(".ts", "")
1536
+ });
1537
+ _diff = diffLines(analysis.eslintRcMjsText, _res, {});
1538
+ _s = "";
1539
+ _diff.forEach(function (part) {
1540
+ if (part.added) {
1541
+ _s += chalk.green(part.value);
1542
+ } else if (part.removed) {
1543
+ _s += chalk.red(part.value);
1544
+ } else {
1545
+ _s += part.value;
1546
+ }
1547
+ });
1495
1548
  if (defaultAnswers) {
1496
- _context3.next = 253;
1549
+ _context3.next = 258;
1497
1550
  break;
1498
1551
  }
1499
- _context3.next = 250;
1552
+ _context3.next = 255;
1500
1553
  return confirm({
1501
- message: "Append .gitignore entry for Val cache? (recommended)",
1554
+ message: "Automatically patch ".concat(analysis.eslintRcMjsPath, " file?"),
1502
1555
  "default": true
1503
1556
  });
1504
- case 250:
1557
+ case 255:
1505
1558
  _context3.t10 = _context3.sent;
1506
- _context3.next = 254;
1559
+ _context3.next = 259;
1507
1560
  break;
1508
- case 253:
1561
+ case 258:
1509
1562
  _context3.t10 = true;
1510
- case 254:
1563
+ case 259:
1511
1564
  _answer10 = _context3.t10;
1512
- if (_answer10) {
1565
+ if (!_answer10) {
1566
+ _context3.next = 272;
1567
+ break;
1568
+ }
1569
+ if (defaultAnswers) {
1570
+ _context3.next = 267;
1571
+ break;
1572
+ }
1573
+ _context3.next = 264;
1574
+ return confirm({
1575
+ message: "Do you accept the following patch:\n".concat(_s, "\n"),
1576
+ "default": true
1577
+ });
1578
+ case 264:
1579
+ _context3.t11 = _context3.sent;
1580
+ _context3.next = 268;
1581
+ break;
1582
+ case 267:
1583
+ _context3.t11 = true;
1584
+ case 268:
1585
+ _answer11 = _context3.t11;
1586
+ if (!_answer11) {
1587
+ warn(NO_PATCH_WARNING);
1588
+ plan.updateEslint = false;
1589
+ } else {
1590
+ plan.updateEslint = {
1591
+ path: analysis.eslintRcMjsPath,
1592
+ source: _res
1593
+ };
1594
+ }
1595
+ _context3.next = 273;
1596
+ break;
1597
+ case 272:
1598
+ warn(NO_PATCH_WARNING);
1599
+ case 273:
1600
+ _context3.next = 276;
1601
+ break;
1602
+ case 275:
1603
+ warn(NO_PATCH_WARNING);
1604
+ case 276:
1605
+ _context3.next = 279;
1606
+ break;
1607
+ case 278:
1608
+ warn("Cannot patch eslint: failed to find eslint config file");
1609
+ case 279:
1610
+ if (!analysis.gitIgnorePath) {
1611
+ _context3.next = 291;
1612
+ break;
1613
+ }
1614
+ if (defaultAnswers) {
1615
+ _context3.next = 286;
1616
+ break;
1617
+ }
1618
+ _context3.next = 283;
1619
+ return confirm({
1620
+ message: "Append .gitignore entry for Val cache? (recommended)",
1621
+ "default": true
1622
+ });
1623
+ case 283:
1624
+ _context3.t12 = _context3.sent;
1625
+ _context3.next = 287;
1626
+ break;
1627
+ case 286:
1628
+ _context3.t12 = true;
1629
+ case 287:
1630
+ _answer12 = _context3.t12;
1631
+ if (_answer12) {
1513
1632
  plan.updateGitIgnore = {
1514
1633
  path: analysis.gitIgnorePath,
1515
1634
  source: (analysis.gitIgnoreFile ? "".concat(analysis.gitIgnoreFile, "\n\n") : "") + "# Val local cache\n.val\n"
@@ -1517,59 +1636,59 @@ function _plan() {
1517
1636
  } else {
1518
1637
  plan.updateGitIgnore = false;
1519
1638
  }
1520
- _context3.next = 259;
1639
+ _context3.next = 292;
1521
1640
  break;
1522
- case 258:
1641
+ case 291:
1523
1642
  plan.updateGitIgnore = false;
1524
- case 259:
1643
+ case 292:
1525
1644
  if (defaultAnswers) {
1526
- _context3.next = 265;
1645
+ _context3.next = 298;
1527
1646
  break;
1528
1647
  }
1529
- _context3.next = 262;
1648
+ _context3.next = 295;
1530
1649
  return confirm({
1531
1650
  message: "Add the Val Build IntelliSense to .vscode/extensions.json?",
1532
1651
  "default": true
1533
1652
  });
1534
- case 262:
1535
- _context3.t11 = _context3.sent;
1536
- _context3.next = 266;
1653
+ case 295:
1654
+ _context3.t13 = _context3.sent;
1655
+ _context3.next = 299;
1537
1656
  break;
1538
- case 265:
1539
- _context3.t11 = true;
1540
- case 266:
1541
- _answer11 = _context3.t11;
1542
- if (!_answer11) {
1543
- _context3.next = 292;
1657
+ case 298:
1658
+ _context3.t13 = true;
1659
+ case 299:
1660
+ _answer13 = _context3.t13;
1661
+ if (!_answer13) {
1662
+ _context3.next = 325;
1544
1663
  break;
1545
1664
  }
1546
1665
  vscodeDir = path.join(analysis.root, ".vscode");
1547
1666
  settingsPath = path.join(vscodeDir, "extensions.json");
1548
1667
  currentSettings = {};
1549
- _context3.prev = 271;
1668
+ _context3.prev = 304;
1550
1669
  currentSettingsFile = fs.readFileSync(settingsPath, "utf-8");
1551
1670
  if (!currentSettingsFile) {
1552
- _context3.next = 282;
1671
+ _context3.next = 315;
1553
1672
  break;
1554
1673
  }
1555
- _context3.prev = 274;
1674
+ _context3.prev = 307;
1556
1675
  currentSettings = JSON.parse(currentSettingsFile);
1557
- _context3.next = 282;
1676
+ _context3.next = 315;
1558
1677
  break;
1559
- case 278:
1560
- _context3.prev = 278;
1561
- _context3.t12 = _context3["catch"](274);
1562
- warn("Failed to parse VS Code extensions.json found here: ".concat(settingsPath, ".").concat(_context3.t12 instanceof Error ? "Parse error: ".concat(_context3.t12.message) : ""));
1678
+ case 311:
1679
+ _context3.prev = 311;
1680
+ _context3.t14 = _context3["catch"](307);
1681
+ warn("Failed to parse VS Code extensions.json found here: ".concat(settingsPath, ".").concat(_context3.t14 instanceof Error ? "Parse error: ".concat(_context3.t14.message) : ""));
1563
1682
  return _context3.abrupt("return", {
1564
1683
  abort: true
1565
1684
  });
1566
- case 282:
1567
- _context3.next = 286;
1685
+ case 315:
1686
+ _context3.next = 319;
1568
1687
  break;
1569
- case 284:
1570
- _context3.prev = 284;
1571
- _context3.t13 = _context3["catch"](271);
1572
- case 286:
1688
+ case 317:
1689
+ _context3.prev = 317;
1690
+ _context3.t15 = _context3["catch"](304);
1691
+ case 319:
1573
1692
  currentRecommendations =
1574
1693
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1575
1694
  currentSettings.recommendations;
@@ -1583,17 +1702,17 @@ function _plan() {
1583
1702
  path: settingsPath,
1584
1703
  source: JSON.stringify(currentSettings, null, 2)
1585
1704
  };
1586
- _context3.next = 293;
1705
+ _context3.next = 326;
1587
1706
  break;
1588
- case 292:
1707
+ case 325:
1589
1708
  plan.updateVSCodeSettings = false;
1590
- case 293:
1709
+ case 326:
1591
1710
  return _context3.abrupt("return", plan);
1592
- case 294:
1711
+ case 327:
1593
1712
  case "end":
1594
1713
  return _context3.stop();
1595
1714
  }
1596
- }, _callee3, null, [[271, 284], [274, 278]]);
1715
+ }, _callee3, null, [[304, 317], [307, 311]]);
1597
1716
  }));
1598
1717
  return _plan.apply(this, arguments);
1599
1718
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valbuild/init",
3
- "version": "0.69.1",
3
+ "version": "0.71.0",
4
4
  "description": "Initialize a new val.build project",
5
5
  "exports": {
6
6
  "./main": {
@@ -0,0 +1,22 @@
1
+ import j from "jscodeshift";
2
+
3
+ export function addEslintPluginToEslintMjs(
4
+ fileInfo: j.FileInfo,
5
+ api: j.API,
6
+ options: j.Options,
7
+ ) {
8
+ if (!options.configImportPath) {
9
+ throw new Error("configImportPath is required");
10
+ }
11
+ const root = api.jscodeshift(fileInfo.source);
12
+ root
13
+ .findVariableDeclarators("eslintConfig")
14
+ .find(j.ArrayExpression)
15
+ .find(j.SpreadElement)
16
+ .find(j.CallExpression)
17
+ .find(j.Literal)
18
+ .at(-1)
19
+ .insertAfter(j.literal("plugin:@valbuild/recommended"));
20
+
21
+ return root.toSource();
22
+ }
@@ -1 +1,2 @@
1
1
  export * from "./transformNextAppRouterValProvider";
2
+ export * from "./addEslintPluginToEslintMjs";
@@ -1,5 +1,6 @@
1
1
  import jcs from "jscodeshift";
2
2
  import { transformNextAppRouterValProvider } from "./codemods/transformNextAppRouterValProvider";
3
+ import { addEslintPluginToEslintMjs } from "./codemods/addEslintPluginToEslintMjs";
3
4
 
4
5
  const APP_ROUTER_LAYOUT_SANS_VAL_PROVIDER = `import type { Metadata } from "next";
5
6
  import { Inter } from "next/font/google";
@@ -70,6 +71,57 @@ export default function RootLayout({
70
71
  </html>)
71
72
  );
72
73
  }
74
+ `);
75
+ });
76
+
77
+ test("add eslint plugin to eslint.config.mjs generated by create-next-app", async () => {
78
+ const res = addEslintPluginToEslintMjs(
79
+ {
80
+ path: "./eslint.config.mjs",
81
+ source: `import { dirname } from "path";
82
+ import { fileURLToPath } from "url";
83
+ import { FlatCompat } from "@eslint/eslintrc";
84
+
85
+ const __filename = fileURLToPath(import.meta.url);
86
+ const __dirname = dirname(__filename);
87
+
88
+ const compat = new FlatCompat({
89
+ baseDirectory: __dirname,
90
+ });
91
+
92
+ const eslintConfig = [
93
+ ...compat.extends("next/core-web-vitals", "next/typescript"),
94
+ ];
95
+
96
+ export default eslintConfig;
97
+ `,
98
+ },
99
+ {
100
+ j: jcs,
101
+ jscodeshift: jcs,
102
+ stats: () => {},
103
+ report: () => {},
104
+ },
105
+ {
106
+ configImportPath: "../val.config",
107
+ },
108
+ );
109
+ expect(res).toEqual(`import { dirname } from "path";
110
+ import { fileURLToPath } from "url";
111
+ import { FlatCompat } from "@eslint/eslintrc";
112
+
113
+ const __filename = fileURLToPath(import.meta.url);
114
+ const __dirname = dirname(__filename);
115
+
116
+ const compat = new FlatCompat({
117
+ baseDirectory: __dirname,
118
+ });
119
+
120
+ const eslintConfig = [
121
+ ...compat.extends("next/core-web-vitals", "next/typescript", "plugin:@valbuild/recommended"),
122
+ ];
123
+
124
+ export default eslintConfig;
73
125
  `);
74
126
  });
75
127
  });
package/src/init.ts CHANGED
@@ -19,6 +19,7 @@ import {
19
19
  VAL_SERVER,
20
20
  } from "./templates";
21
21
  import * as logger from "./logger";
22
+ import { addEslintPluginToEslintMjs } from "./codemods";
22
23
 
23
24
  const MIN_VAL_VERSION = packageJson.version;
24
25
  const MIN_NEXT_VERSION = "13.4.0";
@@ -92,6 +93,8 @@ type Analysis = Partial<{
92
93
  eslintRcJsonText: string;
93
94
  eslintRcJsPath: string;
94
95
  eslintRcJsText: string;
96
+ eslintRcMjsPath: string;
97
+ eslintRcMjsText: string;
95
98
  valEslintVersion: string;
96
99
  isValEslintRulesConfigured: boolean;
97
100
 
@@ -191,6 +194,20 @@ const analyze = async (root: string, files: string[]): Promise<Analysis> => {
191
194
  );
192
195
  }
193
196
  }
197
+ analysis.eslintRcMjsPath = files.find((file) =>
198
+ file.endsWith("eslint.config.mjs"),
199
+ );
200
+ if (analysis.eslintRcMjsPath) {
201
+ analysis.eslintRcMjsText = fs.readFileSync(
202
+ analysis.eslintRcMjsPath,
203
+ "utf8",
204
+ );
205
+ if (analysis.eslintRcMjsText) {
206
+ // TODO: Evaluate and extract config?
207
+ analysis.isValEslintRulesConfigured =
208
+ analysis.eslintRcMjsText.includes("@valbuild");
209
+ }
210
+ }
194
211
  analysis.eslintRcJsonPath =
195
212
  files.find((file) => file.endsWith(".eslintrc.json")) ||
196
213
  files.find((file) => file.endsWith(".eslintrc"));
@@ -718,9 +735,11 @@ async function plan(
718
735
  logger.warn(" @valbuild/eslint-plugin rules: already configured");
719
736
  } else {
720
737
  if (analysis.eslintRcJsPath) {
721
- logger.warn(
722
- 'Cannot patch eslint: found .eslintrc.js but can only patch JSON files (at the moment).\nAdd the following to your eslint config:\n\n "extends": ["plugin:@valbuild/recommended"]\n',
723
- );
738
+ await confirm({
739
+ message:
740
+ ' Cannot patch eslint: found .eslintrc.js but can only patch JSON files (at the moment).\nAdd the following to your eslint config:\n\n "extends": ["plugin:@valbuild/recommended"]\n\n',
741
+ default: true,
742
+ });
724
743
  } else if (analysis.eslintRcJsonPath) {
725
744
  const answer = !defaultAnswers
726
745
  ? await confirm({
@@ -751,6 +770,67 @@ async function plan(
751
770
  source: JSON.stringify(parsedEslint, null, 2) + "\n",
752
771
  };
753
772
  }
773
+ } else if (analysis.eslintRcMjsPath) {
774
+ if (analysis.eslintRcMjsText) {
775
+ const res = addEslintPluginToEslintMjs(
776
+ {
777
+ path: analysis.eslintRcMjsPath,
778
+ source: analysis.eslintRcMjsText,
779
+ },
780
+ {
781
+ j: jcs,
782
+ jscodeshift: jcs.withParser("tsx"),
783
+ stats: () => {},
784
+ report: () => {},
785
+ },
786
+ {
787
+ configImportPath: path
788
+ .relative(path.dirname(analysis.eslintRcMjsPath), valConfigPath)
789
+ .replace(".js", "")
790
+ .replace(".ts", ""),
791
+ },
792
+ );
793
+
794
+ const diff = diffLines(analysis.eslintRcMjsText, res, {});
795
+
796
+ let s = "";
797
+ diff.forEach((part) => {
798
+ if (part.added) {
799
+ s += chalk.green(part.value);
800
+ } else if (part.removed) {
801
+ s += chalk.red(part.value);
802
+ } else {
803
+ s += part.value;
804
+ }
805
+ });
806
+ const answer = !defaultAnswers
807
+ ? await confirm({
808
+ message: `Automatically patch ${analysis.eslintRcMjsPath} file?`,
809
+ default: true,
810
+ })
811
+ : true;
812
+ if (answer) {
813
+ const answer = !defaultAnswers
814
+ ? await confirm({
815
+ message: `Do you accept the following patch:\n${s}\n`,
816
+ default: true,
817
+ })
818
+ : true;
819
+ if (!answer) {
820
+ logger.warn(NO_PATCH_WARNING);
821
+ plan.updateEslint = false;
822
+ } else {
823
+ plan.updateEslint = {
824
+ path: analysis.eslintRcMjsPath,
825
+ source: res,
826
+ };
827
+ }
828
+ } else {
829
+ logger.warn(NO_PATCH_WARNING);
830
+ }
831
+ } else {
832
+ logger.warn(NO_PATCH_WARNING);
833
+ }
754
834
  } else {
755
835
  logger.warn("Cannot patch eslint: failed to find eslint config file");
756
836
  }