@alint-js/cli 0.0.6 → 0.0.7
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/bin/index.mjs
CHANGED
|
@@ -6,18 +6,20 @@ import { AlintRunError, hasDiscoveryFilePatterns, matchesDiscoveryFile, normaliz
|
|
|
6
6
|
import { relative, resolve } from "pathe";
|
|
7
7
|
import { getBorderCharacters, table } from "table";
|
|
8
8
|
import { errorMessageFrom } from "@moeru/std/error";
|
|
9
|
-
import { readdir, stat } from "node:fs/promises";
|
|
9
|
+
import { readFile, readdir, stat } from "node:fs/promises";
|
|
10
10
|
import c, { createColors } from "tinyrainbow";
|
|
11
11
|
import cliSpinners from "cli-spinners";
|
|
12
12
|
import { relative as relative$1 } from "node:path";
|
|
13
13
|
import Gitignore from "gitignore-fs";
|
|
14
14
|
import { minimatch } from "minimatch";
|
|
15
|
+
import { errorMessageFrom as errorMessageFrom$1 } from "@moeru/std";
|
|
15
16
|
//#region src/cli/commands/command.ts
|
|
16
17
|
function defineCommand(node) {
|
|
17
18
|
return node;
|
|
18
19
|
}
|
|
19
|
-
function registerCommandTree(cli, nodes, context, setPendingResult) {
|
|
20
|
+
function registerCommandTree(cli, nodes, context, setPendingResult, help = {}) {
|
|
20
21
|
for (const node of nodes) registerRootCommand(cli, node, context, setPendingResult);
|
|
22
|
+
cli.globalCommand.helpCallback = (sections) => formatCommandHelp(sections, nodes, cli.rawArgs, help);
|
|
21
23
|
}
|
|
22
24
|
function collectCommandOptions(node) {
|
|
23
25
|
const options = /* @__PURE__ */ new Map();
|
|
@@ -36,9 +38,91 @@ function dispatchCommand(context, node, args, options, path) {
|
|
|
36
38
|
if (!node.action) return Promise.resolve(reportUnknownCommand(context, path, args));
|
|
37
39
|
return Promise.resolve(node.action(context, ...parseCommandArguments(node, args), options));
|
|
38
40
|
}
|
|
41
|
+
function formatChildCommandHelp(parentPath, child) {
|
|
42
|
+
const parts = [...parentPath, child.name];
|
|
43
|
+
if (!child.children && child.arguments) parts.push(child.arguments);
|
|
44
|
+
return {
|
|
45
|
+
description: child.description,
|
|
46
|
+
pattern: parts.join(" ")
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function formatCommandHelp(sections, nodes, argv, rootHelp) {
|
|
50
|
+
const helpPath = resolveHelpPath(nodes, argv);
|
|
51
|
+
const node = helpPath.at(-1)?.node;
|
|
52
|
+
if (!node) return insertExamplesSection(insertHelpSection(sections, rootHelp), rootHelp);
|
|
53
|
+
const path = helpPath.map((item) => item.node.name);
|
|
54
|
+
const normalizedSections = rewriteUsageSection(insertExamplesSection(insertHelpSection(sections.filter((section) => section.title !== "Options"), node), node), path, node);
|
|
55
|
+
if (!node.children) {
|
|
56
|
+
const optionSection = formatOptionsSection(node.options ?? []);
|
|
57
|
+
return optionSection ? [...normalizedSections, optionSection] : normalizedSections;
|
|
58
|
+
}
|
|
59
|
+
const commands = (node.children ?? []).map((child) => formatChildCommandHelp(path, child));
|
|
60
|
+
const longestCommand = Math.max(...commands.map((command) => command.pattern.length));
|
|
61
|
+
const commandSection = {
|
|
62
|
+
body: commands.map((command) => ` ${command.pattern.padEnd(longestCommand)} ${command.description}`).join("\n"),
|
|
63
|
+
title: "Commands"
|
|
64
|
+
};
|
|
65
|
+
const usageIndex = normalizedSections.findIndex((section) => section.title === "Usage");
|
|
66
|
+
if (usageIndex === -1) return [commandSection, ...normalizedSections];
|
|
67
|
+
return [
|
|
68
|
+
...normalizedSections.slice(0, usageIndex + 1),
|
|
69
|
+
commandSection,
|
|
70
|
+
...normalizedSections.slice(usageIndex + 1)
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
function formatExamples(examples) {
|
|
74
|
+
return examples.map((example) => example.split("\n").map((line) => ` ${line}`).join("\n")).join("\n\n");
|
|
75
|
+
}
|
|
76
|
+
function formatOptionDescription(option) {
|
|
77
|
+
if (option.config?.default === void 0) return option.description;
|
|
78
|
+
return `${option.description} (default: ${option.config.default})`;
|
|
79
|
+
}
|
|
80
|
+
function formatOptionsSection(options) {
|
|
81
|
+
if (options.length === 0) return;
|
|
82
|
+
const rows = options.map((option) => ({
|
|
83
|
+
description: formatOptionDescription(option),
|
|
84
|
+
flags: option.flags
|
|
85
|
+
}));
|
|
86
|
+
const longestFlag = Math.max(...rows.map((row) => row.flags.length));
|
|
87
|
+
return {
|
|
88
|
+
body: rows.map((row) => ` ${row.flags.padEnd(longestFlag)} ${row.description}`).join("\n"),
|
|
89
|
+
title: "Options"
|
|
90
|
+
};
|
|
91
|
+
}
|
|
39
92
|
function formatUnknownCommand(path, args) {
|
|
40
93
|
return [...path, ...args].filter(Boolean).join(" ");
|
|
41
94
|
}
|
|
95
|
+
function formatUsagePattern(path, node) {
|
|
96
|
+
const parts = [...path];
|
|
97
|
+
if (!node.children && node.arguments) parts.push(node.arguments);
|
|
98
|
+
return parts.join(" ");
|
|
99
|
+
}
|
|
100
|
+
function insertExamplesSection(sections, node) {
|
|
101
|
+
if (!node.examples?.length) return sections;
|
|
102
|
+
const usageIndex = sections.findIndex((section) => section.title === "Usage");
|
|
103
|
+
const examplesSection = {
|
|
104
|
+
body: formatExamples(node.examples),
|
|
105
|
+
title: "Examples"
|
|
106
|
+
};
|
|
107
|
+
if (usageIndex === -1) return [...sections, examplesSection];
|
|
108
|
+
return [
|
|
109
|
+
...sections.slice(0, usageIndex),
|
|
110
|
+
examplesSection,
|
|
111
|
+
...sections.slice(usageIndex)
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
function insertHelpSection(sections, node) {
|
|
115
|
+
const help = node.help ?? node.description;
|
|
116
|
+
if (!help) return sections;
|
|
117
|
+
const usageIndex = sections.findIndex((section) => section.title === "Usage");
|
|
118
|
+
const helpSection = { body: help };
|
|
119
|
+
if (usageIndex === -1) return [...sections, helpSection];
|
|
120
|
+
return [
|
|
121
|
+
...sections.slice(0, usageIndex),
|
|
122
|
+
helpSection,
|
|
123
|
+
...sections.slice(usageIndex)
|
|
124
|
+
];
|
|
125
|
+
}
|
|
42
126
|
function parseCommandArguments(node, args) {
|
|
43
127
|
if (!node.arguments) return [];
|
|
44
128
|
const parts = node.arguments.split(/\s+/u).filter(Boolean);
|
|
@@ -67,12 +151,56 @@ function registerRootCommand(cli, node, context, setPendingResult) {
|
|
|
67
151
|
});
|
|
68
152
|
}
|
|
69
153
|
function reportUnknownCommand(context, path, args) {
|
|
70
|
-
context.io.stderr.write(`unknown
|
|
154
|
+
context.io.stderr.write(`unknown command: ${formatUnknownCommand(path, args)}\n`);
|
|
71
155
|
return 2;
|
|
72
156
|
}
|
|
157
|
+
function resolveHelpPath(nodes, argv) {
|
|
158
|
+
const path = [];
|
|
159
|
+
let currentNodes = nodes;
|
|
160
|
+
let skipNext = false;
|
|
161
|
+
for (const arg of argv.slice(2)) {
|
|
162
|
+
if (skipNext) {
|
|
163
|
+
skipNext = false;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (arg.startsWith("-")) {
|
|
167
|
+
skipNext = shouldSkipOptionValue(arg);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const node = currentNodes.find((item) => item.name === arg || item.alias?.includes(arg));
|
|
171
|
+
if (!node) break;
|
|
172
|
+
path.push({ node });
|
|
173
|
+
currentNodes = node.children ?? [];
|
|
174
|
+
}
|
|
175
|
+
return path;
|
|
176
|
+
}
|
|
177
|
+
function rewriteUsageSection(sections, path, node) {
|
|
178
|
+
return sections.map((section) => section.title === "Usage" ? {
|
|
179
|
+
...section,
|
|
180
|
+
body: ` $ alint ${formatUsagePattern(path, node)}`
|
|
181
|
+
} : section);
|
|
182
|
+
}
|
|
183
|
+
function shouldSkipOptionValue(arg) {
|
|
184
|
+
if (arg.includes("=")) return false;
|
|
185
|
+
return [
|
|
186
|
+
"--cache-location",
|
|
187
|
+
"--config",
|
|
188
|
+
"--file-concurrency",
|
|
189
|
+
"--format",
|
|
190
|
+
"--model",
|
|
191
|
+
"--provider-endpoint",
|
|
192
|
+
"--provider-header",
|
|
193
|
+
"--provider-id",
|
|
194
|
+
"--provider-model",
|
|
195
|
+
"--rule-concurrency",
|
|
196
|
+
"--timeout-ms",
|
|
197
|
+
"-f",
|
|
198
|
+
"-l"
|
|
199
|
+
].includes(arg);
|
|
200
|
+
}
|
|
73
201
|
//#endregion
|
|
74
202
|
//#region src/cli/commands/config/inspect.ts
|
|
75
|
-
const inspect$
|
|
203
|
+
const inspect$2 = defineCommand({
|
|
76
204
|
action: (context, file, options) => runConfigInspectCommand(file, options.config, context.io),
|
|
77
205
|
arguments: "<file>",
|
|
78
206
|
description: "Inspect resolved config for a file",
|
|
@@ -243,6 +371,8 @@ const models = defineCommand({
|
|
|
243
371
|
}
|
|
244
372
|
},
|
|
245
373
|
description: "Probe OpenAI-compatible models",
|
|
374
|
+
examples: [["# Probe a provider endpoint and print available model ids", "alint config models probe --endpoint https://openrouter.ai/api/v1"].join("\n"), ["# Probe an endpoint that requires an authorization header", "alint config models probe --endpoint https://api.example.com/v1 --provider-header \"Authorization=Bearer $TOKEN\""].join("\n")],
|
|
375
|
+
help: ["Probe an OpenAI-compatible models endpoint before saving it in setup config.", "The command calls the provider models endpoint using the supplied endpoint and optional headers, then prints the model ids returned by that provider."].join("\n\n"),
|
|
246
376
|
name: "probe",
|
|
247
377
|
options: [{
|
|
248
378
|
description: "Provider endpoint",
|
|
@@ -269,6 +399,7 @@ const models = defineCommand({
|
|
|
269
399
|
})
|
|
270
400
|
],
|
|
271
401
|
description: "Manage configured models",
|
|
402
|
+
help: ["Inspect, list, and probe model entries from alint setup configuration.", "Model entries describe the provider/model ids alint can use for model-backed rules. Probe endpoints before saving them when you want to verify what model ids a provider exposes."].join("\n\n"),
|
|
272
403
|
name: "models"
|
|
273
404
|
});
|
|
274
405
|
//#endregion
|
|
@@ -313,7 +444,7 @@ const probe = defineCommand({
|
|
|
313
444
|
//#region src/cli/commands/config/config.ts
|
|
314
445
|
const config = defineCommand({
|
|
315
446
|
children: [
|
|
316
|
-
inspect$
|
|
447
|
+
inspect$2,
|
|
317
448
|
models,
|
|
318
449
|
defineCommand({
|
|
319
450
|
children: [
|
|
@@ -339,6 +470,26 @@ const config = defineCommand({
|
|
|
339
470
|
})
|
|
340
471
|
],
|
|
341
472
|
description: "Manage alint configuration",
|
|
473
|
+
examples: [
|
|
474
|
+
["# Show the effective alint config for a file", "alint config inspect src/index.ts"].join("\n"),
|
|
475
|
+
["# Inspect a file using a custom config path", "alint --config alint.config.ts config inspect src/index.ts"].join("\n"),
|
|
476
|
+
[
|
|
477
|
+
"# List configured providers and models",
|
|
478
|
+
"alint config providers list",
|
|
479
|
+
"alint config models list"
|
|
480
|
+
].join("\n"),
|
|
481
|
+
[
|
|
482
|
+
"# Show one configured provider or model by id",
|
|
483
|
+
"alint config providers show openrouter",
|
|
484
|
+
"alint config models show z-ai/glm-5.2"
|
|
485
|
+
].join("\n"),
|
|
486
|
+
[
|
|
487
|
+
"# Probe an OpenAI-compatible endpoint before saving it",
|
|
488
|
+
"alint config providers probe --endpoint https://openrouter.ai/api/v1",
|
|
489
|
+
"alint config models probe --endpoint https://openrouter.ai/api/v1"
|
|
490
|
+
].join("\n")
|
|
491
|
+
],
|
|
492
|
+
help: ["Inspect and update alint setup/configuration state.", "Use these commands to understand the effective config for a file, inspect saved provider/model setup, and probe OpenAI-compatible endpoints before using them in model-backed rules."].join("\n\n"),
|
|
342
493
|
name: "config"
|
|
343
494
|
});
|
|
344
495
|
//#endregion
|
|
@@ -900,7 +1051,10 @@ function resolveRunnerCacheConfig(setupCache, configCache, options) {
|
|
|
900
1051
|
//#endregion
|
|
901
1052
|
//#region src/cli/commands/lint/index.ts
|
|
902
1053
|
const lint = defineCommand({
|
|
903
|
-
action: (context, files = [], options) => runLintCommand(files,
|
|
1054
|
+
action: (context, files = [], options) => runLintCommand(files, {
|
|
1055
|
+
...options,
|
|
1056
|
+
outputLanguage: options.lang ?? context.globalOptions.outputLanguage
|
|
1057
|
+
}, context.io, context.interceptConsoleOutput),
|
|
904
1058
|
alias: ["!"],
|
|
905
1059
|
arguments: "[...files]",
|
|
906
1060
|
default: true,
|
|
@@ -939,6 +1093,7 @@ async function runLintCommand(files, options, io, interceptConsoleOutput) {
|
|
|
939
1093
|
cwd: io.cwd,
|
|
940
1094
|
files: lintFiles,
|
|
941
1095
|
modelOverride: options.model,
|
|
1096
|
+
outputLanguage: options.outputLanguage,
|
|
942
1097
|
progress: progress?.reporter,
|
|
943
1098
|
runner,
|
|
944
1099
|
setupConfig
|
|
@@ -962,6 +1117,85 @@ function shouldEnableProgress(options, io) {
|
|
|
962
1117
|
return options.format === "stylish" && io.stderr.isTTY === true;
|
|
963
1118
|
}
|
|
964
1119
|
//#endregion
|
|
1120
|
+
//#region src/cli/commands/output-inspect/inspect.ts
|
|
1121
|
+
const inspect$1 = defineCommand({
|
|
1122
|
+
action: (context, file, options) => inspectOutputFile(context.io, file, options),
|
|
1123
|
+
arguments: "<file>",
|
|
1124
|
+
description: "Inspect saved alint JSON output",
|
|
1125
|
+
examples: [
|
|
1126
|
+
["# Pretty-print saved JSON output", "alint output inspect alint-output.json"].join("\n"),
|
|
1127
|
+
["# Validate and reprint normalized JSON", "alint output inspect alint-output.json --format json"].join("\n"),
|
|
1128
|
+
[
|
|
1129
|
+
"# Save a run as JSON, then inspect it later",
|
|
1130
|
+
"alint --format json src > alint-output.json",
|
|
1131
|
+
"alint output inspect alint-output.json"
|
|
1132
|
+
].join("\n")
|
|
1133
|
+
],
|
|
1134
|
+
help: ["Read a saved alint JSON run result and render it with a reporter.", "Defaults to the human-friendly stylish reporter, which groups diagnostics by file and prints the same summary style as a normal alint run. Use `--format json` to validate the file and reprint normalized JSON."].join("\n\n"),
|
|
1135
|
+
name: "inspect",
|
|
1136
|
+
options: [{
|
|
1137
|
+
config: { default: "stylish" },
|
|
1138
|
+
description: "Reporter used to render the parsed run result. One of: stylish, json",
|
|
1139
|
+
flags: "-f, --format <format>"
|
|
1140
|
+
}]
|
|
1141
|
+
});
|
|
1142
|
+
async function inspectOutputFile(io, file, options) {
|
|
1143
|
+
const filePath = resolve(io.cwd, file);
|
|
1144
|
+
let text;
|
|
1145
|
+
try {
|
|
1146
|
+
text = await readFile(filePath, "utf8");
|
|
1147
|
+
} catch (error) {
|
|
1148
|
+
io.stderr.write(`Could not read output file "${file}": ${errorMessageFrom$1(error)}\n`);
|
|
1149
|
+
return 2;
|
|
1150
|
+
}
|
|
1151
|
+
let parsed;
|
|
1152
|
+
try {
|
|
1153
|
+
parsed = JSON.parse(text);
|
|
1154
|
+
} catch (error) {
|
|
1155
|
+
io.stderr.write(`Could not parse output file "${file}": ${errorMessageFrom$1(error)}\n`);
|
|
1156
|
+
return 2;
|
|
1157
|
+
}
|
|
1158
|
+
if (!isRunResult(parsed)) {
|
|
1159
|
+
io.stderr.write(`Invalid alint output "${file}": expected a run result with diagnostics and usage.\n`);
|
|
1160
|
+
return 2;
|
|
1161
|
+
}
|
|
1162
|
+
try {
|
|
1163
|
+
io.stdout.write(formatDiagnostics(options.format, parsed, { color: io.stdout.isTTY === true }));
|
|
1164
|
+
} catch (error) {
|
|
1165
|
+
io.stderr.write(`${errorMessageFrom$1(error)}\n`);
|
|
1166
|
+
return 2;
|
|
1167
|
+
}
|
|
1168
|
+
return parsed.diagnostics.length > 0 ? 1 : 0;
|
|
1169
|
+
}
|
|
1170
|
+
function isDiagnostic(value) {
|
|
1171
|
+
if (!isRecord(value)) return false;
|
|
1172
|
+
if (typeof value.filePath !== "string" || typeof value.message !== "string" || typeof value.ruleId !== "string" || value.severity !== "warn" && value.severity !== "error") return false;
|
|
1173
|
+
if (value.loc === void 0) return true;
|
|
1174
|
+
if (!isRecord(value.loc)) return false;
|
|
1175
|
+
if (value.loc.start === void 0) return true;
|
|
1176
|
+
if (!isRecord(value.loc.start)) return false;
|
|
1177
|
+
return (value.loc.start.line === void 0 || typeof value.loc.start.line === "number") && (value.loc.start.column === void 0 || typeof value.loc.start.column === "number");
|
|
1178
|
+
}
|
|
1179
|
+
function isRecord(value) {
|
|
1180
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1181
|
+
}
|
|
1182
|
+
function isRunResult(value) {
|
|
1183
|
+
if (!isRecord(value)) return false;
|
|
1184
|
+
if (!Array.isArray(value.diagnostics) || !value.diagnostics.every(isDiagnostic)) return false;
|
|
1185
|
+
return isUsage(value.usage);
|
|
1186
|
+
}
|
|
1187
|
+
function isUsage(value) {
|
|
1188
|
+
return isRecord(value) && typeof value.inputTokens === "number" && typeof value.outputTokens === "number" && Array.isArray(value.records) && typeof value.totalTokens === "number";
|
|
1189
|
+
}
|
|
1190
|
+
//#endregion
|
|
1191
|
+
//#region src/cli/commands/output-inspect/output.ts
|
|
1192
|
+
const output = defineCommand({
|
|
1193
|
+
children: [inspect$1],
|
|
1194
|
+
description: "Inspect alint output files",
|
|
1195
|
+
help: ["Inspect saved alint run outputs without rerunning rules or model calls.", "Use this when you already have JSON from `alint --format json` and want to render, validate, or transform that result for humans or tools."].join("\n\n"),
|
|
1196
|
+
name: "output"
|
|
1197
|
+
});
|
|
1198
|
+
//#endregion
|
|
965
1199
|
//#region src/cli/commands/setup/interactive.ts
|
|
966
1200
|
const nonTtyMessage = "interactive setup requires a TTY. Use -N/--no-interactive with --provider-id and --provider-endpoint.\n";
|
|
967
1201
|
const backValue = "__alint_back__";
|
|
@@ -1225,6 +1459,12 @@ const setup = defineCommand({
|
|
|
1225
1459
|
noInteractive: context.setupNoInteractive
|
|
1226
1460
|
}, context.io),
|
|
1227
1461
|
description: "Write alint provider configuration",
|
|
1462
|
+
examples: [
|
|
1463
|
+
["# Configure a provider interactively", "alint setup"].join("\n"),
|
|
1464
|
+
["# Write a project-local provider config without prompts", "alint setup --local -N --provider-id openrouter --provider-endpoint https://openrouter.ai/api/v1 --provider-model z-ai/glm-5.2"].join("\n"),
|
|
1465
|
+
["# Add an authorization header for an OpenAI-compatible provider", "alint setup --local -N --provider-id openrouter --provider-endpoint https://openrouter.ai/api/v1 --provider-model z-ai/glm-5.2 --provider-header \"Authorization=Bearer $OPENROUTER_API_KEY\""].join("\n")
|
|
1466
|
+
],
|
|
1467
|
+
help: ["Write alint provider and model configuration.", "Run without flags for interactive setup, or use `-N` with provider flags in scripts and CI. Use `--local` when the provider config should live with the current project instead of the user-level setup file."].join("\n\n"),
|
|
1228
1468
|
name: "setup",
|
|
1229
1469
|
options: [
|
|
1230
1470
|
{
|
|
@@ -1295,6 +1535,7 @@ function toArray(value) {
|
|
|
1295
1535
|
const commandTree = [
|
|
1296
1536
|
setup,
|
|
1297
1537
|
config,
|
|
1538
|
+
output,
|
|
1298
1539
|
lint
|
|
1299
1540
|
];
|
|
1300
1541
|
//#endregion
|
|
@@ -1302,17 +1543,36 @@ const commandTree = [
|
|
|
1302
1543
|
async function executeCli(argv, io) {
|
|
1303
1544
|
const cli = cac("alint");
|
|
1304
1545
|
const setupNoInteractive = argv.includes("-N") || argv.includes("--no-interactive");
|
|
1546
|
+
const globalOptions = { outputLanguage: parseStringOption(argv, ["--lang", "-l"]) };
|
|
1305
1547
|
let pendingResult;
|
|
1306
1548
|
const setPendingResult = (result) => {
|
|
1307
1549
|
pendingResult = result;
|
|
1308
1550
|
return result;
|
|
1309
1551
|
};
|
|
1310
|
-
cli.option("--no-cache", "Disable cache for this run").option("--cache-location <path>", "Path to the alint cache file or directory").option("--config <path>", "Path to alint config file").option("--file-concurrency <count>", "Number of files to lint concurrently").option("--format <format>", "Reporter format", { default: "stylish" }).option("--model <model>", "Force a model override").option("--progress", "Show run progress").option("--rule-concurrency <count>", "Number of rules to run concurrently within a file").option("--timeout-ms <ms>", "Rule execution timeout in milliseconds").help();
|
|
1552
|
+
cli.option("--no-cache", "Disable cache for this run").option("--cache-location <path>", "Path to the alint cache file or directory").option("--config <path>", "Path to alint config file").option("--file-concurrency <count>", "Number of files to lint concurrently").option("--format <format>", "Reporter format", { default: "stylish" }).option("--model <model>", "Force a model override").option("-l, --lang <language>", "Ask model-backed rules to write diagnostics in this language").option("--progress", "Show run progress").option("--rule-concurrency <count>", "Number of rules to run concurrently within a file").option("--timeout-ms <ms>", "Rule execution timeout in milliseconds").help();
|
|
1311
1553
|
registerCommandTree(cli, commandTree, {
|
|
1554
|
+
globalOptions,
|
|
1312
1555
|
interceptConsoleOutput,
|
|
1313
1556
|
io,
|
|
1314
1557
|
setupNoInteractive
|
|
1315
|
-
}, setPendingResult
|
|
1558
|
+
}, setPendingResult, {
|
|
1559
|
+
examples: [
|
|
1560
|
+
["# Configure a provider interactively", "alint setup"].join("\n"),
|
|
1561
|
+
["# Run alint on source files with the default stylish reporter", "alint src"].join("\n"),
|
|
1562
|
+
[
|
|
1563
|
+
"# Run alint and save machine-readable JSON for later inspection",
|
|
1564
|
+
"alint --format json src > alint-output.json",
|
|
1565
|
+
"alint output inspect alint-output.json"
|
|
1566
|
+
].join("\n"),
|
|
1567
|
+
["# Inspect the effective config that applies to a file", "alint config inspect src/index.ts"].join("\n"),
|
|
1568
|
+
[
|
|
1569
|
+
"# List configured providers and models",
|
|
1570
|
+
"alint config providers list",
|
|
1571
|
+
"alint config models list"
|
|
1572
|
+
].join("\n")
|
|
1573
|
+
],
|
|
1574
|
+
help: ["AI-assisted linting for source files, saved run outputs, and provider/model setup.", "Start with `alint setup` to configure a model provider, run `alint <files>` to analyze files, and use `alint output inspect` to read saved JSON output without rerunning rules."].join("\n\n")
|
|
1575
|
+
});
|
|
1316
1576
|
const restoreConsole = interceptConsoleOutput(shouldCaptureHelp(argv) ? io.stdout : io.stderr);
|
|
1317
1577
|
try {
|
|
1318
1578
|
cli.parse(argv);
|
|
@@ -1344,6 +1604,16 @@ function interceptConsoleOutput(stdout) {
|
|
|
1344
1604
|
cliConsole.log = originalConsoleLog;
|
|
1345
1605
|
};
|
|
1346
1606
|
}
|
|
1607
|
+
function parseStringOption(argv, flags) {
|
|
1608
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
1609
|
+
const value = argv[index];
|
|
1610
|
+
for (const flag of flags) {
|
|
1611
|
+
const equalsPrefix = `${flag}=`;
|
|
1612
|
+
if (value?.startsWith(equalsPrefix)) return value.slice(equalsPrefix.length);
|
|
1613
|
+
if (value === flag) return argv[index + 1];
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1347
1617
|
function shouldCaptureHelp(argv) {
|
|
1348
1618
|
return argv.includes("--help") || argv.includes("-h");
|
|
1349
1619
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as formatJson, n as formatDiagnostics, r as formatStylish, t as executeCli } from "./cli-
|
|
1
|
+
import { i as formatJson, n as formatDiagnostics, r as formatStylish, t as executeCli } from "./cli-D7cUTZnE.mjs";
|
|
2
2
|
export { executeCli, formatDiagnostics, formatJson, formatStylish };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alint-js/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.7",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./dist/index.d.mts",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"pathe": "^2.0.3",
|
|
26
26
|
"table": "^6.9.0",
|
|
27
27
|
"tinyrainbow": "^3.1.0",
|
|
28
|
-
"@alint-js/
|
|
29
|
-
"@alint-js/
|
|
28
|
+
"@alint-js/core": "0.0.7",
|
|
29
|
+
"@alint-js/config": "0.0.7"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^26.0.1",
|