Skip to content

chore: migrate tooling to oxlint, oxfmt and tsc - #2422

Merged
dinwwwh merged 12 commits into
mainfrom
claude/wizardly-turing-6xl35j
Nov 5, 2026
Merged

dinwwwh merged 12 commits into
mainfrom
claude/wizardly-turing-6xl35j

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

Follows middleapi/standard-server#184: replace ESLint and obuild with oxlint, oxfmt and plain tsc, matching standard-server's configs except where oRPC needs something different (listed below).

Lint and type check

  • pnpm check / pnpm fix run oxlint with type-aware rules and type checking (via oxlint-tsgolint). This covers packages, tests, *.test-d.ts, playgrounds and the docs site, and replaces both pnpm lint and pnpm type:check.
  • pnpm format runs oxfmt. CI doesn't check formatting.
  • The config starts from standard-server's and keeps oRPC's restrictions: JSON.stringify, .bytes, throwIfAborted and AbortSignal.any as banned properties, plus restricted globals and restricted imports.
  • Findings are fixed in code rather than turned off where possible:
    • void on intentional fire-and-forget promises
    • import * as z from 'zod'
    • explicit return undefined
    • toSorted/toReversed outside packages
    • inline oxlint-disable-next-line at the few deliberate sites
  • Removed: eslint and its plugins, lint-staged and simple-git-hooks.

TypeScript and build

  • TypeScript 7 with module: nodenext and verbatimModuleSyntax. Relative imports use explicit .ts extensions, which tsc rewrites to .js.
  • tsconfig.base.json is folded into tsconfig.json + tsconfig.lib.json, and project references are dropped.
  • Packages build with tsc (per-file .js + .d.ts). Exports change from .mjs/.d.mts to .js/.d.ts. obuild, build.config.ts and verifyDist are removed.
  • bun, cloudflare and nest type check with tsconfig.json (which includes their tests) and build with tsconfig.build.json.
  • packages/next/src/server-function.test.tsx shared its name with server-function.test.ts, so TypeScript skipped it and it was never type checked. It's renamed to server-function.action-state.test.tsx.

Formatting

The repo is reformatted with oxfmt, including code samples in docs .mdx files, in its own commit (chore: format with oxfmt) to keep review manageable. @ts-expect-error directives that the reformat moved away from their error lines are moved back.

