@alint-js/cli 0.0.33 → 0.0.34
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 +1 -1
- package/dist/{cli-BL285NYN.mjs → cli-D8-tnU0B.mjs} +235 -27
- package/dist/index.mjs +1 -1
- package/package.json +3 -3
package/dist/bin/index.mjs
CHANGED
|
@@ -16,7 +16,7 @@ import Gitignore from "gitignore-fs";
|
|
|
16
16
|
import { Minimatch, minimatch } from "minimatch";
|
|
17
17
|
import { errorMessageFrom as errorMessageFrom$1 } from "@moeru/std";
|
|
18
18
|
//#region package.json
|
|
19
|
-
var version = "0.0.
|
|
19
|
+
var version = "0.0.34";
|
|
20
20
|
//#endregion
|
|
21
21
|
//#region src/cli/commands/command.ts
|
|
22
22
|
function defineCommand(node) {
|
|
@@ -641,6 +641,7 @@ function formatDiagnostics(format, result, options = {}) {
|
|
|
641
641
|
function createPlainProgressReporter(options) {
|
|
642
642
|
const writeLine = (line) => options.write(`${line}\n`);
|
|
643
643
|
return {
|
|
644
|
+
onJobRetry: () => {},
|
|
644
645
|
onJobStart: (payload) => {
|
|
645
646
|
const target = payload.job.target.name ? `${payload.job.target.kind} ${payload.job.target.name}` : payload.job.target.kind;
|
|
646
647
|
writeLine(`scan ${payload.job.inputPath} > ${target} > ${payload.job.ruleId}`);
|
|
@@ -661,6 +662,40 @@ function countDiagnostics$1(diagnostics, severity) {
|
|
|
661
662
|
return diagnostics.filter((diagnostic) => diagnostic.severity === severity).length;
|
|
662
663
|
}
|
|
663
664
|
//#endregion
|
|
665
|
+
//#region src/cli/reporters/progress/bar.ts
|
|
666
|
+
const minBarWidth = 4;
|
|
667
|
+
const maxBarWidth = 16;
|
|
668
|
+
const animationThreshold = .4;
|
|
669
|
+
function formatMiniBar(options) {
|
|
670
|
+
if (options.planned <= 0 || options.width < minBarWidth) return "";
|
|
671
|
+
const width = Math.min(Math.max(Math.floor(options.width), minBarWidth), maxBarWidth);
|
|
672
|
+
const ratio = Math.min(Math.max(options.completed / options.planned, 0), 1);
|
|
673
|
+
const completeCells = Math.min(Math.floor(ratio * width), width);
|
|
674
|
+
if (width - completeCells === 0) return `[${"█".repeat(width)}]`;
|
|
675
|
+
if (ratio < animationThreshold) return formatStaticBar(completeCells, width);
|
|
676
|
+
const frontierIndex = completeCells;
|
|
677
|
+
const phase = positiveModulo(options.tick, frontierIndex + 2);
|
|
678
|
+
if (phase === frontierIndex + 1) return formatStaticBar(completeCells, width);
|
|
679
|
+
return `[${Array.from({ length: width }, (_, index) => {
|
|
680
|
+
if (phase === 0) {
|
|
681
|
+
if (index === 0) return "▓";
|
|
682
|
+
if (index <= frontierIndex) return "█";
|
|
683
|
+
return "░";
|
|
684
|
+
}
|
|
685
|
+
if (index < phase - 1) return "█";
|
|
686
|
+
if (index === phase - 1) return "░";
|
|
687
|
+
if (index === phase) return "▓";
|
|
688
|
+
if (index <= frontierIndex) return "█";
|
|
689
|
+
return "░";
|
|
690
|
+
}).join("")}]`;
|
|
691
|
+
}
|
|
692
|
+
function formatStaticBar(completeCells, width) {
|
|
693
|
+
return `[${"█".repeat(completeCells)}${"░".repeat(width - completeCells)}]`;
|
|
694
|
+
}
|
|
695
|
+
function positiveModulo(value, divisor) {
|
|
696
|
+
return (Math.floor(value) % divisor + divisor) % divisor;
|
|
697
|
+
}
|
|
698
|
+
//#endregion
|
|
664
699
|
//#region src/cli/reporters/progress/summary.ts
|
|
665
700
|
const colors$2 = createColors({ force: true });
|
|
666
701
|
const graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
@@ -674,8 +709,15 @@ function createSummaryProgressReporter(options) {
|
|
|
674
709
|
},
|
|
675
710
|
onJobEnd: (payload) => {
|
|
676
711
|
const current = state.jobs.get(payload.job.id);
|
|
712
|
+
if (payload.state === "cached" && current?.state !== "cached") {
|
|
713
|
+
const cachedTokens = state.jobTokens.get(payload.job.id) ?? 0;
|
|
714
|
+
state.totalTokens = Math.max(state.totalTokens - cachedTokens, 0);
|
|
715
|
+
state.cachedTokens += cachedTokens;
|
|
716
|
+
}
|
|
677
717
|
state.jobs.set(payload.job.id, {
|
|
718
|
+
endedAt: payload.endedAt ?? now(),
|
|
678
719
|
job: payload.job,
|
|
720
|
+
retry: current?.retry,
|
|
679
721
|
startedAt: payload.startedAt ?? current?.startedAt,
|
|
680
722
|
state: payload.state
|
|
681
723
|
});
|
|
@@ -688,6 +730,19 @@ function createSummaryProgressReporter(options) {
|
|
|
688
730
|
});
|
|
689
731
|
state.execution.queued += 1;
|
|
690
732
|
},
|
|
733
|
+
onJobRetry: (payload) => {
|
|
734
|
+
const current = state.jobs.get(payload.job.id);
|
|
735
|
+
state.jobs.set(payload.job.id, {
|
|
736
|
+
job: payload.job,
|
|
737
|
+
retry: {
|
|
738
|
+
attempt: payload.attempt,
|
|
739
|
+
maxAttempts: payload.maxAttempts,
|
|
740
|
+
startedAt: payload.startedAt
|
|
741
|
+
},
|
|
742
|
+
startedAt: current?.startedAt ?? payload.startedAt ?? now(),
|
|
743
|
+
state: current?.state ?? "running"
|
|
744
|
+
});
|
|
745
|
+
},
|
|
691
746
|
onJobStart: (payload) => {
|
|
692
747
|
state.jobs.set(payload.job.id, {
|
|
693
748
|
job: payload.job,
|
|
@@ -700,22 +755,44 @@ function createSummaryProgressReporter(options) {
|
|
|
700
755
|
state.diagnostics = [...payload.diagnostics];
|
|
701
756
|
state.execution = { ...payload.execution };
|
|
702
757
|
state.totalTokens = payload.usage.totalTokens;
|
|
758
|
+
state.cachedTokens = payload.usage.cached?.totalTokens ?? 0;
|
|
759
|
+
state.runStartedAt = payload.startedAt ?? state.runStartedAt;
|
|
703
760
|
},
|
|
704
|
-
onRunStart: ({ jobsTotal }) => {
|
|
761
|
+
onRunStart: ({ jobsTotal, startedAt }) => {
|
|
705
762
|
state.diagnostics = [];
|
|
706
763
|
state.execution = createCounts(jobsTotal);
|
|
707
764
|
state.jobs.clear();
|
|
765
|
+
state.runStartedAt = startedAt ?? now();
|
|
708
766
|
state.spinnerIndex = 0;
|
|
767
|
+
state.cachedTokens = 0;
|
|
768
|
+
state.jobTokens.clear();
|
|
709
769
|
state.totalTokens = 0;
|
|
710
770
|
},
|
|
711
|
-
onUsage: ({ record }) => {
|
|
712
|
-
if (record.totalTokens != null && Number.isFinite(record.totalTokens))
|
|
771
|
+
onUsage: ({ job, record }) => {
|
|
772
|
+
if (record.totalTokens != null && Number.isFinite(record.totalTokens)) {
|
|
773
|
+
state.jobTokens.set(job.id, (state.jobTokens.get(job.id) ?? 0) + record.totalTokens);
|
|
774
|
+
if (state.jobs.get(job.id)?.state === "cached") state.cachedTokens += record.totalTokens;
|
|
775
|
+
else state.totalTokens += record.totalTokens;
|
|
776
|
+
}
|
|
713
777
|
},
|
|
714
778
|
tick: () => {
|
|
715
779
|
state.spinnerIndex = (state.spinnerIndex + 1) % Math.max(options.spinnerFrames.length, 1);
|
|
716
780
|
}
|
|
717
781
|
};
|
|
718
782
|
}
|
|
783
|
+
function compareRuleGroups(left, right) {
|
|
784
|
+
const leftActive = left.jobs.some((job) => job.state === "running") ? 1 : 0;
|
|
785
|
+
const rightActive = right.jobs.some((job) => job.state === "running") ? 1 : 0;
|
|
786
|
+
if (leftActive !== rightActive) return rightActive - leftActive;
|
|
787
|
+
if (left.failed !== right.failed) return right.failed - left.failed;
|
|
788
|
+
return left.firstJobIndex - right.firstJobIndex;
|
|
789
|
+
}
|
|
790
|
+
function compareRunningJobs(left, right) {
|
|
791
|
+
const leftStartedAt = left.startedAt ?? Number.POSITIVE_INFINITY;
|
|
792
|
+
const rightStartedAt = right.startedAt ?? Number.POSITIVE_INFINITY;
|
|
793
|
+
if (leftStartedAt !== rightStartedAt) return leftStartedAt - rightStartedAt;
|
|
794
|
+
return left.job.index - right.job.index;
|
|
795
|
+
}
|
|
719
796
|
function completeGraphemeBoundary(input, maximumIndex) {
|
|
720
797
|
let boundary = 0;
|
|
721
798
|
for (const segment of graphemeSegmenter.segment(input)) {
|
|
@@ -742,9 +819,11 @@ function createCounts(planned = 0) {
|
|
|
742
819
|
}
|
|
743
820
|
function createInitialState() {
|
|
744
821
|
return {
|
|
822
|
+
cachedTokens: 0,
|
|
745
823
|
diagnostics: [],
|
|
746
824
|
execution: createCounts(),
|
|
747
825
|
jobs: /* @__PURE__ */ new Map(),
|
|
826
|
+
jobTokens: /* @__PURE__ */ new Map(),
|
|
748
827
|
spinnerIndex: 0,
|
|
749
828
|
totalTokens: 0
|
|
750
829
|
};
|
|
@@ -753,18 +832,49 @@ function createRows(state, options, now) {
|
|
|
753
832
|
if (options.rows !== void 0 && options.rows <= 0) return [];
|
|
754
833
|
const warnCount = countDiagnostics(state.diagnostics, "warn");
|
|
755
834
|
const errorCount = countDiagnostics(state.diagnostics, "error");
|
|
756
|
-
const
|
|
757
|
-
const footerRows =
|
|
758
|
-
const separatorRows = options.rows === void 0 || options.rows
|
|
759
|
-
const
|
|
760
|
-
const
|
|
761
|
-
const
|
|
762
|
-
const
|
|
763
|
-
if (
|
|
764
|
-
|
|
765
|
-
visible.push(formatFooter(state, warnCount, errorCount, options));
|
|
835
|
+
const groups = createRuleGroups(state);
|
|
836
|
+
const footerRows = options.rows === void 0 ? 3 : Math.min(options.rows, 3);
|
|
837
|
+
const separatorRows = options.rows === void 0 || options.rows - footerRows > 1 ? 1 : 0;
|
|
838
|
+
const visible = formatContentRows(groups, state, options, now, options.rows === void 0 ? Number.POSITIVE_INFINITY : Math.max(options.rows - footerRows - separatorRows, 0));
|
|
839
|
+
const footer = formatFooters(state, options, now);
|
|
840
|
+
const actualSeparatorRows = visible.length > 0 ? separatorRows : 0;
|
|
841
|
+
const visibleFooters = options.rows === void 0 ? footer : footer.slice(0, Math.max(options.rows - visible.length - actualSeparatorRows, 0));
|
|
842
|
+
if (actualSeparatorRows === 1) visible.push("");
|
|
843
|
+
visible.push(...visibleFooters);
|
|
766
844
|
return options.color ? visible.map((row) => styleRow(row, state, warnCount, errorCount, options)) : visible;
|
|
767
845
|
}
|
|
846
|
+
function createRuleGroups(state) {
|
|
847
|
+
const groups = /* @__PURE__ */ new Map();
|
|
848
|
+
for (const job of state.jobs.values()) {
|
|
849
|
+
const group = groups.get(job.job.ruleId) ?? {
|
|
850
|
+
cached: 0,
|
|
851
|
+
cancelled: 0,
|
|
852
|
+
completed: 0,
|
|
853
|
+
failed: 0,
|
|
854
|
+
firstJobIndex: job.job.index,
|
|
855
|
+
jobs: [],
|
|
856
|
+
planned: 0,
|
|
857
|
+
ruleId: job.job.ruleId,
|
|
858
|
+
skipped: 0,
|
|
859
|
+
terminalDurationMs: 0
|
|
860
|
+
};
|
|
861
|
+
group.firstJobIndex = Math.min(group.firstJobIndex, job.job.index);
|
|
862
|
+
group.jobs.push(job);
|
|
863
|
+
group.planned = Math.max(group.planned, job.job.ruleTotal);
|
|
864
|
+
if (job.state === "cached") group.cached += 1;
|
|
865
|
+
if (job.state === "cancelled") group.cancelled += 1;
|
|
866
|
+
if (job.state === "completed") group.completed += 1;
|
|
867
|
+
if (job.state === "failed") group.failed += 1;
|
|
868
|
+
if (job.state === "skipped") group.skipped += 1;
|
|
869
|
+
if (job.endedAt !== void 0 && job.startedAt !== void 0 && job.state !== "cached") group.terminalDurationMs += Math.max(job.endedAt - job.startedAt, 0);
|
|
870
|
+
groups.set(group.ruleId, group);
|
|
871
|
+
}
|
|
872
|
+
return [...groups.values()].sort(compareRuleGroups);
|
|
873
|
+
}
|
|
874
|
+
function estimateEta(durationMs, terminal, planned) {
|
|
875
|
+
if (terminal <= 0 || planned <= 0 || durationMs <= 0) return "eta ?";
|
|
876
|
+
return `eta ~${formatDuration(durationMs * (planned - terminal) / terminal)}`;
|
|
877
|
+
}
|
|
768
878
|
function fitRow(row, columns) {
|
|
769
879
|
if (columns <= 0) return "";
|
|
770
880
|
if (fastStringWidth(row) <= columns) return row;
|
|
@@ -783,25 +893,88 @@ function fitRow(row, columns) {
|
|
|
783
893
|
}
|
|
784
894
|
return "";
|
|
785
895
|
}
|
|
896
|
+
function formatCollapsedRunningRow(hidden, options) {
|
|
897
|
+
return fitRow(` └─ ${hidden} more running`, options.columns);
|
|
898
|
+
}
|
|
899
|
+
function formatContentRows(groups, state, options, now, contentBudget) {
|
|
900
|
+
const rows = [];
|
|
901
|
+
const renderableGroups = groups.filter((group) => group.jobs.some((job) => job.state === "running") || group.failed > 0);
|
|
902
|
+
const runningCount = renderableGroups.reduce((sum, group) => sum + group.jobs.filter((job) => job.state === "running").length, 0);
|
|
903
|
+
if (contentBudget === 1) {
|
|
904
|
+
const failedGroup = renderableGroups.find((group) => group.failed > 0);
|
|
905
|
+
if (failedGroup) return [formatRuleRow(failedGroup, state, options)];
|
|
906
|
+
if (runningCount > 0) return [formatCollapsedRunningRow(runningCount, options)];
|
|
907
|
+
}
|
|
908
|
+
for (const [groupIndex, group] of renderableGroups.entries()) {
|
|
909
|
+
if (rows.length >= contentBudget) break;
|
|
910
|
+
const groupStart = rows.length;
|
|
911
|
+
rows.push(formatRuleRow(group, state, options));
|
|
912
|
+
const runningJobs = group.jobs.filter((job) => job.state === "running").sort(compareRunningJobs);
|
|
913
|
+
const remainingGroups = renderableGroups.length - groupIndex - 1;
|
|
914
|
+
for (const [index, job] of runningJobs.entries()) {
|
|
915
|
+
const rowsReservedForLaterGroups = Math.min(remainingGroups, Math.max(contentBudget - rows.length, 0));
|
|
916
|
+
if (rows.length >= contentBudget) {
|
|
917
|
+
const hidden = runningJobs.length - index;
|
|
918
|
+
if (rows.length > groupStart + 1 && hidden > 0) rows[rows.length - 1] = formatCollapsedRunningRow(hidden, options);
|
|
919
|
+
break;
|
|
920
|
+
}
|
|
921
|
+
if (rows.length + 1 + rowsReservedForLaterGroups >= contentBudget) {
|
|
922
|
+
if (runningJobs.length > 1) rows.push(formatCollapsedRunningRow(runningJobs.length - index, options));
|
|
923
|
+
break;
|
|
924
|
+
}
|
|
925
|
+
rows.push(formatTargetRow(job, options, now, index === runningJobs.length - 1));
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
return rows;
|
|
929
|
+
}
|
|
786
930
|
function formatDuration(ms) {
|
|
787
931
|
return `${(Math.max(ms, 0) / 1e3).toFixed(1)}s`;
|
|
788
932
|
}
|
|
789
|
-
function
|
|
790
|
-
const
|
|
791
|
-
|
|
933
|
+
function formatFooters(state, options, now) {
|
|
934
|
+
const terminal = terminalCount(state.execution);
|
|
935
|
+
const elapsed = state.runStartedAt === void 0 ? 0 : now - state.runStartedAt;
|
|
936
|
+
const progressBar = formatMiniBarSegment(terminal, state.execution.planned, state.spinnerIndex, options);
|
|
937
|
+
const eta = estimateEta(elapsed, terminal, state.execution.planned);
|
|
938
|
+
const projectedTokens = terminal > 0 && state.execution.planned > 0 ? Math.ceil((state.totalTokens + state.cachedTokens) * state.execution.planned / terminal) : void 0;
|
|
939
|
+
return [
|
|
940
|
+
fitRow(`${terminal}/${state.execution.planned}${progressBar} ${formatDuration(elapsed)} -> ${eta === "eta ?" ? "~?" : eta.replace("eta ", "")}`, options.columns),
|
|
941
|
+
fitRow(`${state.execution.running} concurrency / ${state.execution.queued} queued / ${state.execution.cached} cached / ${state.execution.failed} failed`, options.columns),
|
|
942
|
+
fitRow(`${state.totalTokens.toLocaleString("en-US")} tokens (${state.cachedTokens.toLocaleString("en-US")} cached) -> ${projectedTokens === void 0 ? "~?" : `~${projectedTokens.toLocaleString("en-US")} tokens`}`, options.columns)
|
|
943
|
+
];
|
|
944
|
+
}
|
|
945
|
+
function formatMiniBarSegment(completed, planned, tick, options) {
|
|
946
|
+
if (options.columns < 60) return "";
|
|
947
|
+
return ` ${formatMiniBar({
|
|
948
|
+
completed,
|
|
949
|
+
planned,
|
|
950
|
+
tick,
|
|
951
|
+
width: 10
|
|
952
|
+
})}`;
|
|
792
953
|
}
|
|
793
|
-
function
|
|
954
|
+
function formatRuleRow(group, state, options) {
|
|
794
955
|
const spinner = options.spinnerFrames[state.spinnerIndex] ?? "";
|
|
956
|
+
const terminal = group.completed + group.cached + group.failed + group.cancelled + group.skipped;
|
|
957
|
+
const percent = group.planned > 0 ? Math.floor(terminal / group.planned * 100) : 0;
|
|
958
|
+
const bar = formatMiniBarSegment(terminal, group.planned, state.spinnerIndex, options);
|
|
959
|
+
const running = group.jobs.filter((job) => job.state === "running").length;
|
|
960
|
+
const failed = group.failed > 0 ? ` ${group.failed} failed` : "";
|
|
961
|
+
const eta = estimateEta(group.terminalDurationMs, terminal, group.planned);
|
|
962
|
+
return fitRow(`${spinner} ${group.ruleId} ${terminal}/${group.planned} ${percent}%${bar} ${eta} ${running} running${failed}`, options.columns);
|
|
963
|
+
}
|
|
964
|
+
function formatTargetRow(jobState, options, now, last) {
|
|
795
965
|
const inputPath = options.cwd ? relative$1(options.cwd, jobState.job.inputPath) || "." : jobState.job.inputPath;
|
|
796
966
|
const target = jobState.job.target.name ? `${jobState.job.target.kind} ${jobState.job.target.name}` : jobState.job.target.kind;
|
|
797
|
-
const startedAt = jobState.startedAt ?? now;
|
|
798
|
-
return fitRow(`${
|
|
967
|
+
const startedAt = jobState.retry?.startedAt ?? jobState.startedAt ?? now;
|
|
968
|
+
return fitRow(`${last ? " └─" : " ├─"} ${inputPath} > ${target} ${jobState.retry ? `${jobState.retry.attempt}/${jobState.retry.maxAttempts} retrying elapsed ${formatDuration(now - startedAt)}` : `running ${formatDuration(now - startedAt)}`}`, options.columns);
|
|
799
969
|
}
|
|
800
970
|
function styleRow(row, state, warnCount, errorCount, options) {
|
|
801
971
|
let styledRow = row;
|
|
802
972
|
const spinner = options.spinnerFrames[state.spinnerIndex] ?? "";
|
|
803
973
|
if (spinner) styledRow = styledRow.replace(spinner, colors$2.cyan(spinner));
|
|
804
|
-
return styledRow.replace(
|
|
974
|
+
return styledRow.replace(`${state.execution.running} concurrency`, colors$2.cyan(`${state.execution.running} concurrency`)).replace(`${state.totalTokens.toLocaleString("en-US")} tokens`, colors$2.cyan(`${state.totalTokens.toLocaleString("en-US")} tokens`)).replace(`(${state.cachedTokens.toLocaleString("en-US")} cached)`, colors$2.dim(`(${state.cachedTokens.toLocaleString("en-US")} cached)`)).replace(` / ${state.execution.cached} cached / `, ` / ${colors$2.dim(`${state.execution.cached} cached`)} / `).replace(`${warnCount} warn`, colors$2.yellow(`${warnCount} warn`)).replace(`${errorCount} error`, (errorCount > 0 ? colors$2.red : colors$2.gray)(`${errorCount} error`)).replace(`${state.execution.failed} failed`, (state.execution.failed > 0 ? colors$2.red : colors$2.gray)(`${state.execution.failed} failed`)).replace(/\[([█▓░]*?)(░+)\]/g, (_, active, pending) => `[${active}${colors$2.gray(pending)}]`).replace(/\//g, colors$2.gray("/"));
|
|
975
|
+
}
|
|
976
|
+
function terminalCount(counts) {
|
|
977
|
+
return counts.completed + counts.failed + counts.cached + counts.skipped + counts.cancelled;
|
|
805
978
|
}
|
|
806
979
|
function transition(counts, from, to) {
|
|
807
980
|
counts[from] -= 1;
|
|
@@ -903,6 +1076,10 @@ function createRenderingProgressReporter(summary, renderer) {
|
|
|
903
1076
|
summary.onJobQueued?.(payload);
|
|
904
1077
|
renderer.render();
|
|
905
1078
|
},
|
|
1079
|
+
onJobRetry: (payload) => {
|
|
1080
|
+
summary.onJobRetry?.(payload);
|
|
1081
|
+
renderer.render();
|
|
1082
|
+
},
|
|
906
1083
|
onJobStart: (payload) => {
|
|
907
1084
|
summary.onJobStart?.(payload);
|
|
908
1085
|
renderer.render();
|
|
@@ -1101,15 +1278,42 @@ function formatCancelledError(error, color) {
|
|
|
1101
1278
|
return `${color ? colors$1.red("error") : "error"} ${error.message}\n`;
|
|
1102
1279
|
}
|
|
1103
1280
|
function formatRunError(error, color) {
|
|
1281
|
+
const label = color ? colors$1.red("error") : "error";
|
|
1282
|
+
const groups = groupFailuresByRule(error.failures);
|
|
1104
1283
|
return [
|
|
1105
|
-
`${
|
|
1106
|
-
|
|
1107
|
-
|
|
1284
|
+
`${label} ${error.message}`,
|
|
1285
|
+
"",
|
|
1286
|
+
`Failed Rules ${groups.length}`,
|
|
1287
|
+
"",
|
|
1288
|
+
...formatFailureGroups(groups, color)
|
|
1108
1289
|
].join("\n");
|
|
1109
1290
|
}
|
|
1110
|
-
function
|
|
1291
|
+
function formatFailureGroups(groups, color) {
|
|
1292
|
+
const lines = [];
|
|
1293
|
+
for (const [ruleId, group] of groups) {
|
|
1294
|
+
const failLabel = color ? colors$1.bgRed(colors$1.bold(" FAIL ")) : "FAIL";
|
|
1295
|
+
const targetLabel = group.length === 1 ? "target" : "targets";
|
|
1296
|
+
lines.push(`${failLabel} ${ruleId} ${group.length} ${targetLabel}`);
|
|
1297
|
+
for (const failure of group.sort((left, right) => left.job.index - right.job.index)) {
|
|
1298
|
+
lines.push(` ${formatTarget(failure)}`);
|
|
1299
|
+
lines.push(` [${failure.kind}] ${failure.message}`);
|
|
1300
|
+
}
|
|
1301
|
+
lines.push("");
|
|
1302
|
+
}
|
|
1303
|
+
return lines;
|
|
1304
|
+
}
|
|
1305
|
+
function formatTarget(failure) {
|
|
1111
1306
|
const target = failure.job.target.name ? `${failure.job.target.kind} ${failure.job.target.name}` : failure.job.target.kind;
|
|
1112
|
-
return
|
|
1307
|
+
return `${failure.job.inputPath} > ${target}`;
|
|
1308
|
+
}
|
|
1309
|
+
function groupFailuresByRule(failures) {
|
|
1310
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1311
|
+
for (const failure of failures) {
|
|
1312
|
+
const group = groups.get(failure.job.ruleId) ?? [];
|
|
1313
|
+
group.push(failure);
|
|
1314
|
+
groups.set(failure.job.ruleId, group);
|
|
1315
|
+
}
|
|
1316
|
+
return [...groups];
|
|
1113
1317
|
}
|
|
1114
1318
|
//#endregion
|
|
1115
1319
|
//#region src/cli/commands/lint/runner.ts
|
|
@@ -1432,6 +1636,9 @@ function mergeProgressReporters(base, extra) {
|
|
|
1432
1636
|
onJobQueued: (payload) => {
|
|
1433
1637
|
deliverBoth((reporter) => reporter.onJobQueued?.(payload));
|
|
1434
1638
|
},
|
|
1639
|
+
onJobRetry: (payload) => {
|
|
1640
|
+
deliverBoth((reporter) => reporter.onJobRetry?.(payload));
|
|
1641
|
+
},
|
|
1435
1642
|
onJobStart: (payload) => {
|
|
1436
1643
|
deliverBoth((reporter) => reporter.onJobStart?.(payload));
|
|
1437
1644
|
},
|
|
@@ -1542,6 +1749,7 @@ async function runLintCommand(files, options, io, interceptConsoleOutput) {
|
|
|
1542
1749
|
let result;
|
|
1543
1750
|
try {
|
|
1544
1751
|
result = await runAlint({
|
|
1752
|
+
cacheOnly: options.cacheOnly,
|
|
1545
1753
|
config,
|
|
1546
1754
|
cwd: io.cwd,
|
|
1547
1755
|
directories: lintTargets.directories,
|
|
@@ -2240,7 +2448,7 @@ async function executeCli(argv, io) {
|
|
|
2240
2448
|
pendingResult = result;
|
|
2241
2449
|
return result;
|
|
2242
2450
|
};
|
|
2243
|
-
cli.option("--no-cache", "Disable cache for this run").option("--cache-location <path>", "Path to the alint cache file or directory").option("-c, --config <path>", "Path to alint config file").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>", "Maximum rule executions across the entire run").option("--no-stats", "Do not record run stats for this run").option("--timeout-ms <ms>", "Rule execution timeout in milliseconds").version(version).help();
|
|
2451
|
+
cli.option("--no-cache", "Disable cache for this run").option("--cache-location <path>", "Path to the alint cache file or directory").option("--cache-only", "Report only cached diagnostics; skip rules that miss the cache and call no model").option("-c, --config <path>", "Path to alint config file").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>", "Maximum rule executions across the entire run").option("--no-stats", "Do not record run stats for this run").option("--timeout-ms <ms>", "Rule execution timeout in milliseconds").version(version).help();
|
|
2244
2452
|
registerCommandTree(cli, commandTree, {
|
|
2245
2453
|
globalOptions,
|
|
2246
2454
|
interceptConsoleOutput,
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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-D8-tnU0B.mjs";
|
|
2
2
|
import { ignorePatternsAIAgents, ignorePatternsBuildOutputs, ignorePatternsCaches, ignorePatternsCommon, ignorePatternsEslintDefaults, ignorePatternsGenerated } from "@alint-js/config";
|
|
3
3
|
import { defineConfig } from "@alint-js/core";
|
|
4
4
|
export { defineConfig, executeCli, formatDiagnostics, formatJson, formatStylish, ignorePatternsAIAgents, ignorePatternsBuildOutputs, ignorePatternsCaches, ignorePatternsCommon, ignorePatternsEslintDefaults, ignorePatternsGenerated };
|
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.34",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./dist/index.d.mts",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"pathe": "^2.0.3",
|
|
28
28
|
"table": "^6.9.0",
|
|
29
29
|
"tinyrainbow": "^3.1.0",
|
|
30
|
-
"@alint-js/
|
|
31
|
-
"@alint-js/
|
|
30
|
+
"@alint-js/config": "0.0.34",
|
|
31
|
+
"@alint-js/core": "0.0.34"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@pnpm/find-workspace-dir": "^1000.1.5",
|