@kubb/plugin-fetch 5.5.9 → 5.5.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,99 @@
1
+ # Server-sent events
2
+
3
+ Operations returning `text/event-stream` produce a typed stream rather than a `RequestResult`.
4
+
5
+ ## Consume a stream
6
+
7
+ Read the `EventStreamResult.stream` with `for await`:
8
+
9
+ ```typescript
10
+ import { streamEvents } from './gen/clients/streamEvents'
11
+
12
+ const { stream } = await streamEvents({})
13
+
14
+ for await (const event of stream) {
15
+ console.info(event.data)
16
+ }
17
+ ```
18
+
19
+ `data` is typed from the operation's response schema. Each event also carries the optional SSE
20
+ fields, so you can branch on the event name or read the id:
21
+
22
+ ```typescript
23
+ type ServerSentEvent<TData> = {
24
+ data: TData
25
+ event?: string
26
+ id?: string
27
+ retry?: number
28
+ }
29
+ ```
30
+
31
+ The runtime parses each event's `data` as JSON when it is valid and keeps it as the raw string
32
+ otherwise.
33
+
34
+ ## Stop early
35
+
36
+ Break out of the loop to stop reading. The underlying reader is canceled when the iterator
37
+ finishes, so an early `break` releases the stream:
38
+
39
+ ```typescript
40
+ const { stream } = await streamEvents({})
41
+
42
+ for await (const event of stream) {
43
+ if (event.event === 'done') break
44
+ render(event.data)
45
+ }
46
+ ```
47
+
48
+ To stop a stream from outside the loop, pass an `AbortSignal` and abort it. Aborting ends the
49
+ request and the iteration:
50
+
51
+ ```typescript
52
+ const controller = new AbortController()
53
+ const { stream } = await streamEvents({ signal: controller.signal })
54
+
55
+ // elsewhere, for example on component unmount
56
+ controller.abort()
57
+ ```
58
+
59
+ ## Read the response
60
+
61
+ Read status and headers from the native `response` before iterating:
62
+
63
+ ```typescript
64
+ const { stream, response } = await streamEvents({})
65
+
66
+ console.info(response.status) // 200
67
+ console.info(response.headers.get('x-stream-id'))
68
+
69
+ for await (const event of stream) {
70
+ handle(event.data)
71
+ }
72
+ ```
73
+
74
+ ## Handle errors
75
+
76
+ Catch non-2xx responses around the call and iteration, and rethrow other errors such as connection failures:
77
+
78
+ ```typescript
79
+ import { ResponseError } from './gen/.kubb/client'
80
+
81
+ try {
82
+ const { stream } = await streamEvents({})
83
+ for await (const event of stream) {
84
+ handle(event.data)
85
+ }
86
+ } catch (error) {
87
+ if (!ResponseError.is(error)) throw error
88
+ console.error('stream rejected', error.status)
89
+ }
90
+ ```
91
+
92
+ > [!NOTE]
93
+ > A drop mid-stream ends the `for await` loop. Track the last event's `id` if you need to reconnect
94
+ > from where the stream stopped.
95
+
96
+ ## See also
97
+
98
+ - [Call operations](https://kubb.dev/extensions/kubb-labs/plugin-fetch/guides/calling-operations)
99
+ - [Handle errors](https://kubb.dev/extensions/kubb-labs/plugin-fetch/guides/error-handling)
@@ -0,0 +1,71 @@
1
+ # Use a custom transport
2
+
3
+ Set a transport at runtime to replace the network send. The client still builds URLs, serializes parameters, resolves authentication, and handles results.
4
+
5
+ The transport is a function. Use interceptors for request headers or response logging.
6
+
7
+ ## Write a transport function
8
+
9
+ `@kubb/plugin-fetch` types the transport as a function that receives a fully resolved request and returns a result:
10
+
11
+ ```typescript
12
+ type Transport = (request: ResolvedRequest) => Promise<TransportResult>
13
+
14
+ type ResolvedRequest = {
15
+ url: string
16
+ method: string
17
+ headers: Record<string, string>
18
+ body?: RequestBody
19
+ signal?: AbortSignal
20
+ credentials?: RequestCredentials
21
+ options?: FetchOptions
22
+ responseType?: ResponseType
23
+ }
24
+
25
+ type TransportResult<TData = unknown> = {
26
+ data: TData
27
+ status: number
28
+ statusText: string
29
+ headers: Headers
30
+ contentType?: string
31
+ request: Request
32
+ response: Response
33
+ }
34
+ ```
35
+
36
+ The core hands you a `ResolvedRequest` with the URL built, the query and body serialized, and auth headers set. Return the parsed `data` along with the native `request` and `response`, so status, headers, and the raw body stay reachable on the result.
37
+
38
+ ## Mock the network in tests
39
+
40
+ Return a fixed result from an isolated client in tests:
41
+
42
+ ```typescript
43
+ import { createClient } from './gen/.kubb/client'
44
+ import { getPetById } from './gen/clients/getPetById'
45
+
46
+ const testClient = createClient({
47
+ transport: async (request) => ({
48
+ data: { id: 1, name: 'Fluffy' },
49
+ status: 200,
50
+ statusText: 'OK',
51
+ headers: new Headers(),
52
+ request: new Request(request.url),
53
+ response: new Response(),
54
+ }),
55
+ })
56
+
57
+ const { data } = await getPetById({ path: { petId: 1 }, client: testClient })
58
+ // ^ { id: 1, name: 'Fluffy' }
59
+ ```
60
+
61
+ Pass the isolated client per operation or to a query plugin.
62
+
63
+ ## Where to set it
64
+
65
+ Use `client.setConfig({ transport })` for shared configuration, `createClient({ transport })` for an isolated instance, or pass `transport` on an operation to override it for one call.
66
+
67
+ ## See also
68
+
69
+ - [Add interceptors](https://kubb.dev/extensions/kubb-labs/plugin-fetch/guides/interceptors)
70
+ - [Set the base URL](https://kubb.dev/extensions/kubb-labs/plugin-fetch/guides/base-url)
71
+ - [Call operations](https://kubb.dev/extensions/kubb-labs/plugin-fetch/guides/calling-operations)
@@ -0,0 +1,173 @@
1
+ # Options
2
+
3
+ Pass these options to `pluginFetch()`. Shared options link to [Shared plugin options](https://kubb.dev/docs/5.x/reference/plugin-options).
4
+
5
+ ## Options overview
6
+
7
+ | Option | Purpose | Default |
8
+ | ------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------ |
9
+ | [`output`](https://kubb.dev/docs/5.x/reference/plugin-options#output) | Where files are written: `path`, `mode`, `barrel`, `banner`, `footer`. | `{ path: 'clients', barrel: { type: 'named' } }` |
10
+ | [`group`](https://kubb.dev/docs/5.x/reference/plugin-options#group) | Split output by tag or path: `type`, `name`. | None |
11
+ | [`baseURL`](#baseurl) | Base URL prepended to every request. | None |
12
+ | [`throwOnErrorDefault`](#throwonerrordefault) | Default error behavior and return type for generated operations. | `true` |
13
+ | [`validator`](#validator) | Validate request and response bodies with Zod. | `false` |
14
+ | [`sdk`](#sdk) | Generate a class-based SDK instead of functions. | None |
15
+ | [`returnType`](#returntype) | Shape of the value a generated call resolves to. | `'full'` |
16
+ | [`include`](https://kubb.dev/docs/5.x/reference/plugin-options#include) | Keep only operations that match. | None |
17
+ | [`exclude`](https://kubb.dev/docs/5.x/reference/plugin-options#exclude) | Skip operations that match. | `[]` |
18
+ | [`override`](https://kubb.dev/docs/5.x/reference/plugin-options#override) | Apply different options per pattern. | `[]` |
19
+ | [`resolver`](#resolver) | Customize generated names and file paths. | `resolverClient` |
20
+ | [`macros`](https://kubb.dev/docs/5.x/reference/plugin-options#macros) | Rewrite AST nodes before printing. | `[]`, run after the built-in client macros |
21
+
22
+ ## Option details
23
+
24
+ ### baseURL
25
+
26
+ Base URL prepended to every request. When omitted, each request uses the operation's relative path from the spec. A value with a `${...}` interpolation is emitted as a template literal in the generated client config, so `baseURL: '${process.env.API_URL}'` reads the environment variable at runtime.
27
+
28
+ | | |
29
+ | -------- | -------- |
30
+ | Type | `string` |
31
+ | Required | `false` |
32
+
33
+ ### throwOnErrorDefault
34
+
35
+ Set `throwOnErrorDefault: false` to return documented error responses as values by default. It sets the fallback on each generated request and the default `ThrowOnError` type parameter on functions and SDK methods. It applies to the whole plugin, so `override` cannot set it. A call that passes `throwOnError` still wins. With `throwOnError: true`, a non-2xx response throws and the return type narrows to successful responses. Query hooks always pass `throwOnError: true`.
36
+
37
+ | | |
38
+ | -------- | --------- |
39
+ | Type | `boolean` |
40
+ | Required | `false` |
41
+ | Default | `true` |
42
+
43
+ ```typescript
44
+ // with pluginFetch({ throwOnErrorDefault: false })
45
+ const result = await getPetById({ path: { petId: 1 } })
46
+ if (result.status !== 200) console.error(result.status, result.error)
47
+ ```
48
+
49
+ ### validator
50
+
51
+ Validates request and response bodies with schemas from `@kubb/plugin-zod`, so add `pluginZod()` too. An invalid body makes the generated function throw a `ParseError`.
52
+
53
+ | | |
54
+ | -------- | --------------------------------------------------------- |
55
+ | Type | `false \| 'zod' \| { request?: 'zod'; response?: 'zod' }` |
56
+ | Required | `false` |
57
+ | Default | `false` |
58
+
59
+ ::field-group
60
+
61
+ :::field{name="false"}
62
+ Default value. Does no validation and returns the response cast to the generated type.
63
+ :::
64
+
65
+ :::field{name="'zod'"}
66
+ Validates the success response body, and the error body when a non-2xx call does not throw.
67
+ :::
68
+
69
+ :::field{name="{ request?: 'zod', response?: 'zod' }"}
70
+ Opts in per direction. `request` validates the request body before the call, and `response` validates the response body after it.
71
+ :::
72
+
73
+ ::
74
+
75
+ ```typescript [kubb.config.ts]
76
+ import { defineConfig } from 'kubb/config'
77
+ import { pluginTs } from '@kubb/plugin-ts'
78
+ import { pluginZod } from '@kubb/plugin-zod'
79
+ import { pluginFetch } from '@kubb/plugin-fetch'
80
+
81
+ export default defineConfig({
82
+ input: './petStore.yaml',
83
+ output: { path: './src/gen' },
84
+ plugins: [
85
+ pluginTs(),
86
+ pluginZod(),
87
+ pluginFetch({ validator: { request: 'zod', response: 'zod' } }),
88
+ ],
89
+ })
90
+ ```
91
+
92
+ ### sdk
93
+
94
+ Generates a class-based SDK. Each instance takes its own client config, so environments can use separate clients. Leave `sdk` unset to keep the standalone functions that query plugins call.
95
+
96
+ | | |
97
+ | -------- | ------------------------------------------- |
98
+ | Type | `{ mode?: 'tag' \| 'flat'; name?: string }` |
99
+ | Required | `false` |
100
+
101
+ ::field-group
102
+
103
+ :::field{name="'tag'"}
104
+ Default value for `sdk.mode`. Generates one class per tag, such as `PetClient`. Set `sdk.name` to also get a root class that shares one config, used as `new PetStore(config).pet.getPetById(...)`.
105
+ :::
106
+
107
+ :::field{name="'flat'"}
108
+ Generates one class named by `sdk.name`, with every operation as a method. Supports single-file output.
109
+ :::
110
+
111
+ ::
112
+
113
+ `mode: 'tag'` needs one file per tag, so it throws [`KUBB_INVALID_PLUGIN_OPTIONS`](https://kubb.dev/docs/5.x/reference/diagnostics#kubb-invalid-plugin-options) with single-file output. Use `mode: 'flat'` for a single file.
114
+
115
+ Methods take the same grouped options and return the same result as the standalone functions. See [Call operations](https://kubb.dev/extensions/kubb-labs/plugin-fetch/guides/calling-operations).
116
+
117
+ ```typescript
118
+ const pet = new PetClient({ baseURL: 'https://petstore.swagger.io/v2' })
119
+ const { data } = await pet.getPetById({ path: { petId: 1 } })
120
+ ```
121
+
122
+ ### returnType
123
+
124
+ Shape of the value a generated call resolves to.
125
+
126
+ | | |
127
+ | -------- | ------------------ |
128
+ | Type | `'full' \| 'data'` |
129
+ | Required | `false` |
130
+ | Default | `'full'` |
131
+
132
+ ::field-group
133
+
134
+ :::field{name="'full'"}
135
+ Default value. Returns `{ status, data, error, contentType, request, response }`.
136
+ :::
137
+
138
+ :::field{name="'data'"}
139
+ Returns the success body when `throwOnError` is `true`. With `throwOnError: false`, returns the full result so callers can tell errors from successes.
140
+ :::
141
+
142
+ ::
143
+
144
+ ```typescript
145
+ pluginFetch({ returnType: 'data' })
146
+
147
+ const pet = await getPetById({ path: { petId: 1 } }) // Pet, not { status, data, ... }
148
+ ```
149
+
150
+ It applies to the functions and the SDK. The query plugins and `@kubb/plugin-mcp` read it too, including a per-operation value set through [`override`](https://kubb.dev/docs/5.x/reference/plugin-options#override). To read headers such as `ETag` under `'data'`, pass `throwOnError: false` and call `result.response.headers.get('etag')`.
151
+
152
+ ### resolver
153
+
154
+ Overrides generated file and symbol names. Omitted members keep `resolverClient`. The shared members (`name`, `file`, `imports`) and the `this` context are described under [`resolver`](https://kubb.dev/docs/5.x/reference/plugin-options#resolver).
155
+
156
+ | | |
157
+ | -------- | ------------------------------- |
158
+ | Type | `ResolverPatch<ResolverClient>` |
159
+ | Required | `false` |
160
+
161
+ ```typescript [Partial override]
162
+ type ResolverClientPatch = {
163
+ name?(name: string): string
164
+ file?: {
165
+ baseName?(params: { name: string; extname: string }): string
166
+ path?(params: { baseName: string; output: Output }): string
167
+ }
168
+ imports?(options: ResolveImportsOptions): Array<ImportNode>
169
+ className?(name: string): string
170
+ groupName?(name: string): string // → 'PetClient'
171
+ propertyName?(name: string): string
172
+ }
173
+ ```
@@ -0,0 +1,40 @@
1
+ # Fetch
2
+
3
+ The Fetch plugin turns each operation in your OpenAPI spec into a typed async function that sends the request with the native Fetch API. Each function takes grouped `path`, `query`, `headers`, and `body` parameters and returns a result keyed by status code.
4
+
5
+ The query plugins (`@kubb/plugin-react-query`, `@kubb/plugin-vue-query`, and `@kubb/plugin-swr`) and `@kubb/plugin-mcp` call these functions. The plugin also copies its runtime files (`client.ts`, `serializers.ts`, and `standardSchema.ts`) to `.kubb/` in the root output folder.
6
+
7
+ ## Setup
8
+
9
+ - Add `@kubb/plugin-ts` for the operation types, or `@kubb/plugin-zod` with `inferred: true`.
10
+ - Add `@kubb/plugin-zod` when you set `validator`, and install `zod` v4. Without the plugin, `validator` does nothing.
11
+ - No HTTP client package is needed. The generated code calls the global `fetch`.
12
+
13
+ ## Options worth knowing
14
+
15
+ - `baseURL` is prepended to every request. The spec's `servers` URL is not used, so without `baseURL` you set one at runtime with `client.setConfig({ baseURL })`.
16
+ - `validator: 'zod'` validates response bodies with the schemas from `@kubb/plugin-zod`. Use `{ request: 'zod', response: 'zod' }` to also validate request bodies.
17
+ - `throwOnErrorDefault: false` returns non-2xx responses as values instead of throwing. A single call can still pass `throwOnError`.
18
+ - `returnType: 'data'` makes a call resolve to the success body instead of the full result. With `throwOnError: false`, the call still returns the full result.
19
+ - `sdk` generates a class-based SDK, grouped by tag or flat, instead of standalone functions. The query plugins and `@kubb/plugin-mcp` need the standalone functions, so leave `sdk` unset when you use them.
20
+
21
+ See [Options](https://kubb.dev/extensions/kubb-labs/plugin-fetch/options) for every option and its default.
22
+
23
+ ## Example
24
+
25
+ The config below generates a Fetch client that sends every request to the Petstore API.
26
+
27
+ ```typescript [kubb.config.ts]
28
+ import { defineConfig } from 'kubb/config'
29
+ import { pluginTs } from '@kubb/plugin-ts'
30
+ import { pluginFetch } from '@kubb/plugin-fetch'
31
+
32
+ export default defineConfig({
33
+ input: './petStore.yaml',
34
+ output: { path: './src/gen' },
35
+ plugins: [
36
+ pluginTs(),
37
+ pluginFetch({ baseURL: 'https://petstore.swagger.io/v2' }),
38
+ ],
39
+ })
40
+ ```
@@ -10,9 +10,16 @@
10
10
  "light": "https://kubb.dev/feature/javascript.svg"
11
11
  },
12
12
  "tags": ["api-client", "fetch", "http-client", "codegen", "openapi", "validator"],
13
- "docs": "https://kubb.dev/plugins/plugin-fetch",
13
+ "docs": "https://kubb.dev/extensions/kubb-labs/plugin-fetch",
14
+ "maintainers": [
15
+ {
16
+ "name": "Stijn Van Hulle",
17
+ "github": "stijnvanhulle"
18
+ }
19
+ ],
20
+ "dependencies": ["plugin-ts"],
14
21
  "compatibility": {
15
- "kubb": ">=5.8.0",
22
+ "kubb": ">=5.8.3",
16
23
  "node": ">=22"
17
24
  },
18
25
  "role": "client",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/plugin-fetch",
3
- "version": "5.5.9",
3
+ "version": "5.5.11",
4
4
  "description": "Generate a slim, type-safe HTTP client with Kubb based on the native Fetch api.",
5
5
  "keywords": [
6
6
  "api-client",
@@ -13,7 +13,7 @@
13
13
  "swagger",
14
14
  "typescript"
15
15
  ],
16
- "homepage": "https://kubb.dev/plugins/plugin-fetch",
16
+ "homepage": "https://kubb.dev/extensions/kubb-labs/plugin-fetch",
17
17
  "license": "MIT",
18
18
  "author": "stijnvanhulle",
19
19
  "repository": {
@@ -40,7 +40,7 @@
40
40
  "dist",
41
41
  "templates",
42
42
  "kubb-extension.json",
43
- "OVERVIEW.md",
43
+ "docs",
44
44
  "!/**/**.test.**",
45
45
  "!/**/__tests__/**",
46
46
  "!/**/__snapshots__/**"
@@ -68,17 +68,17 @@
68
68
  "registry": "https://registry.npmjs.org/"
69
69
  },
70
70
  "dependencies": {
71
- "@kubb/plugin-ts": "^5.0.8",
72
- "@kubb/plugin-zod": "^5.4.6"
71
+ "@kubb/plugin-ts": "^5.0.10",
72
+ "@kubb/plugin-zod": "^5.4.8"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@internals/client": "0.0.0",
76
76
  "@internals/shared": "0.0.0",
77
- "kubb": "^5.8.1",
77
+ "kubb": "^5.8.3",
78
78
  "typescript": "^6.0.3"
79
79
  },
80
80
  "peerDependencies": {
81
- "kubb": "^5.8.1"
81
+ "kubb": "^5.8.3"
82
82
  },
83
83
  "engines": {
84
84
  "node": ">=22"
package/src/plugin.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import path from 'node:path'
2
2
  import { createSdkGenerator, defaultMacros, resolverClient } from '@internals/client'
3
3
  import { createGroupConfig } from '@internals/shared'
4
- import { addGenerator, definePlugin, injectFile, Resolver, setMacros, setResolver, useConfig } from 'kubb/kit'
4
+ import { addGenerator, defineExtension, injectFile, Resolver, setMacros, setResolver, useConfig } from 'kubb/kit'
5
5
  import { compatibility } from '../kubb-extension.json'
6
6
  import { version } from '../package.json'
7
7
  import { pluginTsName } from '@kubb/plugin-ts'
@@ -38,7 +38,8 @@ export const pluginFetchName = 'plugin-fetch' satisfies PluginFetch['name']
38
38
  * })
39
39
  * ```
40
40
  */
41
- export const pluginFetch = definePlugin<PluginFetch>({
41
+ export const pluginFetch = defineExtension<PluginFetch>({
42
+ kind: 'plugin',
42
43
  meta: { name: pluginFetchName, version, compatibility },
43
44
  // Both are ordering hints, skipped when the plugin is not in the pipeline. `plugin-ts` supplies
44
45
  // the operation types unless it is absent, in which case `pluginZod({ inferred: true })` does.
package/OVERVIEW.md DELETED
@@ -1,19 +0,0 @@
1
- # Fetch
2
-
3
- Generates a type-safe HTTP client based on the native Fetch API from your OpenAPI spec. Each operation becomes one async function with grouped `path`, `query`, `headers`, and `body` parameters and a result keyed by status code.
4
-
5
- This plugin provides the client runtime. Query plugins such as `@kubb/plugin-react-query`, `@kubb/plugin-vue-query`, `@kubb/plugin-swr`, and `@kubb/plugin-mcp` call the functions it generates.
6
-
7
- ## Setup
8
-
9
- - Add `@kubb/plugin-ts` for the operation types. Without it, `@kubb/plugin-zod` with `inferred: true` supplies them.
10
- - Add `@kubb/plugin-zod` when you set `validator`.
11
- - No HTTP client package is needed.
12
-
13
- ## Options worth knowing
14
-
15
- - `baseURL` is prepended to every request.
16
- - `validator: 'zod'` validates request and response bodies with the schemas from `@kubb/plugin-zod`.
17
- - `sdk` generates a class-based SDK, grouped by tag or flat, instead of standalone functions. Query plugins need the standalone functions, so leave `sdk` unset when you use them.
18
- - `returnType: 'data'` makes a call resolve to the success body instead of the full result with status, data, and error.
19
- - `throwOnErrorDefault: false` returns documented error responses as values instead of throwing. A single call can still pass `throwOnError`.