Repo

  • Editor settings for VS Code and Zed now use oxc. CI runs pnpm check.
  • Dependabot groups @standard-server/*, @openapi-spec/* and dev-dependency minor/patch updates.
  • pnpm repo:fix runs sherif --fix, ignoring typescript versions because the next and nest playgrounds stay on TypeScript 6 on purpose. sherif only matches exact versions, so a version-specific ignore would stop working after the next bump.
  • pnpm is pinned via packageManager: pnpm@12.16.1.
  • CLAUDE.md and the Claude Code format hook are removed; AGENTS.md is the concise instructions file.
  • The vendored agent skills stay committed and are excluded from lint and format via ignorePatterns. skills-lock.json doesn't pin versions, so git is the pin.

Differences from standard-server

  • Rules off everywhere:
    • no-generated-empty-object-type: fixing it would change public types.
    • no-unnecessary-type-assertion: its auto-fix broke type checking on generic code.
    • unbound-method: about 400 false positives on next taken from interceptor options.
    • no-shadow: 127 hits in package source.
  • Relaxed override: the override for tests and playgrounds also covers apps/content, and turns off require-yield, no-unsafe-optional-chaining and await-thenable for test fixtures.
  • Kept on purpose:
    • jsx and the .test.tsx / __tests__ entries in the tsconfigs.
    • The typescript-6 alias for the docs JSDoc checker, which needs the TS compiler API that TS7 doesn't have.
    • TypeScript 6 in the next and nest playgrounds, for the same reason.
    • The docs:validate step in CI.

Verification

  • pnpm check and oxfmt --check pass.
  • Tests pass: vitest 4390, @orpc/cloudflare 81 (workerd), @orpc/bun 100.
  • All 29 packages build with tsc.
  • pnpm docs:validate passes, and blume build succeeds.
  • The playground type checks pass (next and nest on TS6, cloudflare on TS7).

For contributors: existing clones still have simple-git-hooks' pre-commit hook, which calls the removed lint-staged. Delete it once with rm .git/hooks/pre-commit.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VVaw7NPXNhdw5kppy7fFNE

Lint and type check
- `check`/`fix` run oxlint with type-aware rules and type checking (via
  oxlint-tsgolint), covering packages, tests, *.test-d.ts and playgrounds;
  `format` runs oxfmt and is not checked in CI
- port the ban/restricted-globals/restricted-imports rules to
  `no-restricted-properties`, `no-restricted-globals` and
  `no-restricted-imports`
- `correctness` and `suspicious` categories as errors; rules that would change
  public types or misfire on oRPC patterns are turned off with a reason
- fix the remaining findings: `void` for intentionally floating promises,
  `toSorted` outside packages, stale disable directives
- remove eslint, @antfu/eslint-config, eslint plugins, lint-staged,
  simple-git-hooks and sherif

TypeScript
- TypeScript 7 for builds and type checks; the docs JSDoc checker keeps the
  TypeScript 6 API through the `typescript-6` alias
- inline tsconfig.base.json into tsconfig.json + tsconfig.lib.json
- `module: nodenext`, `verbatimModuleSyntax`; relative imports use explicit
  `.ts` extensions, rewritten to `.js` on build
- drop project references and per-package include/exclude; bun, cloudflare
  and nest type check with tsconfig.json and build with tsconfig.build.json
- rename next's server-function.test.tsx, which shadowed
  server-function.test.ts and was never type checked

Build
- replace obuild with plain `tsc` (per-file .js + .d.ts in dist) and drop
  verifyDist

Editors and agents
- VS Code recommends the oxc extension; VS Code and Zed format and fix on save
  through oxfmt and oxlint
- the Claude Code hook formats edited files with oxfmt
- CLAUDE.md becomes AGENTS.md (CLAUDE.md imports it)

Misc
- pin pnpm via `packageManager` instead of `devEngines`

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVaw7NPXNhdw5kppy7fFNE
Run `pnpm format` across the repo, and move the `@ts-expect-error`
directives that the reformat separated from the line they expect an error on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVaw7NPXNhdw5kppy7fFNE
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVaw7NPXNhdw5kppy7fFNE
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVaw7NPXNhdw5kppy7fFNE
- oxlint: start from standard-server's config; keep oRPC's restriction rules,
  turn off only rules whose fixes would change public types or break type
  checking, plus test-fixture patterns; fix the rest (`void` for intentional
  floating promises, `import * as z from 'zod'`, explicit `return undefined`,
  `toSorted`/`toReversed` in tests, ...)
- `oxlint-disable` comments instead of `eslint-disable`, inline in scripts
- drop ignorePatterns: generated sponsor modules are formatted by
  `sponsors:sync`, and vendored agent skills are no longer committed (restore
  them with `npx skills experimental_install`)
- tsconfig: drop allowImportingTsExtensions, resolveJsonModule,
  isolatedDeclarations and the package.json include
- vitest only excludes .claude/worktrees; dependabot without groups; VS Code
  settings as in standard-server
- remove CLAUDE.md and the Claude Code format hook; run `pnpm format` manually
- AGENTS.md: multi-scope PR title example

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVaw7NPXNhdw5kppy7fFNE
- oxlint: keep `no-base-to-string`, `no-unnecessary-type-parameters`,
  `no-redundant-type-constituents`, `no-unassigned-import`,
  `consistent-function-scoping`, `no-array-sort`/`no-array-reverse`,
  `no-thenable`, `no-extraneous-class` and `no-misused-spread` on as in
  standard-server, with inline disables at the few intentional sites; move
  `no-unassigned-import` and `consistent-function-scoping` to the test
  override; hoist `isPrimitive` and `countWords`
- `oxlint-disable-next-line` instead of the trailing `disable-line`
- packages/node uses lib ES2022 like standard-server's node packages
- pnpm 12.16.1; cloudflare playground on TypeScript 7

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVaw7NPXNhdw5kppy7fFNE
The tests import from vitest, so vitest/globals is not needed; matches
tsconfig.build.json.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVaw7NPXNhdw5kppy7fFNE
Move the rule into the root rules and add apps/content to the override that
relaxes rules for tests and playgrounds; drop the disables and lint-only edits
there that this makes unnecessary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVaw7NPXNhdw5kppy7fFNE
skills-lock.json does not pin a version (restoring downloads the latest
upstream and rewrites the hash), so commit the reviewed skills and leave them
to lint and format through ignorePatterns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVaw7NPXNhdw5kppy7fFNE
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
orpc a2218b0 Commit Preview URL

Branch Preview URL
Nov 05 2026, 10:01 AM

@pkg-pr-new

pkg-pr-new Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
More templates

@orpc/ai-sdk

npm i https://pkg.pr.new/@orpc/ai-sdk@2422

@orpc/arktype

npm i https://pkg.pr.new/@orpc/arktype@2422

@orpc/bun

npm i https://pkg.pr.new/@orpc/bun@2422

@orpc/client

npm i https://pkg.pr.new/@orpc/client@2422

@orpc/cloudflare

npm i https://pkg.pr.new/@orpc/cloudflare@2422

@orpc/contract

npm i https://pkg.pr.new/@orpc/contract@2422

@orpc/effect

npm i https://pkg.pr.new/@orpc/effect@2422

@orpc/evlog

npm i https://pkg.pr.new/@orpc/evlog@2422

@orpc/hibernation

npm i https://pkg.pr.new/@orpc/hibernation@2422

@orpc/json-schema

npm i https://pkg.pr.new/@orpc/json-schema@2422

@orpc/experimental-lock

npm i https://pkg.pr.new/@orpc/experimental-lock@2422

@orpc/mcp

npm i https://pkg.pr.new/@orpc/mcp@2422

@orpc/msw

npm i https://pkg.pr.new/@orpc/msw@2422

@orpc/nest

npm i https://pkg.pr.new/@orpc/nest@2422

@orpc/next

npm i https://pkg.pr.new/@orpc/next@2422

@orpc/node

npm i https://pkg.pr.new/@orpc/node@2422

@orpc/openapi

npm i https://pkg.pr.new/@orpc/openapi@2422

@orpc/opentelemetry

npm i https://pkg.pr.new/@orpc/opentelemetry@2422

@orpc/pinia-colada

npm i https://pkg.pr.new/@orpc/pinia-colada@2422

@orpc/pino

npm i https://pkg.pr.new/@orpc/pino@2422

@orpc/publisher

npm i https://pkg.pr.new/@orpc/publisher@2422

@orpc/ratelimit

npm i https://pkg.pr.new/@orpc/ratelimit@2422

@orpc/server

npm i https://pkg.pr.new/@orpc/server@2422

@orpc/shared

npm i https://pkg.pr.new/@orpc/shared@2422

@orpc/swr

npm i https://pkg.pr.new/@orpc/swr@2422

@orpc/tanstack-query

npm i https://pkg.pr.new/@orpc/tanstack-query@2422

@orpc/trpc

npm i https://pkg.pr.new/@orpc/trpc@2422

@orpc/valibot

npm i https://pkg.pr.new/@orpc/valibot@2422

@orpc/zod

npm i https://pkg.pr.new/@orpc/zod@2422

commit: a2218b0

@codecov

codecov Bot commented Nov 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed

codspeed Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

1 warning

⚠️ 6 benchmarks are dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

✅ 28 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing claude/wizardly-turing-6xl35j (a2218b0) with main (52a3ca1)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

- `pnpm repo:fix` runs `sherif --fix`, ignoring the TypeScript 6 the next and
  nest playgrounds need for the compiler API
- dependabot groups `@standard-server/*`, `@openapi-spec/*` and dev
  dependency minor/patch updates

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVaw7NPXNhdw5kppy7fFNE
sherif only matches exact versions, so `typescript@^6.0.3` would stop matching
once the TypeScript 6 playgrounds are bumped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVaw7NPXNhdw5kppy7fFNE
`compression` was inlined into @orpc/interop, which #1653 removed together
with the dependency, so the dependabot exclude and the restricted import no
longer match anything.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVaw7NPXNhdw5kppy7fFNE

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • Lint and type check move to oxlint: check/fix now run oxlint with typeAware and typeCheck, folding pnpm type:check into one command; ESLint, its plugins, lint-staged, simple-git-hooks and sherif are removed.
  • Build moves from obuild to tsc: per-file .js/.d.ts emit, prepack: tsc in every package, publish exports switched from .mjs/.d.mts to .js/.d.ts, and every build.config.ts plus verifyDist deleted.
  • Module resolution and tsconfigs: module: nodenext, verbatimModuleSyntax, explicit .ts relative imports rewritten on emit; tsconfig.base.json folded into tsconfig.json + tsconfig.lib.json; project references dropped; bun, cloudflare and nest pinned to their own build configs.
  • Lint-fix code edits: void on intentionally floating promises, toSorted in tests and scripts, explicit return undefined, { cause } on the retry TypeError, String() inside template literals, and a rename of packages/next/src/server-function.test.tsx so it is actually type checked.
  • Reformat: oxfmt across source, docs .mdx code samples, JSON/JSONC and markdown, with the moved @ts-expect-error directives re-anchored.
  • Repo/agent config: CLAUDE.md and the Claude format hook replaced by AGENTS.md, VS Code/Zed switched to oxc, dependabot groups dropped, pnpm pinned via packageManager, and the vendored .agents/skills committed and excluded via ignorePatterns.

I verified the central claims against the branch with a fresh install: pnpm check passes and genuinely type checks (injected TS2322/TS18048, *.test-d.ts assertion failures, and a process.cwd() probe in @orpc/shared were all reported, and strict mode is on), oxfmt --check passes, oxlint --fix leaves the tree clean, all 29 packages build with prepack, and a consumer importing the built dist of @orpc/server, @orpc/client, @orpc/shared and @orpc/openapi type-checks and runs under Node. I also confirmed every publishConfig export target maps to an existing src file, dev and publish export keys match in all packages, and the emitted dist has no relative-import breakage, undeclared dependencies or import cycles. Root vitest gives 4387 passing; the only failures were three tests in tests/rpc/cancel-and-abort.test.ts, which pass when that file is run alone (pre-existing timing flake under load — the file's diff is import-extension only). pnpm docs:validate and blume build both succeed.

ℹ️ verifyDist guardrails no longer run

The obuild hook that failed publishing on undeclared imports, relative imports to non-emitted files, and import cycles is gone. I re-ran all three checks against the current emitted dist by hand and found no violations — only bun and cloudflare:workers platform imports exist outside declared dependencies, no cycles, and every relative specifier resolves. Worth knowing that nothing will catch these automatically on future changes, especially now that declarations are emitted per file rather than through a bundler hook.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏

dinwwwh commented Nov 5, 2026

Copy link
Copy Markdown
Member Author

Re the Pullfrog note that verifyDist guardrails no longer run: this is intentional. The maintainer asked not to port verifyDist to the tsc build. Pullfrog's manual re-check found the current dist clean (no undeclared imports, no broken relative imports, no cycles), so nothing changes here.


Generated by Claude Code

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes (incremental since the prior review at d5c78e8)

  • sherif restored: repo:fix script (sherif --fix -i typescript), sherif ^1.13.0 in devDependencies, and the AGENTS.md command list updated. -i typescript correctly suppresses the only finding sherif reports (multiple-dependency-versions for typescript, because the next and nest playgrounds deliberately stay on TS6); sherif -i typescript exits clean.
  • Dependabot groups restored: @standard-server/*, @openapi-spec/* and dev-dependency minor/patch. The eslint group stays gone with the ESLint removal.
  • Compression cleanup: compression dropped from no-restricted-imports and from the dependabot exclude patterns. That was genuinely leftover — it only ever appeared as a package keyword, never as a dependency or source import.
  • PR description and AGENTS.md updated to match the restored repo:fix command.

Re-verified after these commits: pnpm install --frozen-lockfile is consistent with the lockfile, pnpm check still reports 0 warnings/errors, oxfmt --check still passes, and the working tree stays clean.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏

@dinwwwh
dinwwwh merged commit f7a7a2a into main Nov 5, 2026
12 checks passed
dinwwwh pushed a commit that referenced this pull request Nov 9, 2026
Since #2422, `tsc` built the packages and dropped imports from
declarations when their only use was inside a `declare module`
augmentation that another file of the program also augmented:
`@orpc/effect/extensions/effect` lost `DecoratedProcedure`, so `.effect()`
returned an unresolved type and `createRouterClient` accepted any context
and input. tsc's import elision depends on the whole program, so this
can come back with any new augmentation.

obuild's transform mode emits one `.mjs` + `.d.mts` per file with oxc's
isolated declarations, which only depend on the file itself:

- one shared `build.config.ts` at the root, run by every package's
  `prepack` (`node ../../build.config.ts`)
- `import x from './file.json' with { type: 'json' }` is inlined into the
  emitted code, keeping only the properties that are read
  (`@orpc/opentelemetry` reads `name` and `version` of package.json)
- `verifyDist` from before #2422 is back: dependencies, emitted relative
  imports, import cycles, missing declarations (obuild only warns on
  `isolatedDeclarations` errors) and package.json paths
- `pnpm build` builds and verifies every package, and CI runs it
- `isolatedDeclarations` in tsconfig.lib.json, with explicit types in
  `@orpc/shared` regexes
- exports move back from `.js`/`.d.ts` to `.mjs`/`.d.mts`
- the `DecoratedProcedure` alias workaround in the effect extension is
  reverted

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVaw7NoNaJhK4MBSMMhE4E
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.

2 participants