Skip to content

fix: serialize format: date query params as YYYY-MM-DD#3723

Open
rolego wants to merge 4 commits intohey-api:mainfrom
rolego:fix/date-query-param-serialization
Open

fix: serialize format: date query params as YYYY-MM-DD#3723
rolego wants to merge 4 commits intohey-api:mainfrom
rolego:fix/date-query-param-serialization

Conversation

@rolego
Copy link
Copy Markdown
Contributor

@rolego rolego commented Apr 7, 2026

Summary

  • When dates: true is enabled in @hey-api/transformers, query parameters with format: date are typed as Date. Previously, Date objects were serialized via .toISOString() producing full timestamps like 2025-12-17T00:00:00.000Z instead of the RFC 3339 full-date 2025-12-17.
  • Adds a date option to QuerySerializerOptions and emits per-parameter date format hints ({ date: 'date' } or { date: 'date-time' }) in the SDK codegen.
  • All 7 client bundles (angular, axios, fetch, ky, next, nuxt, ofetch) now check instanceof Date before serializing query params, using .toISOString().slice(0, 10) for format: date and full .toISOString() for format: date-time.

Test plan

  • Added test spec specs/3.1.x/transformers-date-query-params.json with both date and date-time query params
  • Added snapshot test in 3.1.x.test.ts — verifies generated SDK emits querySerializer: { parameters: { stichdatum: { date: 'date' }, timestamp: { date: 'date-time' } } }
  • Updated ~500 snapshot files to reflect new instanceof Date check in generated client code
  • pnpm build, pnpm typecheck, and pnpm lint pass
  • Verified in a real Angular project that stichdatum=2025-12-17 is sent instead of stichdatum=2025-12-17T00:00:00.000Z

…l ISO timestamp

When dates: true is enabled in @hey-api/transformers, query parameters
with format: date are typed as Date. Previously, Date objects were
serialized via .toISOString() producing full timestamps like
2025-12-17T00:00:00.000Z instead of the expected 2025-12-17.

Adds a date option to QuerySerializerOptions and emits per-parameter
date format hints in the SDK codegen. All 7 client bundles now check
instanceof Date before serializing query params.
@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 #3723. The approach is sound — instanceof Date checks are correctly placed in all 7 client bundles, and the codegen properly emits per-parameter date hints. Main feedback: the date hint emission in operation.ts is unconditional (runs even without @hey-api/transformers), producing dead config in non-transformer setups. Suggested gating it on the transformer plugin, and recommended adding runtime unit tests for the new Date serialization path.

Task list (6/6 completed)
  • Read the diff to identify major areas of change
  • Review core logic changes (query serialization, client bundles)
  • Review codegen changes (SDK parameter hints)
  • Review test spec and snapshots
  • Impact analysis and self-critique
  • Submit review

Pullfrog  | View workflow run | Triggered by Pullfrog𝕏

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 7, 2026

⚠️ No Changeset found

Latest commit: 22e4f07

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 size:L This PR changes 100-499 lines, ignoring generated files. label Apr 7, 2026
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 7, 2026

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

A member of the Team first needs to authorize it.

@dosubot dosubot bot added the bug 🔥 Broken or incorrect behavior. label Apr 7, 2026
@pullfrog
Copy link
Copy Markdown

pullfrog bot commented Apr 7, 2026

TL;DR — Query parameters declared with format: "date" were being serialized as full ISO datetime strings (e.g. 2025-04-07T00:00:00.000Z). This PR fixes the runtime serializer and code generator so Date values on format: date params are emitted as YYYY-MM-DD — but only when @hey-api/transformers with dates: true is active, since that's the only scenario where query params become Date objects.

Key changes

  • Add Date instance handling to createQuerySerializer in all client bundles — A new branch intercepts Date values before array/object checks and formats them as YYYY-MM-DD when the parameter's date option is 'date', or full ISO otherwise.
  • Extend QuerySerializerOptionsObject with a date property — Adds date?: 'date' | 'date-time' so per-parameter serialization config can specify the desired date format.
  • Emit per-parameter querySerializer config in generated SDKs, gated on transformers plugin — The code generator inspects each query parameter's schema for type: string + format: date/date-time and emits serializer hints, but only when @hey-api/transformers is configured with dates enabled.
  • Add test spec and snapshot for format: date query params — New OpenAPI 3.1 spec (transformers-date-query-params.json) with both date and date-time query params, plus a corresponding test case.
  • Regenerate example client code and ~560 snapshot files — All existing utils.gen.ts and bodySerializer.gen.ts snapshots updated to reflect the new serializer logic across examples, SDKs, Valibot, and Zod test fixtures.

