Allow specifying type-safe meta values#3996
Conversation
|
|
|
@matthewjamesadam is attempting to deploy a commit to the Hey API Team on Vercel. A member of the Team first needs to authorize it. |
🦋 Changeset detectedLatest commit: b7ee3fd The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3996 +/- ##
==========================================
- Coverage 39.07% 39.06% -0.02%
==========================================
Files 610 610
Lines 21561 21561
Branches 6348 6348
==========================================
- Hits 8426 8423 -3
- Misses 10697 10700 +3
Partials 2438 2438
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
ℹ️ Minor suggestion — one inline note about the generated JSDoc.
Reviewed changes — introduces an augmentable ClientMeta interface and Meta conditional type so the SDK's meta option becomes type-safe at the call site while remaining fully backward compatible.
- Add
ClientMetaandMetatoclient-core/bundle/types.ts— the single source of truth;Metaresolves toRecord<string, unknown>when unaugmented and the augmentedClientMetaotherwise. - Add
ClientMetaandMetatocustom-client/src/core/types.ts— same pattern for the standalone@hey-api/custom-clientpackage. - Re-export from all 7 client bundle indexes —
client-fetch,client-axios,client-ofetch,client-ky,client-nuxt,client-next,client-angular. - Add
Metasymbol to the SDK plugin and wire it intotypeOptions.ts— themetaproperty on the generatedOptionstype changes frommeta?: Record<string, unknown>tometa?: Meta. - Add type-level regression test (
clientMeta.type-test.ts) — covers augmented (strict typing) and unaugmented (backward-compatible) cases. - Document the feature under a new "Metadata" section in the SDK plugin docs.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
| * field stays backward compatible. Augment it to make `meta` typesafe: | ||
| * | ||
| * ```ts | ||
| * declare module '@hey-api/client-fetch' { |
There was a problem hiding this comment.
declare module '@hey-api/client-fetch', but this file is copied verbatim into every generated client output (axios, nuxt, ky, etc.). An axios user reading their core/types.gen.ts would see @hey-api/client-fetch in the example, which is misleading since they need to augment @hey-api/client-axios instead.
Technical details
# JSDoc hardcodes client-fetch module for all generated clients
## Affected sites
- `packages/openapi-ts/src/plugins/@hey-api/client-core/bundle/types.ts:98-103` — the `declare module '@hey-api/client-fetch'` JSDoc block
- All ~600 generated `core/types.gen.ts` snapshots — every client output inherits the same text
## Required outcome
- The JSDoc in the source file should not name a specific client module, or
- The `generateClientBundle`/`replaceImports` pipeline should rewrite the module name during generation
## Suggested approach
Replace the `declare module` example with a sentence like "Augment the `ClientMeta` interface on the module you import your client from." The full example lives in the docs already; the JSDoc just needs to tell the user to read the docs or look at which module they import from.|
@matthewjamesadam any thoughts on inlining the |
@mrlubos I'm definitely open to changing this -- just so I make sure I understand, are you proposing that instead of exporting Meta in the types file: and using it in the sdk file: we instead inline it in the sdk file: If that's what you're saying then I think that makes sense! |

Motivation
The
@hey-api/sdkplugin generates ametafield onOptionshardcoded toRecord<string, unknown>, which can be used as a side-channel for data tointerceptors/middleware. However this value is in effect untyped which can lead to
bugs:
This issue has been previously reported here: #2425 (comment)
Solution
hey-apidefines the meta property to be of typeClientMeta, which by default isRecord<string, unknown>. Client applications can define this type to a concrete value via ambient declarations — the canonicalTypeScript extension-point pattern (same as vue-router's RouteMeta):
Unaugmented → Meta resolves to Record<string, unknown> — identical to today's behavior, fully backward compatible.
Augmented → meta becomes strict: unknown keys, wrong types, and primitives are all rejected at the call site.