eslint-plugin-ai-guard 1.1.3 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +458 -370
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1305,29 +1305,29 @@ function getMemberPath(node) {
|
|
|
1305
1305
|
}
|
|
1306
1306
|
return [...objectPath, node.property.name];
|
|
1307
1307
|
}
|
|
1308
|
-
function hasPathPrefix(
|
|
1309
|
-
if (!
|
|
1308
|
+
function hasPathPrefix(path9, prefix) {
|
|
1309
|
+
if (!path9 || path9.length < prefix.length) {
|
|
1310
1310
|
return false;
|
|
1311
1311
|
}
|
|
1312
1312
|
for (let i = 0; i < prefix.length; i += 1) {
|
|
1313
|
-
if (
|
|
1313
|
+
if (path9[i] !== prefix[i]) {
|
|
1314
1314
|
return false;
|
|
1315
1315
|
}
|
|
1316
1316
|
}
|
|
1317
1317
|
return true;
|
|
1318
1318
|
}
|
|
1319
|
-
function isLikelyResourceIdPath(
|
|
1320
|
-
if (!
|
|
1319
|
+
function isLikelyResourceIdPath(path9) {
|
|
1320
|
+
if (!path9 || path9.length < 3) {
|
|
1321
1321
|
return false;
|
|
1322
1322
|
}
|
|
1323
|
-
if (!hasPathPrefix(
|
|
1323
|
+
if (!hasPathPrefix(path9, ["req", "params"]) && !hasPathPrefix(path9, ["req", "body"]) && !hasPathPrefix(path9, ["req", "query"])) {
|
|
1324
1324
|
return false;
|
|
1325
1325
|
}
|
|
1326
|
-
const last =
|
|
1326
|
+
const last = path9[path9.length - 1].toLowerCase();
|
|
1327
1327
|
return last === "id" || last.endsWith("id");
|
|
1328
1328
|
}
|
|
1329
|
-
function isReqUserPath(
|
|
1330
|
-
return hasPathPrefix(
|
|
1329
|
+
function isReqUserPath(path9) {
|
|
1330
|
+
return hasPathPrefix(path9, ["req", "user"]);
|
|
1331
1331
|
}
|
|
1332
1332
|
function containsAuthorizationHelper(node) {
|
|
1333
1333
|
if (node.type === import_utils15.AST_NODE_TYPES.CallExpression && (node.callee.type === import_utils15.AST_NODE_TYPES.Identifier && AUTHZ_HELPER_NAMES.includes(node.callee.name) || node.callee.type === import_utils15.AST_NODE_TYPES.MemberExpression && node.callee.property.type === import_utils15.AST_NODE_TYPES.Identifier && AUTHZ_HELPER_NAMES.includes(node.callee.property.name))) {
|
|
@@ -1366,8 +1366,8 @@ function collectBodySignals(node) {
|
|
|
1366
1366
|
}
|
|
1367
1367
|
}
|
|
1368
1368
|
if (current.type === import_utils15.AST_NODE_TYPES.MemberExpression) {
|
|
1369
|
-
const
|
|
1370
|
-
if (isLikelyResourceIdPath(
|
|
1369
|
+
const path9 = getMemberPath(current);
|
|
1370
|
+
if (isLikelyResourceIdPath(path9)) {
|
|
1371
1371
|
hasResourceIdAccess = true;
|
|
1372
1372
|
}
|
|
1373
1373
|
}
|
|
@@ -1819,6 +1819,285 @@ var init_src = __esm({
|
|
|
1819
1819
|
}
|
|
1820
1820
|
});
|
|
1821
1821
|
|
|
1822
|
+
// cli/utils/config-manager.ts
|
|
1823
|
+
var config_manager_exports = {};
|
|
1824
|
+
__export(config_manager_exports, {
|
|
1825
|
+
addIgnoresToFlatConfig: () => addIgnoresToFlatConfig,
|
|
1826
|
+
addIgnoresToLegacyConfig: () => addIgnoresToLegacyConfig,
|
|
1827
|
+
backupConfig: () => backupConfig,
|
|
1828
|
+
generateFlatConfig: () => generateFlatConfig,
|
|
1829
|
+
generateLegacyConfig: () => generateLegacyConfig,
|
|
1830
|
+
getConfigFilePath: () => getConfigFilePath,
|
|
1831
|
+
isInvalidAiGuardConfig: () => isInvalidAiGuardConfig,
|
|
1832
|
+
patchFlatConfig: () => patchFlatConfig,
|
|
1833
|
+
patchLegacyConfig: () => patchLegacyConfig,
|
|
1834
|
+
readConfig: () => readConfig,
|
|
1835
|
+
removeNukeIgnore: () => removeNukeIgnore,
|
|
1836
|
+
repairInvalidFlatConfig: () => repairInvalidFlatConfig,
|
|
1837
|
+
validateFlatConfigText: () => validateFlatConfigText,
|
|
1838
|
+
validateLegacyConfigText: () => validateLegacyConfigText,
|
|
1839
|
+
writeConfig: () => writeConfig
|
|
1840
|
+
});
|
|
1841
|
+
function backupConfig(configPath) {
|
|
1842
|
+
const backupPath = `${configPath}.bak`;
|
|
1843
|
+
import_fs2.default.copyFileSync(configPath, backupPath);
|
|
1844
|
+
return backupPath;
|
|
1845
|
+
}
|
|
1846
|
+
function readConfig(configPath) {
|
|
1847
|
+
return import_fs2.default.readFileSync(configPath, "utf-8");
|
|
1848
|
+
}
|
|
1849
|
+
function writeConfig(configPath, content) {
|
|
1850
|
+
import_fs2.default.writeFileSync(configPath, content, "utf-8");
|
|
1851
|
+
}
|
|
1852
|
+
function generateFlatConfig(preset) {
|
|
1853
|
+
return `import aiGuard from 'eslint-plugin-ai-guard';
|
|
1854
|
+
|
|
1855
|
+
export default [
|
|
1856
|
+
// Ignore generated / dependency directories
|
|
1857
|
+
{
|
|
1858
|
+
ignores: [
|
|
1859
|
+
'node_modules/**',
|
|
1860
|
+
'.next/**',
|
|
1861
|
+
'dist/**',
|
|
1862
|
+
'build/**',
|
|
1863
|
+
'coverage/**',
|
|
1864
|
+
'out/**',
|
|
1865
|
+
],
|
|
1866
|
+
},
|
|
1867
|
+
|
|
1868
|
+
// ai-guard: catch AI-generated code patterns
|
|
1869
|
+
{
|
|
1870
|
+
plugins: {
|
|
1871
|
+
'ai-guard': aiGuard.default,
|
|
1872
|
+
},
|
|
1873
|
+
rules: {
|
|
1874
|
+
...aiGuard.${preset}.rules,
|
|
1875
|
+
},
|
|
1876
|
+
},
|
|
1877
|
+
];
|
|
1878
|
+
`;
|
|
1879
|
+
}
|
|
1880
|
+
function generateLegacyConfig(preset) {
|
|
1881
|
+
return `module.exports = {
|
|
1882
|
+
plugins: ['ai-guard'],
|
|
1883
|
+
extends: ['plugin:ai-guard/${preset}'],
|
|
1884
|
+
ignorePatterns: [
|
|
1885
|
+
'node_modules/',
|
|
1886
|
+
'.next/',
|
|
1887
|
+
'dist/',
|
|
1888
|
+
'build/',
|
|
1889
|
+
'coverage/',
|
|
1890
|
+
'out/',
|
|
1891
|
+
],
|
|
1892
|
+
};
|
|
1893
|
+
`;
|
|
1894
|
+
}
|
|
1895
|
+
function isInvalidAiGuardConfig(content) {
|
|
1896
|
+
if (!content.includes("eslint-plugin-ai-guard") && !content.includes("ai-guard")) {
|
|
1897
|
+
return false;
|
|
1898
|
+
}
|
|
1899
|
+
if (content.includes(".configs.")) return true;
|
|
1900
|
+
if (/(['"]ai-guard['"]\s*:\s*aiGuard)(?!\.default)/.test(content)) return true;
|
|
1901
|
+
return false;
|
|
1902
|
+
}
|
|
1903
|
+
function repairInvalidFlatConfig(content) {
|
|
1904
|
+
let repaired = content;
|
|
1905
|
+
repaired = repaired.replace(/(['"]ai-guard['"]\s*:\s*aiGuard)(?!\.default)/g, "$1.default");
|
|
1906
|
+
repaired = repaired.replace(/rules\s*:\s*aiGuard\.configs\.([a-zA-Z0-9_]+)\.rules(,?)/g, "rules: {\n ...aiGuard.$1.rules,\n }$2");
|
|
1907
|
+
repaired = repaired.replace(/\.\.\.aiGuard\.configs\.([a-zA-Z0-9_]+)\.rules/g, "...aiGuard.$1.rules");
|
|
1908
|
+
return repaired;
|
|
1909
|
+
}
|
|
1910
|
+
function patchFlatConfig(existing, preset) {
|
|
1911
|
+
if (isInvalidAiGuardConfig(existing)) {
|
|
1912
|
+
return repairInvalidFlatConfig(existing);
|
|
1913
|
+
}
|
|
1914
|
+
if (existing.includes(AI_GUARD_MARKER)) {
|
|
1915
|
+
return existing;
|
|
1916
|
+
}
|
|
1917
|
+
const importLine = `import aiGuard from 'eslint-plugin-ai-guard';
|
|
1918
|
+
`;
|
|
1919
|
+
const rulesBlock = `
|
|
1920
|
+
// ai-guard injected by ai-guard CLI
|
|
1921
|
+
{
|
|
1922
|
+
plugins: {
|
|
1923
|
+
'ai-guard': aiGuard.default,
|
|
1924
|
+
},
|
|
1925
|
+
rules: {
|
|
1926
|
+
...aiGuard.${preset}.rules,
|
|
1927
|
+
},
|
|
1928
|
+
},
|
|
1929
|
+
`;
|
|
1930
|
+
let patched = existing;
|
|
1931
|
+
const lastImportIdx = findLastImportEnd(patched);
|
|
1932
|
+
if (lastImportIdx > -1) {
|
|
1933
|
+
patched = patched.slice(0, lastImportIdx) + importLine + patched.slice(lastImportIdx);
|
|
1934
|
+
} else {
|
|
1935
|
+
patched = importLine + patched;
|
|
1936
|
+
}
|
|
1937
|
+
const lastBracket = patched.lastIndexOf("];");
|
|
1938
|
+
if (lastBracket !== -1) {
|
|
1939
|
+
patched = patched.slice(0, lastBracket) + rulesBlock + patched.slice(lastBracket);
|
|
1940
|
+
}
|
|
1941
|
+
return patched;
|
|
1942
|
+
}
|
|
1943
|
+
function findLastImportEnd(src) {
|
|
1944
|
+
const lines = src.split("\n");
|
|
1945
|
+
let lastImportLine = -1;
|
|
1946
|
+
let charCount = 0;
|
|
1947
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1948
|
+
const line = lines[i];
|
|
1949
|
+
if (/^\s*import\s+/.test(line)) lastImportLine = i;
|
|
1950
|
+
charCount += line.length + 1;
|
|
1951
|
+
}
|
|
1952
|
+
if (lastImportLine === -1) return -1;
|
|
1953
|
+
let offset = 0;
|
|
1954
|
+
for (let i = 0; i <= lastImportLine; i++) {
|
|
1955
|
+
offset += lines[i].length + 1;
|
|
1956
|
+
}
|
|
1957
|
+
return offset;
|
|
1958
|
+
}
|
|
1959
|
+
function patchLegacyConfig(existing, preset) {
|
|
1960
|
+
if (existing.includes("ai-guard")) {
|
|
1961
|
+
return existing;
|
|
1962
|
+
}
|
|
1963
|
+
let patched = existing;
|
|
1964
|
+
if (patched.includes("plugins:")) {
|
|
1965
|
+
patched = patched.replace(/plugins:\s*\[/, `plugins: ['ai-guard', `);
|
|
1966
|
+
} else {
|
|
1967
|
+
patched = patched.replace(
|
|
1968
|
+
"module.exports = {",
|
|
1969
|
+
`module.exports = {
|
|
1970
|
+
plugins: ['ai-guard'],`
|
|
1971
|
+
);
|
|
1972
|
+
}
|
|
1973
|
+
if (patched.includes("extends:")) {
|
|
1974
|
+
patched = patched.replace(
|
|
1975
|
+
/extends:\s*\[/,
|
|
1976
|
+
`extends: ['plugin:ai-guard/${preset}', `
|
|
1977
|
+
);
|
|
1978
|
+
} else {
|
|
1979
|
+
patched = patched.replace(
|
|
1980
|
+
"module.exports = {",
|
|
1981
|
+
`module.exports = {
|
|
1982
|
+
extends: ['plugin:ai-guard/${preset}'],`
|
|
1983
|
+
);
|
|
1984
|
+
}
|
|
1985
|
+
return patched;
|
|
1986
|
+
}
|
|
1987
|
+
function removeNukeIgnore(existing) {
|
|
1988
|
+
const nukePatterns = [/"?\*\*\/\*"?/g];
|
|
1989
|
+
const hasNuke = existing.includes('"**/*"') || existing.includes("'**/*'");
|
|
1990
|
+
if (!hasNuke) return { content: existing, changed: false };
|
|
1991
|
+
let patched = existing.replace(
|
|
1992
|
+
/ignorePatterns:\s*\[.*?\*\*\/\*.*?\]/gs,
|
|
1993
|
+
`ignorePatterns: ['node_modules/', '.next/', 'dist/', 'build/', 'coverage/']`
|
|
1994
|
+
).replace(
|
|
1995
|
+
/ignores:\s*\[.*?\*\*\/\*.*?\]/gs,
|
|
1996
|
+
`ignores: ['node_modules/**', '.next/**', 'dist/**', 'build/**', 'coverage/**']`
|
|
1997
|
+
);
|
|
1998
|
+
for (const re of nukePatterns) {
|
|
1999
|
+
patched = patched.replace(re, "");
|
|
2000
|
+
}
|
|
2001
|
+
return { content: patched, changed: patched !== existing };
|
|
2002
|
+
}
|
|
2003
|
+
function addIgnoresToFlatConfig(existing) {
|
|
2004
|
+
if (existing.includes("ignores:")) return existing;
|
|
2005
|
+
const block = `
|
|
2006
|
+
// Default ignores added by ai-guard CLI
|
|
2007
|
+
{
|
|
2008
|
+
ignores: ${JSON.stringify(DEFAULT_FLAT_IGNORES)},
|
|
2009
|
+
},
|
|
2010
|
+
`;
|
|
2011
|
+
const lastBracket = existing.lastIndexOf("];");
|
|
2012
|
+
if (lastBracket !== -1) {
|
|
2013
|
+
return existing.slice(0, lastBracket) + block + existing.slice(lastBracket);
|
|
2014
|
+
}
|
|
2015
|
+
return existing;
|
|
2016
|
+
}
|
|
2017
|
+
function addIgnoresToLegacyConfig(existing) {
|
|
2018
|
+
if (existing.includes("ignorePatterns")) return existing;
|
|
2019
|
+
return existing.replace(
|
|
2020
|
+
"module.exports = {",
|
|
2021
|
+
`module.exports = {
|
|
2022
|
+
ignorePatterns: ${JSON.stringify(DEFAULT_LEGACY_IGNORES)},`
|
|
2023
|
+
);
|
|
2024
|
+
}
|
|
2025
|
+
function getConfigFilePath(configType, cwd = process.cwd()) {
|
|
2026
|
+
switch (configType) {
|
|
2027
|
+
case "flat-js":
|
|
2028
|
+
return import_path3.default.join(cwd, "eslint.config.js");
|
|
2029
|
+
case "flat-mjs":
|
|
2030
|
+
return import_path3.default.join(cwd, "eslint.config.mjs");
|
|
2031
|
+
case "flat-cjs":
|
|
2032
|
+
return import_path3.default.join(cwd, "eslint.config.cjs");
|
|
2033
|
+
case "eslintrc-js":
|
|
2034
|
+
return import_path3.default.join(cwd, ".eslintrc.js");
|
|
2035
|
+
case "eslintrc-cjs":
|
|
2036
|
+
return import_path3.default.join(cwd, ".eslintrc.cjs");
|
|
2037
|
+
case "eslintrc-json":
|
|
2038
|
+
return import_path3.default.join(cwd, ".eslintrc.json");
|
|
2039
|
+
default:
|
|
2040
|
+
return import_path3.default.join(cwd, ".eslintrc.js");
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
function validateFlatConfigText(content) {
|
|
2044
|
+
const problems = [];
|
|
2045
|
+
if (!content.includes("export default")) {
|
|
2046
|
+
problems.push("Missing `export default` \u2014 file must be an ES module");
|
|
2047
|
+
}
|
|
2048
|
+
if (!content.includes("eslint-plugin-ai-guard") && !content.includes("aiGuard")) {
|
|
2049
|
+
problems.push("Plugin import not found \u2014 ai-guard plugin may not be referenced");
|
|
2050
|
+
}
|
|
2051
|
+
if (!content.trim().endsWith("];") && !content.trim().endsWith("];")) {
|
|
2052
|
+
}
|
|
2053
|
+
if (content.includes('"**/*"') || content.includes("'**/*'")) {
|
|
2054
|
+
problems.push(
|
|
2055
|
+
'Config contains "**/*" ignore pattern \u2014 this will prevent all files from being linted'
|
|
2056
|
+
);
|
|
2057
|
+
}
|
|
2058
|
+
return problems;
|
|
2059
|
+
}
|
|
2060
|
+
function validateLegacyConfigText(content) {
|
|
2061
|
+
const problems = [];
|
|
2062
|
+
if (!content.includes("module.exports")) {
|
|
2063
|
+
problems.push("Missing `module.exports` \u2014 legacy config must use CJS exports");
|
|
2064
|
+
}
|
|
2065
|
+
if (!content.includes("ai-guard")) {
|
|
2066
|
+
problems.push("Plugin not referenced \u2014 add ai-guard to plugins and extends");
|
|
2067
|
+
}
|
|
2068
|
+
if (content.includes('"**/*"') || content.includes("'**/*'")) {
|
|
2069
|
+
problems.push(
|
|
2070
|
+
'Config contains "**/*" ignore pattern \u2014 this will prevent all files from being linted'
|
|
2071
|
+
);
|
|
2072
|
+
}
|
|
2073
|
+
return problems;
|
|
2074
|
+
}
|
|
2075
|
+
var import_fs2, import_path3, AI_GUARD_MARKER, DEFAULT_FLAT_IGNORES, DEFAULT_LEGACY_IGNORES;
|
|
2076
|
+
var init_config_manager = __esm({
|
|
2077
|
+
"cli/utils/config-manager.ts"() {
|
|
2078
|
+
"use strict";
|
|
2079
|
+
import_fs2 = __toESM(require("fs"));
|
|
2080
|
+
import_path3 = __toESM(require("path"));
|
|
2081
|
+
AI_GUARD_MARKER = "eslint-plugin-ai-guard";
|
|
2082
|
+
DEFAULT_FLAT_IGNORES = [
|
|
2083
|
+
"node_modules/**",
|
|
2084
|
+
".next/**",
|
|
2085
|
+
"dist/**",
|
|
2086
|
+
"build/**",
|
|
2087
|
+
"coverage/**",
|
|
2088
|
+
"out/**"
|
|
2089
|
+
];
|
|
2090
|
+
DEFAULT_LEGACY_IGNORES = [
|
|
2091
|
+
"node_modules/",
|
|
2092
|
+
".next/",
|
|
2093
|
+
"dist/",
|
|
2094
|
+
"build/",
|
|
2095
|
+
"coverage/",
|
|
2096
|
+
"out/"
|
|
2097
|
+
];
|
|
2098
|
+
}
|
|
2099
|
+
});
|
|
2100
|
+
|
|
1822
2101
|
// cli/index.ts
|
|
1823
2102
|
var import_commander = require("commander");
|
|
1824
2103
|
|
|
@@ -1828,6 +2107,73 @@ var import_chalk2 = __toESM(require("chalk"));
|
|
|
1828
2107
|
|
|
1829
2108
|
// cli/utils/eslint-runner.ts
|
|
1830
2109
|
var import_path = __toESM(require("path"));
|
|
2110
|
+
|
|
2111
|
+
// cli/utils/logger.ts
|
|
2112
|
+
var import_chalk = __toESM(require("chalk"));
|
|
2113
|
+
var PREFIX = {
|
|
2114
|
+
success: import_chalk.default.green("\u2714"),
|
|
2115
|
+
error: import_chalk.default.red("\u2716"),
|
|
2116
|
+
warn: import_chalk.default.yellow("\u26A0"),
|
|
2117
|
+
info: import_chalk.default.cyan("\u2139"),
|
|
2118
|
+
section: import_chalk.default.bold.white,
|
|
2119
|
+
bullet: import_chalk.default.gray("\u2022")
|
|
2120
|
+
};
|
|
2121
|
+
var log = {
|
|
2122
|
+
info(msg) {
|
|
2123
|
+
console.log(` ${PREFIX.info} ${import_chalk.default.white(msg)}`);
|
|
2124
|
+
},
|
|
2125
|
+
success(msg) {
|
|
2126
|
+
console.log(` ${PREFIX.success} ${import_chalk.default.green(msg)}`);
|
|
2127
|
+
},
|
|
2128
|
+
warn(msg) {
|
|
2129
|
+
console.log(` ${PREFIX.warn} ${import_chalk.default.yellow(msg)}`);
|
|
2130
|
+
},
|
|
2131
|
+
error(msg) {
|
|
2132
|
+
console.error(` ${PREFIX.error} ${import_chalk.default.red(msg)}`);
|
|
2133
|
+
},
|
|
2134
|
+
section(title) {
|
|
2135
|
+
console.log("");
|
|
2136
|
+
console.log(import_chalk.default.bold.cyan(` \u2500\u2500 ${title} \u2500\u2500`));
|
|
2137
|
+
console.log("");
|
|
2138
|
+
},
|
|
2139
|
+
rule(ruleName, count) {
|
|
2140
|
+
console.log(
|
|
2141
|
+
` ${PREFIX.bullet} ${import_chalk.default.yellow(ruleName)} ${import_chalk.default.gray(`(${count} issue${count !== 1 ? "s" : ""})`)}`
|
|
2142
|
+
);
|
|
2143
|
+
},
|
|
2144
|
+
file(filePath, count) {
|
|
2145
|
+
console.log(
|
|
2146
|
+
` ${PREFIX.bullet} ${import_chalk.default.white(filePath)} ${import_chalk.default.gray(`\u2192 ${count} issue${count !== 1 ? "s" : ""}`)}`
|
|
2147
|
+
);
|
|
2148
|
+
},
|
|
2149
|
+
issue(msg, severity, line, col) {
|
|
2150
|
+
const icon = severity === 2 ? import_chalk.default.red("error") : import_chalk.default.yellow(" warn");
|
|
2151
|
+
console.log(
|
|
2152
|
+
` ${import_chalk.default.gray(`${line}:${col}`).padEnd(12)} ${icon} ${import_chalk.default.white(msg)}`
|
|
2153
|
+
);
|
|
2154
|
+
},
|
|
2155
|
+
divider() {
|
|
2156
|
+
console.log(import_chalk.default.gray(" " + "\u2500".repeat(60)));
|
|
2157
|
+
},
|
|
2158
|
+
blank() {
|
|
2159
|
+
console.log("");
|
|
2160
|
+
},
|
|
2161
|
+
banner(title) {
|
|
2162
|
+
console.log("");
|
|
2163
|
+
console.log(import_chalk.default.bold.bgCyan.black(` ${title} `));
|
|
2164
|
+
console.log("");
|
|
2165
|
+
},
|
|
2166
|
+
print(msg) {
|
|
2167
|
+
console.log(msg);
|
|
2168
|
+
},
|
|
2169
|
+
debug(msg) {
|
|
2170
|
+
if (process.env.AI_GUARD_DEBUG === "1") {
|
|
2171
|
+
console.log(` ${import_chalk.default.gray("\xB7")} ${import_chalk.default.gray(msg)}`);
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
};
|
|
2175
|
+
|
|
2176
|
+
// cli/utils/eslint-runner.ts
|
|
1831
2177
|
function normalizePlugin(raw) {
|
|
1832
2178
|
if (raw && raw.default && raw.default.rules) return raw.default;
|
|
1833
2179
|
if (raw && raw.rules) return raw;
|
|
@@ -1890,6 +2236,12 @@ var DEFAULT_IGNORE_PATTERNS = [
|
|
|
1890
2236
|
"**/out/**",
|
|
1891
2237
|
"**/.git/**"
|
|
1892
2238
|
];
|
|
2239
|
+
function isSkippablePatternError(error) {
|
|
2240
|
+
const msg = error.message.toLowerCase();
|
|
2241
|
+
const hasNoFilesSignal = msg.includes("no files") || msg.includes("no files matching");
|
|
2242
|
+
const hasIgnoredSignal = msg.includes("ignored") || msg.includes("all files matched by") || msg.includes("are ignored") || msg.includes("was ignored") || msg.includes("file ignored");
|
|
2243
|
+
return hasNoFilesSignal || hasIgnoredSignal;
|
|
2244
|
+
}
|
|
1893
2245
|
async function runEslint(options) {
|
|
1894
2246
|
const { ESLint } = await import("eslint").catch(() => {
|
|
1895
2247
|
throw new Error(
|
|
@@ -1982,112 +2334,53 @@ async function runEslint(options) {
|
|
|
1982
2334
|
const r = await eslint.lintFiles([pattern]);
|
|
1983
2335
|
allRawResults.push(...r);
|
|
1984
2336
|
} catch (err) {
|
|
1985
|
-
const
|
|
1986
|
-
if (
|
|
2337
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
2338
|
+
if (isSkippablePatternError(error)) {
|
|
2339
|
+
log.debug(`Skipping pattern '${pattern}' (no lintable files)`);
|
|
1987
2340
|
continue;
|
|
1988
2341
|
}
|
|
1989
|
-
throw
|
|
2342
|
+
throw error;
|
|
1990
2343
|
}
|
|
1991
2344
|
}
|
|
1992
2345
|
const rawResults = allRawResults;
|
|
1993
2346
|
const durationMs = Date.now() - startMs;
|
|
1994
|
-
const files = [];
|
|
1995
|
-
const ruleBreakdown = /* @__PURE__ */ new Map();
|
|
1996
|
-
let totalErrors = 0;
|
|
1997
|
-
let totalWarnings = 0;
|
|
1998
|
-
for (const result of rawResults) {
|
|
1999
|
-
if (result.messages.length === 0) continue;
|
|
2000
|
-
const issues = result.messages.map((m) => ({
|
|
2001
|
-
ruleId: m.ruleId ?? "unknown",
|
|
2002
|
-
severity: m.severity,
|
|
2003
|
-
message: m.message,
|
|
2004
|
-
line: m.line,
|
|
2005
|
-
column: m.column
|
|
2006
|
-
}));
|
|
2007
|
-
const errorCount = result.errorCount;
|
|
2008
|
-
const warningCount = result.warningCount;
|
|
2009
|
-
totalErrors += errorCount;
|
|
2010
|
-
totalWarnings += warningCount;
|
|
2011
|
-
for (const issue of issues) {
|
|
2012
|
-
ruleBreakdown.set(
|
|
2013
|
-
issue.ruleId,
|
|
2014
|
-
(ruleBreakdown.get(issue.ruleId) ?? 0) + 1
|
|
2015
|
-
);
|
|
2016
|
-
}
|
|
2017
|
-
const relPath = import_path.default.relative(process.cwd(), result.filePath);
|
|
2018
|
-
files.push({ filePath: relPath, issues, errorCount, warningCount });
|
|
2019
|
-
}
|
|
2020
|
-
const topFiles = [...files].sort((a, b) => b.issues.length - a.issues.length).slice(0, 10).map((f) => ({ path: f.filePath, count: f.issues.length }));
|
|
2021
|
-
return {
|
|
2022
|
-
files,
|
|
2023
|
-
totalErrors,
|
|
2024
|
-
totalWarnings,
|
|
2025
|
-
totalIssues: totalErrors + totalWarnings,
|
|
2026
|
-
ruleBreakdown,
|
|
2027
|
-
topFiles,
|
|
2028
|
-
durationMs
|
|
2029
|
-
};
|
|
2030
|
-
}
|
|
2031
|
-
|
|
2032
|
-
// cli/utils/logger.ts
|
|
2033
|
-
var import_chalk = __toESM(require("chalk"));
|
|
2034
|
-
var PREFIX = {
|
|
2035
|
-
success: import_chalk.default.green("\u2714"),
|
|
2036
|
-
error: import_chalk.default.red("\u2716"),
|
|
2037
|
-
warn: import_chalk.default.yellow("\u26A0"),
|
|
2038
|
-
info: import_chalk.default.cyan("\u2139"),
|
|
2039
|
-
section: import_chalk.default.bold.white,
|
|
2040
|
-
bullet: import_chalk.default.gray("\u2022")
|
|
2041
|
-
};
|
|
2042
|
-
var log = {
|
|
2043
|
-
info(msg) {
|
|
2044
|
-
console.log(` ${PREFIX.info} ${import_chalk.default.white(msg)}`);
|
|
2045
|
-
},
|
|
2046
|
-
success(msg) {
|
|
2047
|
-
console.log(` ${PREFIX.success} ${import_chalk.default.green(msg)}`);
|
|
2048
|
-
},
|
|
2049
|
-
warn(msg) {
|
|
2050
|
-
console.log(` ${PREFIX.warn} ${import_chalk.default.yellow(msg)}`);
|
|
2051
|
-
},
|
|
2052
|
-
error(msg) {
|
|
2053
|
-
console.error(` ${PREFIX.error} ${import_chalk.default.red(msg)}`);
|
|
2054
|
-
},
|
|
2055
|
-
section(title) {
|
|
2056
|
-
console.log("");
|
|
2057
|
-
console.log(import_chalk.default.bold.cyan(` \u2500\u2500 ${title} \u2500\u2500`));
|
|
2058
|
-
console.log("");
|
|
2059
|
-
},
|
|
2060
|
-
rule(ruleName, count) {
|
|
2061
|
-
console.log(
|
|
2062
|
-
` ${PREFIX.bullet} ${import_chalk.default.yellow(ruleName)} ${import_chalk.default.gray(`(${count} issue${count !== 1 ? "s" : ""})`)}`
|
|
2063
|
-
);
|
|
2064
|
-
},
|
|
2065
|
-
file(filePath, count) {
|
|
2066
|
-
console.log(
|
|
2067
|
-
` ${PREFIX.bullet} ${import_chalk.default.white(filePath)} ${import_chalk.default.gray(`\u2192 ${count} issue${count !== 1 ? "s" : ""}`)}`
|
|
2068
|
-
);
|
|
2069
|
-
},
|
|
2070
|
-
issue(msg, severity, line, col) {
|
|
2071
|
-
const icon = severity === 2 ? import_chalk.default.red("error") : import_chalk.default.yellow(" warn");
|
|
2072
|
-
console.log(
|
|
2073
|
-
` ${import_chalk.default.gray(`${line}:${col}`).padEnd(12)} ${icon} ${import_chalk.default.white(msg)}`
|
|
2074
|
-
);
|
|
2075
|
-
},
|
|
2076
|
-
divider() {
|
|
2077
|
-
console.log(import_chalk.default.gray(" " + "\u2500".repeat(60)));
|
|
2078
|
-
},
|
|
2079
|
-
blank() {
|
|
2080
|
-
console.log("");
|
|
2081
|
-
},
|
|
2082
|
-
banner(title) {
|
|
2083
|
-
console.log("");
|
|
2084
|
-
console.log(import_chalk.default.bold.bgCyan.black(` ${title} `));
|
|
2085
|
-
console.log("");
|
|
2086
|
-
},
|
|
2087
|
-
print(msg) {
|
|
2088
|
-
console.log(msg);
|
|
2347
|
+
const files = [];
|
|
2348
|
+
const ruleBreakdown = /* @__PURE__ */ new Map();
|
|
2349
|
+
let totalErrors = 0;
|
|
2350
|
+
let totalWarnings = 0;
|
|
2351
|
+
for (const result of rawResults) {
|
|
2352
|
+
if (result.messages.length === 0) continue;
|
|
2353
|
+
const issues = result.messages.map((m) => ({
|
|
2354
|
+
ruleId: m.ruleId ?? "unknown",
|
|
2355
|
+
severity: m.severity,
|
|
2356
|
+
message: m.message,
|
|
2357
|
+
line: m.line,
|
|
2358
|
+
column: m.column
|
|
2359
|
+
}));
|
|
2360
|
+
const errorCount = result.errorCount;
|
|
2361
|
+
const warningCount = result.warningCount;
|
|
2362
|
+
totalErrors += errorCount;
|
|
2363
|
+
totalWarnings += warningCount;
|
|
2364
|
+
for (const issue of issues) {
|
|
2365
|
+
ruleBreakdown.set(
|
|
2366
|
+
issue.ruleId,
|
|
2367
|
+
(ruleBreakdown.get(issue.ruleId) ?? 0) + 1
|
|
2368
|
+
);
|
|
2369
|
+
}
|
|
2370
|
+
const relPath = import_path.default.relative(process.cwd(), result.filePath);
|
|
2371
|
+
files.push({ filePath: relPath, issues, errorCount, warningCount });
|
|
2089
2372
|
}
|
|
2090
|
-
};
|
|
2373
|
+
const topFiles = [...files].sort((a, b) => b.issues.length - a.issues.length).slice(0, 10).map((f) => ({ path: f.filePath, count: f.issues.length }));
|
|
2374
|
+
return {
|
|
2375
|
+
files,
|
|
2376
|
+
totalErrors,
|
|
2377
|
+
totalWarnings,
|
|
2378
|
+
totalIssues: totalErrors + totalWarnings,
|
|
2379
|
+
ruleBreakdown,
|
|
2380
|
+
topFiles,
|
|
2381
|
+
durationMs
|
|
2382
|
+
};
|
|
2383
|
+
}
|
|
2091
2384
|
|
|
2092
2385
|
// cli/commands/run.ts
|
|
2093
2386
|
function registerRunCommand(program2) {
|
|
@@ -2220,7 +2513,7 @@ function formatIssueCount(errors, warnings) {
|
|
|
2220
2513
|
|
|
2221
2514
|
// cli/commands/init.ts
|
|
2222
2515
|
var import_chalk3 = __toESM(require("chalk"));
|
|
2223
|
-
var
|
|
2516
|
+
var import_path4 = __toESM(require("path"));
|
|
2224
2517
|
var import_fs3 = __toESM(require("fs"));
|
|
2225
2518
|
|
|
2226
2519
|
// cli/utils/detector.ts
|
|
@@ -2322,225 +2615,8 @@ function detect(cwd = process.cwd()) {
|
|
|
2322
2615
|
};
|
|
2323
2616
|
}
|
|
2324
2617
|
|
|
2325
|
-
// cli/utils/config-manager.ts
|
|
2326
|
-
var import_fs2 = __toESM(require("fs"));
|
|
2327
|
-
function backupConfig(configPath) {
|
|
2328
|
-
const backupPath = `${configPath}.bak`;
|
|
2329
|
-
import_fs2.default.copyFileSync(configPath, backupPath);
|
|
2330
|
-
return backupPath;
|
|
2331
|
-
}
|
|
2332
|
-
function readConfig(configPath) {
|
|
2333
|
-
return import_fs2.default.readFileSync(configPath, "utf-8");
|
|
2334
|
-
}
|
|
2335
|
-
function writeConfig(configPath, content) {
|
|
2336
|
-
import_fs2.default.writeFileSync(configPath, content, "utf-8");
|
|
2337
|
-
}
|
|
2338
|
-
function generateFlatConfig(preset) {
|
|
2339
|
-
return `import aiGuard from 'eslint-plugin-ai-guard';
|
|
2340
|
-
|
|
2341
|
-
export default [
|
|
2342
|
-
// Ignore generated / dependency directories
|
|
2343
|
-
{
|
|
2344
|
-
ignores: [
|
|
2345
|
-
'node_modules/**',
|
|
2346
|
-
'.next/**',
|
|
2347
|
-
'dist/**',
|
|
2348
|
-
'build/**',
|
|
2349
|
-
'coverage/**',
|
|
2350
|
-
'out/**',
|
|
2351
|
-
],
|
|
2352
|
-
},
|
|
2353
|
-
|
|
2354
|
-
// ai-guard: catch AI-generated code patterns
|
|
2355
|
-
{
|
|
2356
|
-
plugins: {
|
|
2357
|
-
'ai-guard': aiGuard.default,
|
|
2358
|
-
},
|
|
2359
|
-
rules: {
|
|
2360
|
-
...aiGuard.${preset}.rules,
|
|
2361
|
-
},
|
|
2362
|
-
},
|
|
2363
|
-
];
|
|
2364
|
-
`;
|
|
2365
|
-
}
|
|
2366
|
-
function generateLegacyConfig(preset) {
|
|
2367
|
-
return `module.exports = {
|
|
2368
|
-
plugins: ['ai-guard'],
|
|
2369
|
-
extends: ['plugin:ai-guard/${preset}'],
|
|
2370
|
-
ignorePatterns: [
|
|
2371
|
-
'node_modules/',
|
|
2372
|
-
'.next/',
|
|
2373
|
-
'dist/',
|
|
2374
|
-
'build/',
|
|
2375
|
-
'coverage/',
|
|
2376
|
-
'out/',
|
|
2377
|
-
],
|
|
2378
|
-
};
|
|
2379
|
-
`;
|
|
2380
|
-
}
|
|
2381
|
-
var AI_GUARD_MARKER = "eslint-plugin-ai-guard";
|
|
2382
|
-
function patchFlatConfig(existing, preset) {
|
|
2383
|
-
if (existing.includes(AI_GUARD_MARKER)) {
|
|
2384
|
-
return existing;
|
|
2385
|
-
}
|
|
2386
|
-
const importLine = `import aiGuard from 'eslint-plugin-ai-guard';
|
|
2387
|
-
`;
|
|
2388
|
-
const rulesBlock = `
|
|
2389
|
-
// ai-guard injected by ai-guard CLI
|
|
2390
|
-
{
|
|
2391
|
-
plugins: {
|
|
2392
|
-
'ai-guard': aiGuard.default,
|
|
2393
|
-
},
|
|
2394
|
-
rules: {
|
|
2395
|
-
...aiGuard.${preset}.rules,
|
|
2396
|
-
},
|
|
2397
|
-
},
|
|
2398
|
-
`;
|
|
2399
|
-
let patched = existing;
|
|
2400
|
-
const lastImportIdx = findLastImportEnd(patched);
|
|
2401
|
-
if (lastImportIdx > -1) {
|
|
2402
|
-
patched = patched.slice(0, lastImportIdx) + importLine + patched.slice(lastImportIdx);
|
|
2403
|
-
} else {
|
|
2404
|
-
patched = importLine + patched;
|
|
2405
|
-
}
|
|
2406
|
-
const lastBracket = patched.lastIndexOf("];");
|
|
2407
|
-
if (lastBracket !== -1) {
|
|
2408
|
-
patched = patched.slice(0, lastBracket) + rulesBlock + patched.slice(lastBracket);
|
|
2409
|
-
}
|
|
2410
|
-
return patched;
|
|
2411
|
-
}
|
|
2412
|
-
function findLastImportEnd(src) {
|
|
2413
|
-
const lines = src.split("\n");
|
|
2414
|
-
let lastImportLine = -1;
|
|
2415
|
-
let charCount = 0;
|
|
2416
|
-
for (let i = 0; i < lines.length; i++) {
|
|
2417
|
-
const line = lines[i];
|
|
2418
|
-
if (/^\s*import\s+/.test(line)) lastImportLine = i;
|
|
2419
|
-
charCount += line.length + 1;
|
|
2420
|
-
}
|
|
2421
|
-
if (lastImportLine === -1) return -1;
|
|
2422
|
-
let offset = 0;
|
|
2423
|
-
for (let i = 0; i <= lastImportLine; i++) {
|
|
2424
|
-
offset += lines[i].length + 1;
|
|
2425
|
-
}
|
|
2426
|
-
return offset;
|
|
2427
|
-
}
|
|
2428
|
-
function patchLegacyConfig(existing, preset) {
|
|
2429
|
-
if (existing.includes("ai-guard")) {
|
|
2430
|
-
return existing;
|
|
2431
|
-
}
|
|
2432
|
-
let patched = existing;
|
|
2433
|
-
if (patched.includes("plugins:")) {
|
|
2434
|
-
patched = patched.replace(/plugins:\s*\[/, `plugins: ['ai-guard', `);
|
|
2435
|
-
} else {
|
|
2436
|
-
patched = patched.replace(
|
|
2437
|
-
"module.exports = {",
|
|
2438
|
-
`module.exports = {
|
|
2439
|
-
plugins: ['ai-guard'],`
|
|
2440
|
-
);
|
|
2441
|
-
}
|
|
2442
|
-
if (patched.includes("extends:")) {
|
|
2443
|
-
patched = patched.replace(
|
|
2444
|
-
/extends:\s*\[/,
|
|
2445
|
-
`extends: ['plugin:ai-guard/${preset}', `
|
|
2446
|
-
);
|
|
2447
|
-
} else {
|
|
2448
|
-
patched = patched.replace(
|
|
2449
|
-
"module.exports = {",
|
|
2450
|
-
`module.exports = {
|
|
2451
|
-
extends: ['plugin:ai-guard/${preset}'],`
|
|
2452
|
-
);
|
|
2453
|
-
}
|
|
2454
|
-
return patched;
|
|
2455
|
-
}
|
|
2456
|
-
function removeNukeIgnore(existing) {
|
|
2457
|
-
const nukePatterns = [/"?\*\*\/\*"?/g];
|
|
2458
|
-
const hasNuke = existing.includes('"**/*"') || existing.includes("'**/*'");
|
|
2459
|
-
if (!hasNuke) return { content: existing, changed: false };
|
|
2460
|
-
let patched = existing.replace(
|
|
2461
|
-
/ignorePatterns:\s*\[.*?\*\*\/\*.*?\]/gs,
|
|
2462
|
-
`ignorePatterns: ['node_modules/', '.next/', 'dist/', 'build/', 'coverage/']`
|
|
2463
|
-
).replace(
|
|
2464
|
-
/ignores:\s*\[.*?\*\*\/\*.*?\]/gs,
|
|
2465
|
-
`ignores: ['node_modules/**', '.next/**', 'dist/**', 'build/**', 'coverage/**']`
|
|
2466
|
-
);
|
|
2467
|
-
for (const re of nukePatterns) {
|
|
2468
|
-
patched = patched.replace(re, "");
|
|
2469
|
-
}
|
|
2470
|
-
return { content: patched, changed: patched !== existing };
|
|
2471
|
-
}
|
|
2472
|
-
var DEFAULT_FLAT_IGNORES = [
|
|
2473
|
-
"node_modules/**",
|
|
2474
|
-
".next/**",
|
|
2475
|
-
"dist/**",
|
|
2476
|
-
"build/**",
|
|
2477
|
-
"coverage/**",
|
|
2478
|
-
"out/**"
|
|
2479
|
-
];
|
|
2480
|
-
var DEFAULT_LEGACY_IGNORES = [
|
|
2481
|
-
"node_modules/",
|
|
2482
|
-
".next/",
|
|
2483
|
-
"dist/",
|
|
2484
|
-
"build/",
|
|
2485
|
-
"coverage/",
|
|
2486
|
-
"out/"
|
|
2487
|
-
];
|
|
2488
|
-
function addIgnoresToFlatConfig(existing) {
|
|
2489
|
-
if (existing.includes("ignores:")) return existing;
|
|
2490
|
-
const block = `
|
|
2491
|
-
// Default ignores added by ai-guard CLI
|
|
2492
|
-
{
|
|
2493
|
-
ignores: ${JSON.stringify(DEFAULT_FLAT_IGNORES)},
|
|
2494
|
-
},
|
|
2495
|
-
`;
|
|
2496
|
-
const lastBracket = existing.lastIndexOf("];");
|
|
2497
|
-
if (lastBracket !== -1) {
|
|
2498
|
-
return existing.slice(0, lastBracket) + block + existing.slice(lastBracket);
|
|
2499
|
-
}
|
|
2500
|
-
return existing;
|
|
2501
|
-
}
|
|
2502
|
-
function addIgnoresToLegacyConfig(existing) {
|
|
2503
|
-
if (existing.includes("ignorePatterns")) return existing;
|
|
2504
|
-
return existing.replace(
|
|
2505
|
-
"module.exports = {",
|
|
2506
|
-
`module.exports = {
|
|
2507
|
-
ignorePatterns: ${JSON.stringify(DEFAULT_LEGACY_IGNORES)},`
|
|
2508
|
-
);
|
|
2509
|
-
}
|
|
2510
|
-
function validateFlatConfigText(content) {
|
|
2511
|
-
const problems = [];
|
|
2512
|
-
if (!content.includes("export default")) {
|
|
2513
|
-
problems.push("Missing `export default` \u2014 file must be an ES module");
|
|
2514
|
-
}
|
|
2515
|
-
if (!content.includes("eslint-plugin-ai-guard") && !content.includes("aiGuard")) {
|
|
2516
|
-
problems.push("Plugin import not found \u2014 ai-guard plugin may not be referenced");
|
|
2517
|
-
}
|
|
2518
|
-
if (!content.trim().endsWith("];") && !content.trim().endsWith("];")) {
|
|
2519
|
-
}
|
|
2520
|
-
if (content.includes('"**/*"') || content.includes("'**/*'")) {
|
|
2521
|
-
problems.push(
|
|
2522
|
-
'Config contains "**/*" ignore pattern \u2014 this will prevent all files from being linted'
|
|
2523
|
-
);
|
|
2524
|
-
}
|
|
2525
|
-
return problems;
|
|
2526
|
-
}
|
|
2527
|
-
function validateLegacyConfigText(content) {
|
|
2528
|
-
const problems = [];
|
|
2529
|
-
if (!content.includes("module.exports")) {
|
|
2530
|
-
problems.push("Missing `module.exports` \u2014 legacy config must use CJS exports");
|
|
2531
|
-
}
|
|
2532
|
-
if (!content.includes("ai-guard")) {
|
|
2533
|
-
problems.push("Plugin not referenced \u2014 add ai-guard to plugins and extends");
|
|
2534
|
-
}
|
|
2535
|
-
if (content.includes('"**/*"') || content.includes("'**/*'")) {
|
|
2536
|
-
problems.push(
|
|
2537
|
-
'Config contains "**/*" ignore pattern \u2014 this will prevent all files from being linted'
|
|
2538
|
-
);
|
|
2539
|
-
}
|
|
2540
|
-
return problems;
|
|
2541
|
-
}
|
|
2542
|
-
|
|
2543
2618
|
// cli/commands/init.ts
|
|
2619
|
+
init_config_manager();
|
|
2544
2620
|
function classifyVerifyError(err) {
|
|
2545
2621
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2546
2622
|
const clean = msg.replace(/\s+at\s+.+/gm, "").trim();
|
|
@@ -2564,7 +2640,7 @@ async function verifyConfigLoads(configPath, cwd) {
|
|
|
2564
2640
|
overrideConfigFile: configPath
|
|
2565
2641
|
});
|
|
2566
2642
|
await eslint.lintText("", {
|
|
2567
|
-
filePath:
|
|
2643
|
+
filePath: import_path4.default.join(cwd, "_ai_guard_probe_.js")
|
|
2568
2644
|
});
|
|
2569
2645
|
return null;
|
|
2570
2646
|
} catch (err) {
|
|
@@ -2600,7 +2676,7 @@ function registerInitCommand(program2) {
|
|
|
2600
2676
|
log.warn("eslint-plugin-ai-guard not found");
|
|
2601
2677
|
}
|
|
2602
2678
|
if (env.configType !== "none") {
|
|
2603
|
-
log.success(`ESLint config found: ${import_chalk3.default.white(
|
|
2679
|
+
log.success(`ESLint config found: ${import_chalk3.default.white(import_path4.default.relative(cwd, env.configPath ?? env.configType))}`);
|
|
2604
2680
|
} else {
|
|
2605
2681
|
log.info("No ESLint config found \u2014 will generate one");
|
|
2606
2682
|
}
|
|
@@ -2609,7 +2685,7 @@ function registerInitCommand(program2) {
|
|
|
2609
2685
|
log.blank();
|
|
2610
2686
|
log.warn("Conflicting configs detected:");
|
|
2611
2687
|
for (const p of env.allConfigPaths) {
|
|
2612
|
-
log.print(` ${import_chalk3.default.yellow("\u2192")} ${import_chalk3.default.white(
|
|
2688
|
+
log.print(` ${import_chalk3.default.yellow("\u2192")} ${import_chalk3.default.white(import_path4.default.relative(cwd, p))}`);
|
|
2613
2689
|
}
|
|
2614
2690
|
log.print(` ${import_chalk3.default.gray("Multiple config formats found \u2014 this can cause unpredictable behavior.")}`);
|
|
2615
2691
|
}
|
|
@@ -2637,7 +2713,7 @@ function registerInitCommand(program2) {
|
|
|
2637
2713
|
try {
|
|
2638
2714
|
const { createRequire } = await import("module");
|
|
2639
2715
|
const { pathToFileURL } = await import("url");
|
|
2640
|
-
const req = createRequire(
|
|
2716
|
+
const req = createRequire(import_path4.default.join(cwd, "_probe.js"));
|
|
2641
2717
|
const resolvedPath = req.resolve("eslint-plugin-ai-guard");
|
|
2642
2718
|
const aiGuard = await import(pathToFileURL(resolvedPath).href);
|
|
2643
2719
|
const plugin2 = aiGuard.default || aiGuard;
|
|
@@ -2655,7 +2731,7 @@ function registerInitCommand(program2) {
|
|
|
2655
2731
|
if (eslintNeedsFlat && existingIsLegacy) {
|
|
2656
2732
|
log.section("Config Migration Required");
|
|
2657
2733
|
log.warn(`ESLint v${env.eslintMajor} requires flat config, but a legacy config was found:`);
|
|
2658
|
-
log.print(` ${import_chalk3.default.white(
|
|
2734
|
+
log.print(` ${import_chalk3.default.white(import_path4.default.relative(cwd, env.configPath))}`);
|
|
2659
2735
|
log.blank();
|
|
2660
2736
|
log.print(` ${import_chalk3.default.bold("ai-guard will create a new flat config.")}`);
|
|
2661
2737
|
log.blank();
|
|
@@ -2667,7 +2743,7 @@ function registerInitCommand(program2) {
|
|
|
2667
2743
|
const raw = readConfig(env.configPath);
|
|
2668
2744
|
const { content: fixed, changed } = removeNukeIgnore(raw);
|
|
2669
2745
|
if (changed) {
|
|
2670
|
-
log.warn(`Removed "**/*" ignore pattern from ${
|
|
2746
|
+
log.warn(`Removed "**/*" ignore pattern from ${import_path4.default.relative(cwd, env.configPath)}`);
|
|
2671
2747
|
if (!isDryRun) {
|
|
2672
2748
|
backupConfig(env.configPath);
|
|
2673
2749
|
writeConfig(env.configPath, fixed);
|
|
@@ -2679,7 +2755,7 @@ function registerInitCommand(program2) {
|
|
|
2679
2755
|
}
|
|
2680
2756
|
if (env.configType === "none" || eslintNeedsFlat && existingIsLegacy) {
|
|
2681
2757
|
const targetName = useFlat ? "eslint.config.mjs" : ".eslintrc.js";
|
|
2682
|
-
finalConfigPath =
|
|
2758
|
+
finalConfigPath = import_path4.default.join(cwd, targetName);
|
|
2683
2759
|
const content2 = useFlat ? generateFlatConfig(preset) : generateLegacyConfig(preset);
|
|
2684
2760
|
if (isDryRun) {
|
|
2685
2761
|
log.print(` ${import_chalk3.default.gray(`[dry-run] would create: ${targetName}`)}`);
|
|
@@ -2698,19 +2774,25 @@ function registerInitCommand(program2) {
|
|
|
2698
2774
|
configWritten = true;
|
|
2699
2775
|
}
|
|
2700
2776
|
} else if (useFlat && existingIsFlat) {
|
|
2777
|
+
const { isInvalidAiGuardConfig: isInvalidAiGuardConfig2 } = await Promise.resolve().then(() => (init_config_manager(), config_manager_exports));
|
|
2701
2778
|
const existing = readConfig(env.configPath);
|
|
2779
|
+
const isInvalid = isInvalidAiGuardConfig2(existing);
|
|
2702
2780
|
const patched = patchFlatConfig(existing, preset);
|
|
2703
|
-
if (patched === existing) {
|
|
2781
|
+
if (patched === existing && !isInvalid) {
|
|
2704
2782
|
log.warn("ai-guard is already present in your config \u2014 no changes made");
|
|
2705
2783
|
finalConfigPath = env.configPath;
|
|
2706
2784
|
} else if (isDryRun) {
|
|
2707
2785
|
finalConfigPath = env.configPath;
|
|
2708
|
-
log.print(` ${import_chalk3.default.gray(`[dry-run] would patch: ${
|
|
2786
|
+
log.print(` ${import_chalk3.default.gray(`[dry-run] would patch: ${import_path4.default.relative(cwd, env.configPath)}`)}`);
|
|
2709
2787
|
} else {
|
|
2710
2788
|
const bak = backupConfig(env.configPath);
|
|
2711
|
-
log.info(`Backed up \u2192 ${import_chalk3.default.gray(
|
|
2789
|
+
log.info(`Backed up \u2192 ${import_chalk3.default.gray(import_path4.default.relative(cwd, bak))}`);
|
|
2712
2790
|
writeConfig(env.configPath, patched);
|
|
2713
|
-
|
|
2791
|
+
if (isInvalid) {
|
|
2792
|
+
log.success(`Detected invalid ai-guard config \u2014 repairing ${import_chalk3.default.white(import_path4.default.relative(cwd, env.configPath))}`);
|
|
2793
|
+
} else {
|
|
2794
|
+
log.success(`Patched ${import_chalk3.default.white(import_path4.default.relative(cwd, env.configPath))}`);
|
|
2795
|
+
}
|
|
2714
2796
|
finalConfigPath = env.configPath;
|
|
2715
2797
|
configWritten = true;
|
|
2716
2798
|
}
|
|
@@ -2722,12 +2804,12 @@ function registerInitCommand(program2) {
|
|
|
2722
2804
|
finalConfigPath = env.configPath;
|
|
2723
2805
|
} else if (isDryRun) {
|
|
2724
2806
|
finalConfigPath = env.configPath;
|
|
2725
|
-
log.print(` ${import_chalk3.default.gray(`[dry-run] would patch: ${
|
|
2807
|
+
log.print(` ${import_chalk3.default.gray(`[dry-run] would patch: ${import_path4.default.relative(cwd, env.configPath)}`)}`);
|
|
2726
2808
|
} else {
|
|
2727
2809
|
const bak = backupConfig(env.configPath);
|
|
2728
|
-
log.info(`Backed up \u2192 ${import_chalk3.default.gray(
|
|
2810
|
+
log.info(`Backed up \u2192 ${import_chalk3.default.gray(import_path4.default.relative(cwd, bak))}`);
|
|
2729
2811
|
writeConfig(env.configPath, patched);
|
|
2730
|
-
log.success(`Patched ${import_chalk3.default.white(
|
|
2812
|
+
log.success(`Patched ${import_chalk3.default.white(import_path4.default.relative(cwd, env.configPath))}`);
|
|
2731
2813
|
finalConfigPath = env.configPath;
|
|
2732
2814
|
configWritten = true;
|
|
2733
2815
|
}
|
|
@@ -2745,7 +2827,7 @@ function registerInitCommand(program2) {
|
|
|
2745
2827
|
}
|
|
2746
2828
|
} else {
|
|
2747
2829
|
cleanedUp = true;
|
|
2748
|
-
log.print(` ${import_chalk3.default.gray(`[dry-run] would rename ${
|
|
2830
|
+
log.print(` ${import_chalk3.default.gray(`[dry-run] would rename ${import_path4.default.relative(cwd, p)} to ${import_path4.default.basename(p)}.bak`)}`);
|
|
2749
2831
|
}
|
|
2750
2832
|
}
|
|
2751
2833
|
}
|
|
@@ -2764,7 +2846,7 @@ function registerInitCommand(program2) {
|
|
|
2764
2846
|
log.blank();
|
|
2765
2847
|
log.section("Validation");
|
|
2766
2848
|
if (!import_fs3.default.existsSync(finalConfigPath)) {
|
|
2767
|
-
log.error(`Config file not found after write: ${
|
|
2849
|
+
log.error(`Config file not found after write: ${import_path4.default.relative(cwd, finalConfigPath)}`);
|
|
2768
2850
|
log.blank();
|
|
2769
2851
|
log.print(` ${import_chalk3.default.bold("Problem:")} File write may have failed.`);
|
|
2770
2852
|
log.print(` ${import_chalk3.default.bold("Fix:")} Check disk space and file permissions, then re-run.`);
|
|
@@ -2780,7 +2862,7 @@ function registerInitCommand(program2) {
|
|
|
2780
2862
|
log.print(` ${import_chalk3.default.red("\u2716")} ${e}`);
|
|
2781
2863
|
}
|
|
2782
2864
|
} else {
|
|
2783
|
-
log.success(`Config structure valid: ${import_chalk3.default.white(
|
|
2865
|
+
log.success(`Config structure valid: ${import_chalk3.default.white(import_path4.default.relative(cwd, finalConfigPath))}`);
|
|
2784
2866
|
}
|
|
2785
2867
|
log.info("Verifying ESLint can load the config\u2026");
|
|
2786
2868
|
const loadError = await verifyConfigLoads(finalConfigPath, cwd);
|
|
@@ -2804,7 +2886,7 @@ function registerInitCommand(program2) {
|
|
|
2804
2886
|
}
|
|
2805
2887
|
log.blank();
|
|
2806
2888
|
log.print(` ${import_chalk3.default.bold("Fix:")}`);
|
|
2807
|
-
log.print(` 1. Check the syntax in ${import_chalk3.default.cyan(
|
|
2889
|
+
log.print(` 1. Check the syntax in ${import_chalk3.default.cyan(import_path4.default.relative(cwd, finalConfigPath))}`);
|
|
2808
2890
|
log.print(` 2. Make sure ${import_chalk3.default.cyan("eslint-plugin-ai-guard")} is installed`);
|
|
2809
2891
|
log.print(` 3. Run ${import_chalk3.default.cyan("ai-guard doctor")} for full diagnostics`);
|
|
2810
2892
|
log.blank();
|
|
@@ -2826,7 +2908,7 @@ function registerInitCommand(program2) {
|
|
|
2826
2908
|
if (loadError === null && !lingeringConflicts) {
|
|
2827
2909
|
log.print(` ${import_chalk3.default.green("\u2714")} ${import_chalk3.default.bold.green("Configuration validated successfully")}`);
|
|
2828
2910
|
}
|
|
2829
|
-
log.print(` ${import_chalk3.default.green("\u2714")} ${import_chalk3.default.bold("ESLint config:")} ${import_chalk3.default.cyan(
|
|
2911
|
+
log.print(` ${import_chalk3.default.green("\u2714")} ${import_chalk3.default.bold("ESLint config:")} ${import_chalk3.default.cyan(import_path4.default.relative(cwd, finalConfigPath))}`);
|
|
2830
2912
|
log.print(` ${import_chalk3.default.green("\u2714")} ${import_chalk3.default.bold("Mode:")} ${import_chalk3.default.cyan(useFlat ? `Flat config (ESLint v${env.eslintMajor ?? 9})` : `Legacy config (ESLint v${env.eslintMajor ?? 8})`)}`);
|
|
2831
2913
|
log.print(` ${import_chalk3.default.green("\u2714")} ${import_chalk3.default.bold("Preset:")} ${import_chalk3.default.cyan(preset)}`);
|
|
2832
2914
|
log.blank();
|
|
@@ -2840,12 +2922,13 @@ function registerInitCommand(program2) {
|
|
|
2840
2922
|
|
|
2841
2923
|
// cli/commands/doctor.ts
|
|
2842
2924
|
var import_chalk4 = __toESM(require("chalk"));
|
|
2843
|
-
var
|
|
2925
|
+
var import_path5 = __toESM(require("path"));
|
|
2926
|
+
init_config_manager();
|
|
2844
2927
|
async function probeConfigLoad(configPath, cwd) {
|
|
2845
2928
|
try {
|
|
2846
2929
|
const { ESLint } = await import("eslint");
|
|
2847
2930
|
const eslint = new ESLint({ cwd, overrideConfigFile: configPath });
|
|
2848
|
-
await eslint.lintText("", { filePath:
|
|
2931
|
+
await eslint.lintText("", { filePath: import_path5.default.join(cwd, "_probe_.js") });
|
|
2849
2932
|
return { ok: true, error: null };
|
|
2850
2933
|
} catch (err) {
|
|
2851
2934
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -2880,7 +2963,7 @@ function registerDoctorCommand(program2) {
|
|
|
2880
2963
|
checks.push({
|
|
2881
2964
|
label: "ESLint config present",
|
|
2882
2965
|
pass: hasConfig,
|
|
2883
|
-
detail: hasConfig ? `${
|
|
2966
|
+
detail: hasConfig ? `${import_path5.default.relative(cwd, env.configPath ?? "")} (${env.configType})` : "No eslint.config.* or .eslintrc.* found",
|
|
2884
2967
|
fix: hasConfig ? void 0 : "ai-guard init",
|
|
2885
2968
|
note: hasConfig ? void 0 : "This will generate the correct config format for your ESLint version"
|
|
2886
2969
|
});
|
|
@@ -2899,25 +2982,28 @@ function registerDoctorCommand(program2) {
|
|
|
2899
2982
|
}
|
|
2900
2983
|
if (hasConfig && env.configPath) {
|
|
2901
2984
|
let pluginWired = false;
|
|
2985
|
+
let isInvalidConfig = false;
|
|
2902
2986
|
let readError = null;
|
|
2903
2987
|
try {
|
|
2988
|
+
const { isInvalidAiGuardConfig: isInvalidAiGuardConfig2 } = await Promise.resolve().then(() => (init_config_manager(), config_manager_exports));
|
|
2904
2989
|
const content = readConfig(env.configPath);
|
|
2905
2990
|
pluginWired = content.includes("ai-guard") || content.includes("eslint-plugin-ai-guard");
|
|
2991
|
+
isInvalidConfig = isInvalidAiGuardConfig2(content);
|
|
2906
2992
|
} catch (err) {
|
|
2907
2993
|
readError = err instanceof Error ? err.message : String(err);
|
|
2908
2994
|
}
|
|
2909
2995
|
checks.push({
|
|
2910
2996
|
label: "Plugin wired in config",
|
|
2911
|
-
pass: pluginWired,
|
|
2912
|
-
detail: readError ? `Could not read config: ${readError}` : pluginWired ? "eslint-plugin-ai-guard referenced in config" : `Config exists but ai-guard plugin not found in ${
|
|
2913
|
-
fix: pluginWired
|
|
2997
|
+
pass: pluginWired && !isInvalidConfig,
|
|
2998
|
+
detail: readError ? `Could not read config: ${readError}` : isInvalidConfig ? "Invalid ai-guard config detected (wrong export usage)" : pluginWired ? "eslint-plugin-ai-guard referenced in config" : `Config exists but ai-guard plugin not found in ${import_path5.default.relative(cwd, env.configPath)}`,
|
|
2999
|
+
fix: isInvalidConfig || !pluginWired && !readError ? "ai-guard init (will patch/repair your existing config)" : void 0
|
|
2914
3000
|
});
|
|
2915
3001
|
}
|
|
2916
3002
|
checks.push({
|
|
2917
3003
|
label: "No conflicting config files",
|
|
2918
3004
|
pass: !env.hasConflictingConfigs,
|
|
2919
3005
|
detail: env.hasConflictingConfigs ? `Conflicting config detected:
|
|
2920
|
-
${env.allConfigPaths.map((p) => ` ${
|
|
3006
|
+
${env.allConfigPaths.map((p) => ` ${import_path5.default.relative(cwd, p)}`).join("\n")}` : "Only one config format detected",
|
|
2921
3007
|
fix: env.hasConflictingConfigs ? "Remove or backup legacy config" : void 0,
|
|
2922
3008
|
note: env.hasConflictingConfigs ? "ESLint v9 silently ignores .eslintrc.* when a flat config exists. This can cause confusion." : void 0
|
|
2923
3009
|
});
|
|
@@ -2944,7 +3030,7 @@ ${env.allConfigPaths.map((p) => ` ${import_path4.default.relative(cwd, p)}
|
|
|
2944
3030
|
label: "ESLint config loads without errors",
|
|
2945
3031
|
pass: probe.ok,
|
|
2946
3032
|
detail: probe.ok ? "ESLint loaded config successfully" : probe.error ?? "Unknown error",
|
|
2947
|
-
fix: probe.ok ? void 0 : `Check syntax in ${
|
|
3033
|
+
fix: probe.ok ? void 0 : `Check syntax in ${import_path5.default.relative(cwd, env.configPath)}`,
|
|
2948
3034
|
note: probe.ok ? void 0 : "Run: ai-guard init --dry-run to preview a fresh config"
|
|
2949
3035
|
});
|
|
2950
3036
|
}
|
|
@@ -3007,7 +3093,8 @@ ${env.allConfigPaths.map((p) => ` ${import_path4.default.relative(cwd, p)}
|
|
|
3007
3093
|
// cli/commands/preset.ts
|
|
3008
3094
|
var import_prompts = require("@inquirer/prompts");
|
|
3009
3095
|
var import_chalk5 = __toESM(require("chalk"));
|
|
3010
|
-
|
|
3096
|
+
init_config_manager();
|
|
3097
|
+
var import_path6 = __toESM(require("path"));
|
|
3011
3098
|
function registerPresetCommand(program2) {
|
|
3012
3099
|
program2.command("preset").description("Interactively select and apply an ai-guard preset to your ESLint config").action(async () => {
|
|
3013
3100
|
const cwd = process.cwd();
|
|
@@ -3035,21 +3122,21 @@ function registerPresetCommand(program2) {
|
|
|
3035
3122
|
const env = detect(cwd);
|
|
3036
3123
|
const useFlat = env.eslintMajor !== null && env.eslintMajor >= 9 || isFlat(env.configType);
|
|
3037
3124
|
if (env.configType === "none") {
|
|
3038
|
-
const configPath = useFlat ?
|
|
3125
|
+
const configPath = useFlat ? import_path6.default.join(cwd, "eslint.config.mjs") : import_path6.default.join(cwd, ".eslintrc.js");
|
|
3039
3126
|
const content = useFlat ? generateFlatConfig(preset) : generateLegacyConfig(preset);
|
|
3040
3127
|
writeConfig(configPath, content);
|
|
3041
|
-
log.success(`Created ${import_chalk5.default.white(
|
|
3128
|
+
log.success(`Created ${import_chalk5.default.white(import_path6.default.relative(cwd, configPath))} with ${import_chalk5.default.cyan(preset)} preset`);
|
|
3042
3129
|
} else {
|
|
3043
3130
|
const configPath = env.configPath;
|
|
3044
3131
|
const backupPath = backupConfig(configPath);
|
|
3045
|
-
log.info(`Backed up \u2192 ${import_chalk5.default.gray(
|
|
3132
|
+
log.info(`Backed up \u2192 ${import_chalk5.default.gray(import_path6.default.relative(cwd, backupPath))}`);
|
|
3046
3133
|
const existing = readConfig(configPath);
|
|
3047
3134
|
const patched = isFlat(env.configType) ? patchFlatConfig(existing, preset) : patchLegacyConfig(existing, preset);
|
|
3048
3135
|
if (patched === existing) {
|
|
3049
3136
|
log.warn("Config already contains ai-guard. Edit manually to change preset.");
|
|
3050
3137
|
} else {
|
|
3051
3138
|
writeConfig(configPath, patched);
|
|
3052
|
-
log.success(`Patched ${import_chalk5.default.white(
|
|
3139
|
+
log.success(`Patched ${import_chalk5.default.white(import_path6.default.relative(cwd, configPath))}`);
|
|
3053
3140
|
}
|
|
3054
3141
|
}
|
|
3055
3142
|
log.blank();
|
|
@@ -3088,7 +3175,8 @@ function registerPresetCommand(program2) {
|
|
|
3088
3175
|
|
|
3089
3176
|
// cli/commands/ignore.ts
|
|
3090
3177
|
var import_chalk6 = __toESM(require("chalk"));
|
|
3091
|
-
|
|
3178
|
+
init_config_manager();
|
|
3179
|
+
var import_path7 = __toESM(require("path"));
|
|
3092
3180
|
var DEFAULT_IGNORES = [
|
|
3093
3181
|
".next/",
|
|
3094
3182
|
"dist/",
|
|
@@ -3110,21 +3198,21 @@ function registerIgnoreCommand(program2) {
|
|
|
3110
3198
|
const env = detect(cwd);
|
|
3111
3199
|
if (env.configType === "none") {
|
|
3112
3200
|
const useFlat = env.eslintMajor !== null && env.eslintMajor >= 9;
|
|
3113
|
-
const configPath = useFlat ?
|
|
3201
|
+
const configPath = useFlat ? import_path7.default.join(cwd, "eslint.config.mjs") : import_path7.default.join(cwd, ".eslintrc.js");
|
|
3114
3202
|
const content = useFlat ? generateFlatConfig("recommended") : generateLegacyConfig("recommended");
|
|
3115
3203
|
writeConfig(configPath, content);
|
|
3116
|
-
log.success(`No config found \u2014 generated ${import_chalk6.default.white(
|
|
3204
|
+
log.success(`No config found \u2014 generated ${import_chalk6.default.white(import_path7.default.relative(cwd, configPath))} with ignores included`);
|
|
3117
3205
|
} else {
|
|
3118
3206
|
const configPath = env.configPath;
|
|
3119
3207
|
const backupPath = backupConfig(configPath);
|
|
3120
|
-
log.info(`Backed up \u2192 ${import_chalk6.default.gray(
|
|
3208
|
+
log.info(`Backed up \u2192 ${import_chalk6.default.gray(import_path7.default.relative(cwd, backupPath))}`);
|
|
3121
3209
|
const existing = readConfig(configPath);
|
|
3122
3210
|
const patched = isFlat(env.configType) ? addIgnoresToFlatConfig(existing) : addIgnoresToLegacyConfig(existing);
|
|
3123
3211
|
if (patched === existing) {
|
|
3124
3212
|
log.warn("Ignore patterns already present in config \u2014 no changes made.");
|
|
3125
3213
|
} else {
|
|
3126
3214
|
writeConfig(configPath, patched);
|
|
3127
|
-
log.success(`Patched ${import_chalk6.default.white(
|
|
3215
|
+
log.success(`Patched ${import_chalk6.default.white(import_path7.default.relative(cwd, configPath))} with ignore patterns`);
|
|
3128
3216
|
}
|
|
3129
3217
|
}
|
|
3130
3218
|
log.blank();
|
|
@@ -3136,7 +3224,7 @@ function registerIgnoreCommand(program2) {
|
|
|
3136
3224
|
|
|
3137
3225
|
// cli/commands/baseline.ts
|
|
3138
3226
|
var import_fs4 = __toESM(require("fs"));
|
|
3139
|
-
var
|
|
3227
|
+
var import_path8 = __toESM(require("path"));
|
|
3140
3228
|
var import_chalk7 = __toESM(require("chalk"));
|
|
3141
3229
|
var import_ora2 = __toESM(require("ora"));
|
|
3142
3230
|
var BASELINE_FILE = ".ai-guard-baseline.json";
|
|
@@ -3156,12 +3244,12 @@ function saveBaseline(result, preset, cwd) {
|
|
|
3156
3244
|
totalIssues: result.totalIssues,
|
|
3157
3245
|
entries
|
|
3158
3246
|
};
|
|
3159
|
-
const baselinePath =
|
|
3247
|
+
const baselinePath = import_path8.default.join(cwd, BASELINE_FILE);
|
|
3160
3248
|
import_fs4.default.writeFileSync(baselinePath, JSON.stringify(baseline, null, 2), "utf-8");
|
|
3161
3249
|
return baselinePath;
|
|
3162
3250
|
}
|
|
3163
3251
|
function loadBaseline(cwd) {
|
|
3164
|
-
const baselinePath =
|
|
3252
|
+
const baselinePath = import_path8.default.join(cwd, BASELINE_FILE);
|
|
3165
3253
|
if (!import_fs4.default.existsSync(baselinePath)) return null;
|
|
3166
3254
|
try {
|
|
3167
3255
|
const raw = import_fs4.default.readFileSync(baselinePath, "utf-8");
|
|
@@ -3238,7 +3326,7 @@ function registerBaselineCommand(program2) {
|
|
|
3238
3326
|
}
|
|
3239
3327
|
const baselinePath = saveBaseline(result, preset, cwd);
|
|
3240
3328
|
log.success(
|
|
3241
|
-
`Baseline saved \u2192 ${import_chalk7.default.white(
|
|
3329
|
+
`Baseline saved \u2192 ${import_chalk7.default.white(import_path8.default.relative(cwd, baselinePath))}`
|
|
3242
3330
|
);
|
|
3243
3331
|
log.info(` ${result.totalIssues} issues recorded (${result.totalErrors} errors, ${result.totalWarnings} warnings)`);
|
|
3244
3332
|
log.info(` Preset: ${import_chalk7.default.cyan(preset)}`);
|