pob 39.3.0 → 40.1.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.
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
1
3
|
import path from "node:path";
|
|
4
|
+
import { runTransform } from "@pob/codemods";
|
|
2
5
|
import { format } from "oxfmt";
|
|
6
|
+
import semver from "semver";
|
|
3
7
|
import Generator from "yeoman-generator";
|
|
4
8
|
import { quoteArg } from "../../../utils/execUtils.js";
|
|
5
9
|
import inMonorepo from "../../../utils/inMonorepo.js";
|
|
@@ -56,6 +60,23 @@ const isPreviousEslintConfigOutput = async (
|
|
|
56
60
|
return false;
|
|
57
61
|
};
|
|
58
62
|
|
|
63
|
+
// from this major, eslint no longer runs the rules checked by oxlint
|
|
64
|
+
const OXLINT_ONLY_ESLINT_CONFIG_MAJOR = 68;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Whether the project used a version of @pob/eslint-config running the rules
|
|
68
|
+
* checked by oxlint in eslint too.
|
|
69
|
+
*
|
|
70
|
+
* @param {string | undefined} range
|
|
71
|
+
*/
|
|
72
|
+
const isBeforeOxlintOnlyEslintConfig = (range) => {
|
|
73
|
+
if (!range || !semver.validRange(range)) return false;
|
|
74
|
+
const minVersion = semver.minVersion(range);
|
|
75
|
+
return (
|
|
76
|
+
minVersion !== null && minVersion.major < OXLINT_ONLY_ESLINT_CONFIG_MAJOR
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
59
80
|
// same as the base ignores of @pob/eslint-config: ignorePatterns are not
|
|
60
81
|
// inherited through "extends"
|
|
61
82
|
const oxlintBaseIgnorePatterns = [
|
|
@@ -202,6 +223,12 @@ export default class CommonFormatLintGenerator extends Generator {
|
|
|
202
223
|
|
|
203
224
|
async writing() {
|
|
204
225
|
const pkg = this.fs.readJSON(this.destinationPath("package.json"));
|
|
226
|
+
// the codemods run once from the root, which lints the whole project
|
|
227
|
+
this.runOxlintOnlyCodemods =
|
|
228
|
+
(!inMonorepo || inMonorepo.root || this.options.monorepo) &&
|
|
229
|
+
isBeforeOxlintOnlyEslintConfig(
|
|
230
|
+
pkg.devDependencies?.["@pob/eslint-config"],
|
|
231
|
+
);
|
|
205
232
|
const babelEnvs =
|
|
206
233
|
(pkg.pob &&
|
|
207
234
|
(pkg.pob.babelEnvs ||
|
|
@@ -379,17 +406,14 @@ export default class CommonFormatLintGenerator extends Generator {
|
|
|
379
406
|
pkg.name !== "@pob/use-eslint-plugin"
|
|
380
407
|
) {
|
|
381
408
|
packageUtils.addDevDependencies(pkg, ["@pob/eslint-config"]);
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
shouldHavePluginsDependencies,
|
|
391
|
-
["eslint-plugin-node"],
|
|
392
|
-
);
|
|
409
|
+
// eslint plugins are dependencies of @pob/eslint-config, loaded by
|
|
410
|
+
// the flat config
|
|
411
|
+
packageUtils.removeDevDependencies(pkg, [
|
|
412
|
+
"eslint-plugin-import",
|
|
413
|
+
"eslint-plugin-node",
|
|
414
|
+
"eslint-plugin-unicorn",
|
|
415
|
+
"@typescript-eslint/eslint-plugin",
|
|
416
|
+
]);
|
|
393
417
|
|
|
394
418
|
if ((inMonorepo && inMonorepo.root) || this.options.monorepo) {
|
|
395
419
|
if (hasReact) {
|
|
@@ -405,16 +429,18 @@ export default class CommonFormatLintGenerator extends Generator {
|
|
|
405
429
|
"@pob/eslint-config-typescript-react",
|
|
406
430
|
]);
|
|
407
431
|
}
|
|
432
|
+
// import-x loads the TypeScript parser by name, from the project
|
|
433
|
+
// with yarn PnP
|
|
408
434
|
packageUtils.addOrRemoveDevDependencies(
|
|
409
435
|
pkg,
|
|
410
436
|
this.options.typescript && shouldHavePluginsDependencies,
|
|
411
|
-
["@typescript-eslint/
|
|
437
|
+
["@typescript-eslint/parser"],
|
|
412
438
|
);
|
|
413
439
|
} else {
|
|
414
440
|
packageUtils.addOrRemoveDevDependencies(
|
|
415
441
|
pkg,
|
|
416
442
|
useTypescript && shouldHavePluginsDependencies,
|
|
417
|
-
["@typescript-eslint/
|
|
443
|
+
["@typescript-eslint/parser"],
|
|
418
444
|
);
|
|
419
445
|
|
|
420
446
|
packageUtils.addOrRemoveDevDependencies(pkg, hasReact, [
|
|
@@ -426,8 +452,10 @@ export default class CommonFormatLintGenerator extends Generator {
|
|
|
426
452
|
|
|
427
453
|
/**
|
|
428
454
|
* @param {boolean} withReact
|
|
455
|
+
* @param {boolean} [legacy] the output of pob before @pob/eslint-config
|
|
456
|
+
* 68, to update it
|
|
429
457
|
*/
|
|
430
|
-
const getEslintConfig = (withReact) => {
|
|
458
|
+
const getEslintConfig = (withReact, legacy = false) => {
|
|
431
459
|
if (pkg.name === "@pob/eslint-config-monorepo") {
|
|
432
460
|
return {
|
|
433
461
|
imports: [
|
|
@@ -441,16 +469,19 @@ export default class CommonFormatLintGenerator extends Generator {
|
|
|
441
469
|
}
|
|
442
470
|
|
|
443
471
|
const flatCascade = (() => {
|
|
444
|
-
if (!useTypescript) {
|
|
472
|
+
if (!useTypescript && legacy) {
|
|
445
473
|
return [
|
|
446
474
|
useNode
|
|
447
475
|
? `...pobConfig.configs.node${pkg.type === "commonjs" ? "Commonjs" : "Module"}`
|
|
448
476
|
: `...pobConfig.configs.base${pkg.type === "commonjs" ? "Commonjs" : "Module"}`,
|
|
449
477
|
];
|
|
450
478
|
}
|
|
451
|
-
|
|
479
|
+
// configs.node and configs.baseModule handle "type": "commonjs"
|
|
480
|
+
if (!useTypescript || !withReact) {
|
|
452
481
|
return [
|
|
453
|
-
useNode
|
|
482
|
+
useNode
|
|
483
|
+
? "...pobConfig.configs.node"
|
|
484
|
+
: `...pobConfig.configs.${legacy ? "base" : "baseModule"}`,
|
|
454
485
|
];
|
|
455
486
|
}
|
|
456
487
|
|
|
@@ -458,7 +489,7 @@ export default class CommonFormatLintGenerator extends Generator {
|
|
|
458
489
|
useNode
|
|
459
490
|
? "...pobTypescriptConfigReact.configs.node"
|
|
460
491
|
: "...pobTypescriptConfigReact.configs.base",
|
|
461
|
-
|
|
492
|
+
legacy && this.options.isApp && "...pobConfig.configs.app",
|
|
462
493
|
pkg.dependencies?.["react-native-web"] &&
|
|
463
494
|
'...pobTypescriptConfigReact.configs["react-native-web"]',
|
|
464
495
|
];
|
|
@@ -560,20 +591,25 @@ export default class CommonFormatLintGenerator extends Generator {
|
|
|
560
591
|
(await isPreviousEslintConfigOutput(
|
|
561
592
|
eslintConfigPath,
|
|
562
593
|
existingEslintConfig,
|
|
563
|
-
[
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
(
|
|
594
|
+
[false, true]
|
|
595
|
+
.flatMap((legacy) => [
|
|
596
|
+
getEslintConfig(!hasReact, legacy),
|
|
597
|
+
legacy && getEslintConfig(hasReact, legacy),
|
|
598
|
+
// before the react configs were used when react is detected
|
|
599
|
+
hasReact && {
|
|
600
|
+
...getEslintConfig(hasReact, legacy),
|
|
601
|
+
flatCascade: getEslintConfig(
|
|
602
|
+
hasReact,
|
|
603
|
+
legacy,
|
|
604
|
+
).flatCascade.map((config) =>
|
|
570
605
|
config.replace(
|
|
571
606
|
/^\.\.\.pobTypescriptConfigReact\.configs\.(node|base)$/,
|
|
572
607
|
"...pobConfig.configs.$1",
|
|
573
608
|
),
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
609
|
+
),
|
|
610
|
+
},
|
|
611
|
+
])
|
|
612
|
+
.filter(Boolean),
|
|
577
613
|
)))
|
|
578
614
|
) {
|
|
579
615
|
this.fs.write(eslintConfigPath, eslintConfigContent);
|
|
@@ -599,19 +635,20 @@ export default class CommonFormatLintGenerator extends Generator {
|
|
|
599
635
|
...oxlintConfig,
|
|
600
636
|
extends: [
|
|
601
637
|
pobOxlintConfigPath("base"),
|
|
602
|
-
// ES module rules, not for
|
|
638
|
+
// ES module rules, not for .js files of "type": "commonjs" packages
|
|
603
639
|
(useTypescript || pkg.type !== "commonjs") &&
|
|
604
640
|
pobOxlintConfigPath("module"),
|
|
605
|
-
|
|
641
|
+
useNode && pobOxlintConfigPath("node"),
|
|
642
|
+
// .js files of "type": "commonjs" packages, after node.json
|
|
606
643
|
useNode &&
|
|
607
|
-
|
|
608
|
-
|
|
644
|
+
!useTypescript &&
|
|
645
|
+
pkg.type === "commonjs" &&
|
|
646
|
+
pobOxlintConfigPath("commonjs"),
|
|
609
647
|
// type-aware rules: oxlint fails without tsgolint, even in a
|
|
610
648
|
// project without TypeScript files
|
|
611
649
|
useTypescript && pobOxlintConfigPath("typescript"),
|
|
612
|
-
// overrides of typescript.json
|
|
613
|
-
//
|
|
614
|
-
// the others are kept when added by hand.
|
|
650
|
+
// overrides of typescript.json. Only app is known here: the others
|
|
651
|
+
// are kept when added by hand.
|
|
615
652
|
...(useTypescript
|
|
616
653
|
? [
|
|
617
654
|
"app",
|
|
@@ -626,8 +663,7 @@ export default class CommonFormatLintGenerator extends Generator {
|
|
|
626
663
|
)
|
|
627
664
|
.map(pobOxlintConfigPath)
|
|
628
665
|
: []),
|
|
629
|
-
//
|
|
630
|
-
// module.json and node.json: they override import/extensions.
|
|
666
|
+
// after module.json and node.json: they override import/extensions.
|
|
631
667
|
// react-native.json is kept when added by hand.
|
|
632
668
|
...(hasReact
|
|
633
669
|
? ["react", "react-native", "react-native-web"]
|
|
@@ -688,4 +724,38 @@ export default class CommonFormatLintGenerator extends Generator {
|
|
|
688
724
|
|
|
689
725
|
this.fs.writeJSON(this.destinationPath("package.json"), pkg);
|
|
690
726
|
}
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* Updates eslint-disable comments and eslint.config.js for
|
|
730
|
+
* @pob/eslint-config running the rules checked by oxlint in oxlint only.
|
|
731
|
+
*/
|
|
732
|
+
async end() {
|
|
733
|
+
if (!this.runOxlintOnlyCodemods) return;
|
|
734
|
+
const cwd = this.destinationPath();
|
|
735
|
+
const files = execFileSync(
|
|
736
|
+
"git",
|
|
737
|
+
["ls-files", "--cached", "--others", "--exclude-standard"],
|
|
738
|
+
{ cwd, encoding: "utf8" },
|
|
739
|
+
)
|
|
740
|
+
.split("\n")
|
|
741
|
+
.filter((file) => /\.[cm]?[jt]sx?$/.test(file) && !file.endsWith(".d.ts"))
|
|
742
|
+
.map((file) => path.join(cwd, file));
|
|
743
|
+
console.log(
|
|
744
|
+
"@pob/eslint-config 68: rewriting eslint-disable comments of rules checked by oxlint",
|
|
745
|
+
);
|
|
746
|
+
await runTransform("oxlint-directives", files, { silent: true });
|
|
747
|
+
|
|
748
|
+
const eslintConfigPath = ["eslint.config.js", "eslint.config.mjs"]
|
|
749
|
+
.map((fileName) => path.join(cwd, fileName))
|
|
750
|
+
.find((filePath) => fs.existsSync(filePath));
|
|
751
|
+
if (eslintConfigPath) {
|
|
752
|
+
await runTransform("oxlint-eslint-config", [eslintConfigPath]);
|
|
753
|
+
const { code } = await format(
|
|
754
|
+
eslintConfigPath,
|
|
755
|
+
fs.readFileSync(eslintConfigPath, "utf8"),
|
|
756
|
+
{ printWidth: 80 },
|
|
757
|
+
);
|
|
758
|
+
fs.writeFileSync(eslintConfigPath, code);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
691
761
|
}
|
package/lib/utils/package.js
CHANGED
|
@@ -5,10 +5,7 @@ import sortPkg from "@pob/sort-pkg";
|
|
|
5
5
|
import parseAuthor from "parse-author";
|
|
6
6
|
import pobDependencies from "pob-dependencies";
|
|
7
7
|
import semver from "semver";
|
|
8
|
-
import {
|
|
9
|
-
pobEslintConfig,
|
|
10
|
-
pobEslintConfigTypescriptReact,
|
|
11
|
-
} from "./dependenciesPackages.cjs";
|
|
8
|
+
import { pobEslintConfig } from "./dependenciesPackages.cjs";
|
|
12
9
|
import pobPkg from "./packagejson.js";
|
|
13
10
|
|
|
14
11
|
export { default as parseAuthor } from "parse-author";
|
|
@@ -63,24 +60,8 @@ const internalRemoveDependencies = (pkg, type, dependencyKeys) => {
|
|
|
63
60
|
};
|
|
64
61
|
|
|
65
62
|
const getVersionFromDependencyName = (dependency) => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// 'eslint-import-resolver-node',
|
|
69
|
-
"eslint-plugin-import",
|
|
70
|
-
"eslint-plugin-node",
|
|
71
|
-
"eslint-plugin-unicorn",
|
|
72
|
-
].includes(dependency)
|
|
73
|
-
) {
|
|
74
|
-
return pobEslintConfig.dependencies[dependency];
|
|
75
|
-
}
|
|
76
|
-
if (["eslint-plugin-jsx-a11y", "eslint-plugin-react"].includes(dependency)) {
|
|
77
|
-
return pobEslintConfigTypescriptReact.dependencies[dependency];
|
|
78
|
-
}
|
|
79
|
-
if (
|
|
80
|
-
["@typescript-eslint/eslint-plugin", "@typescript-eslint/parser"].includes(
|
|
81
|
-
dependency,
|
|
82
|
-
)
|
|
83
|
-
) {
|
|
63
|
+
// loaded by name by import-x, from the project with yarn PnP
|
|
64
|
+
if (dependency === "@typescript-eslint/parser") {
|
|
84
65
|
return pobEslintConfig.dependencies[dependency];
|
|
85
66
|
}
|
|
86
67
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pob",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "40.1.0",
|
|
4
4
|
"description": "Pile of bones, library generator with git/babel/typescript/typedoc/readme/vitest",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"skeleton"
|
|
@@ -31,8 +31,9 @@
|
|
|
31
31
|
"./package.json": "./package.json"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@pob/
|
|
35
|
-
"@pob/eslint-config
|
|
34
|
+
"@pob/codemods": "0.18.0",
|
|
35
|
+
"@pob/eslint-config": "68.0.0",
|
|
36
|
+
"@pob/eslint-config-typescript-react": "68.0.0",
|
|
36
37
|
"@pob/sort-object": "11.2.0",
|
|
37
38
|
"@pob/sort-pkg": "13.2.0",
|
|
38
39
|
"@types/inquirer": "9.0.10",
|
|
@@ -50,7 +51,7 @@
|
|
|
50
51
|
"minimist": "1.2.8",
|
|
51
52
|
"oxfmt": "0.72.0",
|
|
52
53
|
"parse-author": "2.0.0",
|
|
53
|
-
"pob-dependencies": "
|
|
54
|
+
"pob-dependencies": "28.1.0",
|
|
54
55
|
"semver": "7.8.5",
|
|
55
56
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
56
57
|
"validate-npm-package-name": "^8.0.0",
|
|
@@ -58,7 +59,7 @@
|
|
|
58
59
|
"yeoman-generator": "10.0.1"
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
61
|
-
"@pob/root": "
|
|
62
|
+
"@pob/root": "28.1.0",
|
|
62
63
|
"@types/node": "24.19.1",
|
|
63
64
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
64
65
|
"@yeoman/types": "1.13.1"
|