Skip to content

feat(framework): Vite dev adapter (#86)#95

Merged
qantrepreneur merged 11 commits into
mainfrom
86-vite-dev-adapter
May 15, 2026
Merged

feat(framework): Vite dev adapter (#86)#95
qantrepreneur merged 11 commits into
mainfrom
86-vite-dev-adapter

Conversation

@qantrepreneur
Copy link
Copy Markdown
Contributor

@qantrepreneur qantrepreneur commented May 15, 2026

Summary

  • Add dev server middleware to the Vite plugin for serving pages and API routes during development
  • Convert between Node's req/res and Web Standard Request/Response
  • Wire route scanning, module loading, and template resolution through createRequestHandler
  • Route list auto-updates on file add/unlink
  • Load createRequestHandler via server.ssrLoadModule("@sundayceo/framework") to avoid dual module instance problem (shared SlotContext)
  • Use req.originalUrl to handle Vite's historyApiFallback rewrite (//index.html)
  • All requests go through the framework handler — unmatched routes get the framework's 404 page
  • HTML responses go through server.transformIndexHtml() to inject the Vite HMR client (/@vite/client)
  • Route scanner excludes .test.tsx/.test.ts files from routes and codegen
  • Routes support both .ts and .tsx extensions; templates remain .tsx-only
  • Strip .tsx/.ts extensions from generated import paths in routes.gen.ts
  • Runtime type guards instead of as casts throughout

Test plan

  • Unit tests for Node-to-Web request conversion (URL, method, headers, body, originalUrl)
  • Unit tests for Web-to-Node response writing (status, headers, body, empty body)
  • Unit tests for test file exclusion in route scanner
  • Unit tests for .ts and .tsx route support
  • Manual testing: pnpm dev in playground serves pages at /, /demo, /api/health
  • Manual testing: unknown routes return 404
  • Manual testing: Vite HMR client injected in HTML responses
  • Manual testing: API responses (JSON) not transformed
  • Manual testing: .test.tsx routes no longer accessible
  • All 255 tests pass, lint clean, type-check clean

Closes #86

🤖 Generated with Claude Code

Lorenzo and others added 7 commits May 15, 2026 09:52
Add dev server middleware to the Vite plugin so that `pnpm dev` serves
pages and handles API routes. Converts between Node req/res and Web
Standard Request/Response, wires route scanning and module loading
through createRequestHandler, and auto-updates routes on file changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Vite rewrites / to /index.html before our middleware runs. Using
req.originalUrl preserves the original path for route matching.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The bundled dist creates separate module instances from Vite's SSR
module graph, causing SlotProvider and Slot to use different React
contexts. Loading createRequestHandler through ssrLoadModule ensures
all framework code shares the same module instances.

Also uses req.originalUrl to handle Vite's historyApiFallback rewrite
of / to /index.html.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Check matchRoute before invoking the handler. Unmatched URLs fall
through to Vite for static files and HMR. Matched URLs always get
the framework response, including 404 pages defined as routes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Removes route pre-matching so unmatched URLs get the framework's
default 404 page instead of falling through to Vite's empty 404.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
HTML responses now go through server.transformIndexHtml() to inject
the /@vite/client script for HMR support. Test files (.test.tsx) are
excluded from route scanning and codegen to prevent SSR evaluation
errors and spurious route entries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Lorenzo and others added 4 commits May 15, 2026 11:45
TypeScript requires allowImportingTsExtensions for .tsx imports.
Generated routes.gen.ts now uses extensionless import paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Routes can now use either .ts or .tsx extensions. Templates remain
.tsx-only since they contain JSX. Updated route scanner, codegen,
dev middleware, and vite plugin to accept both extensions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Generated file contains a comment header that triggers the
custom/no-comments rule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@qantrepreneur qantrepreneur merged commit 5dc5e93 into main May 15, 2026
2 checks passed
@github-actions github-actions Bot mentioned this pull request May 15, 2026
qantrepreneur added a commit that referenced this pull request May 21, 2026
* feat(framework): add Vite dev adapter for request handling (#86)

Add dev server middleware to the Vite plugin so that `pnpm dev` serves
pages and handles API routes. Converts between Node req/res and Web
Standard Request/Response, wires route scanning and module loading
through createRequestHandler, and auto-updates routes on file changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: replace type casts with runtime guards, use async/await

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use originalUrl to handle Vite's historyApiFallback rewrite

Vite rewrites / to /index.html before our middleware runs. Using
req.originalUrl preserves the original path for route matching.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: load createRequestHandler via ssrLoadModule to share SlotContext

The bundled dist creates separate module instances from Vite's SSR
module graph, causing SlotProvider and Slot to use different React
contexts. Loading createRequestHandler through ssrLoadModule ensures
all framework code shares the same module instances.

Also uses req.originalUrl to handle Vite's historyApiFallback rewrite
of / to /index.html.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use route pre-match instead of response sniffing for fallthrough

Check matchRoute before invoking the handler. Unmatched URLs fall
through to Vite for static files and HMR. Matched URLs always get
the framework response, including 404 pages defined as routes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: handle all requests through the framework, not just matched routes

Removes route pre-matching so unmatched URLs get the framework's
default 404 page instead of falling through to Vite's empty 404.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: inject Vite HMR client and exclude test files from routes

HTML responses now go through server.transformIndexHtml() to inject
the /@vite/client script for HMR support. Test files (.test.tsx) are
excluded from route scanning and codegen to prevent SSR evaluation
errors and spurious route entries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: strip .tsx extensions from generated import paths

TypeScript requires allowImportingTsExtensions for .tsx imports.
Generated routes.gen.ts now uses extensionless import paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: support both .ts and .tsx route files

Routes can now use either .ts or .tsx extensions. Templates remain
.tsx-only since they contain JSX. Updated route scanner, codegen,
dev middleware, and vite plugin to accept both extensions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add routes.gen.ts to ESLint ignores

Generated file contains a comment header that triggers the
custom/no-comments rule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: format with Prettier

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Lorenzo <lorenzofkramer@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This was referenced May 23, 2026
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.

feat(framework): Vite dev adapter

1 participant