Summary | 576 files | 4 commits | base: mainfix/date-query-param-serialization


Runtime Date serialization in query strings

Before: Date objects in query parameters fell through to the generic object serializer, producing full ISO timestamps like 2025-04-07T00:00:00.000Z — even for format: date params that should only carry the date portion.
After: createQuerySerializer now explicitly checks value instanceof Date and reads an options.date flag to decide the output format — 'date' produces YYYY-MM-DD via toISOString().slice(0, 10), while 'date-time' (or unset) produces the full ISO string.

The same logic is added to all seven client bundles (fetch, axios, angular, ky, next, nuxt, ofetch) so the fix applies regardless of which HTTP client the consumer uses.

packages/openapi-ts/src/plugins/@hey-api/client-fetch/bundle/utils.ts · packages/openapi-ts/src/plugins/@hey-api/client-core/bundle/bodySerializer.ts


Code generation emits date serializer hints only when transformers are active

Before: The SDK code generator emitted querySerializer date hints for any query param with format: date/date-time, regardless of whether the transformers plugin was enabled.
After: The generator now checks plugin.getPlugin('@hey-api/transformers')?.config.dates before emitting per-parameter date format hints, ensuring the metadata is only generated when date transforms are actually in use.

This refinement prevents unnecessary querySerializer config from appearing in generated SDKs that don't use @hey-api/transformers — where query params remain plain strings and never become Date objects.

How does the per-parameter config flow from spec to runtime?

At code generation time, operation.ts inspects each query parameter's schema. When it finds type: 'string' with format: 'date' or 'date-time' and the transformers plugin has dates enabled, it emits a querySerializer.parameters entry — e.g. { stichdatum: { date: 'date' } }. At runtime, createQuerySerializer reads this config and applies the correct Date formatting before passing the value to serializePrimitiveParam.

packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts · specs/3.1.x/transformers-date-query-params.json · packages/openapi-ts-tests/main/test/3.1.x.test.ts

Pullfrog  | View workflow run | Triggered by Pullfrog𝕏

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

The codegen emits querySerializer date hints unconditionally — even when @hey-api/transformers is not enabled (and the param type is string, not Date). This is harmless at runtime but adds dead config to every generated SDK that has format: date query params without transformers. Consider gating the hint emission on the transformer plugin being active, consistent with how responseTransformer is already gated at line 350.

No runtime tests exist for the new instanceof Date branch — only snapshot coverage for the generated code. A unit test for createQuerySerializer with a Date value and { date: 'date' } option would be valuable.

The overall approach is sound: placing instanceof Date before Array.isArray() is correct (since Date passes typeof value === 'object' and would otherwise be serialized as [object Object]), the date type option is cleanly scoped, and all 7 client bundles are updated consistently. The new else if branch in operation.ts follows the existing pattern for array/object serializers.

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

rolego added 3 commits April 7, 2026 15:52
Only emit per-parameter date format hints in querySerializer config
when @hey-api/transformers is enabled with dates: true. Without the
transformer, params are typed as string (not Date), so the instanceof
Date check would never match at runtime.
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 40.21%. Comparing base (b8519b0) to head (22e4f07).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3723      +/-   ##
==========================================
- Coverage   40.24%   40.21%   -0.04%     
==========================================
  Files         520      520              
  Lines       19302    19335      +33     
  Branches     5726     5745      +19     
==========================================
+ Hits         7769     7776       +7     
- Misses       9337     9348      +11     
- Partials     2196     2211      +15     
Flag Coverage Δ
unittests 40.21% <ø> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 7, 2026

Open in StackBlitz

@hey-api/codegen-core

npm i https://pkg.pr.new/@hey-api/codegen-core@3723

@hey-api/json-schema-ref-parser

npm i https://pkg.pr.new/@hey-api/json-schema-ref-parser@3723

@hey-api/nuxt

npm i https://pkg.pr.new/@hey-api/nuxt@3723

@hey-api/openapi-ts

npm i https://pkg.pr.new/@hey-api/openapi-ts@3723

@hey-api/shared

npm i https://pkg.pr.new/@hey-api/shared@3723

@hey-api/spec-types

npm i https://pkg.pr.new/@hey-api/spec-types@3723

@hey-api/types

npm i https://pkg.pr.new/@hey-api/types@3723

@hey-api/vite-plugin

npm i https://pkg.pr.new/@hey-api/vite-plugin@3723

commit: 22e4f07

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

Labels

bug 🔥 Broken or incorrect behavior. size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant