Skip to content

feat(ast): /types subpath, concurrent walk(), and a trimmed public API#3402

Merged
stijnvanhulle merged 4 commits into
mainfrom
claude/kubbs-ast-improvements-FDiyo
May 29, 2026
Merged

feat(ast): /types subpath, concurrent walk(), and a trimmed public API#3402
stijnvanhulle merged 4 commits into
mainfrom
claude/kubbs-ast-improvements-FDiyo

Conversation

@stijnvanhulle
Copy link
Copy Markdown
Collaborator

@stijnvanhulle stijnvanhulle commented May 28, 2026

Summary

Improvements to @kubb/ast for performance, ease of use, and lower complexity, informed by the patterns in Babel (@babel/traverse/@babel/types), the TypeScript factory, and the oxc toolchain in this repo. Crucially, the public-API trim is backed by real usage data: I measured every @kubb/ast export against both this monorepo and the plugins repo (kubb-labs/plugins, which consumes ast via @kubb/core's export * as ast).

Changes

1. @kubb/ast/types subpath now exists (ease of use)

The README's import type { Node } from '@kubb/ast/types' previously failed — the subpath was never in the package exports. Added a types tsdown entry (exports: true regenerates the map). Mirrors @babel/types. ESM + CJS resolution verified.

2. walk() is genuinely concurrent (performance)

walk() advertised a concurrency limit (default 30) and "siblings run concurrently", but awaited each child one at a time, so the option was inert and async visitors ran serially. Siblings now traverse via Promise.all gated by the shared limiter. Added a test asserting real parallelism (the old test only checked the upper bound, which a serial impl passes trivially).

3. Trimmed the public API surface (complexity) — breaking

Removed only exports unused across both repos that also duplicate/back a public counterpart:

Export Disposition Why safe / rationale
nodeKinds, mediaTypes deleted Dead — zero references anywhere, even internally
RefMap type deleted Dead — only the definition existed
InferSchema type deleted Self-described "backward-compatible alias" of InferSchemaNode
collectLazy internal Lower-level generator twin of the public, used collect
createContent, createRequestBody internal Building blocks normalized for you by createResponse/createOperation

Also fixed the README Refs example, which referenced helpers that never existed (buildRefMap/resolveRef) — now documents extractRefName.

Verified: ast typecheck + 303 tests pass; @kubb/core, @kubb/adapter-oas, @kubb/parser-ts, @kubb/renderer-jsx all typecheck against the trimmed package; oxlint + oxfmt clean. Major changeset included.

Further trim candidates — left for your call

These are also unused across both repos, but they're plausibly-intended public utilities rather than clear dead code, so I did not remove them. Say the word and I'll trim any subset:

  • isScalarPrimitive, resolveRefName, collectReferencedSchemaNames, isSchemaEqual — standalone utilities (no public alternative)
  • isInputNode / isOutputNode — kept for guard-set symmetry with the used isOperationNode / isSchemaNode
  • mergeAdjacentObjects (eager) — twin of the used mergeAdjacentObjectsLazy, but it has its own test coverage

Roadmap (not in this PR)

  • signature.ts — the 9-kind ShapeField/SHAPE_KEYS table machinery is the package's heaviest abstraction; could collapse to direct per-type descriptor builders (medium risk — drives dedupe; needs test expansion first).
  • utils.ts (956 LOC) — mixes ref-graph, import/export combining, and operation-param building; a pure file split would improve navigability.
  • combineImports/combineExports — share a sort→merge→dedup skeleton that could be extracted.
  • createLimit duplicates p-limit (already a catalog dep).

Notes

  • dist/ is gitignored; only src, configs, README, and changesets are committed.

https://claude.ai/code/session_01UHmX1Z5cshiSKjzPoExazB

The README documents `import ... from '@kubb/ast/types'`, but the subpath
was never wired into the package exports, so the import failed. Add a
`types` tsdown entry so the type-only subpath is emitted and exported.

`walk()` awaited each child sequentially, so its documented `concurrency`
option never parallelized anything — async visitor callbacks always ran
one at a time. Traverse siblings via the shared limiter instead, so the
limit is honored, and tighten the test to assert real parallelism.

https://claude.ai/code/session_01UHmX1Z5cshiSKjzPoExazB
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 28, 2026

Open in StackBlitz

@kubb/adapter-oas

npm i https://pkg.pr.new/@kubb/adapter-oas@3402

@kubb/agent

npm i https://pkg.pr.new/@kubb/agent@3402

@kubb/ast

npm i https://pkg.pr.new/@kubb/ast@3402

@kubb/cli

npm i https://pkg.pr.new/@kubb/cli@3402

@kubb/core

npm i https://pkg.pr.new/@kubb/core@3402

kubb

npm i https://pkg.pr.new/kubb@3402

@kubb/mcp

npm i https://pkg.pr.new/@kubb/mcp@3402

@kubb/middleware-barrel

npm i https://pkg.pr.new/@kubb/middleware-barrel@3402

@kubb/parser-md

npm i https://pkg.pr.new/@kubb/parser-md@3402

@kubb/parser-ts

npm i https://pkg.pr.new/@kubb/parser-ts@3402

@kubb/renderer-jsx

npm i https://pkg.pr.new/@kubb/renderer-jsx@3402

unplugin-kubb

npm i https://pkg.pr.new/unplugin-kubb@3402

commit: 996d419

Remove exports that are unused across both this monorepo and the plugins
repo, and that duplicate or back a public counterpart:

- delete dead constants `nodeKinds` and `mediaTypes` (no references)
- delete the `RefMap` type and the `InferSchema` alias (use InferSchemaNode)
- stop exporting `collectLazy` (use eager `collect`) and the `createContent`
  / `createRequestBody` builders (normalized by createResponse/createOperation)

Also fix the README Refs example, which referenced helpers that never
existed (`buildRefMap`/`resolveRef`); it now documents `extractRefName`.

BREAKING CHANGE: the listed exports are no longer part of @kubb/ast.

https://claude.ai/code/session_01UHmX1Z5cshiSKjzPoExazB
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 28, 2026

🦋 Changeset detected

Latest commit: ad3182b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 12 packages
Name Type
@kubb/ast Major
@kubb/agent Major
@kubb/core Major
@kubb/middleware-barrel Major
@kubb/parser-ts Major
@kubb/renderer-jsx Major
@kubb/cli Major
kubb Major
@kubb/adapter-oas Major
@kubb/mcp Major
@kubb/parser-md Major
unplugin-kubb Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@stijnvanhulle stijnvanhulle changed the title feat(ast): ship @kubb/ast/types subpath and make walk() concurrent feat(ast): /types subpath, concurrent walk(), and a trimmed public API May 28, 2026
Following the public-API trim, remove the remaining exports that are
unused across both this monorepo and the plugins repo. Each keeps its
internal callers and test coverage; it just leaves the public surface.

- isScalarPrimitive, resolveRefName, collectReferencedSchemaNames
- isSchemaEqual (use schemaSignature equality)
- isInputNode / isOutputNode
- mergeAdjacentObjects (use mergeAdjacentObjectsLazy)

BREAKING CHANGE: the listed exports are no longer part of @kubb/ast.

https://claude.ai/code/session_01UHmX1Z5cshiSKjzPoExazB
@stijnvanhulle stijnvanhulle marked this pull request as ready for review May 28, 2026 20:35
@dosubot dosubot Bot added enhancement New feature or request typescript labels May 28, 2026
@stijnvanhulle stijnvanhulle merged commit 0274bf0 into main May 29, 2026
6 of 7 checks passed
@stijnvanhulle stijnvanhulle deleted the claude/kubbs-ast-improvements-FDiyo branch May 29, 2026 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request typescript

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants