Skip to content

feat: add support for ky v2 #3724#3725

Open
atomicpages wants to merge 3 commits intohey-api:mainfrom
atomicpages:main
Open

feat: add support for ky v2 #3724#3725
atomicpages wants to merge 3 commits intohey-api:mainfrom
atomicpages:main

Conversation

@atomicpages
Copy link
Copy Markdown

@atomicpages atomicpages commented Apr 7, 2026

  • Align generated Config / kyOptions types: omit prefix instead of removed prefixUrl.
  • Handle HTTPError with isHTTPError, use error.data when Ky has consumed the body, and fall back to response.text() when the body is still readable (e.g. tests).
  • Add unit test for Ky-style errors with data and a failing response.text().
  • Refresh openapi-ts-tests snapshots for @hey-api/client-ky; bump ky to 2.x in the Ky example and test package; regenerate example client output.
  • Docs: update docs/openapi-ts/clients/ky.md for Ky 2, prefixUrlprefix, and kyOptions example.

Note: the tests I delegated to cursor. I'm happy to either revert and/or amend any changes. LMK

@bolt-new-by-stackblitz
Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@pullfrog
Copy link
Copy Markdown

pullfrog bot commented Apr 7, 2026

Reviewed PR #3725. Found a redundant/dead code path in the error-handling logic at client.ts:207-214 and a personal .vscode/settings.json change that should be reverted. The core ky v2 migration (import changes, isHTTPError, prefixUrlprefix, error.data handling) looks correct. Submitted review with inline comments.

Task list (6/6 completed)
  • Read diff and identify major areas of change
  • Review core client implementation (bundle/client.ts, bundle/types.ts)
  • Review test changes
  • Review docs, examples, and dependency changes
  • Review snapshots for consistency
  • Submit review

Pullfrog  | View workflow run | Triggered by Pullfrog𝕏

@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Apr 7, 2026
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 7, 2026

@atomicpages is attempting to deploy a commit to the Hey API Team on Vercel.

A member of the Team first needs to authorize it.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 7, 2026

⚠️ No Changeset found

Latest commit: 66797c9

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@dosubot dosubot bot added the feature 🚀 Feature request. label Apr 7, 2026
@pullfrog
Copy link
Copy Markdown

pullfrog bot commented Apr 7, 2026

TL;DR — Upgrades the @hey-api/client-ky plugin from Ky 1.x to Ky 2.0, adopting the new isHTTPError type guard and HTTPError.data property for error handling, and renaming prefixUrl to prefix throughout the generated client types.

Key changes

  • Upgrade Ky dependency to v2.0.0 — Bumps ky from 1.14.x to 2.0.0 across the main package, test package, and example, raising the minimum Node.js requirement to 22.
  • Use isHTTPError instead of manual duck-typing — Replaces the HTTPError type import and manual 'response' in error check with Ky 2's exported isHTTPError guard for proper error discrimination.
  • Handle HTTPError.data for consumed response bodies — When Ky 2 has already consumed the response body (populating error.data), the client now passes that data through to parseErrorResponse instead of attempting to re-read the body.
  • Rename prefixUrl to prefix in generated types — Updates the Config and kyOptions Omit keys to reflect Ky 2's renamed option.
  • Update documentation and add upgrade guide — Bumps the docs page from "Ky v1" to "Ky v2", adds a migration section covering the prefixUrlprefix rename and other Ky 2 breaking changes, and adds a new collaborator.
  • Add test for HTTPError.data path — New test case verifies the client correctly surfaces error data when Ky has already consumed the response body.

Summary | 35 files | 2 commits | base: mainatomicpages:main


Ky 2 error handling with isHTTPError and HTTPError.data

Before: The client imported the HTTPError type and checked errors with error && typeof error === 'object' && 'response' in error, then always read the response body via response.text() to extract the error payload.
After: The client uses Ky 2's isHTTPError guard for type-safe error detection and leverages HTTPError.data when Ky has already consumed the body, avoiding double-read errors.

