Add config generation and extends support for layered configs#2597
Draft
mosch wants to merge 3 commits into
Draft
Add config generation and extends support for layered configs#2597mosch wants to merge 3 commits into
mosch wants to merge 3 commits into
Conversation
Adds a UI-driven config workflow: a serializable spec (emitted e.g. by the Zuplo portal) is turned into a typed Zudoku config layer with real static plugin imports, which the user's config composes via a new `extends` field. - `extends` on ZudokuConfig: layers fold left to right with the config on top; scalars/objects later-wins, `plugins` concatenate. Resolved in the loader, `virtual:zudoku-config` (routing), and the prerender worker so layer-contributed plugins reach the route tree in dev, SSR, and build. - `zudoku generate spec.json -o zudoku.base.ts`: validates the spec (`$schema`-versioned, strict top level, per-plugin option schemas) and emits a typed config module; also exported programmatically from `zudoku/codegen` as `generateConfig`. - `zudoku schema`: emits the publishable JSON Schema for the spec, derived from the Zod config schema with non-serializable (code-holding) fields omitted and preset plugin options composed as a union keyed by `id`. - Curated preset registry (graphql, monetization) in core; drift guarded by type tests in each plugin package (vitest typecheck now enabled there). - `examples/config-spec`: generated layer + extends wiring, built in CI with a smoke test asserting layer-contributed routes prerender. https://claude.ai/code/session_01AZzEMtJTS9L4azMgsBfPH6
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Coverage Report
File Coverage |
`extends` entries are now module specifiers (tsconfig-style) resolved at config-load time instead of statically imported config objects. This makes generated layers lazy: `zudoku generate` can emit the base config just before `zudoku dev`/`zudoku build` runs, and the committed config never needs the file to exist. - Specifiers resolve relative to the declaring config file, extension optional; bare package specifiers go through module resolution. A missing layer fails with a hint to run `zudoku generate`. Inline config objects still work and can be mixed with strings. - The loader walks the extends chain depth-first, importing each layer through the same Vite pipeline as the config itself, watches layer files for dev reload, and records the ordered specifiers in `__meta`. - New `virtual:zudoku-raw-config` emits a static import per layer and replays the same walk, so layer plugin instances are created in the config module's realm. It feeds `virtual:zudoku-config` and replaces the config file as the SSR build's `zudoku.config` entry, covering dev, SSG prerender, and SSR runtime. - The example now demonstrates the lazy flow: `zudoku.base.ts` is gitignored and regenerated by the dev/build scripts; the config uses `extends: ["./zudoku.base"]`. https://claude.ai/code/session_01AZzEMtJTS9L4azMgsBfPH6
The config-spec smoke step was inserted mid-step, orphaning the favicon/asset-prefix checks (which reference the unset `$nested`) inside the new step and failing the job. https://claude.ai/code/session_01AZzEMtJTS9L4azMgsBfPH6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds support for composing Zudoku configurations from multiple layers via
extends, and introduceszudoku generateandzudoku schemaCLI commands. Together they enable a workflow where a tool (e.g. the Zuplo portal) emits a serializable config spec that is turned into a typed config layer with real plugin imports just beforezudoku dev/zudoku buildruns — the committed config references it lazily and never needs the file to exist.Key Changes
Lazy config layering via
extends: entries are module specifiers, tsconfig-style —extends: ["./zudoku.base"]— resolved at config-load time relative to the declaring file (extension optional; bare package specifiers supported; inline config objects can be mixed in). A missing layer fails with a hint to runzudoku generate. Merge semantics: layers fold left-to-right with the config on top; scalars/objects later-wins,pluginsconcatenate, other arrays replace; chains resolve depth-first with cycle detection.Layer resolution across all runtimes:
virtual:zudoku-raw-configmodule emits a static import per layer and replays the same walk, so layer plugin instances are created in the config module's realm (build-time virtual modules resolve). It feedsvirtual:zudoku-config(routing) and replaces the config file as the SSR build'szudoku.configentry, covering dev, SSG prerender, and SSR runtime.Config spec validation and generation:
spec.tsdefines the serializable projection ofZudokuConfigandvalidateSpec()with$schemaversion checking (https://schemas.zudoku.dev/config-spec/v1.json)generate.tsimplementsgenerateConfig(): validated spec → typed TypeScript config module with real plugin factory importsJSON Schema generation:
buildSpecJsonSchema()derives the publishable schema from the Zod source — non-serializable fields (functions, React nodes) are omitted unless annotated via.meta(), plugin refs compose as a union keyed byid, unused$defsare pruned.Preset plugin registry:
preset-registry.tscurates the available plugins (graphql, monetization) with their option schemas. The registry lives in core because the CLI cannot import plugin packages at runtime; type tests in each plugin package (preset-descriptor.test-d.ts) guard against drift.CLI commands:
zudoku generate <spec> -o zudoku.base.tsreads a JSON spec, validates it, and writes a typed config modulezudoku schemaemits the JSON Schema for spec validation in editors/UIsExample project:
examples/config-spec/demonstrates the lazy flow:zudoku.base.tsis gitignored and regenerated by the dev/build scripts fromspec.json; the hand-written config composes it viaextends: ["./zudoku.base"]. Built in CI with a smoke test asserting that routes contributed solely by the generated layer prerender.https://claude.ai/code/session_01AZzEMtJTS9L4azMgsBfPH6