diff --git a/docs/5.x/ai/mcp.md b/docs/5.x/ai/mcp.md index b94d96cd..a6e64538 100644 --- a/docs/5.x/ai/mcp.md +++ b/docs/5.x/ai/mcp.md @@ -9,7 +9,7 @@ outline: [2, 3] Kubb ships a [Model Context Protocol](https://modelcontextprotocol.io/) server. It exposes code-generation tools to any MCP-capable client. Once connected, your editor or agent runs Kubb -generation, validates schemas, and inspects configuration from the chat. +generation, validates schemas, and scaffolds configuration from the chat. > [!IMPORTANT] > The built-in MCP server needs Kubb v5 or higher. diff --git a/docs/5.x/community/contributing.md b/docs/5.x/community/contributing.md index 38719a0f..1f379e5e 100644 --- a/docs/5.x/community/contributing.md +++ b/docs/5.x/community/contributing.md @@ -92,7 +92,7 @@ Contribute a plugin in two ways. Build a community plugin in your own repository 1. Follow the [Creating Your First Plugin](/docs/5.x/guide/going-further/creating-plugins) guide. 2. Use [`@kubb/plugin-axios`](https://github.com/kubb-labs/plugins/tree/main/packages/plugin-axios) as the layout to copy. -3. Publish to npm under the `kubb-plugin-*` or `@scope/plugin-*` naming convention. +3. Publish to npm under the `kubb-plugin-*` naming convention. 4. Submit it to the registry by opening a PR on [kubb-labs/docs](https://github.com/kubb-labs/docs) that adds a `plugins//index.md` page with the required frontmatter. ### Propose an official plugin diff --git a/docs/5.x/guide/going-further/claude-mcp-plugin.md b/docs/5.x/guide/going-further/claude-mcp-plugin.md index 106e452a..5e06622a 100644 --- a/docs/5.x/guide/going-further/claude-mcp-plugin.md +++ b/docs/5.x/guide/going-further/claude-mcp-plugin.md @@ -13,7 +13,7 @@ const mcpTree = [ { name: 'mcp', type: 'dir', children: [ { name: 'addPet.ts' }, { name: 'getPetById.ts' }, - { name: 'mcp.json' }, + { name: '.mcp.json' }, { name: 'server.ts' }, ] }, { name: 'clients', type: 'dir', children: [ @@ -24,7 +24,7 @@ const mcpTree = [ { name: 'addPetSchema.ts' }, { name: 'getPetByIdSchema.ts' }, ] }, - { name: 'models', type: 'dir', children: [ + { name: 'types', type: 'dir', children: [ { name: 'AddPet.ts' }, { name: 'GetPetById.ts' }, ] }, @@ -154,13 +154,13 @@ The `src/mcp` folder holds the files that build an [MCP server](https://modelcon The `addPetHandler` function takes the pet body and calls the generated `addPet` client function. It returns the response as a JSON text message that [MCP](https://modelcontextprotocol.io) uses in conversations. ```typescript [src/mcp/addPet.ts] -import type { AddPetRequestConfig } from '../models/ts/AddPet' +import type { AddPetOptions } from '../types/AddPet' import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol' import type { CallToolResult, ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types' import { addPet } from '../clients/addPet' export async function addPetHandler( - { body }: AddPetRequestConfig, + { body }: AddPetOptions, request: RequestHandlerExtra, ): Promise> { const res = await addPet({ body }) @@ -177,19 +177,19 @@ export async function addPetHandler( } ``` -### src/mcp/mcp.json +### src/mcp/.mcp.json This config registers an [MCP](https://modelcontextprotocol.io) server named `"Swagger PetStore - OpenAPI 3.0"`. The name comes from `info.title` in your OpenAPI file. It runs the TypeScript server (`server.ts`) through `tsx`, so [MCP](https://modelcontextprotocol.io) handles tool calls over standard input and output. -```json [src/mcp/mcp.json] +```json [src/mcp/.mcp.json] { "mcpServers": { "Swagger PetStore - OpenAPI 3.0": { "type": "stdio", "command": "npx", - "args": ["tsx", "/mcp/src/gen/mcp/server.ts"] + "args": ["tsx", "server.ts"] } } } @@ -252,7 +252,7 @@ startServer() ## Start Claude with the MCP server -Point [Claude](https://claude.ai) at your [MCP](https://modelcontextprotocol.io) server config (`src/mcp/mcp.json`). Open Claude desktop and go to settings. +Point [Claude](https://claude.ai) at your [MCP](https://modelcontextprotocol.io) server config (`src/mcp/.mcp.json`). Open Claude desktop and go to settings. ![Claude setup 1](/public/screenshots/claude-setup1.png) @@ -266,7 +266,7 @@ In the settings panel, open the `developer` section and click `edit config`. A w ![Claude setup 2](/public/screenshots/claude-setup2.png) -Copy the content of `src/mcp/mcp.json` so [Claude](https://claude.ai) picks up your [MCP](https://modelcontextprotocol.io) server. +Copy the content of `src/mcp/.mcp.json` so [Claude](https://claude.ai) picks up your [MCP](https://modelcontextprotocol.io) server. > [!TIP] > With multiple MCP servers, append your entry instead of overwriting the file. diff --git a/docs/5.x/guide/going-further/creating-plugins.md b/docs/5.x/guide/going-further/creating-plugins.md index d0af6fbe..ba501c45 100644 --- a/docs/5.x/guide/going-further/creating-plugins.md +++ b/docs/5.x/guide/going-further/creating-plugins.md @@ -609,7 +609,7 @@ export const schemaGenerator = defineGenerator({ ### Extending an existing plugin -Declare `dependencies` when your plugin must run after another. Kubb verifies the dependency at startup and throws when it is missing: +Declare `dependencies` when your plugin must run after another, to control run order. Kubb does not verify a missing dependency at startup: it silently ignores the dependency while ordering plugins, and the error only surfaces when a generator calls `ctx.requirePlugin('plugin-ts')`, which throws naming the plugin that required it: ```typescript twoslash [plugin-with-dep.ts] import { ast, definePlugin, defineGenerator } from 'kubb/kit' diff --git a/docs/5.x/reference/configuration.md b/docs/5.x/reference/configuration.md index 4a68aeed..78606af9 100644 --- a/docs/5.x/reference/configuration.md +++ b/docs/5.x/reference/configuration.md @@ -296,7 +296,7 @@ Auto-generated banner injected at the top of each file. | Required: | `false` | | Default: | `'simple'` | -`'simple'` adds a short "Generated by Kubb" notice. `'full'` adds the notice plus `Source`, `Title`, `Description`, and `OpenAPI spec version` from the spec. `false` writes no banner. +`'simple'` adds a short "Generated by Kubb" notice. `'full'` adds the notice plus `Source`, `Title`, and `OpenAPI spec version` from the spec. `false` writes no banner. ::: code-group @@ -313,7 +313,6 @@ Auto-generated banner injected at the top of each file. * Do not edit manually. * Source: petStore.yaml * Title: Pet Store - * Description: A sample API that uses a petstore as an example. * OpenAPI spec version: 1.0.0 */ ``` diff --git a/docs/5.x/reference/diagnostics.md b/docs/5.x/reference/diagnostics.md index 6b6a3ac6..2fd93019 100644 --- a/docs/5.x/reference/diagnostics.md +++ b/docs/5.x/reference/diagnostics.md @@ -11,7 +11,7 @@ When a build fails, Kubb prints a diagnostic. It carries a stable code, the mess your document, and a suggested fix. The CLI leads with the code and lists the details below it: ```text [Terminal] -[KUBB_REF_NOT_FOUND] @kubb/plugin-zod: Could not find a definition for #/components/schemas/Pet. +[KUBB_REF_NOT_FOUND]: Could not find a definition for #/components/schemas/Pet. at: #/components/schemas/Pet fix: Add the schema under components.schemas, or fix the $ref. see: https://kubb.dev/docs/5.x/reference/diagnostics/kubb-ref-not-found @@ -102,12 +102,12 @@ without scraping the terminal: { "name": "", "status": "failed", - "plugins": { "passed": 2, "failed": ["@kubb/plugin-zod"], "total": 3 }, + "plugins": { "passed": 2, "failed": ["plugin-zod"], "total": 3 }, "counts": { "errors": 1, "warnings": 0, "infos": 0 }, "filesCreated": 0, "durationMs": 312, "output": "/project/src/gen", - "timings": [{ "plugin": "@kubb/plugin-ts", "durationMs": 84 }], + "timings": [{ "plugin": "plugin-ts", "durationMs": 84 }], "diagnostics": [ { "code": "KUBB_REF_NOT_FOUND", diff --git a/docs/5.x/reference/diagnostics/kubb-adapter-required.md b/docs/5.x/reference/diagnostics/kubb-adapter-required.md index 8fdfca90..1b67f8f6 100644 --- a/docs/5.x/reference/diagnostics/kubb-adapter-required.md +++ b/docs/5.x/reference/diagnostics/kubb-adapter-required.md @@ -14,7 +14,7 @@ An action needs an adapter but none is configured. ## What happened -The adapter turns your spec into the AST that plugins generate from. It has to be set before any plugin runs. This diagnostic fires when the config has no `adapter`. +The adapter turns your spec into the AST that plugins generate from. It has to be set before any plugin runs. This diagnostic is defined in Kubb's diagnostic catalog, but no code path in the current source reports it. `defineConfig` (the standard entry point, used in the example below) always fills in a default adapter (`adapterOas()`) when `adapter` is omitted, so a config without an explicit `adapter` does not trigger this diagnostic today. ## How to fix it diff --git a/docs/5.x/reference/diagnostics/kubb-deprecated.md b/docs/5.x/reference/diagnostics/kubb-deprecated.md index 5fa488d3..51d5adce 100644 --- a/docs/5.x/reference/diagnostics/kubb-deprecated.md +++ b/docs/5.x/reference/diagnostics/kubb-deprecated.md @@ -36,7 +36,7 @@ components: ## Example output ```text [Terminal] -[KUBB_DEPRECATED] @kubb/adapter-oas: This schema is marked as deprecated. +[KUBB_DEPRECATED]: This schema is marked as deprecated. at: #/components/schemas/Pet see: https://kubb.dev/docs/5.x/reference/diagnostics/kubb-deprecated ``` diff --git a/docs/5.x/reference/diagnostics/kubb-input-not-found.md b/docs/5.x/reference/diagnostics/kubb-input-not-found.md index c8f7f531..d1f4f29c 100644 --- a/docs/5.x/reference/diagnostics/kubb-input-not-found.md +++ b/docs/5.x/reference/diagnostics/kubb-input-not-found.md @@ -31,7 +31,7 @@ Kubb resolves a file `input` relative to the config file, then confirms the file ## Example output ```text [Terminal] -[KUBB_INPUT_NOT_FOUND] @kubb/adapter-oas: Cannot read the file set as `input` (or via `kubb generate PATH`): ./petStore.yaml +[KUBB_INPUT_NOT_FOUND]: Cannot read the file set as `input` (or via `kubb generate PATH`): ./petStore.yaml fix: Check that the path exists and is readable, then set it as `input` or pass it as `kubb generate PATH`. see: https://kubb.dev/docs/5.x/reference/diagnostics/kubb-input-not-found ``` diff --git a/docs/5.x/reference/diagnostics/kubb-input-required.md b/docs/5.x/reference/diagnostics/kubb-input-required.md index 8f04fb30..77f509b9 100644 --- a/docs/5.x/reference/diagnostics/kubb-input-required.md +++ b/docs/5.x/reference/diagnostics/kubb-input-required.md @@ -45,7 +45,7 @@ export default defineConfig({ ## Example output ```text [Terminal] -[KUBB_INPUT_REQUIRED] @kubb/adapter-oas: An adapter is configured without an input. +[KUBB_INPUT_REQUIRED]: An adapter is configured without an input. fix: Set `input` to a file path, a URL, an inline spec (JSON/YAML string), or a parsed object in your Kubb config. see: https://kubb.dev/docs/5.x/reference/diagnostics/kubb-input-required ``` diff --git a/docs/5.x/reference/diagnostics/kubb-performance.md b/docs/5.x/reference/diagnostics/kubb-performance.md index 872dec4e..a480acc8 100644 --- a/docs/5.x/reference/diagnostics/kubb-performance.md +++ b/docs/5.x/reference/diagnostics/kubb-performance.md @@ -31,9 +31,9 @@ kubb generate --verbose Duration 81ms Output ./src/gen Timings - • @kubb/plugin-react-query ████ 42ms - • @kubb/plugin-zod ██ 21ms - • @kubb/plugin-ts ██ 18ms + • plugin-react-query █ 42ms + • plugin-zod █ 21ms + • plugin-ts █ 18ms ``` The total is the sum of plugin timings, so it counts generation only. It leaves out the config load, the formatter, the linter, and post-generate hooks. diff --git a/docs/5.x/reference/diagnostics/kubb-plugin-failed.md b/docs/5.x/reference/diagnostics/kubb-plugin-failed.md index e0589efc..9d09c028 100644 --- a/docs/5.x/reference/diagnostics/kubb-plugin-failed.md +++ b/docs/5.x/reference/diagnostics/kubb-plugin-failed.md @@ -47,7 +47,7 @@ Diagnostics.report({ ## Example output ```text [Terminal] -[KUBB_PLUGIN_FAILED] @kubb/plugin-ts: Cannot generate type for operation getPetById. +[KUBB_PLUGIN_FAILED] plugin-ts: Cannot generate type for operation getPetById. see: https://kubb.dev/docs/5.x/reference/diagnostics/kubb-plugin-failed ``` diff --git a/docs/5.x/reference/diagnostics/kubb-plugin-info.md b/docs/5.x/reference/diagnostics/kubb-plugin-info.md index 403585ac..1755e7ab 100644 --- a/docs/5.x/reference/diagnostics/kubb-plugin-info.md +++ b/docs/5.x/reference/diagnostics/kubb-plugin-info.md @@ -27,7 +27,7 @@ It is informational, so no action is required. ## Example output ```text [Terminal] -[KUBB_PLUGIN_INFO] @kubb/plugin-fetch: Using fetch as the HTTP client. +[KUBB_PLUGIN_INFO] plugin-fetch: Using fetch as the HTTP client. see: https://kubb.dev/docs/5.x/reference/diagnostics/kubb-plugin-info ``` diff --git a/docs/5.x/reference/diagnostics/kubb-plugin-not-found.md b/docs/5.x/reference/diagnostics/kubb-plugin-not-found.md index 03de5e54..0671956c 100644 --- a/docs/5.x/reference/diagnostics/kubb-plugin-not-found.md +++ b/docs/5.x/reference/diagnostics/kubb-plugin-not-found.md @@ -44,8 +44,8 @@ export default defineConfig({ ## Example output ```text [Terminal] -[KUBB_PLUGIN_NOT_FOUND]: Plugin "@kubb/plugin-ts" is required but not found. Make sure it is included in your Kubb config. - fix: Add "@kubb/plugin-ts" to the plugins array in kubb.config.ts, or remove the dependency on it. +[KUBB_PLUGIN_NOT_FOUND]: Plugin "plugin-ts" is required but not found. Make sure it is included in your Kubb config. + fix: Add "plugin-ts" to the plugins array in kubb.config.ts, or remove the dependency on it. see: https://kubb.dev/docs/5.x/reference/diagnostics/kubb-plugin-not-found ``` diff --git a/docs/5.x/reference/diagnostics/kubb-plugin-warning.md b/docs/5.x/reference/diagnostics/kubb-plugin-warning.md index 0313d3af..6a5ec1af 100644 --- a/docs/5.x/reference/diagnostics/kubb-plugin-warning.md +++ b/docs/5.x/reference/diagnostics/kubb-plugin-warning.md @@ -27,7 +27,7 @@ Read the message and adjust the plugin options or the input if the warning is un ## Example output ```text [Terminal] -[KUBB_PLUGIN_WARNING] @kubb/plugin-zod: Falling back to z.any() for an untyped schema. +[KUBB_PLUGIN_WARNING] plugin-zod: Falling back to z.any() for an untyped schema. see: https://kubb.dev/docs/5.x/reference/diagnostics/kubb-plugin-warning ``` diff --git a/docs/5.x/reference/diagnostics/kubb-ref-not-found.md b/docs/5.x/reference/diagnostics/kubb-ref-not-found.md index ec9b2b23..42805c24 100644 --- a/docs/5.x/reference/diagnostics/kubb-ref-not-found.md +++ b/docs/5.x/reference/diagnostics/kubb-ref-not-found.md @@ -46,7 +46,7 @@ paths: ## Example output ```text [Terminal] -[KUBB_REF_NOT_FOUND] @kubb/plugin-zod: Could not find a definition for #/components/schemas/Pet. +[KUBB_REF_NOT_FOUND]: Could not find a definition for #/components/schemas/Pet. at: #/components/schemas/Pet fix: Add the schema under components.schemas, or fix the $ref. Run `kubb validate` to check the spec. see: https://kubb.dev/docs/5.x/reference/diagnostics/kubb-ref-not-found diff --git a/docs/5.x/reference/diagnostics/kubb-unsupported-format.md b/docs/5.x/reference/diagnostics/kubb-unsupported-format.md index 9b54fddc..b598bbbf 100644 --- a/docs/5.x/reference/diagnostics/kubb-unsupported-format.md +++ b/docs/5.x/reference/diagnostics/kubb-unsupported-format.md @@ -42,7 +42,7 @@ components: ## Example output ```text [Terminal] -[KUBB_UNSUPPORTED_FORMAT] @kubb/adapter-oas: Kubb does not map the format "snowflake" to a specific type, so it falls back to the base type. +[KUBB_UNSUPPORTED_FORMAT]: Kubb does not map the format "snowflake" to a specific type, so it falls back to the base type. at: #/components/schemas/Pet/properties/id fix: Use a format Kubb supports, or handle "snowflake" with a custom parser or plugin. see: https://kubb.dev/docs/5.x/reference/diagnostics/kubb-unsupported-format diff --git a/docs/5.x/reference/kit.md b/docs/5.x/reference/kit.md index 4fa714cf..6954ac2f 100644 --- a/docs/5.x/reference/kit.md +++ b/docs/5.x/reference/kit.md @@ -28,7 +28,7 @@ The seven pieces you reach for when you build something new. Each has its own pa | Part | Entry point | What it does | | ------------------------------------------ | -------------------------- | --------------------------------------------------------------- | | [AST and node builders](./kit/ast) | `ast` | The namespace behind `factory` builders, visitors, guards, macros, and printers. | -| [Diagnostics](./diagnostics) | `Diagnostics` | Builds and narrows the structured errors Kubb collects during a build. | +| [Diagnostics](./kit/diagnostics) | `Diagnostics` | Builds and narrows the structured errors Kubb collects during a build. | | [Engine and configuration](./kit/engine) | `defineConfig`, `createKubb` | The `kubb`-package surface that runs your plugins. | | [Lifecycle hooks](./kit/hooks) | `KubbHooks` | Every `kubb:*` hook a build fires, its payload, and when it fires. | | [Testing](./kit/testing) | `kubb/kit/testing` | Vitest-backed helpers for testing plugins, generators, and adapters. | diff --git a/docs/5.x/reference/kit/ast.md b/docs/5.x/reference/kit/ast.md index 8096f040..e6e8ceec 100644 --- a/docs/5.x/reference/kit/ast.md +++ b/docs/5.x/reference/kit/ast.md @@ -194,7 +194,7 @@ for (const node of ast.collect(root, { operation: (node) => n ## Refs and naming helpers -The ref and naming helpers ship on the `ast` namespace, alongside the other string and code-building utilities. Reach them the same way you reach the guards or node types. +The ref and naming helpers split across two surfaces. `resolveRefName` ships on the `ast` namespace, reached the same way you reach the guards or node types. `extractRefName`, `childName`, `enumPropName`, and `syncSchemaRef` are named exports of `kubb/kit` itself, not members of the `ast` namespace (the same split as the built-in macros below). | Helper | Purpose | | ---------------- | ------------------------------------------------------------------- | @@ -205,31 +205,21 @@ The ref and naming helpers ship on the `ast` namespace, alongside the other stri | `syncSchemaRef` | Merge a ref node with its resolved schema, letting usage-site fields (`description`, `nullable`) override. | ```typescript twoslash [refs.ts] -import { ast } from 'kubb/kit' +import { extractRefName } from 'kubb/kit' -const name = ast.extractRefName('#/components/schemas/Pet') +const name = extractRefName('#/components/schemas/Pet') // ^? ``` ## Schema graph -Analyze how schemas reference each other, to prune unused schemas or wrap circular ones in a lazy construct. +Analyze how schemas reference each other, to prune unused schemas or wrap circular ones in a lazy construct. `collectUsedSchemaNames` and `findCircularSchemas` ship on the `ast` namespace. `containsCircularRef` is a named export of `kubb/kit` itself, not a member of the `ast` namespace. | Helper | Purpose | | ------------------------ | ------------------------------------------------------------------------------------------------- | | `collectUsedSchemaNames` | Collect the names of every top-level schema transitively used by a set of operations. Pair it with `include` filters to leave unreferenced schemas ungenerated. | | `findCircularSchemas` | Find every schema that takes part in a circular dependency chain, so those positions can be wrapped in a lazy getter or `z.lazy(() => …)`. | -| `containsCircularRef` | Report whether a schema, or anything nested inside it, references a circular schema. | - -## Schema traversal - -Map the children of a composite schema to printer output, pairing each result with the source node. Printer overrides reach for these to recurse through their own `transform`. - -| Helper | Purpose | -| --------------------- | ------------------------------------------------------------------------ | -| `mapSchemaProperties` | Map each property of an object schema to its transformed output. | -| `mapSchemaMembers` | Map each member of a union or intersection schema to its transformed output. | -| `mapSchemaItems` | Map each item of an array or tuple schema to its transformed output. | +| `containsCircularRef` | Report whether a schema, or anything nested inside it, references a circular schema. Import it from `kubb/kit` directly, not through `ast`. | ## Constants diff --git a/parsers/parser-md/index.md b/parsers/parser-md/index.md index 7a71ee22..950a7d1e 100644 --- a/parsers/parser-md/index.md +++ b/parsers/parser-md/index.md @@ -64,7 +64,7 @@ yarn add -D @kubb/parser-md@beta ## Dependencies -`@kubb/parser-md` has no plugin dependencies. It is a standalone parser you register on a plugin's `output`, and needs no other Kubb plugin. +`@kubb/parser-md` has no plugin dependencies. It is a standalone parser you register on `defineConfig`'s `parsers` array, and needs no other Kubb plugin. ## Frontmatter diff --git a/parsers/parser-ts/index.md b/parsers/parser-ts/index.md index d8507d1b..79232016 100644 --- a/parsers/parser-ts/index.md +++ b/parsers/parser-ts/index.md @@ -72,7 +72,7 @@ yarn add -D @kubb/parser-ts@beta ## Dependencies -`@kubb/parser-ts` has no plugin dependencies. It is a standalone parser you register on a plugin's `output`, and needs no other Kubb plugin. +`@kubb/parser-ts` has no plugin dependencies. It is a standalone parser you register on `defineConfig`'s `parsers` array, and needs no other Kubb plugin. ## Example diff --git a/plugins/plugin-axios/reference/options.md b/plugins/plugin-axios/reference/options.md index f52c3729..932ed6d6 100644 --- a/plugins/plugin-axios/reference/options.md +++ b/plugins/plugin-axios/reference/options.md @@ -11,7 +11,7 @@ Options for `@kubb/plugin-axios`, which generates a type-safe HTTP client pinned | Option | Type | Default | Description | | ------ | ---- | ------- | ----------- | -| [`output`](#output) | `Output` | `{ path: 'clients' }` | Where the generated files are written and exported | +| [`output`](#output) | `Output` | `{ path: 'clients', barrel: { type: 'named' } }` | Where the generated files are written and exported | | [`group`](#group) | `Group` | — | Split output into per-tag or per-path folders | | [`baseURL`](#baseurl) | `string` | — | Base URL prepended to every request | | [`validator`](#validator) | `false \| 'zod' \| { request?: 'zod'; response?: 'zod' }` | `false` | Validate request and response bodies with Zod | diff --git a/plugins/plugin-cypress/index.md b/plugins/plugin-cypress/index.md index 28b4746e..6e571e0f 100644 --- a/plugins/plugin-cypress/index.md +++ b/plugins/plugin-cypress/index.md @@ -45,7 +45,7 @@ resources: `@kubb/plugin-cypress` turns your OpenAPI operations into typed `cy.request()` wrappers, one helper per operation. Each helper types its path params, body, query, and response, so a broken API call fails at compile time instead of in the test runner. Use the helpers in `before` and `beforeEach` hooks to seed data, in custom commands, or in API-only tests. -Each helper takes its parameters as a single grouped options object shaped as `{ body, path, query, headers }`, with camelCase property names. The request still sends the original parameter names from the spec, and Kubb writes that mapping for you. A helper resolves to the response body and its return type is `Cypress.Chainable<{Operation}Response>`. +Each helper takes its parameters as a single grouped options object shaped as `{ body, path, query, headers }`. Property names inside each group match the OpenAPI spec exactly, including snake_case or quoted names, and Kubb forwards that object straight into `cy.request()` with no extra mapping. A helper resolves to the response body and its return type is `Cypress.Chainable<{Operation}Response>`. ## Installation @@ -108,8 +108,8 @@ import { getPetById } from '../gen/cypress/petRequests' describe('Pet API', () => { it('returns the pet by id', () => { - getPetById({ path: { petId: 1 } }).then((pet) => { - expect(pet.id).to.eq(1) + getPetById({ path: { petId: 1n } }).then((pet) => { + expect(pet.id).to.eq(1n) }) }) }) diff --git a/plugins/plugin-cypress/recipes/typed-request-helpers-against-staging.md b/plugins/plugin-cypress/recipes/typed-request-helpers-against-staging.md index f6d59ccf..6dea7493 100644 --- a/plugins/plugin-cypress/recipes/typed-request-helpers-against-staging.md +++ b/plugins/plugin-cypress/recipes/typed-request-helpers-against-staging.md @@ -18,7 +18,7 @@ export default defineConfig({ input: './petStore.yaml', output: { path: './src/gen', clean: true }, plugins: [ - pluginTs(), + pluginTs({ output: { path: 'models.ts', mode: 'file' } }), pluginCypress({ output: { path: 'cypress', mode: 'directory' }, baseURL: 'https://staging.example.com', @@ -44,7 +44,7 @@ describe('Pet API', () => { ## Output example ```typescript [src/gen/cypress/getPetById.ts] -import type { GetPetByIdOptions, GetPetByIdResponse } from '../types/GetPetById' +import type { GetPetByIdOptions, GetPetByIdResponse } from '../models' export function getPetById({ path }: GetPetByIdOptions, options: Partial = {}): Cypress.Chainable { return cy.request({ diff --git a/plugins/plugin-cypress/reference/options.md b/plugins/plugin-cypress/reference/options.md index 4ed0b46d..09849972 100644 --- a/plugins/plugin-cypress/reference/options.md +++ b/plugins/plugin-cypress/reference/options.md @@ -11,7 +11,7 @@ Options for `pluginCypress`, with type and default in the table. | Option | Type | Default | Description | | ------ | ---- | ------- | ----------- | -| [`output`](#output) | `Output` | `{ path: 'cypress' }` | Where the generated files are written and exported | +| [`output`](#output) | `Output` | `{ path: 'cypress', barrel: { type: 'named' } }` | Where the generated files are written and exported | | [`group`](#group) | `Group` | — | Split output into per-tag or per-path folders | | [`baseURL`](#baseurl) | `string` | — | Base URL prepended to every request | | [`include`](#include) | `Array` | — | Keep only operations that match | diff --git a/plugins/plugin-fetch/reference/options.md b/plugins/plugin-fetch/reference/options.md index 711f508f..7cf0be6c 100644 --- a/plugins/plugin-fetch/reference/options.md +++ b/plugins/plugin-fetch/reference/options.md @@ -11,7 +11,7 @@ Pass these options to `pluginFetch()` to control what it generates and where the | Option | Type | Default | Description | | ------ | ---- | ------- | ----------- | -| [`output`](#output) | `Output` | `{ path: 'clients' }` | Where the generated files are written and exported | +| [`output`](#output) | `Output` | `{ path: 'clients', barrel: { type: 'named' } }` | Where the generated files are written and exported | | [`group`](#group) | `Group` | — | Split output into per-tag or per-path folders | | [`baseURL`](#baseurl) | `string` | — | Base URL prepended to every request | | [`validator`](#validator) | `false \| 'zod' \| { request?: 'zod'; response?: 'zod' }` | `false` | Validate request and response bodies with Zod | diff --git a/plugins/plugin-mcp/reference/options.md b/plugins/plugin-mcp/reference/options.md index eabdb178..68741749 100644 --- a/plugins/plugin-mcp/reference/options.md +++ b/plugins/plugin-mcp/reference/options.md @@ -11,7 +11,7 @@ Options for `@kubb/plugin-mcp`, which generates an MCP server where each OpenAPI | Option | Type | Default | Description | | ------ | ---- | ------- | ----------- | -| [`output`](#output) | `Output` | `{ path: 'mcp' }` | Where the generated handlers are written and exported | +| [`output`](#output) | `Output` | `{ path: 'mcp', barrel: { type: 'named' } }` | Where the generated handlers are written and exported | | [`group`](#group) | `Group` | — | Split output into per-tag or per-path folders | | [`client`](#client) | `'fetch' \| 'axios'` | — | Which registered client plugin the handlers call | | [`include`](#include) | `Array` | — | Keep only operations that match | diff --git a/plugins/plugin-msw/reference/options.md b/plugins/plugin-msw/reference/options.md index 745c3553..fd68f54c 100644 --- a/plugins/plugin-msw/reference/options.md +++ b/plugins/plugin-msw/reference/options.md @@ -55,7 +55,7 @@ How the plugin consolidates its generated code into files. `'file'` (the default #### group.name -Function that turns a group key into the subdirectory name, used also as a suffix when naming aggregate files. It defaults to `({ group }) => camelCase(group)` for tag groups, while `type: 'path'` groups use the first URL segment as-is. +Function that turns a group key into the subdirectory name. It defaults to `({ group }) => camelCase(group)` for tag groups, while `type: 'path'` groups default to the raw first URL segment, uncased. ### baseURL @@ -81,7 +81,7 @@ export function getPetHandler(data?: GetPetQueryResponse | ((info: Parameters) => [{ url: '/pet/:petId', params: path }] as const -export function useGetPetByIdSuspense>( +type GetPetByIdSuspenseQueryKey = ReturnType + +export function useGetPetByIdSuspense( { path }: { path: GetPetByIdOptions['path'] | (() => GetPetByIdOptions['path']) }, - options: { query?: Partial, TData, TQueryKey>> & { client?: QueryClient }, client?: object } = {}, + options: { query?: Partial, TData, TQueryKey>> & { client?: QueryClient }, client?: Partial> } = {}, ) { // ...builds queryKey/queryOptions, then calls useSuspenseQuery(...) } diff --git a/plugins/plugin-react-query/recipes/wrap-hooks-with-shared-options.md b/plugins/plugin-react-query/recipes/wrap-hooks-with-shared-options.md index 3c815f0a..428f49ca 100644 --- a/plugins/plugin-react-query/recipes/wrap-hooks-with-shared-options.md +++ b/plugins/plugin-react-query/recipes/wrap-hooks-with-shared-options.md @@ -44,16 +44,21 @@ import { queryOptions, useQuery } from '@tanstack/react-query' export function useGetPetById({ path }, options = {}) { const { query: queryConfig = {}, client: config = {} } = options ?? {} + const { client: queryClient, ...resolvedOptions } = queryConfig const resolvedParams = { path: typeof path === 'function' ? path() : path } - const queryKey = getPetByIdQueryKey(resolvedParams) + const queryKey = resolvedOptions?.queryKey ?? getPetByIdQueryKey(resolvedParams) const customOptions = useCustomHookOptions({ hookName: 'useGetPetById', operationId: 'getPetById' }) - return useQuery({ + const queryResult = useQuery({ ...getPetByIdQueryOptions(resolvedParams, config), ...customOptions, - ...queryConfig, + ...resolvedOptions, queryKey, - }) + }, queryClient) + + queryResult.queryKey = queryKey + + return queryResult } ``` diff --git a/plugins/plugin-react-query/reference/options.md b/plugins/plugin-react-query/reference/options.md index b1137782..76b0e5db 100644 --- a/plugins/plugin-react-query/reference/options.md +++ b/plugins/plugin-react-query/reference/options.md @@ -11,7 +11,7 @@ Options for `pluginReactQuery`, with type and default in the table. | Option | Type | Default | Description | | ------ | ---- | ------- | ----------- | -| [`output`](#output) | `Output` | `{ path: 'hooks' }` | Where the generated hooks are written and exported | +| [`output`](#output) | `Output` | `{ path: 'hooks', barrel: { type: 'named' } }` | Where the generated hooks are written and exported | | [`group`](#group) | `Group` | — | Split output into per-tag or per-path folders | | [`client`](#client) | `'axios' \| 'fetch'` | — | Which registered client plugin the hooks call | | [`infinite`](#infinite) | `Partial \| false` | `false` | Generate `useInfiniteQuery` hooks for pagination | diff --git a/plugins/plugin-swr/reference/options.md b/plugins/plugin-swr/reference/options.md index 72aceb49..2e12dd4f 100644 --- a/plugins/plugin-swr/reference/options.md +++ b/plugins/plugin-swr/reference/options.md @@ -26,7 +26,7 @@ Configuration options for `@kubb/plugin-swr`, passed to `pluginSwr({ ... })`. Ev ### output -Where the generated `.ts` files are written and how they are exported. Defaults to `{ path: 'hooks' }`. +Where the generated `.ts` files are written and how they are exported. Defaults to `{ path: 'hooks', barrel: { type: 'named' } }`. #### output.path diff --git a/plugins/plugin-ts/recipes/map-spec-types-to-native-ts.md b/plugins/plugin-ts/recipes/map-spec-types-to-native-ts.md index a0c94a65..67bca3dd 100644 --- a/plugins/plugin-ts/recipes/map-spec-types-to-native-ts.md +++ b/plugins/plugin-ts/recipes/map-spec-types-to-native-ts.md @@ -37,12 +37,13 @@ export default defineConfig({ ## Output example -The petStore fixture has no plain `date` (only `date-time`) schemas, so this excerpt shows the `integer` handler mapping `format: int64` fields to `bigint` (the same printer mechanism the recipe uses for `date`): +The petStore fixture has no plain `date` (only `date-time`) schemas. `format: int64` fields like `id` and `petId` are already `bigint` by default (the adapter's `integerType` option defaults to `'bigint'`), so the override has no effect on them. It does affect `format: int32` fields such as `quantity`, which becomes `bigint` only because of the `integer` handler override (the same printer mechanism the recipe uses for `date`): ```typescript [src/gen/types/Order.ts] export type Order = { id?: bigint; petId?: bigint; + quantity?: bigint; // ... }; ``` diff --git a/plugins/plugin-ts/recipes/strip-descriptions-with-a-macro.md b/plugins/plugin-ts/recipes/strip-descriptions-with-a-macro.md index 1e89fc12..cd599bcb 100644 --- a/plugins/plugin-ts/recipes/strip-descriptions-with-a-macro.md +++ b/plugins/plugin-ts/recipes/strip-descriptions-with-a-macro.md @@ -37,9 +37,6 @@ export default defineConfig({ ```typescript [src/gen/types/Pet.ts] export type Pet = { - /** - * @type string | undefined - */ status?: PetStatusEnumKey; }; ``` diff --git a/plugins/plugin-vue-query/guide/calling-operations.md b/plugins/plugin-vue-query/guide/calling-operations.md index edc55579..4b07badf 100644 --- a/plugins/plugin-vue-query/guide/calling-operations.md +++ b/plugins/plugin-vue-query/guide/calling-operations.md @@ -10,7 +10,7 @@ outline: deep `@kubb/plugin-vue-query` turns each operation into a composable that wraps the client function from `@kubb/plugin-axios` or `@kubb/plugin-fetch`. Read operations become `useFoo`, write operations become `useFoo` mutations, and every composable is typed from the spec. > [!IMPORTANT] -> By default the plugin emits only the factory helpers (`queryOptions`, `mutationOptions`, `queryKey`, `mutationKey`). Set [`hooks: true`](/plugins/plugin-vue-query/reference/options#hooks) in the plugin options to also generate the `use*` composables shown below. +> By default the plugin emits only the factory helpers (`queryOptions`, `queryKey`, `mutationKey`). Set [`hooks: true`](/plugins/plugin-vue-query/reference/options#hooks) in the plugin options to also generate the `use*` composables shown below. ## Queries diff --git a/plugins/plugin-vue-query/reference/options.md b/plugins/plugin-vue-query/reference/options.md index 428259ce..fa5125a7 100644 --- a/plugins/plugin-vue-query/reference/options.md +++ b/plugins/plugin-vue-query/reference/options.md @@ -28,7 +28,7 @@ Options for `@kubb/plugin-vue-query`, which generates TanStack Vue Query composa ### output -Where the generated composables are written and how they are exported. Defaults to `{ path: 'hooks' }`. +Where the generated composables are written and how they are exported. Defaults to `{ path: 'hooks', barrel: { type: 'named' } }`. #### output.path diff --git a/plugins/plugin-zod/recipes/downgrade-int64-to-a-plain-number.md b/plugins/plugin-zod/recipes/downgrade-int64-to-a-plain-number.md index 30134a4c..dfa2b10c 100644 --- a/plugins/plugin-zod/recipes/downgrade-int64-to-a-plain-number.md +++ b/plugins/plugin-zod/recipes/downgrade-int64-to-a-plain-number.md @@ -40,7 +40,7 @@ export const petSchema = z.object({ }) ``` -Without the override, that same field prints `id: z.bigint().optional()`. The `integer` node (for 32-bit `format: int32` fields) is a separate handler from `bigint`, so overriding one does not affect the other. +Without the override, that same field prints `id: z.bigint().optional().meta({ examples: [10] })`. The `integer` node (for 32-bit `format: int32` fields) is a separate handler from `bigint`, so overriding one does not affect the other. ```typescript [usage.ts] import { petSchema } from './src/gen/zod/petSchema' diff --git a/plugins/plugin-zod/reference/options.md b/plugins/plugin-zod/reference/options.md index d36872ce..8d917128 100644 --- a/plugins/plugin-zod/reference/options.md +++ b/plugins/plugin-zod/reference/options.md @@ -11,7 +11,7 @@ Options for `pluginZod`, with type and default in the table. | Option | Type | Default | Description | | ------ | ---- | ------- | ----------- | -| [`output`](#output) | `Output` | `{ path: 'zod' }` | Where the generated files are written and exported | +| [`output`](#output) | `Output` | `{ path: 'zod', barrel: { type: 'named' } }` | Where the generated files are written and exported | | [`group`](#group) | `Group` | — | Split output into per-tag or per-path folders | | [`importPath`](#importpath) | `string` | `mini ? 'zod/mini' : 'zod'` | Module the generated files import `z` from | | [`inferred`](#inferred) | `boolean` | `false` | Emit a `z.infer` alias next to each schema | @@ -74,7 +74,7 @@ Function that turns a group key (first tag or path segment) into a folder or ide | | | | -------: | :--------------------------------------- | | Type: | `(context: { group: string }) => string` | -| Default: | `({ group }) => camelCase(group)` | +| Default: | `'tag'`: `({ group }) => camelCase(group)`; `'path'`: the raw URL segment, uncased | ### importPath @@ -193,6 +193,7 @@ type ResolverZodPatch = { responses?(node: OperationNode): string // → 'listPetsResponsesSchema' response?(node: OperationNode): string // → 'listPetsResponseSchema' error?(node: OperationNode): string // → 'listPetsErrorSchema' + options?(node: OperationNode): string // → 'ListPetsOptionsSchemaType' } } ``` diff --git a/snippets/how-to/authentication.md b/snippets/how-to/authentication.md index 25ad3c62..316b7a25 100644 --- a/snippets/how-to/authentication.md +++ b/snippets/how-to/authentication.md @@ -10,7 +10,7 @@ Every generated function already carries the operation's security, derived from ```typescript export function addPet( - options: Options, + options: Options, ): Promise> { const { client: request = client, ...config } = options diff --git a/snippets/how-to/barrel.md b/snippets/how-to/barrel.md index ca9006bc..eef2dfea 100644 --- a/snippets/how-to/barrel.md +++ b/snippets/how-to/barrel.md @@ -2,4 +2,4 @@ Toggle the export style and depth to see the generated barrels. -Controls how the generated `index.ts` (barrel) re-exports the output. Defaults to `false` (no barrel), and also accepts `{ type: 'named' }` or `{ type: 'all' }`, optionally with `nested: true` (for example `{ type: 'named', nested: true }`) to write an `index.ts` in every subdirectory. +Controls how the generated `index.ts` (barrel) re-exports the output. Accepts `{ type: 'named' }` or `{ type: 'all' }`, optionally with `nested: true` (for example `{ type: 'named', nested: true }`) to write an `index.ts` in every subdirectory, or `false` to skip the barrel entirely. Each generator plugin defaults `output.barrel` to `{ type: 'named' }`; the root `output.barrel` on `defineConfig` defaults to `false`. diff --git a/snippets/how-to/base-url.md b/snippets/how-to/base-url.md index f7c411b2..f3ab2133 100644 --- a/snippets/how-to/base-url.md +++ b/snippets/how-to/base-url.md @@ -6,7 +6,7 @@ Set it at build time or at runtime. At build time you read it from the servers l ## Read it from the spec -When you set no `baseURL` on the client plugin, the client falls back to the server URL the [OpenAPI adapter](/adapters/adapter-oas/) resolves. The adapter resolves one only when you point its `server.index` at an entry in the spec's `servers` array, so set `adapter: adapterOas({ server: { index: 0 } })` to use the first entry. Add `variables` to fill in any `{variable}` placeholders in the chosen URL. Leave `server` unset and the spec contributes no `baseURL`. +Kubb never sets the generated client's `baseURL` for you. Setting `adapter: adapterOas({ server: { index: 0 } })` only resolves a server URL onto the document's metadata (`meta.baseURL`), which a custom `banner` or `footer` function can read. It does not reach the client. Pass [`baseURL`](#use-the-baseurl-option) to the client plugin yourself to prepend a host to every request. ::: code-group diff --git a/snippets/how-to/include.md b/snippets/how-to/include.md index e2bdf29f..9e468c99 100644 --- a/snippets/how-to/include.md +++ b/snippets/how-to/include.md @@ -1,4 +1,4 @@ -Generates only the operations and schemas that match at least one entry, and skips the rest. Each entry filters by `tag`, `operationId`, `path`, `method`, `contentType`, or `schemaName`, with a `pattern` that is a string (exact) or a `RegExp` (fuzzy). +Generates only the operations and schemas that match at least one entry, and skips the rest. Each entry filters by `tag`, `operationId`, `path`, `method`, `contentType`, or `schemaName`, with a `pattern` that can be a string or a `RegExp`, both matched as a regular expression against the value. A string pattern is compiled with `new RegExp(pattern)`, so it is not an exact match: `pattern: 'pet'` also matches `'petType'` or `'superpet'`. ```typescript [Type definition] export type Include = { diff --git a/snippets/how-to/interceptors.md b/snippets/how-to/interceptors.md index ca23ef51..ca9cc8b4 100644 --- a/snippets/how-to/interceptors.md +++ b/snippets/how-to/interceptors.md @@ -95,7 +95,9 @@ client.interceptors.error.use((error) => { The fetch handler receives the `ResponseError`, the axios handler an `AxiosError`. This channel only fires on the throw path. When you read with `throwOnError: false`, a documented non-2xx response resolves and no error interceptor runs, so inspect the returned `error` on the result -instead. A transport failure (no response at all) still throws and still fires the channel. See +instead. A transport failure (no response at all) still throws on both. On axios the channel still +fires, since it is wired directly into axios's own rejection handling. On fetch the channel does +not fire, since there is no result to hand the interceptor stacks. See [error handling](/plugins/plugin-fetch/guide/error-handling) for that path. ## Add, replace, and remove handlers