@useinsider/eslint-config 3.0.2 → 4.0.0-beta.1
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/README.md +285 -64
- package/dist/builders/configFiles.d.ts +13 -0
- package/dist/builders/oxlint.d.ts +51 -0
- package/dist/builders/oxlintOwnership.d.ts +43 -0
- package/dist/cli.cjs +584 -27
- package/dist/cli.cjs.map +1 -1
- package/dist/configs/dependencies.d.ts +3 -0
- package/dist/{javascript-VBXqjVi8.cjs → javascript-DH8-N38w.cjs} +5 -5
- package/dist/{javascript-VBXqjVi8.cjs.map → javascript-DH8-N38w.cjs.map} +1 -1
- package/dist/{javascript-dom-5jRL_yKP.cjs → javascript-dom-CvtQ6_9W.cjs} +4 -4
- package/dist/{javascript-dom-5jRL_yKP.cjs.map → javascript-dom-CvtQ6_9W.cjs.map} +1 -1
- package/dist/{javascript-node-C1AU_4X2.cjs → javascript-node-BNsy3loY.cjs} +4 -4
- package/dist/{javascript-node-C1AU_4X2.cjs.map → javascript-node-BNsy3loY.cjs.map} +1 -1
- package/dist/{jest-CHzjzBtf.cjs → jest-4Es9Ggaa.cjs} +3 -3
- package/dist/{jest-CHzjzBtf.cjs.map → jest-4Es9Ggaa.cjs.map} +1 -1
- package/dist/main.cjs +452 -73
- package/dist/main.cjs.map +1 -1
- package/dist/main.d.ts +9 -2
- package/dist/main.js +435 -56
- package/dist/main.js.map +1 -1
- package/dist/oxlintOwnership-7hpdB3d1.cjs +199 -0
- package/dist/oxlintOwnership-7hpdB3d1.cjs.map +1 -0
- package/dist/oxlintOwnership-Cx0hgA_J.js +127 -0
- package/dist/oxlintOwnership-Cx0hgA_J.js.map +1 -0
- package/dist/removePluginsFromConfigs-D0oSUj2C.cjs.map +1 -1
- package/dist/removePluginsFromConfigs-DzqX2Ju2.js.map +1 -1
- package/dist/{stylistic-Dio0AM2E.cjs → stylistic-CoP3MT1Y.cjs} +4 -4
- package/dist/{stylistic-Dio0AM2E.cjs.map → stylistic-CoP3MT1Y.cjs.map} +1 -1
- package/dist/{typescript-C1icmOxY.cjs → typescript-D3VeLnpn.cjs} +7 -7
- package/dist/{typescript-C1icmOxY.cjs.map → typescript-D3VeLnpn.cjs.map} +1 -1
- package/dist/{typescript-dom-RUJn2WCZ.cjs → typescript-dom-iB_xBTAD.cjs} +4 -4
- package/dist/{typescript-dom-RUJn2WCZ.cjs.map → typescript-dom-iB_xBTAD.cjs.map} +1 -1
- package/dist/{typescript-node-CBEzcc56.cjs → typescript-node-Cq6qhj53.cjs} +4 -4
- package/dist/{typescript-node-CBEzcc56.cjs.map → typescript-node-Cq6qhj53.cjs.map} +1 -1
- package/dist/utils/ensureConfigStructure.d.ts +9 -4
- package/dist/utils/ensureOxlintConfig.d.ts +9 -0
- package/dist/utils/silenceRules.d.ts +9 -0
- package/dist/{vitest-BomI8gtu.cjs → vitest-BlGQswK2.cjs} +3 -3
- package/dist/{vitest-BomI8gtu.cjs.map → vitest-BlGQswK2.cjs.map} +1 -1
- package/dist/{vue2-azKwRgaJ.cjs → vue2-Da1i_oVn.cjs} +8 -8
- package/dist/{vue2-azKwRgaJ.cjs.map → vue2-Da1i_oVn.cjs.map} +1 -1
- package/dist/{vue2-options-api-ma3J-bvM.cjs → vue2-options-api-BSdrUm8H.cjs} +8 -8
- package/dist/{vue2-options-api-ma3J-bvM.cjs.map → vue2-options-api-BSdrUm8H.cjs.map} +1 -1
- package/dist/{vue2-typescript-CZSHzp7I.cjs → vue2-typescript-dXLRSGNP.cjs} +10 -10
- package/dist/{vue2-typescript-CZSHzp7I.cjs.map → vue2-typescript-dXLRSGNP.cjs.map} +1 -1
- package/dist/{vue2-typescript-options-api-B8OzZlje.cjs → vue2-typescript-options-api-LM7U5dWq.cjs} +10 -10
- package/dist/{vue2-typescript-options-api-B8OzZlje.cjs.map → vue2-typescript-options-api-LM7U5dWq.cjs.map} +1 -1
- package/dist/{vue3-Df5UQ1Ys.cjs → vue3-621EM2Ii.cjs} +8 -8
- package/dist/{vue3-Df5UQ1Ys.cjs.map → vue3-621EM2Ii.cjs.map} +1 -1
- package/dist/{vue3-options-api-Bx7yYHza.cjs → vue3-options-api-CC9_fAiq.cjs} +8 -8
- package/dist/{vue3-options-api-Bx7yYHza.cjs.map → vue3-options-api-CC9_fAiq.cjs.map} +1 -1
- package/dist/{vue3-typescript-C0O1JZlk.cjs → vue3-typescript-DONe-IKz.cjs} +10 -10
- package/dist/{vue3-typescript-C0O1JZlk.cjs.map → vue3-typescript-DONe-IKz.cjs.map} +1 -1
- package/dist/{vue3-typescript-options-api-cPal4O-K.cjs → vue3-typescript-options-api-D4pqpDFs.cjs} +10 -10
- package/dist/{vue3-typescript-options-api-cPal4O-K.cjs.map → vue3-typescript-options-api-D4pqpDFs.cjs.map} +1 -1
- package/package.json +8 -5
- package/dist/rolldown-runtime-VH7oDXx4.cjs +0 -28
package/dist/cli.cjs
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
3
|
+
const require_oxlintOwnership = require("./oxlintOwnership-7hpdB3d1.cjs");
|
|
4
4
|
let globals = require("globals");
|
|
5
|
-
globals =
|
|
5
|
+
globals = require_oxlintOwnership.__toESM(globals, 1);
|
|
6
6
|
let node_fs = require("node:fs");
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
let node_url = require("node:url");
|
|
9
|
+
let _typescript_eslint_types = require("@typescript-eslint/types");
|
|
9
10
|
let node_crypto = require("node:crypto");
|
|
10
11
|
let node_os = require("node:os");
|
|
11
12
|
let typescript = require("typescript");
|
|
12
|
-
typescript =
|
|
13
|
+
typescript = require_oxlintOwnership.__toESM(typescript, 1);
|
|
14
|
+
let _typescript_eslint_parser = require("@typescript-eslint/parser");
|
|
13
15
|
//#region src/cli/detect.ts
|
|
14
16
|
var FLAT_CONFIG_FILENAMES = [
|
|
15
17
|
"eslint.config.mjs",
|
|
@@ -329,12 +331,13 @@ function parseScaffoldArgs(argv) {
|
|
|
329
331
|
function printUsage(stderr, unknown) {
|
|
330
332
|
stderr(`[useinsider/eslint-config] Unknown subcommand: ${unknown}`);
|
|
331
333
|
stderr("Usage:");
|
|
332
|
-
stderr(" npx @useinsider/eslint-config [--yes|-y]
|
|
334
|
+
stderr(" npx @useinsider/eslint-config [--yes|-y]");
|
|
335
|
+
stderr(" Scaffold insider.lint.*, eslint.config.* and oxlint.config.*");
|
|
333
336
|
stderr(" npx @useinsider/eslint-config migrate [path] [--yes|-y] [--no-install]");
|
|
334
|
-
stderr("
|
|
337
|
+
stderr(" Split an existing useInsider() or .eslintrc* config into the three-file layout");
|
|
335
338
|
}
|
|
336
339
|
function isScaffoldArgv(argv) {
|
|
337
|
-
return argv.
|
|
340
|
+
return argv.every((arg) => isYesFlag(arg));
|
|
338
341
|
}
|
|
339
342
|
async function dispatch(argv, cwd, deps) {
|
|
340
343
|
if (isScaffoldArgv(argv)) {
|
|
@@ -358,6 +361,9 @@ async function dispatch(argv, cwd, deps) {
|
|
|
358
361
|
return 1;
|
|
359
362
|
}
|
|
360
363
|
//#endregion
|
|
364
|
+
//#region src/configs/dependencies.ts
|
|
365
|
+
var dependencies$14 = { oxlint: true };
|
|
366
|
+
//#endregion
|
|
361
367
|
//#region src/configs/jest/dependencies.ts
|
|
362
368
|
var dependencies$13 = { "eslint-plugin-jest": true };
|
|
363
369
|
//#endregion
|
|
@@ -471,6 +477,7 @@ function buildDependencyList(answers, rawManifest = readOwnEslintConfigManifest$
|
|
|
471
477
|
deps.add(`@useinsider/eslint-config@${manifest.version}`);
|
|
472
478
|
deps.add(pinned(manifest, "eslint"));
|
|
473
479
|
deps.add(pinned(manifest, "globals"));
|
|
480
|
+
applyRecord(deps, manifest, dependencies$14);
|
|
474
481
|
const wantsTypescript = answers.languages.includes("typescript");
|
|
475
482
|
if (answers.framework === "vue") applyRecord(deps, manifest, vueDepsFor(answers.vueMajor ?? 3, wantsTypescript));
|
|
476
483
|
else if (wantsTypescript) applyRecord(deps, manifest, dependencies$12);
|
|
@@ -702,6 +709,132 @@ async function installWithRetry(opts) {
|
|
|
702
709
|
}
|
|
703
710
|
}
|
|
704
711
|
//#endregion
|
|
712
|
+
//#region src/cli/lintLayout.ts
|
|
713
|
+
var OXLINT_LINT_SCRIPT = "oxlint --disable-nested-config && eslint .";
|
|
714
|
+
/**
|
|
715
|
+
* Extension for the lint module and the oxlint config. oxlint only discovers `oxlint.config.ts` and
|
|
716
|
+
* `oxlint.config.mts`, and Node warns on a bare `.ts` file inside a package that declares no
|
|
717
|
+
* `"type"`, so such a consumer gets the unambiguous `.mts` form.
|
|
718
|
+
* @example
|
|
719
|
+
* resolveLayoutExtension('/repo'); // 'ts' when /repo/package.json declares "type": "module"
|
|
720
|
+
*/
|
|
721
|
+
function resolveLayoutExtension(cwd) {
|
|
722
|
+
try {
|
|
723
|
+
const raw = (0, node_fs.readFileSync)((0, node_path.join)(cwd, "package.json"), "utf8");
|
|
724
|
+
return JSON.parse(raw).type === "module" ? "ts" : "mts";
|
|
725
|
+
} catch {
|
|
726
|
+
return "mts";
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
function findExistingEslintConfig(cwd, fallback) {
|
|
730
|
+
return [
|
|
731
|
+
"ts",
|
|
732
|
+
"mts",
|
|
733
|
+
"cts",
|
|
734
|
+
"js",
|
|
735
|
+
"mjs",
|
|
736
|
+
"cjs"
|
|
737
|
+
].map((ext) => `eslint.config.${ext}`).find((filename) => (0, node_fs.existsSync)((0, node_path.join)(cwd, filename))) ?? fallback;
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* The three filenames `useInsider()` requires, resolved against a consumer directory. An existing
|
|
741
|
+
* `eslint.config.*` keeps its name so a migration does not leave two flat configs behind.
|
|
742
|
+
* @example
|
|
743
|
+
* resolveLintLayout('/repo'); // { lintModule: 'insider.lint.mts', eslintConfig: 'eslint.config.mjs', ... }
|
|
744
|
+
*/
|
|
745
|
+
function resolveLintLayout(cwd, eslintConfigFallback = "eslint.config.mjs") {
|
|
746
|
+
const extension = resolveLayoutExtension(cwd);
|
|
747
|
+
return {
|
|
748
|
+
extension,
|
|
749
|
+
lintModule: `insider.lint.${extension}`,
|
|
750
|
+
oxlintConfig: `oxlint.config.${extension}`,
|
|
751
|
+
eslintConfig: findExistingEslintConfig(cwd, eslintConfigFallback)
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Body of the generated `eslint.config.*`. The import names the lint module's real extension
|
|
756
|
+
* because neither linter's loader applies TypeScript's `.js` → `.ts` specifier rewriting.
|
|
757
|
+
* @example
|
|
758
|
+
* renderEslintConfigFile('insider.lint.ts'); // "import { useInsiderESLint } from './insider.lint.ts';\n…"
|
|
759
|
+
*/
|
|
760
|
+
function renderEslintConfigFile(lintModule) {
|
|
761
|
+
return [
|
|
762
|
+
`import { useInsiderESLint } from './${lintModule}';`,
|
|
763
|
+
"",
|
|
764
|
+
"export default useInsiderESLint();",
|
|
765
|
+
""
|
|
766
|
+
].join("\n");
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Body of the generated `oxlint.config.*`.
|
|
770
|
+
* @example
|
|
771
|
+
* renderOxlintConfigFile('insider.lint.mts'); // "…export default await useInsiderOXC();\n"
|
|
772
|
+
*/
|
|
773
|
+
function renderOxlintConfigFile(lintModule) {
|
|
774
|
+
return [
|
|
775
|
+
`import { useInsiderOXC } from './${lintModule}';`,
|
|
776
|
+
"",
|
|
777
|
+
"export default await useInsiderOXC();",
|
|
778
|
+
""
|
|
779
|
+
].join("\n");
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* The two thin files that sit beside a lint module, ready to write.
|
|
783
|
+
* @example
|
|
784
|
+
* renderLintLayoutFiles(resolveLintLayout('/repo')).map(file => file.filename);
|
|
785
|
+
* // ['eslint.config.mjs', 'oxlint.config.mts']
|
|
786
|
+
*/
|
|
787
|
+
function renderLintLayoutFiles(layout) {
|
|
788
|
+
return [{
|
|
789
|
+
filename: layout.eslintConfig,
|
|
790
|
+
source: renderEslintConfigFile(layout.lintModule)
|
|
791
|
+
}, {
|
|
792
|
+
filename: layout.oxlintConfig,
|
|
793
|
+
source: renderOxlintConfigFile(layout.lintModule)
|
|
794
|
+
}];
|
|
795
|
+
}
|
|
796
|
+
var DEFAULT_INDENT = 2;
|
|
797
|
+
function detectIndent$1(raw) {
|
|
798
|
+
const firstBreak = raw.indexOf("\n");
|
|
799
|
+
if (firstBreak === -1) return DEFAULT_INDENT;
|
|
800
|
+
const rest = raw.slice(firstBreak + 1);
|
|
801
|
+
const width = rest.length - rest.trimStart().length;
|
|
802
|
+
return width > 0 ? width : DEFAULT_INDENT;
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Rewrites the consumer's `lint` script so both linters run. Returns the manifest untouched when it
|
|
806
|
+
* already runs oxlint, so re-running the CLI is idempotent.
|
|
807
|
+
* @example
|
|
808
|
+
* setLintScript('{"scripts":{"lint":"eslint ."}}').manifest;
|
|
809
|
+
* // '…"lint": "oxlint --disable-nested-config && eslint ."…'
|
|
810
|
+
*/
|
|
811
|
+
function setLintScript(rawManifest) {
|
|
812
|
+
let parsed;
|
|
813
|
+
try {
|
|
814
|
+
parsed = JSON.parse(rawManifest);
|
|
815
|
+
} catch {
|
|
816
|
+
return {
|
|
817
|
+
manifest: rawManifest,
|
|
818
|
+
changed: false
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
const previous = parsed.scripts?.lint;
|
|
822
|
+
if (previous?.includes("oxlint")) return {
|
|
823
|
+
manifest: rawManifest,
|
|
824
|
+
changed: false,
|
|
825
|
+
previous
|
|
826
|
+
};
|
|
827
|
+
parsed.scripts = {
|
|
828
|
+
...parsed.scripts,
|
|
829
|
+
lint: OXLINT_LINT_SCRIPT
|
|
830
|
+
};
|
|
831
|
+
return {
|
|
832
|
+
manifest: `${JSON.stringify(parsed, null, detectIndent$1(rawManifest))}\n`,
|
|
833
|
+
changed: true,
|
|
834
|
+
previous
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
//#endregion
|
|
705
838
|
//#region src/cli/quote.ts
|
|
706
839
|
function quote(value) {
|
|
707
840
|
return `'${JSON.stringify(value).slice(1, -1).replace(/\\"/g, "\"").replace(/'/g, "\\'")}'`;
|
|
@@ -995,11 +1128,17 @@ function formatScope$1(scope, entries, baseIndent) {
|
|
|
995
1128
|
function renderUseInsiderBody(merged) {
|
|
996
1129
|
return [...merged.entries()].map(([scope, entries]) => formatScope$1(scope, entries, indent$1)).join("\n");
|
|
997
1130
|
}
|
|
998
|
-
|
|
1131
|
+
/**
|
|
1132
|
+
* Body of the generated `insider.lint.*` module — the one file that calls `useInsider()` and the
|
|
1133
|
+
* only one both linter configs import.
|
|
1134
|
+
* @example
|
|
1135
|
+
* renderLintModuleFile(answers); // "…export const { useInsiderESLint, useInsiderOXC } = useInsider({…"
|
|
1136
|
+
*/
|
|
1137
|
+
function renderLintModuleFile(answers) {
|
|
999
1138
|
return [
|
|
1000
1139
|
"import { useInsider } from '@useinsider/eslint-config';",
|
|
1001
1140
|
"",
|
|
1002
|
-
"export
|
|
1141
|
+
"export const { useInsiderESLint, useInsiderOXC } = useInsider({",
|
|
1003
1142
|
renderUseInsiderBody(mergeByScope(buildScopedConfigs(answers))),
|
|
1004
1143
|
"});",
|
|
1005
1144
|
""
|
|
@@ -1440,7 +1579,11 @@ var SCOPE_TO_DEPS = {
|
|
|
1440
1579
|
vitest: dependencies$11,
|
|
1441
1580
|
jsdocBasedTs: dependencies$3
|
|
1442
1581
|
};
|
|
1443
|
-
var ALL_PRESET_DEPS = [
|
|
1582
|
+
var ALL_PRESET_DEPS = [
|
|
1583
|
+
dependencies$14,
|
|
1584
|
+
dependencies$2,
|
|
1585
|
+
...Object.values(SCOPE_TO_DEPS)
|
|
1586
|
+
];
|
|
1444
1587
|
var PRESET_DEPENDENCY_KEYS = new Set(ALL_PRESET_DEPS.flatMap((record) => Object.keys(record)));
|
|
1445
1588
|
function isEslintRelatedDependency(name) {
|
|
1446
1589
|
if (SAFELIST.has(name)) return false;
|
|
@@ -1538,6 +1681,9 @@ function buildInstallList(scopes, manifest) {
|
|
|
1538
1681
|
const fallbacks = [];
|
|
1539
1682
|
appendSpec(specs, "@useinsider/eslint-config@latest");
|
|
1540
1683
|
appendSpec(specs, resolveSpec("eslint", manifest, fallbacks));
|
|
1684
|
+
Object.entries(dependencies$14).forEach(([packageName, shouldInstall]) => {
|
|
1685
|
+
if (shouldInstall) appendSpec(specs, resolveSpec(packageName, manifest, fallbacks));
|
|
1686
|
+
});
|
|
1541
1687
|
[...scopes].forEach((scope) => {
|
|
1542
1688
|
const record = SCOPE_TO_DEPS[scope];
|
|
1543
1689
|
if (!record) return;
|
|
@@ -1597,6 +1743,340 @@ function pruneConsumerPackageJson(cwd) {
|
|
|
1597
1743
|
};
|
|
1598
1744
|
}
|
|
1599
1745
|
//#endregion
|
|
1746
|
+
//#region src/cli/tsconfigFlag.ts
|
|
1747
|
+
var TS_EXTENSIONS_FLAG = "allowImportingTsExtensions";
|
|
1748
|
+
var TS_EXTENSIONS_SNIPPET = [
|
|
1749
|
+
"{",
|
|
1750
|
+
" \"compilerOptions\": {",
|
|
1751
|
+
` "${TS_EXTENSIONS_FLAG}": true`,
|
|
1752
|
+
" }",
|
|
1753
|
+
"}"
|
|
1754
|
+
].join("\n");
|
|
1755
|
+
var DEFAULT_INDENT_UNIT = " ";
|
|
1756
|
+
function readEffectiveFlag(path, raw) {
|
|
1757
|
+
const { config } = typescript.parseConfigFileTextToJson(path, raw);
|
|
1758
|
+
if (!config) return false;
|
|
1759
|
+
return typescript.parseJsonConfigFileContent(config, typescript.sys, (0, node_path.dirname)(path), void 0, path).options.allowImportingTsExtensions === true;
|
|
1760
|
+
}
|
|
1761
|
+
/**
|
|
1762
|
+
* The consumer's root `tsconfig.json` plus whether `allowImportingTsExtensions` already resolves to
|
|
1763
|
+
* `true` — including when it arrives through `extends`, which is followed the same way `tsc` does.
|
|
1764
|
+
* @example
|
|
1765
|
+
* readTsconfigState('/repo')?.enabled; // true when /repo/tsconfig.json extends a base that sets it
|
|
1766
|
+
*/
|
|
1767
|
+
function readTsconfigState(cwd) {
|
|
1768
|
+
const path = (0, node_path.join)(cwd, "tsconfig.json");
|
|
1769
|
+
if (!(0, node_fs.existsSync)(path)) return null;
|
|
1770
|
+
try {
|
|
1771
|
+
const raw = (0, node_fs.readFileSync)(path, "utf8");
|
|
1772
|
+
return {
|
|
1773
|
+
path,
|
|
1774
|
+
raw,
|
|
1775
|
+
enabled: readEffectiveFlag(path, raw)
|
|
1776
|
+
};
|
|
1777
|
+
} catch {
|
|
1778
|
+
return null;
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
function rootObject(source) {
|
|
1782
|
+
const [statement] = source.statements;
|
|
1783
|
+
const expression = statement?.expression;
|
|
1784
|
+
return expression && typescript.isObjectLiteralExpression(expression) ? expression : null;
|
|
1785
|
+
}
|
|
1786
|
+
function findProperty$2(object, name) {
|
|
1787
|
+
return object.properties.find((property) => typescript.isPropertyAssignment(property) && typescript.isStringLiteral(property.name) && property.name.text === name);
|
|
1788
|
+
}
|
|
1789
|
+
function indentAt(raw, position) {
|
|
1790
|
+
const lineStart = raw.lastIndexOf("\n", position - 1) + 1;
|
|
1791
|
+
const prefix = raw.slice(lineStart, position);
|
|
1792
|
+
return prefix.trim().length === 0 ? prefix : "";
|
|
1793
|
+
}
|
|
1794
|
+
function detectIndentUnit(raw) {
|
|
1795
|
+
const match = /\n([\t ]+)\S/u.exec(raw);
|
|
1796
|
+
return match ? match[1] : DEFAULT_INDENT_UNIT;
|
|
1797
|
+
}
|
|
1798
|
+
function splice(raw, start, end, text) {
|
|
1799
|
+
return raw.slice(0, start) + text + raw.slice(end);
|
|
1800
|
+
}
|
|
1801
|
+
function setExistingFlag(raw, source, property) {
|
|
1802
|
+
return splice(raw, property.initializer.getStart(source), property.initializer.getEnd(), "true");
|
|
1803
|
+
}
|
|
1804
|
+
function insertIntoCompilerOptions(raw, source, compilerOptions, object) {
|
|
1805
|
+
const openBrace = object.getStart(source) + 1;
|
|
1806
|
+
const [first] = object.properties;
|
|
1807
|
+
if (first) return splice(raw, openBrace, openBrace, `\n${indentAt(raw, first.getStart(source)) || detectIndentUnit(raw).repeat(2)}"${TS_EXTENSIONS_FLAG}": true,`);
|
|
1808
|
+
const outer = indentAt(raw, compilerOptions.getStart(source));
|
|
1809
|
+
const unit = detectIndentUnit(raw);
|
|
1810
|
+
return splice(raw, openBrace, object.getEnd() - 1, `\n${outer}${unit}"${TS_EXTENSIONS_FLAG}": true\n${outer}`);
|
|
1811
|
+
}
|
|
1812
|
+
function insertCompilerOptions(raw, source, root) {
|
|
1813
|
+
const openBrace = root.getStart(source) + 1;
|
|
1814
|
+
const unit = detectIndentUnit(raw);
|
|
1815
|
+
const [first] = root.properties;
|
|
1816
|
+
const indent = first ? indentAt(raw, first.getStart(source)) || unit : unit;
|
|
1817
|
+
const block = `\n${indent}"compilerOptions": {\n${indent}${unit}"${TS_EXTENSIONS_FLAG}": true\n${indent}}`;
|
|
1818
|
+
if (first) return splice(raw, openBrace, openBrace, `${block},`);
|
|
1819
|
+
return splice(raw, openBrace, root.getEnd() - 1, `${block}\n`);
|
|
1820
|
+
}
|
|
1821
|
+
/**
|
|
1822
|
+
* Turns `allowImportingTsExtensions` on in a `tsconfig.json` source without reformatting it. The
|
|
1823
|
+
* file is edited through its JSON syntax tree rather than re-serialized, so comments, key order and
|
|
1824
|
+
* indentation survive.
|
|
1825
|
+
* @example
|
|
1826
|
+
* enableTsExtensionsFlag('{\n "compilerOptions": {\n "strict": true\n }\n}').changed; // true
|
|
1827
|
+
*/
|
|
1828
|
+
function enableTsExtensionsFlag(raw) {
|
|
1829
|
+
const source = typescript.parseJsonText("tsconfig.json", raw);
|
|
1830
|
+
const root = rootObject(source);
|
|
1831
|
+
if (!root) return {
|
|
1832
|
+
source: raw,
|
|
1833
|
+
changed: false
|
|
1834
|
+
};
|
|
1835
|
+
const compilerOptions = findProperty$2(root, "compilerOptions");
|
|
1836
|
+
if (!compilerOptions) return {
|
|
1837
|
+
source: insertCompilerOptions(raw, source, root),
|
|
1838
|
+
changed: true
|
|
1839
|
+
};
|
|
1840
|
+
if (!typescript.isObjectLiteralExpression(compilerOptions.initializer)) return {
|
|
1841
|
+
source: raw,
|
|
1842
|
+
changed: false
|
|
1843
|
+
};
|
|
1844
|
+
const existing = findProperty$2(compilerOptions.initializer, TS_EXTENSIONS_FLAG);
|
|
1845
|
+
if (existing) {
|
|
1846
|
+
if (existing.initializer.kind === typescript.SyntaxKind.TrueKeyword) return {
|
|
1847
|
+
source: raw,
|
|
1848
|
+
changed: false
|
|
1849
|
+
};
|
|
1850
|
+
return {
|
|
1851
|
+
source: setExistingFlag(raw, source, existing),
|
|
1852
|
+
changed: true
|
|
1853
|
+
};
|
|
1854
|
+
}
|
|
1855
|
+
return {
|
|
1856
|
+
source: insertIntoCompilerOptions(raw, source, compilerOptions, compilerOptions.initializer),
|
|
1857
|
+
changed: true
|
|
1858
|
+
};
|
|
1859
|
+
}
|
|
1860
|
+
function noteManualStep(clack, lintModule) {
|
|
1861
|
+
if (!clack.note) return;
|
|
1862
|
+
clack.note(`\`eslint.config.*\` imports \`./${lintModule}\` by its real extension, which \`tsc\` rejects with TS5097 unless \`${TS_EXTENSIONS_FLAG}\` is on. Add this to your tsconfig.json:\n\n${TS_EXTENSIONS_SNIPPET}`, "tsconfig.json not updated");
|
|
1863
|
+
}
|
|
1864
|
+
async function confirmFlag(clack, path) {
|
|
1865
|
+
const result = await clack.confirm({
|
|
1866
|
+
message: `Set \`${TS_EXTENSIONS_FLAG}: true\` in ${path}? Without it \`tsc\` fails with TS5097 on the generated config files.`,
|
|
1867
|
+
initialValue: true
|
|
1868
|
+
});
|
|
1869
|
+
return !clack.isCancel(result) && result === true;
|
|
1870
|
+
}
|
|
1871
|
+
/**
|
|
1872
|
+
* Offers to set `allowImportingTsExtensions` on the consumer's `tsconfig.json`, and prints the exact
|
|
1873
|
+
* snippet when the offer is declined. A no-op when there is no `tsconfig.json` or the flag already
|
|
1874
|
+
* resolves to `true` through the `extends` chain.
|
|
1875
|
+
* @example
|
|
1876
|
+
* await applyTsExtensionsFlag(clack, { cwd: '/repo', lintModule: 'insider.lint.ts' });
|
|
1877
|
+
*/
|
|
1878
|
+
async function applyTsExtensionsFlag(clack, input) {
|
|
1879
|
+
const state = readTsconfigState(input.cwd);
|
|
1880
|
+
if (!state || state.enabled) return;
|
|
1881
|
+
if (!(input.autoConfirm || await confirmFlag(clack, state.path))) {
|
|
1882
|
+
noteManualStep(clack, input.lintModule);
|
|
1883
|
+
return;
|
|
1884
|
+
}
|
|
1885
|
+
const result = enableTsExtensionsFlag(state.raw);
|
|
1886
|
+
if (!result.changed) {
|
|
1887
|
+
noteManualStep(clack, input.lintModule);
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1890
|
+
(0, node_fs.writeFileSync)(state.path, result.source, "utf8");
|
|
1891
|
+
if (clack.note) clack.note(`Set \`${TS_EXTENSIONS_FLAG}: true\` in ${state.path}.`, "Updated tsconfig.json");
|
|
1892
|
+
}
|
|
1893
|
+
//#endregion
|
|
1894
|
+
//#region src/cli/migrate/disableDirectives.ts
|
|
1895
|
+
var DIRECTIVE_HEAD = /^\s*eslint-disable(-next-line|-line)?(?![\w-])/u;
|
|
1896
|
+
var SCRIPT_BLOCK = /<script\b[^>]*>([\s\S]*?)<\/script>/giu;
|
|
1897
|
+
var SFC_EXTENSIONS = [
|
|
1898
|
+
".astro",
|
|
1899
|
+
".svelte",
|
|
1900
|
+
".vue"
|
|
1901
|
+
];
|
|
1902
|
+
var JSX_EXTENSIONS = [
|
|
1903
|
+
".cjs",
|
|
1904
|
+
".js",
|
|
1905
|
+
".jsx",
|
|
1906
|
+
".mjs",
|
|
1907
|
+
".tsx"
|
|
1908
|
+
];
|
|
1909
|
+
var LINTED_EXTENSIONS = [
|
|
1910
|
+
".astro",
|
|
1911
|
+
".cjs",
|
|
1912
|
+
".cts",
|
|
1913
|
+
".js",
|
|
1914
|
+
".jsx",
|
|
1915
|
+
".mjs",
|
|
1916
|
+
".mts",
|
|
1917
|
+
".svelte",
|
|
1918
|
+
".ts",
|
|
1919
|
+
".tsx",
|
|
1920
|
+
".vue"
|
|
1921
|
+
];
|
|
1922
|
+
var SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
1923
|
+
".git",
|
|
1924
|
+
"coverage",
|
|
1925
|
+
"dist",
|
|
1926
|
+
"build",
|
|
1927
|
+
"node_modules",
|
|
1928
|
+
"out",
|
|
1929
|
+
"vendor"
|
|
1930
|
+
]);
|
|
1931
|
+
function parseDirectiveBody(body) {
|
|
1932
|
+
const [ruleList, ...reasonParts] = body.split("--");
|
|
1933
|
+
return {
|
|
1934
|
+
rules: ruleList.split(",").map((rule) => rule.trim()).filter((rule) => rule.length > 0),
|
|
1935
|
+
reason: reasonParts.join("--").trim()
|
|
1936
|
+
};
|
|
1937
|
+
}
|
|
1938
|
+
function formatDirective(owner, block, kind, rules, reason) {
|
|
1939
|
+
const text = `${owner}-disable${kind} ${reason ? `${rules.join(", ")} -- ${reason}` : rules.join(", ")}`;
|
|
1940
|
+
return block ? `/* ${text} */` : `// ${text}`;
|
|
1941
|
+
}
|
|
1942
|
+
/**
|
|
1943
|
+
* Whether the split hands this rule to oxlint for the given file, so an `eslint-disable` comment
|
|
1944
|
+
* naming it would read as an unused directive to ESLint.
|
|
1945
|
+
* @example
|
|
1946
|
+
* movesToOxlint('no-console', '.ts'); // true
|
|
1947
|
+
* movesToOxlint('@typescript-eslint/no-unused-vars', '.vue'); // false — ESLint still runs it in SFCs
|
|
1948
|
+
*/
|
|
1949
|
+
function movesToOxlint(rule, fileExtension) {
|
|
1950
|
+
if (!require_oxlintOwnership.isOxlintOwned(rule)) return false;
|
|
1951
|
+
return !(SFC_EXTENSIONS.includes(fileExtension) && require_oxlintOwnership.isVueUnsafeRule(rule));
|
|
1952
|
+
}
|
|
1953
|
+
function toSpans(comments, offset) {
|
|
1954
|
+
return comments.map((comment) => ({
|
|
1955
|
+
start: comment.range[0] + offset,
|
|
1956
|
+
end: comment.range[1] + offset,
|
|
1957
|
+
block: comment.type === _typescript_eslint_types.AST_TOKEN_TYPES.Block,
|
|
1958
|
+
value: comment.value
|
|
1959
|
+
}));
|
|
1960
|
+
}
|
|
1961
|
+
function parseComments(source, jsx) {
|
|
1962
|
+
try {
|
|
1963
|
+
return (0, _typescript_eslint_parser.parse)(source, {
|
|
1964
|
+
comment: true,
|
|
1965
|
+
jsx,
|
|
1966
|
+
range: true
|
|
1967
|
+
}).comments ?? [];
|
|
1968
|
+
} catch {
|
|
1969
|
+
return null;
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
function collectFromScript(source, jsx, offset) {
|
|
1973
|
+
const comments = parseComments(source, jsx) ?? parseComments(source, !jsx);
|
|
1974
|
+
return comments ? toSpans(comments, offset) : [];
|
|
1975
|
+
}
|
|
1976
|
+
var CLOSING_SCRIPT_TAG_LENGTH = 9;
|
|
1977
|
+
function collectSfcComments(source, jsx) {
|
|
1978
|
+
return [...source.matchAll(SCRIPT_BLOCK)].flatMap((match) => {
|
|
1979
|
+
const [whole, body] = match;
|
|
1980
|
+
return collectFromScript(body, jsx, (match.index ?? 0) + whole.length - body.length - CLOSING_SCRIPT_TAG_LENGTH);
|
|
1981
|
+
});
|
|
1982
|
+
}
|
|
1983
|
+
/**
|
|
1984
|
+
* Every real comment node in the file, with ranges relative to the whole source. Only comments are
|
|
1985
|
+
* returned, so a string or template literal that happens to spell out a directive is invisible here.
|
|
1986
|
+
* @example
|
|
1987
|
+
* collectComments("const label = '// eslint-disable-next-line';\n", '.ts'); // []
|
|
1988
|
+
*/
|
|
1989
|
+
function collectComments(source, fileExtension) {
|
|
1990
|
+
const jsx = JSX_EXTENSIONS.includes(fileExtension);
|
|
1991
|
+
if (SFC_EXTENSIONS.includes(fileExtension)) return collectSfcComments(source, jsx);
|
|
1992
|
+
return collectFromScript(source, jsx, 0);
|
|
1993
|
+
}
|
|
1994
|
+
function startsItsOwnLine(source, start) {
|
|
1995
|
+
const lineStart = source.lastIndexOf("\n", start - 1) + 1;
|
|
1996
|
+
return source.slice(lineStart, start).trim().length === 0;
|
|
1997
|
+
}
|
|
1998
|
+
function splitLayout(source, span, kind) {
|
|
1999
|
+
if (kind !== "" || !startsItsOwnLine(source, span.start)) return {
|
|
2000
|
+
block: true,
|
|
2001
|
+
separator: " "
|
|
2002
|
+
};
|
|
2003
|
+
const indent = " ".repeat(span.start - (source.lastIndexOf("\n", span.start - 1) + 1));
|
|
2004
|
+
return {
|
|
2005
|
+
block: span.block,
|
|
2006
|
+
separator: `\n${indent}`
|
|
2007
|
+
};
|
|
2008
|
+
}
|
|
2009
|
+
function replacementFor(source, span, fileExtension) {
|
|
2010
|
+
const head = DIRECTIVE_HEAD.exec(span.value);
|
|
2011
|
+
if (!head) return null;
|
|
2012
|
+
const kind = head[1] ?? "";
|
|
2013
|
+
const { rules, reason } = parseDirectiveBody(span.value.slice(head[0].length));
|
|
2014
|
+
if (rules.length === 0) return null;
|
|
2015
|
+
const moved = rules.filter((rule) => movesToOxlint(rule, fileExtension));
|
|
2016
|
+
if (moved.length === 0) return null;
|
|
2017
|
+
const kept = rules.filter((rule) => !moved.includes(rule));
|
|
2018
|
+
if (kept.length === 0) return {
|
|
2019
|
+
start: span.start,
|
|
2020
|
+
end: span.end,
|
|
2021
|
+
text: formatDirective("oxlint", span.block, kind, moved, reason)
|
|
2022
|
+
};
|
|
2023
|
+
const { block, separator } = splitLayout(source, span, kind);
|
|
2024
|
+
const text = formatDirective("oxlint", block, kind, moved, reason) + separator + formatDirective("eslint", block, kind, kept, reason);
|
|
2025
|
+
return {
|
|
2026
|
+
start: span.start,
|
|
2027
|
+
end: span.end,
|
|
2028
|
+
text
|
|
2029
|
+
};
|
|
2030
|
+
}
|
|
2031
|
+
/**
|
|
2032
|
+
* Re-points the rules oxlint now owns onto an `oxlint-disable` comment, leaving the ESLint-owned
|
|
2033
|
+
* ones behind. Only real comment nodes are rewritten, so a string or template literal spelling out
|
|
2034
|
+
* a directive is left alone.
|
|
2035
|
+
* @example
|
|
2036
|
+
* rewriteDirectives('// <eslint>-disable-next-line no-console\nlog();', '.ts').source;
|
|
2037
|
+
* // '// oxlint-disable-next-line no-console\nlog();'
|
|
2038
|
+
*/
|
|
2039
|
+
function rewriteDirectives(source, fileExtension) {
|
|
2040
|
+
const replacements = collectComments(source, fileExtension).map((span) => replacementFor(source, span, fileExtension)).filter((replacement) => replacement !== null).sort((left, right) => right.start - left.start);
|
|
2041
|
+
if (replacements.length === 0) return {
|
|
2042
|
+
source,
|
|
2043
|
+
changed: false
|
|
2044
|
+
};
|
|
2045
|
+
return {
|
|
2046
|
+
source: replacements.reduce((accumulator, replacement) => accumulator.slice(0, replacement.start) + replacement.text + accumulator.slice(replacement.end), source),
|
|
2047
|
+
changed: true
|
|
2048
|
+
};
|
|
2049
|
+
}
|
|
2050
|
+
function isLintedFile(filePath) {
|
|
2051
|
+
return LINTED_EXTENSIONS.includes((0, node_path.extname)(filePath));
|
|
2052
|
+
}
|
|
2053
|
+
function collectFiles(directory, accumulator) {
|
|
2054
|
+
(0, node_fs.readdirSync)(directory).forEach((entry) => {
|
|
2055
|
+
if (SKIPPED_DIRECTORIES.has(entry)) return;
|
|
2056
|
+
const full = (0, node_path.join)(directory, entry);
|
|
2057
|
+
if ((0, node_fs.statSync)(full).isDirectory()) {
|
|
2058
|
+
collectFiles(full, accumulator);
|
|
2059
|
+
return;
|
|
2060
|
+
}
|
|
2061
|
+
if (isLintedFile(full)) accumulator.push(full);
|
|
2062
|
+
});
|
|
2063
|
+
}
|
|
2064
|
+
/**
|
|
2065
|
+
* Applies {@link rewriteDirectives} across a consumer tree, skipping build output and dependencies.
|
|
2066
|
+
* @example
|
|
2067
|
+
* rewriteDisableDirectives('/repo').rewritten; // ['/repo/src/logger.ts']
|
|
2068
|
+
*/
|
|
2069
|
+
function rewriteDisableDirectives(cwd) {
|
|
2070
|
+
const files = [];
|
|
2071
|
+
collectFiles(cwd, files);
|
|
2072
|
+
return { rewritten: files.filter((filePath) => {
|
|
2073
|
+
const result = rewriteDirectives((0, node_fs.readFileSync)(filePath, "utf8"), (0, node_path.extname)(filePath));
|
|
2074
|
+
if (!result.changed) return false;
|
|
2075
|
+
(0, node_fs.writeFileSync)(filePath, result.source, "utf8");
|
|
2076
|
+
return true;
|
|
2077
|
+
}) };
|
|
2078
|
+
}
|
|
2079
|
+
//#endregion
|
|
1600
2080
|
//#region src/cli/migrate/stringEntry.ts
|
|
1601
2081
|
function toEntries(values) {
|
|
1602
2082
|
return values.map((value) => ({ value }));
|
|
@@ -2214,7 +2694,7 @@ function appendScope$1(config, scope, entry) {
|
|
|
2214
2694
|
}
|
|
2215
2695
|
function mergeGlobals(base, extra) {
|
|
2216
2696
|
if (!base && !extra) return;
|
|
2217
|
-
const merged = { ...base
|
|
2697
|
+
const merged = { ...base };
|
|
2218
2698
|
if (extra) Object.entries(extra).forEach(([key, value]) => {
|
|
2219
2699
|
if (!(key in merged)) merged[key] = value;
|
|
2220
2700
|
});
|
|
@@ -3539,11 +4019,11 @@ function renderV2(plan) {
|
|
|
3539
4019
|
parts.push("");
|
|
3540
4020
|
if (plan.useInsiderLeadingComment !== void 0) parts.push(plan.useInsiderLeadingComment);
|
|
3541
4021
|
if (!hasAnyContent(plan)) {
|
|
3542
|
-
parts.push("export
|
|
4022
|
+
parts.push("export const { useInsiderESLint, useInsiderOXC } = useInsider({});");
|
|
3543
4023
|
parts.push("");
|
|
3544
4024
|
return pruneUnusedImports(parts.join("\n"));
|
|
3545
4025
|
}
|
|
3546
|
-
parts.push("export
|
|
4026
|
+
parts.push("export const { useInsiderESLint, useInsiderOXC } = useInsider({");
|
|
3547
4027
|
parts.push(renderConfigBody(plan));
|
|
3548
4028
|
parts.push("});");
|
|
3549
4029
|
parts.push("");
|
|
@@ -3903,14 +4383,52 @@ function formatWarnings(warnings) {
|
|
|
3903
4383
|
}
|
|
3904
4384
|
//#endregion
|
|
3905
4385
|
//#region src/cli/migrate/writer.ts
|
|
4386
|
+
function writeLayout(eslintConfigPath, lintModuleSource) {
|
|
4387
|
+
const directory = (0, node_path.dirname)(eslintConfigPath);
|
|
4388
|
+
const layout = resolveLintLayout(directory, (0, node_path.basename)(eslintConfigPath));
|
|
4389
|
+
const lintModulePath = (0, node_path.join)(directory, layout.lintModule);
|
|
4390
|
+
(0, node_fs.writeFileSync)(lintModulePath, lintModuleSource, "utf8");
|
|
4391
|
+
const writtenPaths = [lintModulePath];
|
|
4392
|
+
renderLintLayoutFiles({
|
|
4393
|
+
...layout,
|
|
4394
|
+
eslintConfig: (0, node_path.basename)(eslintConfigPath)
|
|
4395
|
+
}).forEach((file) => {
|
|
4396
|
+
const path = (0, node_path.join)(directory, file.filename);
|
|
4397
|
+
(0, node_fs.writeFileSync)(path, file.source, "utf8");
|
|
4398
|
+
writtenPaths.push(path);
|
|
4399
|
+
});
|
|
4400
|
+
return {
|
|
4401
|
+
lintModulePath,
|
|
4402
|
+
writtenPaths
|
|
4403
|
+
};
|
|
4404
|
+
}
|
|
4405
|
+
/**
|
|
4406
|
+
* Writes the three-file layout beside an existing flat config: the rendered `useInsider()` call
|
|
4407
|
+
* becomes `insider.lint.*`, and `eslint.config.*` / `oxlint.config.*` become thin re-exports.
|
|
4408
|
+
* @example
|
|
4409
|
+
* writeMigration('/repo/eslint.config.mjs', source).writtenPaths.length; // 3
|
|
4410
|
+
*/
|
|
3906
4411
|
function writeMigration(targetPath, newSource) {
|
|
3907
|
-
|
|
3908
|
-
return {
|
|
4412
|
+
const { lintModulePath, writtenPaths } = writeLayout(targetPath, newSource);
|
|
4413
|
+
return {
|
|
4414
|
+
targetPath,
|
|
4415
|
+
lintModulePath,
|
|
4416
|
+
writtenPaths
|
|
4417
|
+
};
|
|
3909
4418
|
}
|
|
4419
|
+
/**
|
|
4420
|
+
* Same as {@link writeMigration}, but for a legacy `.eslintrc*` source that has to be replaced by a
|
|
4421
|
+
* differently-named flat config. Nominates the old file for deletion when the name changed.
|
|
4422
|
+
* @example
|
|
4423
|
+
* writeMigrationLegacy('/repo/.eslintrc.cjs', '/repo/eslint.config.mjs', source).deletedSourceCandidate;
|
|
4424
|
+
* // '/repo/.eslintrc.cjs'
|
|
4425
|
+
*/
|
|
3910
4426
|
function writeMigrationLegacy(sourcePath, writePath, newSource) {
|
|
3911
|
-
|
|
4427
|
+
const { lintModulePath, writtenPaths } = writeLayout(writePath, newSource);
|
|
3912
4428
|
return {
|
|
3913
4429
|
targetPath: writePath,
|
|
4430
|
+
lintModulePath,
|
|
4431
|
+
writtenPaths,
|
|
3914
4432
|
deletedSourceCandidate: (0, node_path.basename)(sourcePath) === (0, node_path.basename)(writePath) ? void 0 : sourcePath
|
|
3915
4433
|
};
|
|
3916
4434
|
}
|
|
@@ -4080,14 +4598,9 @@ function emitSummary(clack, plan, format) {
|
|
|
4080
4598
|
if (plan.warnings.length > 0 && clack.note) clack.note(formatWarnings(plan.warnings), "Warnings");
|
|
4081
4599
|
}
|
|
4082
4600
|
function writeAndAnnounce(clack, targetPath, writePath, rendered, format) {
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
return { deletedSourceCandidate: result.deletedSourceCandidate };
|
|
4087
|
-
}
|
|
4088
|
-
writeMigration(targetPath, rendered);
|
|
4089
|
-
clack.outro(`Wrote ${targetPath}`);
|
|
4090
|
-
return {};
|
|
4601
|
+
const result = format === "eslintrc" ? writeMigrationLegacy(targetPath, writePath, rendered) : writeMigration(targetPath, rendered);
|
|
4602
|
+
clack.outro(`Wrote ${result.writtenPaths.join(", ")}`);
|
|
4603
|
+
return { deletedSourceCandidate: result.deletedSourceCandidate };
|
|
4091
4604
|
}
|
|
4092
4605
|
async function confirmOverwriteExistingOutput(clack, writePath, sourcePath, initial = false) {
|
|
4093
4606
|
const message = `An \`${(0, node_path.basename)(writePath)}\` already exists. Overwrite + delete \`${(0, node_path.basename)(sourcePath)}\`?`;
|
|
@@ -4232,6 +4745,22 @@ function performWriteAndCleanup(clack, resolved, prepared) {
|
|
|
4232
4745
|
if (prepared.eslintIgnore) safeUnlink(prepared.eslintIgnore.path, clack, ".eslintignore");
|
|
4233
4746
|
if (outcome.deletedSourceCandidate) safeUnlink(outcome.deletedSourceCandidate, clack, "source config");
|
|
4234
4747
|
}
|
|
4748
|
+
function applyLintScript$1(clack, directory) {
|
|
4749
|
+
const manifestPath = (0, node_path.join)(directory, "package.json");
|
|
4750
|
+
if (!(0, node_fs.existsSync)(manifestPath)) return;
|
|
4751
|
+
const result = setLintScript((0, node_fs.readFileSync)(manifestPath, "utf8"));
|
|
4752
|
+
if (!result.changed) return;
|
|
4753
|
+
(0, node_fs.writeFileSync)(manifestPath, result.manifest, "utf8");
|
|
4754
|
+
if (clack.note) {
|
|
4755
|
+
const previous = result.previous ?? "(none)";
|
|
4756
|
+
clack.note(`lint: ${previous} -> oxlint --disable-nested-config && eslint .`, "Updated package.json script");
|
|
4757
|
+
}
|
|
4758
|
+
}
|
|
4759
|
+
function rewriteDirectivesWithNote(clack, directory) {
|
|
4760
|
+
const { rewritten } = rewriteDisableDirectives(directory);
|
|
4761
|
+
if (rewritten.length === 0 || !clack.note) return;
|
|
4762
|
+
clack.note(`Re-pointed eslint-disable comments onto oxlint-disable in ${rewritten.length} file(s).`, "Disable directives");
|
|
4763
|
+
}
|
|
4235
4764
|
function loadPreviousMigrate(clack, cwd) {
|
|
4236
4765
|
const restored = loadSession({ cwd });
|
|
4237
4766
|
const previousMigrate = restored?.command === "migrate" ? restored.migrate : void 0;
|
|
@@ -4271,6 +4800,14 @@ async function runMigrate(input, clackOverride) {
|
|
|
4271
4800
|
if (!await runConfirmations(clack, input, resolved.targetPath, prepared.writePath, previousMigrate)) return 0;
|
|
4272
4801
|
persistMigrateSession(input, prepared, resolved);
|
|
4273
4802
|
performWriteAndCleanup(clack, resolved, prepared);
|
|
4803
|
+
applyLintScript$1(clack, (0, node_path.dirname)(prepared.writePath));
|
|
4804
|
+
rewriteDirectivesWithNote(clack, (0, node_path.dirname)(prepared.writePath));
|
|
4805
|
+
const consumerDir = (0, node_path.dirname)(prepared.writePath);
|
|
4806
|
+
await applyTsExtensionsFlag(clack, {
|
|
4807
|
+
cwd: consumerDir,
|
|
4808
|
+
lintModule: resolveLintLayout(consumerDir).lintModule,
|
|
4809
|
+
autoConfirm: input.yes
|
|
4810
|
+
});
|
|
4274
4811
|
if (depSummary) await applyDepChanges(clack, depSummary, input);
|
|
4275
4812
|
clearSession({ cwd: input.cwd });
|
|
4276
4813
|
return 0;
|
|
@@ -4438,6 +4975,22 @@ async function resolveHybridAnswers(clack, input, answers) {
|
|
|
4438
4975
|
};
|
|
4439
4976
|
return answers;
|
|
4440
4977
|
}
|
|
4978
|
+
function applyLintScript(cwd) {
|
|
4979
|
+
const manifestPath = (0, node_path.join)(cwd, "package.json");
|
|
4980
|
+
if (!(0, node_fs.existsSync)(manifestPath)) return;
|
|
4981
|
+
const result = setLintScript((0, node_fs.readFileSync)(manifestPath, "utf8"));
|
|
4982
|
+
if (result.changed) (0, node_fs.writeFileSync)(manifestPath, result.manifest, "utf8");
|
|
4983
|
+
}
|
|
4984
|
+
function writeLintLayout(cwd, lintModuleSource) {
|
|
4985
|
+
const layout = resolveLintLayout(cwd);
|
|
4986
|
+
const lintModulePath = (0, node_path.join)(cwd, layout.lintModule);
|
|
4987
|
+
(0, node_fs.writeFileSync)(lintModulePath, lintModuleSource, "utf8");
|
|
4988
|
+
renderLintLayoutFiles(layout).forEach((file) => {
|
|
4989
|
+
(0, node_fs.writeFileSync)((0, node_path.join)(cwd, file.filename), file.source, "utf8");
|
|
4990
|
+
});
|
|
4991
|
+
applyLintScript(cwd);
|
|
4992
|
+
return lintModulePath;
|
|
4993
|
+
}
|
|
4441
4994
|
async function installAndWrite(clack, input, answers, options) {
|
|
4442
4995
|
if (options.pruneBeforeInstall) noteOverridePrune(clack, pruneConsumerPackageJson(input.cwd).removed);
|
|
4443
4996
|
const deps = buildDependencyList(answers);
|
|
@@ -4450,9 +5003,7 @@ async function installAndWrite(clack, input, answers, options) {
|
|
|
4450
5003
|
installer: input.overrides?.installer ?? installDependencies,
|
|
4451
5004
|
fsOps: input.overrides?.wipeFs
|
|
4452
5005
|
});
|
|
4453
|
-
|
|
4454
|
-
(0, node_fs.writeFileSync)(targetPath, renderConfigFile(answers), "utf8");
|
|
4455
|
-
return targetPath;
|
|
5006
|
+
return writeLintLayout(input.cwd, renderLintModuleFile(answers));
|
|
4456
5007
|
}
|
|
4457
5008
|
async function runScaffold(input, clackOverride) {
|
|
4458
5009
|
const clack = clackOverride ?? await loadClack();
|
|
@@ -4474,8 +5025,13 @@ async function runScaffold(input, clackOverride) {
|
|
|
4474
5025
|
}
|
|
4475
5026
|
}, { cwd: input.cwd });
|
|
4476
5027
|
const targetPath = await installAndWrite(clack, input, resolvedAnswers, { pruneBeforeInstall: viaOverride });
|
|
5028
|
+
await applyTsExtensionsFlag(clack, {
|
|
5029
|
+
cwd: input.cwd,
|
|
5030
|
+
lintModule: resolveLintLayout(input.cwd).lintModule,
|
|
5031
|
+
autoConfirm: input.yes
|
|
5032
|
+
});
|
|
4477
5033
|
clearSession({ cwd: input.cwd });
|
|
4478
|
-
clack.outro(`Wrote ${targetPath}`);
|
|
5034
|
+
clack.outro(`Wrote ${targetPath} and its sibling linter configs`);
|
|
4479
5035
|
return 0;
|
|
4480
5036
|
}
|
|
4481
5037
|
async function runScaffoldSubcommand(scaffoldInput) {
|
|
@@ -4514,5 +5070,6 @@ if (!isUnderTest()) main().then(exitCleanly).catch((error) => {
|
|
|
4514
5070
|
});
|
|
4515
5071
|
//#endregion
|
|
4516
5072
|
exports.runScaffold = runScaffold;
|
|
5073
|
+
exports.writeLintLayout = writeLintLayout;
|
|
4517
5074
|
|
|
4518
5075
|
//# sourceMappingURL=cli.cjs.map
|