fix(deps): upgrade dependency chain through Next.js 16, fix generated tsconfig detection#199
Merged
Merged
Conversation
…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.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||
`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.
…n-c56399 # Conflicts: # pnpm-lock.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 dir—openapi-tsauto-detectsmoduleResolutionby walking up from its own install location when notsConfigPathis given. In this pnpm monorepo that walk reached this repo's own roottsconfig.json(NodeNext, meant for the library's own source) instead of the target project's config, silently adding.jsextensions to every generated relative import regardless of what the consuming project actually uses. Anchoring the search atprocess.cwd()fixes this; for a normal (non-monorepo) consumer it resolves to the same tsconfig as before. The hand-writtenservices.gen.tsbackward-compat shim also now mirrors whichever extension conventionopenapi-tsused, instead of hardcoding.js.fix(deps): upgrade next.js 15.x to 16.x in nextjs-app— Turbopack is now the default bundler for bothnext devandnext build. Combined with the tsconfig fix above (the previous.js-extension imports were never resolvable by Turbopack — it has no equivalent of webpack'sresolve.extensionAlias), the example now builds natively with no bundler-specific config or flags.ci: verify nextjs-app production build—generate:api+tscalone never caught thatnext buildwas actually broken. This step also now doubles as a regression guard for the tsconfig-detection fix above.Why
next buildforexamples/nextjs-appwas failing withModule not found: Can't resolve './client.gen.js'— never caught by CI because CI only rangenerate:api+tsc, not an actual production build..jsextension 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 ond106698for 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) andnext devboth work;tscpassesreact-appandtanstack-router-app(Vite): regenerate +tsc+buildall pass, extension-less imports preservedNodeNexttsconfig.jsonoutside this repo — bothsdk.gen.tsand theservices.gen.tsshim correctly get.jsextensions, andtscpasses — confirming the anchoring fix doesn't regress non-monorepo NodeNext consumerspnpm install --frozen-lockfilesucceeds (CI parity check)Notes for reviewers
openapi/queries/*.tsfiles generated bycreateImports.mtsdon't carry any extension logic at all, so a NodeNext consumer would still hitTS2835there. 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 lintwas 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.