Skip to content

fix(deps): upgrade dependency chain through Next.js 16, fix generated tsconfig detection#199

Merged
7nohe merged 6 commits into
mainfrom
claude/hopeful-perlman-c56399
Jul 20, 2026
Merged

fix(deps): upgrade dependency chain through Next.js 16, fix generated tsconfig detection#199
7nohe merged 6 commits into
mainfrom
claude/hopeful-perlman-c56399

Conversation

@7nohe

@7nohe 7nohe commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Summary

This branch closes out a dependency-upgrade pass across the examples, ending with Next.js 16, plus a codegen bug found along the way.

  • fix(codegen): anchor tsconfig detection at generation cwd, not install diropenapi-ts auto-detects moduleResolution by walking up from its own install location when no tsConfigPath is given. In this pnpm monorepo that walk reached this repo's own root tsconfig.json (NodeNext, meant for the library's own source) instead of the target project's config, silently adding .js extensions to every generated relative import regardless of what the consuming project actually uses. Anchoring the search at process.cwd() fixes this; for a normal (non-monorepo) consumer it resolves to the same tsconfig as before. The hand-written services.gen.ts backward-compat shim also now mirrors whichever extension convention openapi-ts used, instead of hardcoding .js.
  • fix(deps): upgrade next.js 15.x to 16.x in nextjs-app — Turbopack is now the default bundler for both next dev and next build. Combined with the tsconfig fix above (the previous .js-extension imports were never resolvable by Turbopack — it has no equivalent of webpack's resolve.extensionAlias), the example now builds natively with no bundler-specific config or flags.
  • ci: verify nextjs-app production buildgenerate:api + tsc alone never caught that next build was actually broken. This step also now doubles as a regression guard for the tsconfig-detection fix above.
  • Earlier commits on this branch (already present before this PR) close out several dependency bumps: Next.js 14→15, Vite 5→6, Vitest 1→3, and assorted transitive/same-major security upgrades.

Why

  • next build for examples/nextjs-app was failing with Module not found: Can't resolve './client.gen.js' — never caught by CI because CI only ran generate:api + tsc, not an actual production build.
  • Root-causing the .js extension led to a real bug in how this repo's own generator (src/generate.mts) invokes @hey-api/openapi-ts, not just an example-side config issue — see the commit body on d106698 for the full investigation.

Test plan

  • pnpm -w build (library)
  • pnpm test (70 passed, 1 skipped) + pnpm biome check .
  • nextjs-app: next build (Turbopack, no flags) and next dev both work; tsc passes
  • react-app and tanstack-router-app (Vite): regenerate + tsc + build all pass, extension-less imports preserved
  • Standalone smoke test: generated a client against an isolated NodeNext tsconfig.json outside this repo — both sdk.gen.ts and the services.gen.ts shim correctly get .js extensions, and tsc passes — confirming the anchoring fix doesn't regress non-monorepo NodeNext consumers
  • pnpm install --frozen-lockfile succeeds (CI parity check)

Notes for reviewers

  • A known, pre-existing (unrelated to this PR) gap: the openapi/queries/*.ts files generated by createImports.mts don't carry any extension logic at all, so a NodeNext consumer would still hit TS2835 there. Fixing that is a separate, larger scope (making the query-file templates tsconfig-aware) and wasn't attempted here.
  • examples/nextjs-app's "lint": "next lint" script is now dead — next lint was removed from the Next.js 16 CLI, and this example never had an ESLint config to begin with. Left as-is since it's not exercised by CI; happy to remove it if preferred.

7nohe added 3 commits July 20, 2026 15:08
…l dir

openapi-ts auto-detects moduleResolution by walking up from its own
install location when no tsConfigPath is given. In this pnpm monorepo
that walk reaches this repo's own root tsconfig (NodeNext, meant for
the library's own source) instead of the caller's project config,
silently adding `.js` extensions to every generated relative import
regardless of what the target project actually uses.

Anchor the search at process.cwd() instead, which is the project the
CLI is actually being run against. For a normal (non-monorepo)
consumer this resolves to the same tsconfig as before; it only changes
behavior for this repo's own examples, which were getting the wrong
tsconfig by accident.

The hand-written services.gen.ts backward-compat shim previously
hardcoded `.js` on its re-exports, which not only assumed NodeNext but
also didn't match its own bundler-resolution examples. It now mirrors
whatever extension convention openapi-ts used for sdk.gen.ts's own
imports.

Verified: all three examples regenerate with extension-less imports
(matching their bundler moduleResolution) and pass tsc/build; a
standalone NodeNext project generates with `.js` extensions on both
sdk.gen.ts and the shim, and passes tsc.
Turbopack is now the default bundler for both `next dev` and
`next build`. Combined with the tsconfig-detection fix in
src/generate.mts (the previous `.js`-extension imports were never
resolvable by Turbopack anyway, since it has no equivalent of
webpack's resolve.extensionAlias), the example now builds natively
with no bundler-specific config or flags needed.

`next build` rewrote tsconfig.json's `jsx` to `react-jsx` (mandatory
for the React automatic runtime) and added `.next/dev/types/**/*.ts`
to `include`; kept the existing compact array formatting via biome.

Verified: `next build` (Turbopack) and `next dev` both work with no
config, tsc passes, and the full test suite + biome check still pass.
generate:api + tsc alone never caught that `next build` was broken
(webpack couldn't resolve the generated client's imports, later fixed
in a separate commit). Run the real production build so this class of
regression is caught going forward, including for the tsconfig
detection this build step now implicitly guards.
@vercel

vercel Bot commented Jul 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openapi-react-query-codegen Ready Ready Preview, Comment Jul 20, 2026 6:42am

@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🟢 Lines 99% (🎯 95%) 1989 / 2009
🟢 Statements 99% (🎯 95%) 1989 / 2009
🟢 Functions 100% (🎯 95%) 50 / 50
🟢 Branches 92.1% (🎯 90%) 210 / 228
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/generate.mts 100% 90.9% 100% 100%
Generated in workflow #424 for commit 0d86c3a by the Vitest Coverage Report Action

`next lint` was removed from the Next.js 16 CLI, so `pnpm --filter
nextjs-app lint` failed with "Invalid project directory provided"
(Codex review on PR #199). This example never had an ESLint config to
begin with, and its source is already covered by the workspace-root
`pnpm biome check .` (already run in CI) — no other example carries a
per-package lint script for the same reason. Dropped rather than
wired up a redundant local Biome/ESLint invocation.
No existing test exercised the requests/ output that openapi-ts
generates (only the queries/ react-query wrapper was snapshotted), so
neither the original .js-extension bug nor this session's fix to it
would have been caught by the suite.

Adds:
- Unit tests for findNearestTsConfigPath (now exported), covering
  same-dir match, walking up to an ancestor, preferring exact
  tsconfig.json over tsconfig.*.json variants, and the not-found case.
- End-to-end generate() tests in isolated tmpdir fixtures with their
  own tsconfig.json, chdir'd into for the duration of the call,
  asserting sdk.gen.ts and the services.gen.ts shim get no extension
  under bundler resolution and `.js` under NodeNext, and that the two
  always agree with each other.
@7nohe
7nohe merged commit a95f28d into main Jul 20, 2026
5 checks passed
@7nohe
7nohe deleted the claude/hopeful-perlman-c56399 branch July 20, 2026 06:47
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