oxlint-harness 1.0.1 → 1.0.2

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/command.d.ts CHANGED
@@ -8,10 +8,13 @@ export default class OxlintHarness extends Command {
8
8
  update: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
9
  "fail-on-excess": import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
10
  "show-code": import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
11
+ "results-path": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
12
+ "save-results": import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
13
  };
12
14
  static args: {
13
15
  paths: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
14
16
  };
15
17
  static strict: boolean;
16
18
  run(): Promise<void>;
19
+ private saveResults;
17
20
  }
package/dist/command.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { Command, Flags, Args } from "@oclif/core";
2
+ import { mkdir, writeFile } from "fs/promises";
3
+ import { dirname } from "path";
2
4
  import { OxlintRunner } from "./oxlint-runner.js";
3
5
  import { SuppressionManager } from "./suppression-manager.js";
4
6
  import { ErrorReporter } from "./error-reporter.js";
@@ -41,6 +43,16 @@ The suppression file format uses counts per rule per file:
41
43
  description: "Show code snippets for files with N or fewer errors (0 to disable)",
42
44
  default: 3,
43
45
  }),
46
+ "results-path": Flags.string({
47
+ description: "Path to save oxlint JSON results (default: artifacts/oxlint-results.json)",
48
+ default: "artifacts/oxlint-results.json",
49
+ env: "OXLINT_HARNESS_RESULTS_PATH",
50
+ }),
51
+ "save-results": Flags.boolean({
52
+ description: "Save oxlint JSON results to file",
53
+ default: true,
54
+ allowNo: true,
55
+ }),
44
56
  };
45
57
  static args = {
46
58
  paths: Args.string({
@@ -69,8 +81,14 @@ The suppression file format uses counts per rule per file:
69
81
  this.log(" --fail-on-excess Exit 1 if unsuppressed errors exist (default: true)");
70
82
  this.log(" --no-fail-on-excess Don't exit 1 on unsuppressed errors");
71
83
  this.log(" --show-code <number> Show code snippets for files with N or fewer errors (default: 3, 0 to disable)");
84
+ this.log(" --results-path <path> Path to save oxlint JSON results (default: artifacts/oxlint-results.json)");
85
+ this.log(" --no-save-results Don't save oxlint JSON results to file");
72
86
  this.log(" -h, --help Show this help message");
73
87
  this.log("");
88
+ this.log("ENVIRONMENT VARIABLES");
89
+ this.log(" OXLINT_HARNESS_RESULTS_PATH Override the results file path");
90
+ this.log(" OXLINT_HARNESS_NO_FAIL_ON_EXCESS Set to 'true' to exit 0 on new errors");
91
+ this.log("");
74
92
  this.log("ARGS");
75
93
  this.log(" <paths> Files or directories to lint (passed to oxlint)");
76
94
  this.log("");
@@ -98,6 +116,9 @@ The suppression file format uses counts per rule per file:
98
116
  update: false,
99
117
  "fail-on-excess": true,
100
118
  "show-code": 3,
119
+ "results-path": process.env.OXLINT_HARNESS_RESULTS_PATH ||
120
+ "artifacts/oxlint-results.json",
121
+ "save-results": true,
101
122
  };
102
123
  const knownFlagNames = new Set([
103
124
  "--suppressions",
@@ -107,6 +128,9 @@ The suppression file format uses counts per rule per file:
107
128
  "--fail-on-excess",
108
129
  "--no-fail-on-excess",
109
130
  "--show-code",
131
+ "--results-path",
132
+ "--save-results",
133
+ "--no-save-results",
110
134
  ]);
111
135
  // Manually parse known flags and collect unknown ones
112
136
  for (let i = 0; i < rawArgs.length; i++) {
@@ -128,6 +152,16 @@ The suppression file format uses counts per rule per file:
128
152
  if (value)
129
153
  parsedFlags["show-code"] = parseInt(value, 10) || 3;
130
154
  }
155
+ else if (arg === "--results-path") {
156
+ parsedFlags["results-path"] =
157
+ rawArgs[++i] || parsedFlags["results-path"];
158
+ }
159
+ else if (arg === "--save-results") {
160
+ parsedFlags["save-results"] = true;
161
+ }
162
+ else if (arg === "--no-save-results") {
163
+ parsedFlags["save-results"] = false;
164
+ }
131
165
  else if (!knownFlagNames.has(arg) &&
132
166
  arg !== "--help" &&
133
167
  arg !== "-h") {
@@ -147,11 +181,19 @@ The suppression file format uses counts per rule per file:
147
181
  "true") {
148
182
  flags.update = true;
149
183
  }
184
+ // Check for OXLINT_HARNESS_NO_FAIL_ON_EXCESS environment variable
185
+ if (process.env.OXLINT_HARNESS_NO_FAIL_ON_EXCESS?.toLowerCase() === "true") {
186
+ flags["fail-on-excess"] = false;
187
+ }
150
188
  const colors = new ColorFormatter();
151
189
  try {
152
190
  // Run oxlint with remaining args
153
191
  const runner = new OxlintRunner();
154
192
  const diagnostics = await runner.run(oxlintArgs);
193
+ // Save results if enabled
194
+ if (flags["save-results"]) {
195
+ await this.saveResults(flags["results-path"], diagnostics);
196
+ }
155
197
  // Handle suppression logic
156
198
  const suppressionManager = new SuppressionManager(flags.suppressions);
157
199
  if (flags.update) {
@@ -190,4 +232,9 @@ The suppression file format uses counts per rule per file:
190
232
  this.error(error instanceof Error ? error.message : String(error));
191
233
  }
192
234
  }
235
+ async saveResults(path, diagnostics) {
236
+ const dir = dirname(path);
237
+ await mkdir(dir, { recursive: true });
238
+ await writeFile(path, JSON.stringify(diagnostics, null, 2));
239
+ }
193
240
  }
@@ -1,4 +1,4 @@
1
- import { SuppressionFile, ProcessedDiagnostic, ExcessError } from './types.js';
1
+ import { SuppressionFile, ProcessedDiagnostic, ExcessError } from "./types.js";
2
2
  export declare class SuppressionManager {
3
3
  private suppressionFile;
4
4
  constructor(suppressionFile?: string);
@@ -1,7 +1,7 @@
1
- import { readFileSync, writeFileSync, existsSync } from 'fs';
1
+ import { readFileSync, writeFileSync, existsSync } from "fs";
2
2
  export class SuppressionManager {
3
3
  suppressionFile;
4
- constructor(suppressionFile = '.oxlint-suppressions.json') {
4
+ constructor(suppressionFile = ".oxlint-suppressions.json") {
5
5
  this.suppressionFile = suppressionFile;
6
6
  }
7
7
  loadSuppressions() {
@@ -9,7 +9,7 @@ export class SuppressionManager {
9
9
  return {};
10
10
  }
11
11
  try {
12
- const content = readFileSync(this.suppressionFile, 'utf8');
12
+ const content = readFileSync(this.suppressionFile, "utf8");
13
13
  return JSON.parse(content);
14
14
  }
15
15
  catch (error) {
@@ -19,7 +19,7 @@ export class SuppressionManager {
19
19
  saveSuppressions(suppressions) {
20
20
  try {
21
21
  const content = JSON.stringify(suppressions, null, 2);
22
- writeFileSync(this.suppressionFile, content, 'utf8');
22
+ writeFileSync(this.suppressionFile, content, "utf8");
23
23
  }
24
24
  catch (error) {
25
25
  throw new Error(`Failed to write suppression file ${this.suppressionFile}: ${error instanceof Error ? error.message : String(error)}`);
@@ -71,7 +71,7 @@ export class SuppressionManager {
71
71
  filename,
72
72
  expected,
73
73
  actual,
74
- diagnostics: diagnosticsForRule
74
+ diagnostics: diagnosticsForRule,
75
75
  });
76
76
  }
77
77
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oxlint-harness",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "A harness for oxlint with bulk suppressions support",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -45,4 +45,4 @@
45
45
  "node": ">=22"
46
46
  },
47
47
  "packageManager": "pnpm@9.15.9"
48
- }
48
+ }