Skip to content

Support TypeScript5.9.x and hey-api/openapi-ts 0.92.x#192

Open
TakehiroTada wants to merge 9 commits into7nohe:mainfrom
TakehiroTada:feature/support-ts-5.9.x
Open

Support TypeScript5.9.x and hey-api/openapi-ts 0.92.x#192
TakehiroTada wants to merge 9 commits into7nohe:mainfrom
TakehiroTada:feature/support-ts-5.9.x

Conversation

@TakehiroTada
Copy link

Summary

This PR upgrades the core dependencies to support TypeScript 5.9.x and the latest @hey-api/openapi-ts (0.92.3), which introduced a completely new plugins-based configuration system.

Dependency Upgrades

Package Before After
typescript 5.5.4 5.9.3
ts-morph 23.x 27.x
@hey-api/openapi-ts 0.53.8 0.92.3

Key Changes

1. Migration to @hey-api/openapi-ts Plugins System

@hey-api/openapi-ts 0.92.3 replaced its flat configuration (client, schemas, services, types) with a plugins array. The generate.mts has been updated to build the plugins array from CLI options:

  • @hey-api/client-fetch / @hey-api/client-axios — selected via --client
  • @hey-api/typescript — accepts enums option from --enums
  • @hey-api/sdk — accepts operationId option from --noOperationId
  • @hey-api/schemas — conditionally added (controlled by --noSchemas), accepts type from --schemaType

2. Backward-Compatible services.gen.ts Shim

The new @hey-api/openapi-ts generates sdk.gen.ts (SDK functions) and client.gen.ts (client instance) instead of the old services.gen.ts. To avoid breaking existing user code that imports from services.gen.ts, a shim file is auto-generated:

// services.gen.ts (auto-generated shim)
export * from './client.gen';
export * from './sdk.gen';

3. TypeScript 5.9 Compatibility for ts-morph

In TS 5.9, the SyntaxKind enum values shifted (e.g., ArrowFunction changed from 219 to 220). Since ts-morph bundles its own TypeScript internally, using ts.isArrowFunction() from a separately imported typescript package caused mismatches. The fix:

  • service.mts: Updated getMethodsFromService() to handle both old-style (block body) and new-style (expression body) arrow functions generated by @hey-api/sdk
  • Type narrowing: Replaced as type assertions with proper type guards using ts.isArrowFunction(), ts.isBlock(), etc.

4. Codegen Bug Fixes

  • Error type extraction: Fixed createUseQuery.mts and createUseMutation.mts to correctly extract error types from the new SDK function signatures (generics order changed: <ResponseType, ErrorType, ThrowOnError>)
  • Optional parameters: Fixed generated hooks to make clientOptions optional when the SDK function has no required parameters (using Options<Data, true> = {} default)
  • Import paths: Updated createImports.mts to import Options type from the new client module path instead of the old core path

5. skipLibCheck: false Support

  • Added src/vendor-typestubs.d.ts with type stubs for @hey-api/openapi-ts internal modules that lack proper type exports
  • Added a pnpm patch for @hey-api/openapi-ts@0.92.3 to fix a missing type export
  • Added biome.json to exclude vendor type stubs from linting

6. Documentation Updates

  • Updated directory structure in introduction.mdx to reflect new file layout (sdk.gen.ts, client.gen.ts, client/, core/)
  • Marked --useDateType and --debug as deprecated in cli-options.mdx (no equivalent in the new plugins API)
  • Added notes about --format / --lint only affecting the queries/ directory
  • Updated usage.mdx to mention the services.gen.ts backward-compatibility shim

Deprecated CLI Options

The following options are accepted but have no effect:

Option Reason
--useDateType No equivalent in the @hey-api/typescript plugin
--debug No equivalent in the new @hey-api/openapi-ts config

Files Changed (26 files)

Core codegen:

  • src/generate.mts — Plugins-based config, shim generation, CLI option mapping
  • src/service.mts — TS 5.9 compatible AST traversal for new SDK output format
  • src/createUseQuery.mts — Error type extraction, optional params
  • src/createUseMutation.mts — Error type extraction, optional params
  • src/createExports.mts — Type guard refactoring
  • src/createImports.mts — New import paths
  • src/createSource.mts — Updated service file reference
  • src/common.mts — Simplified type utilities
  • src/constants.mts — Updated service file name constant

Tests:

  • tests/__snapshots__/createSource.test.ts.snap — Updated snapshots
  • tests/__snapshots__/generate.test.ts.snap — Updated snapshots
  • tests/createImports.test.ts — Updated test expectations
  • tests/service.test.ts — Updated test expectations

Docs:

  • docs/src/content/docs/guides/introduction.mdx
  • docs/src/content/docs/guides/cli-options.mdx
  • docs/src/content/docs/guides/usage.mdx

Config & types:

  • package.json, pnpm-lock.yaml
  • biome.json, src/vendor-typestubs.d.ts
  • patches/@hey-api__openapi-ts@0.92.3.patch