Ky 2 automatically parses error responses and exposes the result on HTTPError.data, which also marks the body as consumed. The updated parseErrorResponse accepts an optional kyHttpError parameter: when present, it uses the pre-parsed data directly (attempting JSON parse only if the data is a string); when absent, it falls back to the original response.text() path.

Why three return paths in the catch block?

The catch block handles three scenarios: (1) error.data is defined — pass it directly as already-consumed data, (2) error.data is undefined but the body hasn't been read yet — fall back to the original text-reading path, (3) body is already consumed but data is undefined — still signal bodyConsumed: true to avoid a read error.

bundle/client.ts · bundle/types.ts · client.test.ts


Documentation and migration guide for Ky 2

Before: Docs described the client as "Ky v1" with no migration guidance.
After: Docs describe "Ky v2", note the Node.js 22 requirement, and include a dedicated section on renaming prefixUrl to prefix and other Ky 2 breaking changes.

ky.md


Dependency bumps and snapshot updates

Before: ky@1.14.x across all packages.
After: ky@2.0.0 in packages/openapi-ts, packages/openapi-ts-tests/main, and examples/openapi-ts-ky.

All 10 test snapshot directories under client-ky/ are regenerated with the updated imports (isHTTPError), error handling logic, and prefix rename. The example's generated schemas also drop x-swagger-router-model keys (likely a spec update artifact).

packages/openapi-ts/package.json · openapi-ts-tests/main/package.json · examples/openapi-ts-ky/package.json

Pullfrog  | View workflow run | Triggered by Pullfrog𝕏

import type { HTTPError, Options as KyOptions } from 'ky';
import ky from 'ky';
import type { Options as KyOptions } from 'ky';
import ky, { isHTTPError } from 'ky';
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

this was available in later version of ky v1, not required to use, but helps with tsc

Copy link
Copy Markdown

@pullfrog pullfrog bot left a comment

Choose a reason for hiding this comment

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

Important

Two issues to address: a dead/redundant code path in the error-handling logic, and a personal editor setting that leaked into the diff.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run𝕏

jsonError = JSON.parse(textError);
} catch {
jsonError = undefined;
if (kyHttpError) {
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This is due to:

  1. Make .json() throw on empty bodies and 204 responses instead of returning an empty string (Make json() throw on empty responses sindresorhus/ky#854) sindresorhus/ky@1b8e1ff
  2. Make beforeError hook receive all errors, not just HTTPError (Make beforeError hook receive all errors sindresorhus/ky#829) sindresorhus/ky@101c74b

if (error && typeof error === 'object' && 'response' in error) {
const httpError = error as HTTPError;
response = httpError.response;
if (isHTTPError(error)) {
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

export const client = createClient(
createConfig<ClientOptions2>({ baseUrl: 'https://petstore3.swagger.io/api/v3' }),
);
export const client = createClient(createConfig<ClientOptions2>({ baseUrl: '/api/v3' }));
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Image

Verified the base url remains correct

@pullfrog
Copy link
Copy Markdown

pullfrog bot commented Apr 7, 2026

Acknowledged the author's correction on the truthiness thread — '' is falsy so the || fallback still produces {}, matching old behavior. No code changes needed; thread resolved.

Task list (2/3 completed)
  • Review atomicpages' reply correcting truthiness analysis
  • Reply acknowledging the correction on the truthiness thread
  • Report progress

Pullfrog  | View workflow run | Triggered by Pullfrog𝕏

@pullfrog
Copy link
Copy Markdown

pullfrog bot commented Apr 7, 2026

Fixed the bug in the final error branch of client.ts:212 — replaced error.data (always undefined at that point) with an explicit undefined. Updated the source, 11 snapshots, and the ky example. All 2036 tests pass.

Task list (4/4 completed)
  • Checkout PR branch and read the file
  • Fix final branch: replace error.data with explicit undefined
  • Run tests and update snapshots
  • Commit, push, and reply to review comment

Pullfrog  | View workflow run | Triggered by Pullfrog𝕏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature 🚀 Feature request. size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant