@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.
- package/main/dist/valbuild-init-main.cjs.dev.js +194 -75
- package/main/dist/valbuild-init-main.cjs.prod.js +194 -75
- package/main/dist/valbuild-init-main.esm.js +194 -75
- package/package.json +1 -1
- package/src/codemods/addEslintPluginToEslintMjs.ts +22 -0
- package/src/codemods/index.ts +1 -0
- package/src/codemods.test.ts +52 -0
- package/src/init.ts +83 -3
|
@@ -492,7 +492,7 @@ function transformNextAppRouterValProvider(fileInfo, api, options) {
|
|
|
492
492
|
|
|
493
493
|
var packageJson = {
|
|
494
494
|
name: "@valbuild/init",
|
|
495
|
-
version: "0.
|
|
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 =
|
|
786
|
+
_context.prev = 36;
|
|
768
787
|
git = simpleGit(root);
|
|
769
|
-
_context.next =
|
|
788
|
+
_context.next = 40;
|
|
770
789
|
return git.status([]);
|
|
771
|
-
case
|
|
790
|
+
case 40:
|
|
772
791
|
gitStatus = _context.sent;
|
|
773
|
-
_context.next =
|
|
792
|
+
_context.next = 43;
|
|
774
793
|
return git.remote(["-v"]);
|
|
775
|
-
case
|
|
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 =
|
|
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
|
|
820
|
+
case 56:
|
|
802
821
|
case "end":
|
|
803
822
|
return _context.stop();
|
|
804
823
|
}
|
|
805
|
-
}, _callee, null, [[8, 19], [
|
|
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 =
|
|
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 =
|
|
1453
|
+
_context3.next = 279;
|
|
1430
1454
|
break;
|
|
1431
1455
|
case 220:
|
|
1432
1456
|
if (!analysis.eslintRcJsPath) {
|
|
1433
|
-
_context3.next =
|
|
1457
|
+
_context3.next = 225;
|
|
1434
1458
|
break;
|
|
1435
1459
|
}
|
|
1436
|
-
|
|
1437
|
-
|
|
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
|
|
1468
|
+
case 225:
|
|
1440
1469
|
if (!analysis.eslintRcJsonPath) {
|
|
1441
|
-
_context3.next =
|
|
1470
|
+
_context3.next = 246;
|
|
1442
1471
|
break;
|
|
1443
1472
|
}
|
|
1444
1473
|
if (defaultAnswers) {
|
|
1445
|
-
_context3.next =
|
|
1474
|
+
_context3.next = 232;
|
|
1446
1475
|
break;
|
|
1447
1476
|
}
|
|
1448
|
-
_context3.next =
|
|
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
|
|
1482
|
+
case 229:
|
|
1454
1483
|
_context3.t9 = _context3.sent;
|
|
1455
|
-
_context3.next =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
1486
|
-
_context3.next =
|
|
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.
|
|
1492
|
-
_context3.next =
|
|
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 =
|
|
1549
|
+
_context3.next = 258;
|
|
1497
1550
|
break;
|
|
1498
1551
|
}
|
|
1499
|
-
_context3.next =
|
|
1552
|
+
_context3.next = 255;
|
|
1500
1553
|
return confirm({
|
|
1501
|
-
message: "
|
|
1554
|
+
message: "Automatically patch ".concat(analysis.eslintRcMjsPath, " file?"),
|
|
1502
1555
|
"default": true
|
|
1503
1556
|
});
|
|
1504
|
-
case
|
|
1557
|
+
case 255:
|
|
1505
1558
|
_context3.t10 = _context3.sent;
|
|
1506
|
-
_context3.next =
|
|
1559
|
+
_context3.next = 259;
|
|
1507
1560
|
break;
|
|
1508
|
-
case
|
|
1561
|
+
case 258:
|
|
1509
1562
|
_context3.t10 = true;
|
|
1510
|
-
case
|
|
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 =
|
|
1639
|
+
_context3.next = 292;
|
|
1521
1640
|
break;
|
|
1522
|
-
case
|
|
1641
|
+
case 291:
|
|
1523
1642
|
plan.updateGitIgnore = false;
|
|
1524
|
-
case
|
|
1643
|
+
case 292:
|
|
1525
1644
|
if (defaultAnswers) {
|
|
1526
|
-
_context3.next =
|
|
1645
|
+
_context3.next = 298;
|
|
1527
1646
|
break;
|
|
1528
1647
|
}
|
|
1529
|
-
_context3.next =
|
|
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
|
|
1535
|
-
_context3.
|
|
1536
|
-
_context3.next =
|
|
1653
|
+
case 295:
|
|
1654
|
+
_context3.t13 = _context3.sent;
|
|
1655
|
+
_context3.next = 299;
|
|
1537
1656
|
break;
|
|
1538
|
-
case
|
|
1539
|
-
_context3.
|
|
1540
|
-
case
|
|
1541
|
-
|
|
1542
|
-
if (!
|
|
1543
|
-
_context3.next =
|
|
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 =
|
|
1668
|
+
_context3.prev = 304;
|
|
1550
1669
|
currentSettingsFile = fs.readFileSync(settingsPath, "utf-8");
|
|
1551
1670
|
if (!currentSettingsFile) {
|
|
1552
|
-
_context3.next =
|
|
1671
|
+
_context3.next = 315;
|
|
1553
1672
|
break;
|
|
1554
1673
|
}
|
|
1555
|
-
_context3.prev =
|
|
1674
|
+
_context3.prev = 307;
|
|
1556
1675
|
currentSettings = JSON.parse(currentSettingsFile);
|
|
1557
|
-
_context3.next =
|
|
1676
|
+
_context3.next = 315;
|
|
1558
1677
|
break;
|
|
1559
|
-
case
|
|
1560
|
-
_context3.prev =
|
|
1561
|
-
_context3.
|
|
1562
|
-
warn("Failed to parse VS Code extensions.json found here: ".concat(settingsPath, ".").concat(_context3.
|
|
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
|
|
1567
|
-
_context3.next =
|
|
1685
|
+
case 315:
|
|
1686
|
+
_context3.next = 319;
|
|
1568
1687
|
break;
|
|
1569
|
-
case
|
|
1570
|
-
_context3.prev =
|
|
1571
|
-
_context3.
|
|
1572
|
-
case
|
|
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 =
|
|
1705
|
+
_context3.next = 326;
|
|
1587
1706
|
break;
|
|
1588
|
-
case
|
|
1707
|
+
case 325:
|
|
1589
1708
|
plan.updateVSCodeSettings = false;
|
|
1590
|
-
case
|
|
1709
|
+
case 326:
|
|
1591
1710
|
return _context3.abrupt("return", plan);
|
|
1592
|
-
case
|
|
1711
|
+
case 327:
|
|
1593
1712
|
case "end":
|
|
1594
1713
|
return _context3.stop();
|
|
1595
1714
|
}
|
|
1596
|
-
}, _callee3, null, [[
|
|
1715
|
+
}, _callee3, null, [[304, 317], [307, 311]]);
|
|
1597
1716
|
}));
|
|
1598
1717
|
return _plan.apply(this, arguments);
|
|
1599
1718
|
}
|
package/package.json
CHANGED
|
@@ -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
|
+
}
|
package/src/codemods/index.ts
CHANGED
package/src/codemods.test.ts
CHANGED
|
@@ -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
|
-
|
|
722
|
-
|
|
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
|
}
|