---
url: /docs/5.x/reference/kit/resolvers.md
description: >-
  createResolver builds a Resolver that controls file naming and path resolution
  for a plugin, with auto-injected defaults under resolver.default and
  Resolver.merge for layering overrides.
---

# Resolvers

## `createResolver`

`createResolver` builds a `Resolver` instance that controls file naming and path resolution for a plugin. Pass the plugin-specific fields directly as an object.

The object must include at least `{ pluginName }`. The resolver exposes `name`, `file`, and `imports` methods that generators call. Use `this` to reach sibling members, so a namespace method calls `this.name(...)` for the plugin's identifier casing.

```typescript twoslash [resolver.ts]
import { createResolver } from 'kubb/kit'
import type { PluginFactoryOptions, Resolver } from 'kubb/kit'

// Extend the base Resolver with plugin-specific naming namespaces.
type MyResolver = Resolver & {
  schema: {
    name(node: { name: string }): string
  }
}

type MyPlugin = PluginFactoryOptions<'plugin-example', object, object, MyResolver>

export const resolver = createResolver<MyPlugin>({
  pluginName: 'plugin-example',
  name(name) {
    return `${name.charAt(0).toUpperCase()}${name.slice(1)}`
  },
  schema: {
    name(node) {
      return this.name(node.name)
    },
  },
})
```

### Auto-injected resolver defaults

| Method           | Default behavior                                                        |
| ---------------- | ---------------------------------------------------------------------- |
| `name`           | Active top-level identifier casing; delegates to `default.name` when omitted |
| `file`           | Top-level `FileNode` builder, delegates to `default.file`              |
| `default.name`   | The core `camelCase` generated-identifier casing                       |
| `default.options`| Applies `exclude`, `include`, and `override` filters                   |
| `default.path`   | Resolves to `output.path`, with optional tag/path-based subdirectories |
| `default.file`   | Constructs a full `FileNode` using the resolver's `file.baseName` casing (default `toFilePath`) |
| `default.banner` | Returns `output.banner` or the standard "Generated by Kubb" header     |
| `default.footer` | Returns `output.footer` when set                                       |

### `resolver.imports` {#imports}

`resolver.imports` builds one import entry per `$ref` in a schema tree, so a generator emits the imports for every schema the current node references. Each ref resolves through `ast.resolveRefName`, which prefers the node's `targetName` and falls back to the pointer's last segment.

The resulting names and paths go through the resolver's own `name` and `file` conventions. `extname` defaults to `.ts`.

```typescript twoslash [imports.ts]
import { ast } from 'kubb/kit'
import type { GeneratorContext, PluginFactoryOptions } from 'kubb/kit'

declare const ctx: GeneratorContext<PluginFactoryOptions>
const { resolver, root, output } = { ...ctx, output: { path: 'types' } }
const node = ast.factory.createSchema({ type: 'ref', ref: '#/components/schemas/Pet' })
// ---cut---
const imports = resolver.imports({ node, root, output })
// → [{ kind: 'Import', name: ['pet'], path: '/src/types/pet.ts' }]
```

Pass `name` to override how a referenced schema name becomes the imported identifier, for example to point enum refs at a suffixed type name:

```typescript twoslash [importsName.ts]
import { ast } from 'kubb/kit'
import type { GeneratorContext, PluginFactoryOptions } from 'kubb/kit'

declare const ctx: GeneratorContext<PluginFactoryOptions>
const { resolver, root, output } = { ...ctx, output: { path: 'types' } }
const node = ast.factory.createSchema({ type: 'ref', ref: '#/components/schemas/Pet' })
// ---cut---
const imports = resolver.imports({
  node,
  root,
  output,
  name: (schemaName) => `${resolver.name(schemaName)}Type`,
})
```

### `Resolver.merge`

`Resolver.merge(base, patch)` returns a new resolver with `patch`'s fields layered over `base`'s and every helper re-bound. A top-level `name` replaces, while `file` and each namespace merge per member, so overriding `query.name` keeps the base `query.keyName`.

Framework code uses it to apply a `setResolver` partial override over a plugin's built-in resolver, and you can call it yourself when composing resolvers.

> \[!TIP]
> Type a patch with `ResolverPatch<T>` to keep `this` and namespace shapes checked against the target resolver.

```typescript twoslash [merge.ts]
import { createResolver, Resolver } from 'kubb/kit'
import type { PluginFactoryOptions } from 'kubb/kit'

const resolver = createResolver<PluginFactoryOptions>({ pluginName: 'plugin-example' })
// ---cut---
const patched = Resolver.merge(resolver, {
  name(name) {
    return `Custom${this.default.name(name)}`
  },
})
```

### Related

* [Resolver concepts](/docs/5.x/guide/concepts/resolvers)
* [Override a resolver](/docs/5.x/guide/going-further/resolvers)
* [Creating plugins](/docs/5.x/guide/going-further/creating-plugins)
