Skip to content

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.

resolver.ts
typescript
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

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.

imports.ts
typescript
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:

importsName.ts
typescript
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.

merge.ts
typescript
const 
patched
=
Resolver
.
merge
(
resolver
, {
name
(
name
) {
return `Custom${this.
default
.
name
(
name
)}`
}, })