Test Plan

  • All existing snapshot tests pass (pnpm test)
  • CLI options verified manually with petstore.yaml:
    • --enums javascript / --enums typescript
    • --noOperationId (function names change from operationId-based to HTTP method + path)
    • --noSchemas (schemas.gen.ts not generated)
    • --schemaType form (schemas.gen.ts generated with form type)
    • --useDateType / --debug (deprecated, no error)
  • Example apps updated (nextjs-app, tanstack-router-app)

TakehiroTada and others added 8 commits January 23, 2026 11:43
- Use Identifier.text instead of getText() for robust HTTP method name extraction
- Fix JSDoc extraction by searching from VariableStatement level instead of ArrowFunction
- Update tests/utils.ts to use hey-api 0.90.1 plugins API
- Update test snapshots to include correctly extracted JSDoc comments

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- service.mts: remove all `as` casts by using ts.isArrowFunction,
  ts.isReturnStatement, ts.isCallExpression type guards for proper narrowing
- createExports.mts: use reduce generic, ts.isTypeLiteralNode,
  ts.isPropertySignature type guards, and type predicate filter
- createUseQuery.mts: add comments explaining unavoidable assertions
  on factory-created nodes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Upgrade @hey-api/openapi-ts from 0.90.1 to 0.92.3
- Add vendor-typestubs.d.ts for framework-specific modules (Angular, Vue, Nuxt, ofetch)
  bundled in @hey-api/openapi-ts but not used in this project
- Add @types/semver for @hey-api/shared's semver import
- Patch @hey-api/openapi-ts to suppress TS2416 toAst() variance error
  caused by bundled declaration file incorrectly constraining base type
- Remove skipLibCheck: true from tsconfig.json (now defaults to false)
- Add biome override to allow any in type stubs file

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Generate backward-compatible services.gen.ts shim (re-exports from
  client.gen and sdk.gen) so existing import paths continue to work
- Fix missing error type references: fall back to `unknown` when
  ${methodName}Error type does not exist in generated types
- Fix incorrect `= {}` default for required SDK parameters by checking
  parameter optionality directly instead of extracting type properties
- Add @hey-api/client-fetch to nextjs-app and tanstack-router-app
- Add target: es2017 to nextjs-app tsconfig for iterator support
- Remove stale @hey-api/client-fetch import from react-app App.tsx
- Update test snapshots

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Map CLI options (--enums, --noOperationId, --noSchemas, --schemaType)
  to the new @hey-api/openapi-ts plugins API in generate.mts
- Mark --useDateType and --debug as deprecated (no equivalent in new API)
- Update introduction.mdx with new output directory structure
  (sdk.gen.ts, client.gen.ts, client/, core/)
- Update cli-options.mdx with accurate option descriptions
- Update usage.mdx to mention sdk.gen.ts and services.gen.ts shim

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Feb 11, 2026

@TakehiroTada is attempting to deploy a commit to the Daiki Urata's projects Team on Vercel.

A member of the Team first needs to authorize it.

@7nohe 7nohe self-requested a review February 12, 2026 00:11
Add tests for uncovered branches in generate.mts (axios client, enums,
noOperationId, noSchemas, schemaType options), service.mts edge cases
(non-exported vars, non-arrow functions, JSDoc, deprecated detection),
createImports.mts (axios client), and format.mts (prettier/eslint).
Replace @ts-ignore with proper type assertions in createImports tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR upgrades the codegen toolchain to support TypeScript 5.9.x and @hey-api/openapi-ts@0.92.x, migrating the requests generation to Hey API’s new plugin-based configuration while maintaining backwards compatibility for consumers expecting services.gen.ts.

Changes:

  • Migrate src/generate.mts to the @hey-api/openapi-ts plugins API and auto-generate a services.gen.ts shim that re-exports client.gen and sdk.gen.
  • Update AST/service parsing and hook/type generation to match the new Hey API SDK output and TS 5.9/ts-morph behavior (imports, error type extraction, optional clientOptions, JSDoc/deprecation propagation).
  • Add vendor typings/patching for skipLibCheck: false, and refresh tests, docs, and example apps accordingly.

Reviewed changes

Copilot reviewed 26 out of 28 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/generate.mts Builds Hey API plugin array, runs generation, and writes services.gen.ts shim.
src/service.mts Updates service-method extraction to handle both block and expression-bodied SDK arrow functions.
src/createUseQuery.mts Adjusts response/error typing and parameter optionality for new SDK signatures.
src/createUseMutation.mts Adjusts error typing for new SDK signatures and missing error models.
src/createImports.mts Switches Options import to the new requests client module path.
src/createExports.mts Refactors type guards / reduces assertions while determining infinite-query candidates.
src/createSource.mts Updates client typing to match updated CLI config types.
src/common.mts Makes methodBlock optional and changes request-param optionality detection logic.
src/constants.mts Switches primary service file name from services.gen to sdk.gen.
src/vendor-typestubs.d.ts Adds minimal stubs for Hey API internal type deps to support skipLibCheck: false.
patches/@hey-api__openapi-ts@0.92.3.patch Patches upstream d.ts to address a missing/invalid type export issue.
package.json Bumps dependencies and adds pnpm patchedDependencies configuration.
pnpm-lock.yaml Locks upgraded dependency tree and records patched dependency.
biome.json Excludes vendor type stubs from noExplicitAny.
tests/utils.ts Updates test generation config to plugins-based Hey API config.
tests/service.test.ts Updates/expands method extraction tests (export filtering, JSDoc, deprecated tags).
tests/generate.test.ts Adds generate coverage for axios+enums+noOperationId+schemaType and noSchemas.
tests/format.test.ts Adds tests for processOutput formatter/linter invocation.
tests/createImports.test.ts Updates expectations for new import paths and adds axios import coverage.
tests/snapshots/generate.test.ts.snap Updates snapshots for new request module paths and generated signatures/docs.
tests/snapshots/createSource.test.ts.snap Updates snapshots for new request module layout and error typing changes.
docs/src/content/docs/guides/introduction.mdx Updates documented output structure and shim usage.
docs/src/content/docs/guides/cli-options.mdx Updates CLI docs for plugin mapping and new behavior notes.
docs/src/content/docs/guides/usage.mdx Updates usage guidance for sdk.gen.ts and services.gen.ts shim.
examples/react-app/src/App.tsx Removes obsolete direct createClient usage (config handled elsewhere).
examples/nextjs-app/tsconfig.json Updates TS target for compatibility.
examples/nextjs-app/package.json Adds dependency updates for regenerated client setup.
examples/tanstack-router-app/package.json Adds dependency updates for regenerated client setup.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (2)

examples/nextjs-app/package.json:21

  • @hey-api/client-fetch is added as a dependency, but this example doesn’t appear to import it anymore (the generated client is local under openapi/requests). If it’s not required at runtime, consider removing it to avoid an unnecessary dependency.
  "dependencies": {
    "@hey-api/client-fetch": "^0.6.0",
    "@tanstack/react-query": "^5.59.13",
    "@tanstack/react-query-devtools": "^5.32.1",
    "next": "^14.2.3",
    "react": "^18",
    "react-dom": "^18"

examples/tanstack-router-app/package.json:35

  • @hey-api/client-fetch is added as a dependency, but there are no imports/usages of it in this example (generated client is local under openapi/requests). If it’s not required at runtime, consider removing it to avoid an unnecessary dependency.
  "dependencies": {
    "@hey-api/client-fetch": "^0.6.0",
    "@tanstack/react-query": "^5.59.13",
    "@tanstack/react-query-devtools": "^5.32.1",
    "@tanstack/react-router": "^1.58.7",
    "@tanstack/react-router-with-query": "^1.58.7",
    "@tanstack/router-devtools": "^1.58.7",
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 45 to 49
ts.factory.createImportSpecifier(
true,
undefined,
ts.factory.createIdentifier("Options"),
),
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

This file imports Options from ../requests/client, but createImports also imports all exports from sdk.gen. If sdk.gen exports a type named Options (as shown in the snapshots), the generated code will either have duplicate Options imports or attempt to import a type-only export as a runtime value under verbatimModuleSyntax. Filter out type-only exports (or at least exclude Options) when building serviceNames, or mark type-only specifiers appropriately.

Copilot uses AI. Check for mistakes.
},
"packageManager": "pnpm@9.6.0",
"engines": {
"node": ">=14",
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

The package @hey-api/openapi-ts@0.92.3 requires Node >=20.19.0 (per its engines), but this package still declares "node": ">=14". Update the engines.node range (and any related docs/CI) to match the new minimum supported Node version so installs fail fast with a clear message.

Suggested change
"node": ">=14",
"node": ">=20.19.0",

Copilot uses AI. Check for mistakes.
Comment on lines 88 to +90
### --schemaTypes \<value\>

Type of JSON schema. The default value is `json`.
Type of JSON schema. Only applies when `--noSchemas` is not set. The default value is `json`.
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

Docs list the option as --schemaTypes, but the CLI defines --schemaType (singular). Update the heading/usage string so users can copy/paste the correct flag.

Copilot uses AI. Check for mistakes.
Comment on lines +39 to 43
return exportedStatements.flatMap((variableStatement) => {
const declarations = variableStatement.getDeclarations();
return declarations.map((declaration) => {
if (!ts.isVariableDeclaration(declaration.compilerNode)) {
throw new Error("Variable declaration not found");
}
const initializer = declaration.getInitializer();
if (!initializer) {
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

getMethodsFromService filters variable statements by whether any declaration is an arrow function, but then maps over all declarations and throws if one isn't an arrow function. This will break for export const a = 1, foo = () => ...; style exports. Consider filtering declarations (or flatMap only arrow-function declarations) instead of throwing for non-arrow declarations within the same exported statement.

Copilot uses AI. Check for mistakes.
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