Skip to content

Add oxlint plugin to @fedify/lint#760

Open
nyanrus wants to merge 8 commits intofedify-dev:mainfrom
nyanrus:main
Open

Add oxlint plugin to @fedify/lint#760
nyanrus wants to merge 8 commits intofedify-dev:mainfrom
nyanrus:main

Conversation

@nyanrus
Copy link
Copy Markdown

@nyanrus nyanrus commented May 10, 2026

fix #702

Expose the existing rule set through oxlint's JS plugin API at the new @fedify/lint/oxlint subpath export. The same rules used by the ESLint plugin are reused verbatim — oxlint claims an ESLint-compatible API, so no rule logic is duplicated.

Includes an integration test that spawns the oxlint binary against a tmpdir fixture, plus an example project under examples/lint/oxlint/ that demonstrates the configuration with both a violating and a corrected fixture.

edit:
Deno support added!

Expose the existing rule set through oxlint's JS plugin API at the new
`@fedify/lint/oxlint` subpath export. The same rules used by the ESLint
plugin are reused verbatim — oxlint claims an ESLint-compatible API, so no
rule logic is duplicated. Distributed via npm only since oxlint's JS
plugin loader runs only under Node.js.

Includes an integration test that spawns the oxlint binary against a
tmpdir fixture, plus an example project under examples/lint/oxlint/ that
demonstrates the configuration with both a violating and a corrected
fixture.

Assisted-by: Claude Code:claude-opus-4-7
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 10, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8a8c1797-0850-4c53-b8e1-71cf6523af3c

📥 Commits

Reviewing files that changed from the base of the PR and between f1c8be9 and d9fbb43.

📒 Files selected for processing (1)
  • docs/manual/lint.md

📝 Walkthrough

Walkthrough

Adds an Oxlint subpath export and plugin implementation for @fedify/lint, including documentation, examples, integration tests, and workspace/build config updates to publish and test the Oxlint plugin.

Changes

Oxlint Support Implementation

