Skip to content

feat: Shared Client Core for Domain-Separated Multi-Output Generation #3685

@Wonchang0314

Description

@Wonchang0314

Description

First off, I really appreciate the current design philosophy of keeping each output as a self-contained, isolated unit — it makes individual outputs predictable and portable, and I think that's the right default.

That said, I just wonder if there's room for an providing another option which can share a single client bundle across domain-separated outputs.

The Situation

When generating multiple domain-specific outputs (e.g. payments, orders, users), the client/core/ and client/fetch/ files end up byte-for-byte identical in every output:

src/api/
  payments/
    client/   ← duplicated
    types.gen.ts
    sdk.gen.ts
  orders/
    client/   ← duplicated (identical)
    types.gen.ts
    sdk.gen.ts

As the number of domains grows, so does the redundancy — and it also means client configuration (base URL, auth headers, interceptors) has to be managed in multiple places.

What I'm Imagining

Something like a bundle: false option on the client plugin that references a shared output instead:

export default defineConfig([
  // Shared client — generated once
  {
    output: { path: 'src/api/client' },
    plugins: [{ name: '@hey-api/client-fetch', bundle: true }],
  },

  // Domain outputs — reference shared client
  {
    input: 'specs/payments.yaml',
    output: { path: 'src/api/payments' },
    plugins: [
      { name: '@hey-api/client-fetch', bundle: false, importFrom: '../client' },
      '@hey-api/typescript',
      '@hey-api/sdk',
    ],
  },
  // ...orders, users, etc.
]);

This would keep bundle: true as the default (no breaking change), and only opt into sharing when explicitly configured.

Why It Might Be Worth Considering

  • No redundant files across outputs
  • Single place to configure the client (interceptors, base URL, auth)
  • Tree-shaking still works — each domain imports only what it needs
  • Matches how teams naturally organize domain-separated frontends

Totally understand if this conflicts with the current architecture or is out of scope — just wanted to put it out there in case it resonates. Happy to dig into implementation implications if it's something worth exploring!

Environment

  • @hey-api/openapi-ts: latest
  • @hey-api/client-fetch: latest

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions