Skip to content

chore: replace Biome with oxlint, oxfmt and Knip - #32

Open
Thomasims wants to merge 5 commits into
mainfrom
chore/oxc-tooling
Open

chore: replace Biome with oxlint, oxfmt and Knip#32
Thomasims wants to merge 5 commits into
mainfrom
chore/oxc-tooling

Conversation

@Thomasims

Copy link
Copy Markdown
Contributor

Moves the repository onto the shared @antelopejs/tooling-configs presets: oxlint with the vendored anti-slop rules, oxfmt for formatting, and Knip for dead code.

Tooling

biome.json and @biomejs/biome are gone, replaced by oxlint.config.ts, oxfmt.config.ts and knip.config.ts. lint, lint:fix and format point at the new tools, and format:check and knip are new.

tsconfig

Type-aware linting runs through tsgolint, which rejects options TypeScript 7 removes. moduleResolution: "node" (node10) is one of them, so it goes; baseUrl gives way to an explicit rootDir. Nothing else in the build changes.

module deliberately stays on commonjs rather than moving to node16. Under node16 TypeScript stops downlevelling await import(...) and emits a native ESM dynamic import, which does not go through the AntelopeJS CJS resolver detour. The interface package then gets loaded twice and its internal circular requires blow up — every test fails at construct time with Class extends value undefined is not a constructor or null from @antelopejs/interface-database/dist/datum.js. Dropping moduleResolution entirely and leaving module alone satisfies tsgolint and keeps the CommonJS emit, so type-aware linting is fully enabled here.

Code changes the linter asked for

  • import/no-cycle: query.tsexpression.tsquery.ts. DecodeValue and DecodeFunction are mutually recursive with Expression.decode, so they move into expression.ts alongside the class they recurse with; pipeline.ts and selection.ts import them from there. query.ts is left as the interface entry point (RunQuery, ReadCursor, CloseCursor).
  • import/no-cycle, pipeline.tsselection.ts: this pair carries a targeted disable on each side rather than a rewrite. SelectionQuery extends AggregationPipeline, and AggregationPipeline is also the one that has to decode the right-hand side of union, join and lookup, which is always a full schema/instance/table stream and therefore a SelectionQuery. The cycle is a base class dispatching to its own subclass decoder; every module-level way to break it (a registry, a decoder injected at load time) replaces a compile-time edge with a runtime load-order hazard in the query compiler, which is not a trade worth making for a lint clean-up. Both imports carry oxlint-disable-next-line import/no-cycle with that reasoning.
  • unicorn/no-thenable in stage_lookup: MongoDB's $cond operator literally takes a then branch. The existing biome-ignore becomes an oxlint-disable-next-line with the same reason.
  • typescript/no-floating-promises in Disconnect: internal.UnsetClient() returns a fresh, deliberately unresolved client promise, so awaiting it would deadlock. It is now explicitly void-ed, matching what the interface package itself does.
  • unicorn/no-empty-file: src/implementations/database/index.ts contained nothing but a stale block comment listing features and MongoDB documentation links, and was imported by nothing. It is deleted. Say the word if that scratchpad is still wanted somewhere.
  • Import order across the repository is autofixed by oxlint --fix.

The 5 remaining findings are warnings the preset raises deliberately (max-lines on pipeline.ts, max-params, max-lines-per-function on a test, and two await-thenable) and do not fail the build. They are a backlog to work through, not a gate.

Knip

Removed as genuinely dead: ListDatabases in connection.ts had no callers at all. Un-exported because nothing outside their own file uses them and none are part of the package surface (src/index.ts re-exports none of them): GetDatabase, IndexDefinition, COLLECTION_NAME_SEPARATOR, and Expression (which became file-local once DecodeValue moved in).

reflect-metadata and @types/mocha are recorded as ignored with the reason: emitDecoratorMetadata makes tsc emit Reflect.metadata calls that need the polyfill at runtime even though nothing imports it, and @types/mocha supplies the globals for the suites ajs module test runs. ajs itself is ignored because CI installs @antelopejs/core globally.

Verification

pnpm build, pnpm lint and pnpm knip are clean. pnpm test is 169 passing / 0 failing — identical to untouched main, measured in a throwaway worktree before any of this landed.

The formatting pass is its own commit and is recorded in .git-blame-ignore-revs.

The .github/ISSUE_TEMPLATE/** entry in oxfmt.config.ts is temporary and can be dropped once AntelopeJS/tooling-configs#5 ships.

Adopts the shared @antelopejs/tooling-configs presets: oxlint with the
vendored anti-slop rules, oxfmt for formatting and Knip for dead code.

Type-aware linting needs a tsconfig tsgolint accepts, so the removed
moduleResolution node10 option goes away and baseUrl gives way to rootDir.
The module stays on commonjs: node16 emit turns the dynamic interface
imports into native ESM, which bypasses the AntelopeJS resolver and breaks
every test at construct time.

Breaks the query -> expression -> query cycle by moving DecodeValue and
DecodeFunction next to the Expression class they recurse with, drops a
comment-only file and a handful of exports Knip found unused.
@Thomasims
Thomasims marked this pull request as draft September 7, 2026 10:36
oxfmt formats this repository with two-space indentation; the .editorconfig
still declared tabs at width 4, so editors fought the formatter on every save.
@Thomasims
Thomasims marked this pull request as ready for review September 7, 2026 16:10
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.

1 participant