Layer / File(s) Summary
Package export & build entry
packages/lint/package.json, packages/lint/tsdown.config.ts, packages/lint/deno.json
Adds ./oxlint subpath exports, extends keywords/devDependencies with oxlint, and adds src/oxlint.ts as a build entry; expands deno test permissions.
Oxlint plugin implementation
packages/lint/src/oxlint.ts
Implements and exports an Oxlint-compatible plugin object (meta + rules) and default export.
Integration tests
packages/lint/src/tests/oxlint.test.ts
Runs oxlint against a temp fixture to assert Fedify lint diagnostics (skips if oxlint or built plugin missing).
Public documentation
packages/lint/README.md, docs/manual/lint.md
Documents Oxlint support, shows .oxlintrc.json examples with jsPlugins, and details running Oxlint via scripts and direct CLI.
Examples
examples/lint/oxlint/*
Adds example project with package.json, .oxlintrc.json, federation.ts (bad), federation.fixed.ts (fixed), and README describing usage and expected diagnostics.
Workspace & tooling config
pnpm-workspace.yaml, .hongdown.toml
Adds oxlint to the version catalog, updates workspace package list, and registers "Oxlint" as a proper noun for docs tooling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

type/feature, type/documentation, examples, dependencies

Suggested reviewers

  • 2chanhaeng
  • dahlia
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add oxlint plugin to @fedify/lint' clearly and concisely describes the main change—adding oxlint support to the lint package with a new plugin export.
Description check ✅ Passed The description relates to the changeset by explaining the oxlint plugin implementation, integration test, example project, and Deno support additions, matching the file changes presented.
Linked Issues check ✅ Passed The PR fulfills all coding requirements from issue #702: adds @fedify/lint/oxlint subpath export, reuses ESLint rules, includes integration tests, provides example configuration, documents in README, preserves root exports, and notes alpha status.
Out of Scope Changes check ✅ Passed All changes are in scope: oxlint plugin implementation, documentation updates, tests, examples, build config, workspace config, and tooling (hongdown.toml) updates directly support the oxlint support feature.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/lint/oxlint/README.md`:
- Around line 6-8: Add a short stability caveat to the README.md's intro
paragraph explaining that Oxlint's JavaScript plugin support is currently
upstream alpha; update the opening lines where the example is described (the
paragraph referencing `@fedify/lint` and [oxlint]) to append a single-sentence
note like "Note: Oxlint's JS plugin support is upstream alpha and may be
unstable" so users are aware of adoption risk.

In `@packages/lint/src/tests/oxlint.test.ts`:
- Line 17: The test import uses the Node-only harness; replace the
runtime-specific import by importing the test harness from the repo-standard
package. Update the import statement that currently reads importing "test"
(symbol: test) from "node:test" to import "test" from "@fedify/fixture" so this
file (oxlint.test.ts) uses the repository-standard, runtime-agnostic test
harness.
- Around line 75-120: Wrap the temporary-dir usage in the test in a try/finally:
create dir with mkdtempSync as now, run the test logic (writes, spawnSync,
assertions) inside try, and in finally call rmSync(dir, { recursive: true,
force: true }) to always remove the fixture. If rmSync is not imported, add it
from 'fs' (or call fs.rmSync) so the cleanup compiles; reference the local
variable dir in the finally block and keep the existing assertions and error
handling unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b56fc3b9-8fb2-468b-b50d-f1ec0a5eccb9

📥 Commits

Reviewing files that changed from the base of the PR and between 7415710 and 14f5ce4.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • docs/manual/lint.md
  • examples/lint/oxlint/.oxlintrc.json
  • examples/lint/oxlint/README.md
  • examples/lint/oxlint/federation.fixed.ts
  • examples/lint/oxlint/federation.ts
  • examples/lint/oxlint/package.json
  • packages/lint/README.md
  • packages/lint/package.json
  • packages/lint/src/oxlint.ts
  • packages/lint/src/tests/oxlint.test.ts
  • packages/lint/tsdown.config.ts
  • pnpm-workspace.yaml

Comment thread examples/lint/oxlint/README.md Outdated
Comment thread packages/lint/src/tests/oxlint.test.ts Outdated
Comment thread packages/lint/src/tests/oxlint.test.ts
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for oxlint, a fast Rust-based linter, to the @fedify/lint package. It adds a new subpath export, @fedify/lint/oxlint, which exposes the existing Fedify lint rules in a format compatible with oxlint's JS plugin API. The changes include comprehensive documentation updates, a new example project demonstrating oxlint integration, and an integration test suite. Feedback from the reviewer identifies a documentation issue where a JSON code block containing comments should be labeled as jsonc to ensure syntactic correctness.

Comment thread packages/lint/README.md Outdated
Copy link
Copy Markdown
Member

@dahlia dahlia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left several nitpicking comments. I guess @2chanhaeng, the original author of @fedify/lint, could give you more helpful feedback.

Comment thread docs/manual/lint.md Outdated
Comment thread docs/manual/lint.md Outdated
Comment thread docs/manual/lint.md Outdated
Comment thread docs/manual/lint.md Outdated
Comment thread docs/manual/lint.md Outdated
Comment thread docs/manual/lint.md Outdated
Comment thread docs/manual/lint.md Outdated
Comment thread docs/manual/lint.md Outdated
Comment thread docs/manual/lint.md Outdated
@dahlia dahlia requested a review from 2chanhaeng May 10, 2026 12:53
@codecov
Copy link
Copy Markdown

codecov Bot commented May 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.
see 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

nyanrus added 4 commits May 10, 2026 21:57
The oxlint section of the lint package README and the linting manual
both warned that the JS plugin loader "runs only under Node.js" and
therefore the `@fedify/lint/oxlint` subpath was distributed via npm
only. That claim is not supported by the oxlint docs — it conflated a
note about TypeScript config files (which do require the Node-based
oxlint package) with the JS plugin mechanism, which has no such
restriction documented.

Drop the misleading sentence, expose the same subpath through JSR via
deno.json, and migrate the integration test to `@fedify/fixture`'s
runtime-agnostic `test()` so it runs under both `pnpm test` (node:test)
and `deno task test` (Deno.test) with the same source. The findOxlint
helper now also checks the package-local `node_modules/.bin` so it can
locate the binary under pnpm's hoisting layout in addition to the
workspace-root and PATH lookups.

Refs: fedify-dev#702

Assisted-by: Claude Code:claude-opus-4-7
Match the casing the rest of the docs already use for product names like
Deno Lint and ESLint. Lowercase usages are kept where they refer to the
binary, the config filename, or the package subpath (`@fedify/lint/oxlint`).

The hongdown proper_nouns list gets an "Oxlint" entry so the formatter
preserves the casing in headings on subsequent runs.

Refs: fedify-dev#702

Assisted-by: Claude Code:claude-opus-4-7
The example README's intro previously didn't mention the upstream alpha
status, so users landing directly on the example missed the caveat that
the package and manual docs carry. Append a single sentence to the
intro paragraph so adoption risk is visible at first read.

Refs: fedify-dev#702

Assisted-by: Claude Code:claude-opus-4-7
The example uses a leading `// .oxlintrc.json` comment to label the
filename, which is invalid JSON; the surrounding Deno Lint and ESLint
examples avoid the issue by tagging their blocks `typescript`. Tagging
this one `jsonc` matches the actual content (JSON with comments).

Refs: fedify-dev#702

Assisted-by: Claude Code:claude-opus-4-7
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
packages/lint/src/tests/oxlint.test.ts (1)

72-121: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clean up the temporary fixture directory after the test.

The test creates a temp directory at line 76 but never removes it, which will accumulate temp directories in local dev and CI environments over time.

🧹 Suggested cleanup patch
-import { existsSync, mkdtempSync, writeFileSync } from "node:fs";
+import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
   () => {
     const dir = mkdtempSync(join(tmpdir(), "fedify-lint-oxlint-"));
-    writeFileSync(
-      join(dir, ".oxlintrc.json"),
-      JSON.stringify({
-        jsPlugins: [pluginPath],
-        rules: {
-          "@fedify/lint/actor-id-required": "error",
-        },
-      }),
-    );
-    writeFileSync(join(dir, "federation.ts"), BAD_CODE);
-
-    const result = spawnSync(
-      oxlintBin!,
-      ["--format=json", "."],
-      { cwd: dir, encoding: "utf8" },
-    );
-
-    ok(
-      result.status !== 0,
-      `Expected non-zero exit, got ${result.status}. stderr: ${result.stderr}`,
-    );
-
-    let payload: OxlintJsonReport;
-    try {
-      payload = JSON.parse(result.stdout) as OxlintJsonReport;
-    } catch (err) {
-      throw new Error(
-        `Failed to parse oxlint JSON output: ${(err as Error).message}\n` +
-          `stdout: ${result.stdout}\nstderr: ${result.stderr}`,
-      );
-    }
-
-    const codes = (payload.diagnostics ?? []).map((d) => d.code ?? "");
-    const matched = codes.some((code) =>
-      code === "@fedify/lint(actor-id-required)" ||
-      code.includes("actor-id-required")
-    );
-    ok(
-      matched,
-      `Expected `@fedify/lint`(actor-id-required) diagnostic, got: ${
-        codes.join(", ") || "(none)"
-      }`,
-    );
+    try {
+      writeFileSync(
+        join(dir, ".oxlintrc.json"),
+        JSON.stringify({
+          jsPlugins: [pluginPath],
+          rules: {
+            "@fedify/lint/actor-id-required": "error",
+          },
+        }),
+      );
+      writeFileSync(join(dir, "federation.ts"), BAD_CODE);
+
+      const result = spawnSync(
+        oxlintBin!,
+        ["--format=json", "."],
+        { cwd: dir, encoding: "utf8" },
+      );
+
+      ok(
+        result.status !== 0,
+        `Expected non-zero exit, got ${result.status}. stderr: ${result.stderr}`,
+      );
+
+      let payload: OxlintJsonReport;
+      try {
+        payload = JSON.parse(result.stdout) as OxlintJsonReport;
+      } catch (err) {
+        throw new Error(
+          `Failed to parse oxlint JSON output: ${(err as Error).message}\n` +
+            `stdout: ${result.stdout}\nstderr: ${result.stderr}`,
+        );
+      }
+
+      const codes = (payload.diagnostics ?? []).map((d) => d.code ?? "");
+      const matched = codes.some((code) =>
+        code === "@fedify/lint(actor-id-required)" ||
+        code.includes("actor-id-required")
+      );
+      ok(
+        matched,
+        `Expected `@fedify/lint`(actor-id-required) diagnostic, got: ${
+          codes.join(", ") || "(none)"
+        }`,
+      );
+    } finally {
+      rmSync(dir, { recursive: true, force: true });
+    }
   },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/lint/src/tests/oxlint.test.ts` around lines 72 - 121, The test
creates a temporary directory in the local variable "dir" via mkdtempSync but
never removes it; wrap the test body in a try/finally (or add a teardown) and
remove the temp directory in the finally block using fs.rmSync(dir, { recursive:
true, force: true }) (or equivalent cleanup) to ensure the directory created by
mkdtempSync is always deleted after the test (keep references to the existing
symbols: mkdtempSync, dir, writeFileSync, spawnSync, and the test named "oxlint
plugin: actor-id-required fires on missing id").
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@packages/lint/src/tests/oxlint.test.ts`:
- Around line 72-121: The test creates a temporary directory in the local
variable "dir" via mkdtempSync but never removes it; wrap the test body in a
try/finally (or add a teardown) and remove the temp directory in the finally
block using fs.rmSync(dir, { recursive: true, force: true }) (or equivalent
cleanup) to ensure the directory created by mkdtempSync is always deleted after
the test (keep references to the existing symbols: mkdtempSync, dir,
writeFileSync, spawnSync, and the test named "oxlint plugin: actor-id-required
fires on missing id").

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3e7360ef-6edd-4b6d-8e68-5eaba546c321

📥 Commits

Reviewing files that changed from the base of the PR and between 14f5ce4 and 50be486.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • .hongdown.toml
  • docs/manual/lint.md
  • examples/lint/oxlint/README.md
  • packages/lint/README.md
  • packages/lint/deno.json
  • packages/lint/package.json
  • packages/lint/src/tests/oxlint.test.ts

nyanrus and others added 2 commits May 10, 2026 22:11
Two review points on packages/lint/src/tests/oxlint.test.ts:

  -  Make the runtime story explicit. The test imports `node:*` modules
     and spawns the oxlint binary, which is unusual for this package
     compared with the in-process Deno.lint / ESLint Linter tests. The
     header comment now spells out that Deno's node compat layer is what
     keeps the same source running under both `pnpm test` and
     `deno task test`, that subprocess-spawning is intentional (oxlint
     is a Rust binary), and that the binary plus the built loader are
     ignore-skip preconditions.

  -  Clean up the temp fixture directory. Wrap the test body in
     `try/finally` so `rmSync(dir, { recursive: true, force: true })`
     runs whether the assertions pass or throw. Avoids local/CI temp
     buildup.

Refs: fedify-dev#760

Assisted-by: Claude Code:claude-opus-4-7
Co-authored-by: Hong Minhee (洪 民憙) <hong@minhee.org>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/manual/lint.md`:
- Line 318: Remove the unused reference-style link definition "[Rules]: `#rules`"
from docs/manual/lint.md; locate the literal "[Rules]: `#rules`" (the reference
link definition) and delete that line since the page already uses an inline
anchor "( *Rules* section](`#rules`)" and the reference is unused.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: dedc1a61-f7cd-4198-ad44-257bc24cc719

📥 Commits

Reviewing files that changed from the base of the PR and between de2b2ba and f1c8be9.

📒 Files selected for processing (1)
  • docs/manual/lint.md

Comment thread docs/manual/lint.md Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add official Oxlint support to @fedify/lint

2 participants