Skip to content

Extract Zuplo integration into standalone @zuplo/zudoku package#2593

Draft
mosch wants to merge 2 commits into
mainfrom
claude/charming-brahmagupta-tpueo8
Draft

Extract Zuplo integration into standalone @zuplo/zudoku package#2593
mosch wants to merge 2 commits into
mainfrom
claude/charming-brahmagupta-tpueo8

Conversation

@mosch

@mosch mosch commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Extracts the Zuplo-specific integration logic from the main Zudoku package into a new standalone @zuplo/zudoku package. This enables Zuplo projects to automatically discover and document their OpenAPI files and GraphQL endpoints through a simple plugin, while keeping Zuplo-specific code isolated from the core framework.

Key Changes

  • New @zuplo/zudoku package with:

    • zuploPlugin() - Main plugin that inspects Zuplo projects and builds the Zudoku config
    • inspectZuploContext() - Scans the project's config/ directory for OpenAPI files and GraphQL endpoints
    • applyZuploConfig() - Applies discovered APIs and endpoints to the Zudoku config
    • Zuplo-specific OpenAPI processors (enrichment from policies, MCP server documentation, internal route removal)
    • Companion Vite plugin (zuploVitePlugin) that bakes the inspected context into client/server bundles
  • Context detection discovers:

    • All *.oas.json files in the project's config/ directory
    • GraphQL endpoints marked with x-graphql or x-zuplo-route.mcp.type
    • Filters out internal routes and files with no documentable operations
    • Resolves GraphQL endpoint URLs from the gateway server or route's upstream handler
  • Config application:

    • Mounts single OpenAPI file at /api, multiple files under /api/{filename}
    • Respects user-configured APIs and avoids path conflicts
    • Creates GraphQL plugin instances for each discovered endpoint
    • Applies Zuplo-specific schema processors during config loading
  • Moved/refactored:

    • Zuplo processors moved from packages/zudoku/src/zuplo/ to packages/zuplo/src/processors/
    • Updated imports to use public Zudoku processor APIs
    • Deprecated withZuplo() helper (now automatic via plugin)
  • Updated example (examples/with-zuplo/) to use the new zuploPlugin()

Implementation Details

  • The plugin works in two modes:

    • Config loading (Node): Inspects the project from disk and contributes schema processors
    • Client/server bundles: Uses baked virtual:zuplo-context module to avoid Node dependencies
  • The Vite plugin watches OpenAPI files and reloads when GraphQL endpoints are added/removed

  • GraphQL endpoint detection supports both explicit marking (x-graphql) and MCP server routes (x-zuplo-route.mcp.type)

  • Gracefully handles missing configuration (non-Zuplo projects return empty context) and logs warnings for GraphQL endpoints without introspectable URLs

https://claude.ai/code/session_01Dq4AK4qdCF8sensEVCZf46

Moves the Zuplo-specific code out of zudoku core into a new package that
is only used in the Zuplo context. The package inspects the Zuplo project
(via a transformConfig plugin) and builds the Zudoku config for it:

- Sets up an OpenAPI reference for each OpenAPI file found in the
  project's config/ directory (skipping files the user documents
  themselves)
- Detects GraphQL endpoints (routes marked with x-graphql or exposed as
  GraphQL MCP endpoints) and sets up a @zudoku/plugin-graphql instance
  per endpoint, introspecting through the gateway URL with a fallback to
  the route's upstream
- Applies everything the Zuplo processors did before: policy-based
  enrichment (API key headers, rate limit responses), MCP server route
  documentation, server URL injection, and removal of x-internal routes,
  parameters and x-zuplo extensions

A companion Vite plugin (merged automatically via the plugin's package
vite.config.ts) bakes the inspected context into a virtual module so the
client/server bundles build the same config without filesystem access,
and stubs the node-only entry out of those bundles.

Core changes:
- plugins can now contribute schema processors through the internal
  __processors config field instead of the hardcoded Zuplo import in
  the API vite plugin
- selectPluginConfigs is exported from zudoku/plugins
- traverseAsync is re-exported from zudoku/processors/traverse
- running with --zuplo without the plugin logs a migration warning, and
  the deprecated withZuplo export now points to @zuplo/zudoku
- @zuplo/mcp dependency moved to the new package

The with-zuplo example now uses zuploPlugin() instead of a manual apis
entry.

https://claude.ai/code/session_01Dq4AK4qdCF8sensEVCZf46
@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
zudoku-cosmo-cargo Ready Ready Preview, Comment Jun 11, 2026 3:21pm
zudoku-dev Ready Ready Preview, Comment Jun 11, 2026 3:21pm

Request Review

@github-actions

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 67.87%
🟰 ±0%
4779 / 7041
🔵 Statements 67.12%
⬇️ -0.07%
5152 / 7675
🔵 Functions 58.85%
⬆️ +0.07%
1146 / 1947
🔵 Branches 57.93%
⬆️ +0.32%
3434 / 5927
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/zudoku/src/config/validators/ZudokuConfig.ts 77.5%
⬇️ -0.98%
78.57%
🟰 ±0%
30.43%
⬇️ -1.38%
76.92%
⬇️ -1.00%
111-114, 161-197, 234, 295, 404, 413, 593-599, 636, 672, 685-688, 766
packages/zudoku/src/lib/core/plugins.ts 87.5%
🟰 ±0%
75%
🟰 ±0%
75%
🟰 ±0%
87.5%
🟰 ±0%
37, 41, 134
packages/zudoku/src/lib/plugins/openapi/processors/traverse.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/zuplo/src/apply-config.ts 97.43% 82.75% 100% 100% 70
packages/zuplo/src/context/graphql.ts 100% 100% 100% 100%
packages/zuplo/src/context/inspect.ts 90.74% 88.57% 100% 95.74% 67-68, 71, 76, 91
packages/zuplo/src/test/virtual-graphql-schema.ts 100% 100% 100% 100%
packages/zuplo/src/util/objectEntries.ts 50% 100% 0% 50% 5
Generated in workflow #5829 for commit fee30f3 by the Vitest Coverage Report Action

Zero-config: running `zudoku build --zuplo` now generates the Zudoku
config on the fly without any setup in the user's config file. Two
steps: @zuplo/zudoku inspects the Zuplo project and builds the config,
zudoku consumes it.

- The config loader resolves @zuplo/zudoku from the docs project (it is
  a dependency there, never of zudoku itself) and applies
  `withZuploPlugin` before running config transforms; a warning is
  logged when the package isn't installed
- The generated `virtual:zudoku-config` module applies the same wrapper
  so client/server bundles produce the identical config
- The server entry now exports the fully transformed config and the
  prerenderer consumes it instead of importing the raw config chunk and
  re-running the transform itself, which also removes the
  serverConfigFilename plumbing
- `zuploPlugin()` stays exported for passing options; the automatic
  application backs off when it is configured explicitly

The with-zuplo example is back to a plain config with no Zuplo wiring.

https://claude.ai/code/session_01Dq4AK4qdCF8sensEVCZf46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants