@crescware/dependency-aware-oxlint
v0.0.2
Published
A scope-aware runner for oxlint that applies lint rules based on the import dependency graph.
Downloads
254
Readme
@crescware/dependency-aware-oxlint
A scope-aware runner for oxlint that applies lint rules based on the import dependency graph.
Features
- Runs
oxlintonce per scope defined in a config file, then aggregates the results into a single report. - Two ways to attach an oxlint config to a scope: inline (
oxlintConfig) or by path (oxlintrcPath). include/excludeuse gitignore-style patterns (viaignore).- Exclude is dependency-aware: a file matched by
excludeis still linted if it has any ancestor (an importer, transitively) that is not excluded. - Import graph is built from static imports, re-exports, and string-literal dynamic imports, resolved with
oxc-resolver(optionally using yourtsconfig.json).
Installation
Requires Node 24.x. oxlint is a peer dependency — install both:
pnpm add -D @crescware/dependency-aware-oxlint oxlintGetting started
1. Create dependency-aware-oxlint.config.ts
import type { DependencyAwareOxlintConfig } from "@crescware/dependency-aware-oxlint";
export default {
rootDir: "src",
tsconfig: "tsconfig.json",
scopes: [
{
name: "strict",
oxlintConfig: {
plugins: [],
rules: {
"no-console": "error",
},
},
include: ["**/*.ts"],
exclude: ["**/form-schema.*"],
},
],
} satisfies DependencyAwareOxlintConfig;Alternatively, point at an existing .oxlintrc.* file instead of defining rules inline:
{
name: "strict",
oxlintrcPath: ".oxlintrc.strict.json",
include: ["**/*.ts"],
exclude: ["**/form-schema.*"],
}2. Run the CLI
pnpm dependency-aware-oxlintSample output (from running the CLI against integration-tests/fixtures/inline-config/):
[strict] src/item.ts:1:1
error: Unexpected console statement.
rule: eslint(no-console)
help: Delete this console statement.
[strict] src/api-schema.ts:3:1
error: Unexpected console statement.
rule: eslint(no-console)
help: Delete this console statement.
Summary: 2 errors, 0 warnings across 1 scopeProcess exit code is 1 if any diagnostic has severity: "error", otherwise 0.
Configuration reference
The config file is resolved, in order, as one of:
dependency-aware-oxlint.config.tsdependency-aware-oxlint.config.mtsdependency-aware-oxlint.config.jsdependency-aware-oxlint.config.mjs
Config files are loaded via jiti, so TypeScript sources work without a pre-build step.
Types
type DependencyAwareOxlintConfig = {
rootDir: string;
tsconfig?: string;
scopes: ScopeDefinition[];
};
type ScopeDefinition =
| {
name: string;
include: string[];
exclude?: string[];
oxlintConfig: OxlintConfig; // from "oxlint"
}
| {
name: string;
include: string[];
exclude?: string[];
oxlintrcPath: string;
};rootDir— directory that is walked to collect source files and to whichinclude/excludepatterns are relative. Relative paths are resolved from the config file's directory.tsconfig— optional path to atsconfig.json, passed tooxc-resolver(withreferences: "auto"). If omitted,tsconfig.jsonnext to the config file is used when present.scopes[].name— used as a label in the report and to select via--scope.scopes[].include/scopes[].exclude— gitignore-style patterns matched against the file path relative torootDir(normalized to forward slashes).- Exactly one of
oxlintConfig(inline object) oroxlintrcPath(path to a.oxlintrc.*file) must be set per scope. Inline configs are written to a temporary file and cleaned up after the run.
Source files are discovered by walking rootDir, skipping dotfiles and the directories: node_modules, .git, dist, build, coverage, .next, .turbo. Files with these extensions are picked up: .ts, .tsx, .js, .jsx, .mts, .cts, .mjs, .cjs.
CLI reference
dependency-aware-oxlint [files...]
Options:
-c, --config <path> Path to dependency-aware-oxlint.config.ts
-s, --scope <name> Only run the given scope (can be passed multiple times)
--cwd <path> Working directory (defaults to process.cwd)--config— if omitted, the config file is searched in--cwd(orprocess.cwd()).--scope— can be repeated to select multiple scopes. When omitted, every scope in the config is run.
Scope resolution
For each scope, the set of files to lint is computed against the whole dependency graph rooted at rootDir:
- Start with every file that matches
include. - If the file matches
exclude, keep it only when at least one ancestor (a file that transitively imports it) is not excluded. Files with no ancestors are dropped when they matchexclude.
Example (see integration-tests/fixtures/inline-config/):
include: ["**/*.ts"],exclude: ["**/form-schema.*"]form-schema.tsimportsitem.tsanduser.ts.api-schema.tsalso importsitem.ts.- Result:
form-schema.tsis dropped (matchesexclude, no importer).user.tsis dropped (only ancestor is the excludedform-schema.ts).item.tsis kept (one ancestor,api-schema.ts, is not excluded).api-schema.tsis kept.
Output & exit code
Report lines are emitted in scope order. Each diagnostic renders as:
[<scope>] <relativePath>[:<line>:<column>]
<error|warning>: <message>
rule: <code>
help: <help> # when providedA trailing summary line reports totals:
Summary: <n> errors, <m> warnings across <k> scopesExit code is 1 when errorCount > 0, else 0.
Development
This repository uses pnpm (pinned via packageManager) and the Node version declared in mise.toml.
Scripts (package.json):
| Script | Command |
| ------------- | ------------------------------------- |
| build | tsgo -p tsconfig.json |
| dev | tsgo -p tsconfig.json --watch |
| check | pnpm check:types && pnpm check:lint |
| check:types | tsgo -p tsconfig.json --noEmit |
| check:lint | oxlint && oxfmt --check |
| format | oxlint --fix && oxfmt |
| test | pnpm build && vitest run |
| exec | node dist/cli.js |
License
MIT © Crescware Inc.
