diff --git a/.github/README.md b/.github/README.md
new file mode 100644
index 0000000..380f806
--- /dev/null
+++ b/.github/README.md
@@ -0,0 +1,61 @@
+# GitHub Workflows
+
+This directory contains automated workflows for CI/CD.
+
+## Workflows
+
+### CI (`ci.yml`)
+Runs on every push to `main` and on pull requests:
+- Installs dependencies
+- Builds the plugin
+- Builds the example app
+
+### Preview Package (`preview.yml`)
+Runs on pull requests and pushes to `main`:
+- Builds the package
+- Publishes a preview version via [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new)
+- Adds a comment to PRs with installation instructions
+
+### Publish to npm (`publish.yml`)
+Runs when a GitHub release is created:
+- Builds the package
+- Publishes to npm with the `--access public` flag
+
+## Setup
+
+### For npm Publishing
+
+1. Create an npm access token:
+ - Go to https://www.npmjs.com/settings/YOUR_USERNAME/tokens
+ - Click "Generate New Token" → "Automation"
+ - Copy the token
+
+2. Add the token to your GitHub repository:
+ - Go to your repository Settings → Secrets and variables → Actions
+ - Click "New repository secret"
+ - Name: `NPM_TOKEN`
+ - Value: Paste your npm token
+ - Click "Add secret"
+
+3. Create a release:
+ - Go to your repository → Releases → Draft a new release
+ - Create a tag (e.g., `v0.1.0`)
+ - Click "Publish release"
+ - The workflow will automatically publish to npm
+
+### For pkg.pr.new
+
+No setup required! The workflow will automatically:
+- Publish preview packages for every PR
+- Comment on PRs with installation instructions
+- Update the comment when new commits are pushed
+
+## Testing Locally
+
+Before creating a release, test the build:
+
+```bash
+pnpm install
+pnpm build
+cd example && pnpm build
+```
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..b646674
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,36 @@
+name: CI
+
+on:
+ pull_request:
+ push:
+ branches:
+ - main
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: pnpm/action-setup@v4
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+ cache: 'pnpm'
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Build plugin
+ run: pnpm build
+
+ - name: Build basic example
+ run: |
+ cd examples/basic
+ pnpm build
+
+ - name: Build Vercel example
+ run: |
+ cd examples/vercel
+ pnpm build
diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml
new file mode 100644
index 0000000..8f2432c
--- /dev/null
+++ b/.github/workflows/preview.yml
@@ -0,0 +1,33 @@
+name: Preview Package
+
+on:
+ pull_request:
+ types: [opened, synchronize, reopened]
+ push:
+ branches:
+ - main
+
+jobs:
+ preview:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: write
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: pnpm/action-setup@v4
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+ cache: 'pnpm'
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Build
+ run: pnpm build
+
+ - name: Publish preview
+ run: pnpx pkg-pr-new publish
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000..5148a00
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,33 @@
+name: Publish to npm
+
+on:
+ release:
+ types: [created]
+
+jobs:
+ publish:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ id-token: write
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: pnpm/action-setup@v4
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+ cache: 'pnpm'
+ registry-url: 'https://registry.npmjs.org'
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Build
+ run: pnpm build
+
+ - name: Publish to npm
+ run: pnpm publish --access public --no-git-checks
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bd9fa51
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,52 @@
+# Dependencies
+node_modules/
+.pnpm-store/
+
+# Build output
+dist/
+*.tsbuildinfo
+.vite/
+.turbo/
+
+# Environment files
+.env
+.env.local
+.env.*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+!.vscode/settings.json
+.idea/
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+*.code-workspace
+
+# OS files
+.DS_Store
+Thumbs.db
+
+# Logs
+logs/
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+# Testing
+coverage/
+
+# Temporary files
+*.tmp
+*.temp
+.cache/
+
+# Example build output
+example/dist/
+example/api/
+example/public/
diff --git a/README.md b/README.md
index e69de29..c0858e2 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,285 @@
+# vite-plugin-srvx
+
+A Vite plugin that integrates [srvx](https://srvx.h3.dev/) (Universal Server) with Vite's development server, similar to how `@hono/vite-dev-server` works with Hono.
+
+## Features
+
+- **Automatic index.html serving** - The plugin automatically serves `index.html` on the root path
+- **Hot Module Replacement (HMR)** - Full HMR support for your srvx server
+- **Automatic Vite client script injection** - Vite's dev client is automatically injected into HTML responses
+- **Web Standard APIs** - Use Request/Response APIs that work everywhere
+- **Universal** - Works with Node.js, Deno, and Bun
+- **Lightning fast** - Powered by Vite's blazing fast dev server
+- **Vercel Edge Functions** - Built-in support for deploying to Vercel (auto-detected!)
+
+## Installation
+
+```bash
+npm install vite-plugin-srvx srvx vite
+```
+
+Or with pnpm:
+
+```bash
+pnpm add vite-plugin-srvx srvx vite
+```
+
+## Usage
+
+### 1. Create an index.html file
+
+Create an `index.html` file in your project root:
+
+```html
+
+
+
+
+
+ My srvx App
+
+
+ Hello from srvx + Vite!
+
+
+
+```
+
+### 2. Create your srvx server
+
+Create a `src/server.ts` file for your API routes:
+
+```typescript
+export default {
+ async fetch(request: Request): Promise {
+ const url = new URL(request.url)
+
+ // The plugin automatically serves index.html on '/'
+ // so you only need to handle API routes here
+
+ if (url.pathname === '/api/hello') {
+ return Response.json({
+ message: 'Hello from srvx!',
+ timestamp: new Date().toISOString(),
+ })
+ }
+
+ return new Response('Not Found', { status: 404 })
+ },
+}
+```
+
+### 3. Configure Vite
+
+Create a `vite.config.ts` file:
+
+```typescript
+import { defineConfig } from 'vite'
+import srvx from 'vite-plugin-srvx'
+
+export default defineConfig(({ mode }) => ({
+ build: {
+ outDir: mode === 'server' ? 'dist' : 'dist/public',
+ },
+ plugins: [
+ ...srvx({
+ entry: './src/server.ts',
+ }),
+ ],
+}))
+```
+
+### 4. Run the development server
+
+```bash
+vite
+```
+
+Your srvx server will now run with Vite's dev server! Visit `http://localhost:5173` to see your app:
+- `/` - Automatically serves `index.html`
+- `/api/hello` - Your srvx API endpoint
+- All other routes are handled by your srvx server's fetch handler
+
+## Building for Production
+
+The plugin uses Vite's mode system to handle client and server builds separately.
+
+Add these scripts to your `package.json`:
+
+```json
+{
+ "scripts": {
+ "dev": "vite",
+ "build": "npm run build:client && npm run build:server",
+ "build:client": "vite build",
+ "build:server": "vite build --mode server",
+ "preview": "srvx dist/server.js"
+ }
+}
+```
+
+Then build your app:
+
+```bash
+npm run build
+```
+
+This will:
+1. Build your frontend (HTML, CSS, JS) to `dist/public`
+2. Build your srvx server to `dist/server.js`
+
+Run your production build:
+
+```bash
+npm run preview
+# or directly: srvx dist/server.js
+```
+
+srvx automatically serves static files from the `dist/public` directory!
+
+## Options
+
+### Plugin Options
+
+```typescript
+interface SrvxOptions {
+ // Entry file for your srvx server (default: './src/server.ts')
+ entry?: string
+
+ // Output directory for server build (default: 'dist')
+ outDir?: string
+
+ // Server output filename (default: 'server.js')
+ serverOutFile?: string
+
+ // Development server options
+ // Patterns to exclude from the srvx handler (will be handled by Vite instead)
+ exclude?: (string | RegExp)[]
+
+ // Whether to inject Vite's client script for HMR (default: true)
+ injectClientScript?: boolean
+
+ // Custom module loader (default: uses Vite's ssrLoadModule)
+ loadModule?: (server: ViteDevServer, entry: string) => Promise
+}
+```
+
+> **Note:** The plugin returns an array of two plugins (dev server + build), so use the spread operator: `...srvx({})`
+
+### Example with custom options
+
+```typescript
+import { defineConfig } from 'vite'
+import srvx from 'vite-plugin-srvx'
+
+export default defineConfig(({ mode }) => ({
+ build: {
+ outDir: mode === 'server' ? 'build' : 'build/public',
+ },
+ plugins: [
+ ...srvx({
+ entry: './src/server.ts',
+ outDir: 'build',
+ serverOutFile: 'app.js',
+ exclude: [
+ /.*\.tsx?$/,
+ /.*\.css$/,
+ /^\/@.+$/,
+ ],
+ injectClientScript: true,
+ }),
+ ],
+}))
+```
+
+Then build with:
+```bash
+npm run build:client # builds to build/public
+npm run build:server # builds to build/app.js
+```
+
+And run: `srvx build/app.js` (it will serve static files from `build/public`)
+
+### Using Individual Plugins (Advanced)
+
+If you need more control, you can import the plugins separately:
+
+```typescript
+import { defineConfig } from 'vite'
+import { devServer, srvxBuild } from 'vite-plugin-srvx'
+
+export default defineConfig(({ mode }) => ({
+ build: {
+ outDir: mode === 'server' ? 'dist' : 'dist/public',
+ },
+ plugins: [
+ devServer({ entry: './src/server.ts' }),
+ srvxBuild({ entry: './src/server.ts' }),
+ ],
+}))
+```
+
+## How it works
+
+### Development Mode
+
+The `devServer` plugin creates a Vite middleware that:
+
+1. **Serves index.html on root** - When requesting `/`, the plugin automatically serves and transforms your `index.html` using Vite's `transformIndexHtml` (which handles script injection, etc.)
+2. **Intercepts other HTTP requests** - All non-root requests are passed to your srvx server
+3. **Loads your srvx server module** - Uses Vite's SSR module loader for HMR support
+4. **Converts to Web Standard APIs** - Converts Node.js `IncomingMessage` → Web Standard `Request`
+5. **Calls your fetch handler** - Your srvx server's `fetch` handler processes the request
+6. **Converts the response** - Converts the `Response` back to Node.js `ServerResponse`
+7. **Injects Vite client** - For HTML responses from your server, Vite's client script is injected for HMR
+
+### Production Build
+
+The `srvxBuild` plugin uses Vite's mode system:
+
+1. **Client build** (`vite build`):
+ - Builds frontend to `dist/public`
+ - Plugin is inactive (mode !== 'server')
+
+2. **Server build** (`vite build --mode server`):
+ - Plugin activates (mode === 'server')
+ - Sets `ssr: true` via the `config` hook
+ - Builds server to `dist/server.js`
+
+3. **Run with srvx**:
+ - `srvx dist/server.js`
+ - srvx automatically serves static files from `dist/public`
+
+This approach follows the same pattern as [@hono/vite-build](https://github.com/honojs/vite-plugins/tree/main/packages/build)
+
+This gives you the best of both worlds: srvx's universal server API and Vite's lightning-fast development experience!
+
+## Example
+
+Check out the [example](./example) directory for a full working example.
+
+To run the example:
+
+```bash
+pnpm install
+pnpm build
+cd example
+pnpm dev
+```
+
+## Comparison with @hono/vite-dev-server
+
+This plugin is heavily inspired by `@hono/vite-dev-server` but designed specifically for srvx:
+
+- Similar middleware architecture
+- Same HMR capabilities
+- Compatible API design
+- Works with any framework that uses Web Standard fetch API
+
+## License
+
+MIT
+
+## Credits
+
+Inspired by [@hono/vite-dev-server](https://github.com/honojs/vite-plugins/tree/main/packages/dev-server)
diff --git a/examples/basic/frontend/main.ts b/examples/basic/frontend/main.ts
new file mode 100644
index 0000000..b098194
--- /dev/null
+++ b/examples/basic/frontend/main.ts
@@ -0,0 +1 @@
+console.log("Hello! This is the client module.");
diff --git a/examples/basic/index.html b/examples/basic/index.html
new file mode 100644
index 0000000..2758ad7
--- /dev/null
+++ b/examples/basic/index.html
@@ -0,0 +1,86 @@
+
+
+
+
+
+ srvx + Vite Example
+
+
+
+ 🚀 srvx + Vite
+ Universal Server powered by srvx, running with Vite dev server
+
+
+
+
+
Features
+
+ ✨ Hot Module Replacement (HMR)
+ 🔥 Web Standard APIs (Request/Response)
+ ⚡ Lightning fast with Vite
+ 🌐 Universal - works with Node.js, Deno, Bun
+
+
+
+
+
+
+
diff --git a/examples/basic/package.json b/examples/basic/package.json
new file mode 100644
index 0000000..6256b6f
--- /dev/null
+++ b/examples/basic/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "srvx-vite-example",
+ "version": "0.1.0",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build && vite build --mode server",
+ "start": "srvx --static public dist/server.js"
+ },
+ "dependencies": {
+ "srvx": "^0.9.7"
+ },
+ "devDependencies": {
+ "@types/node": "^22.10.5",
+ "typescript": "^5.7.3",
+ "vite": "^6.0.5",
+ "vite-plugin-srvx": "workspace:*"
+ }
+}
diff --git a/examples/basic/src/server.ts b/examples/basic/src/server.ts
new file mode 100644
index 0000000..9e8739e
--- /dev/null
+++ b/examples/basic/src/server.ts
@@ -0,0 +1,65 @@
+export default {
+ async fetch(request: Request): Promise {
+ const url = new URL(request.url);
+
+ if (url.pathname === "/api/hello") {
+ return Response.json({
+ message: "Hello from srvx!",
+ timestamp: new Date().toISOString(),
+ powered_by: "srvx + Vite",
+ });
+ }
+
+ if (url.pathname === "/api/time") {
+ return Response.json({
+ time: new Date().toLocaleTimeString(),
+ date: new Date().toLocaleDateString(),
+ unix: Date.now(),
+ });
+ }
+
+ if (url.pathname === "/about") {
+ return new Response(
+ `
+
+
+
+
+ About - srvx + Vite
+
+
+
+ About
+ This is an example app demonstrating the integration of srvx with Vite.
+ srvx is a universal server framework based on web standards, and Vite provides lightning-fast development experience.
+ ← Back to home
+
+`,
+ {
+ headers: {
+ "Content-Type": "text/html",
+ },
+ },
+ );
+ }
+
+ return new Response("Not Found", { status: 404 });
+ },
+};
diff --git a/examples/basic/tsconfig.json b/examples/basic/tsconfig.json
new file mode 100644
index 0000000..7e31a45
--- /dev/null
+++ b/examples/basic/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "ESNext",
+ "lib": ["ES2022", "DOM"],
+ "moduleResolution": "bundler",
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "include": ["src", "frontend"]
+}
diff --git a/examples/basic/vite.config.ts b/examples/basic/vite.config.ts
new file mode 100644
index 0000000..e8e825e
--- /dev/null
+++ b/examples/basic/vite.config.ts
@@ -0,0 +1,10 @@
+import { defineConfig } from "vite";
+import srvx from "vite-plugin-srvx";
+
+export default defineConfig({
+ plugins: [
+ ...srvx({
+ entry: "./src/server.ts",
+ }),
+ ],
+});
diff --git a/examples/vercel/.gitignore b/examples/vercel/.gitignore
new file mode 100644
index 0000000..8cf80cd
--- /dev/null
+++ b/examples/vercel/.gitignore
@@ -0,0 +1,20 @@
+# Dependencies
+node_modules/
+
+# Build output
+dist/
+
+# Vercel
+.vercel/
+
+# Environment
+.env
+.env.local
+.env*.local
+
+# Logs
+*.log
+
+# OS
+.DS_Store
+.vercel
diff --git a/examples/vercel/README.md b/examples/vercel/README.md
new file mode 100644
index 0000000..f37b302
--- /dev/null
+++ b/examples/vercel/README.md
@@ -0,0 +1,223 @@
+# Vercel Edge Functions Example
+
+This example demonstrates how to deploy a **srvx** server as a **Vercel Edge Function** using **vite-plugin-srvx**.
+
+## Features
+
+- ⚡ **Vite** for lightning-fast development
+- 🌐 **srvx** Universal Server with Web Standard APIs
+- ▲ **Vercel Edge Functions** for global edge deployment
+- 🎨 Interactive frontend with API testing
+- 🔧 Zero-config deployment setup
+
+## Quick Start
+
+### 1. Install Dependencies
+
+```bash
+pnpm install
+```
+
+### 2. Development
+
+```bash
+pnpm dev
+```
+
+Visit http://localhost:5173 to see the app in development mode.
+
+### 3. Build
+
+```bash
+pnpm build
+```
+
+This creates:
+```
+dist/
+├── api/
+│ └── index.js # Vercel Edge Function
+└── public/ # Static assets
+ ├── index.html
+ └── assets/
+```
+
+### 4. Preview with Vercel CLI
+
+```bash
+pnpm preview
+```
+
+Or manually:
+
+```bash
+vercel dev
+```
+
+## Deploy to Vercel
+
+### Option 1: Deploy via CLI
+
+```bash
+# Install Vercel CLI if you haven't
+npm i -g vercel
+
+# Deploy
+vercel
+```
+
+### Option 2: Deploy via GitHub
+
+1. Push this example to a GitHub repository
+2. Import the repository in [Vercel Dashboard](https://vercel.com/new)
+3. Vercel will automatically detect the configuration and deploy!
+
+## How It Works
+
+### 1. Vite Configuration
+
+The `vite.config.ts` enables Vercel mode:
+
+```typescript
+import { defineConfig } from "vite";
+import srvx from "vite-plugin-srvx";
+
+export default defineConfig({
+ plugins: [
+ ...srvx({
+ entry: "./src/server.ts",
+ framework: "vercel", // Enable Vercel Edge Functions
+ }),
+ ],
+});
+```
+
+### 2. Vercel Configuration
+
+The `vercel.json` tells Vercel where to find the Edge Function:
+
+```json
+{
+ "buildCommand": "pnpm build",
+ "outputDirectory": "dist/public",
+ "functions": {
+ "dist/api/**": {
+ "runtime": "edge"
+ }
+ }
+}
+```
+
+### 3. Server Code
+
+Your srvx server (`src/server.ts`) uses Web Standard APIs:
+
+```typescript
+export default {
+ async fetch(request: Request): Promise {
+ const url = new URL(request.url);
+
+ if (url.pathname === "/api/hello") {
+ return Response.json({ message: "Hello!" });
+ }
+
+ return new Response("Not Found", { status: 404 });
+ },
+};
+```
+
+## API Endpoints
+
+The example includes several API endpoints:
+
+- **`GET /api/hello`** - Returns a greeting message
+- **`GET /api/time`** - Returns current time
+- **`GET /api/user-agent`** - Returns user agent and headers
+
+## Edge Function Benefits
+
+Deploying to Vercel Edge Functions provides:
+
+- ⚡ **Ultra-low latency** - Runs on Vercel's global edge network
+- 🌍 **Global reach** - Automatically deployed to 100+ edge locations
+- 📈 **Auto-scaling** - Scales automatically based on demand
+- 💰 **Cost-effective** - Pay only for what you use
+- 🔒 **Secure** - Runs in isolated V8 environments
+
+## Project Structure
+
+```
+examples/vercel/
+├── frontend/
+│ ├── main.ts # Frontend TypeScript
+│ └── style.css # Styles
+├── src/
+│ └── server.ts # srvx server (Edge Function)
+├── index.html # Entry HTML
+├── package.json # Dependencies
+├── tsconfig.json # TypeScript config
+├── vite.config.ts # Vite + srvx config
+└── vercel.json # Vercel deployment config
+```
+
+## Environment Variables
+
+To use environment variables in your Edge Function:
+
+1. Add them in Vercel Dashboard → Project Settings → Environment Variables
+2. Access them in your server code:
+
+```typescript
+export default {
+ async fetch(request: Request) {
+ const apiKey = process.env.API_KEY;
+ // Use the API key...
+ },
+};
+```
+
+## Limitations
+
+Vercel Edge Functions have some constraints:
+
+- **Max Duration**: 25 seconds (must begin sending response)
+- **Streaming**: Up to 300 seconds
+- **Code Size**: 1 MB (Hobby), 2 MB (Pro), 4 MB (Enterprise) after gzip
+- **No Node.js APIs**: Only Web Standard APIs (which srvx uses!)
+
+## Troubleshooting
+
+### Build fails
+
+Make sure all dependencies are installed:
+```bash
+pnpm install
+```
+
+### Edge Function not found
+
+Verify your `vercel.json` has the correct function configuration:
+```json
+{
+ "functions": {
+ "dist/api/**": {
+ "runtime": "edge"
+ }
+ }
+}
+```
+
+### Static files not loading
+
+Check that your `outputDirectory` points to `dist/public` in `vercel.json`.
+
+## Learn More
+
+- [Vercel Edge Functions Documentation](https://vercel.com/docs/functions/runtimes/edge)
+- [srvx Documentation](https://srvx.h3.dev/)
+- [vite-plugin-srvx Documentation](../../README.md)
+- [Vercel Deployment Guide](../../VERCEL.md)
+
+## License
+
+MIT
diff --git a/examples/vercel/frontend/main.ts b/examples/vercel/frontend/main.ts
new file mode 100644
index 0000000..c72323f
--- /dev/null
+++ b/examples/vercel/frontend/main.ts
@@ -0,0 +1,72 @@
+import "./style.css";
+
+const app = document.querySelector("#app")!;
+
+app.innerHTML = `
+
+
+
+
+ Try the API Endpoints
+
+
+ 👋
+ Hello API
+
+
+ ⏰
+ Time API
+
+
+ 🔍
+ User Agent
+
+
+
+
+
+ Response:
+ Click a button above to test an API endpoint
+
+
+
+
+
+
+`;
+
+// Add event listeners to API buttons
+const buttons = document.querySelectorAll(".api-btn");
+const responseBox = document.querySelector("#response")!;
+
+buttons.forEach((button) => {
+ button.addEventListener("click", async () => {
+ const endpoint = button.dataset.endpoint!;
+ responseBox.textContent = "Loading...";
+ responseBox.classList.add("loading");
+
+ try {
+ const response = await fetch(endpoint);
+ const data = await response.json();
+ responseBox.textContent = JSON.stringify(data, null, 2);
+ responseBox.classList.remove("loading");
+ responseBox.classList.add("success");
+ } catch (error) {
+ responseBox.textContent = `Error: ${error}`;
+ responseBox.classList.remove("loading");
+ responseBox.classList.add("error");
+ }
+ });
+});
diff --git a/examples/vercel/frontend/style.css b/examples/vercel/frontend/style.css
new file mode 100644
index 0000000..6a47cae
--- /dev/null
+++ b/examples/vercel/frontend/style.css
@@ -0,0 +1,172 @@
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
+ Oxygen, Ubuntu, Cantarell, sans-serif;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ min-height: 100vh;
+ padding: 2rem;
+}
+
+.container {
+ max-width: 900px;
+ margin: 0 auto;
+}
+
+header {
+ text-align: center;
+ margin-bottom: 3rem;
+}
+
+h1 {
+ font-size: 3.5rem;
+ margin-bottom: 0.5rem;
+ font-weight: 800;
+}
+
+.subtitle {
+ font-size: 1.5rem;
+ opacity: 0.9;
+ margin-bottom: 1rem;
+}
+
+.badges {
+ display: flex;
+ gap: 0.5rem;
+ justify-content: center;
+ flex-wrap: wrap;
+}
+
+.badge {
+ background: rgba(255, 255, 255, 0.2);
+ padding: 0.5rem 1rem;
+ border-radius: 2rem;
+ font-size: 0.9rem;
+ backdrop-filter: blur(10px);
+}
+
+.features {
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(10px);
+ border-radius: 1rem;
+ padding: 2rem;
+ margin-bottom: 2rem;
+}
+
+h2 {
+ font-size: 2rem;
+ margin-bottom: 1.5rem;
+ text-align: center;
+}
+
+h3 {
+ font-size: 1.5rem;
+ margin-bottom: 1rem;
+}
+
+.api-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+ gap: 1rem;
+}
+
+.api-btn {
+ background: rgba(255, 255, 255, 0.15);
+ border: 2px solid rgba(255, 255, 255, 0.3);
+ color: white;
+ padding: 1.5rem;
+ border-radius: 0.75rem;
+ font-size: 1rem;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.api-btn:hover {
+ background: rgba(255, 255, 255, 0.25);
+ transform: translateY(-2px);
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
+}
+
+.api-btn:active {
+ transform: translateY(0);
+}
+
+.api-btn .emoji {
+ font-size: 2rem;
+}
+
+.response-section {
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(10px);
+ border-radius: 1rem;
+ padding: 2rem;
+ margin-bottom: 2rem;
+}
+
+.response-box {
+ background: rgba(0, 0, 0, 0.3);
+ padding: 1.5rem;
+ border-radius: 0.5rem;
+ overflow-x: auto;
+ font-family: "Courier New", monospace;
+ font-size: 0.9rem;
+ line-height: 1.6;
+ min-height: 150px;
+ border: 1px solid rgba(255, 255, 255, 0.2);
+}
+
+.response-box.loading {
+ color: #ffd700;
+}
+
+.response-box.success {
+ color: #90ee90;
+}
+
+.response-box.error {
+ color: #ff6b6b;
+}
+
+.links {
+ text-align: center;
+ margin-bottom: 2rem;
+}
+
+.link {
+ color: #ffd700;
+ text-decoration: none;
+ font-size: 1.2rem;
+ font-weight: 600;
+ transition: all 0.3s ease;
+ display: inline-block;
+}
+
+.link:hover {
+ transform: translateX(5px);
+ text-decoration: underline;
+}
+
+footer {
+ text-align: center;
+ opacity: 0.8;
+ font-size: 0.9rem;
+}
+
+@media (max-width: 768px) {
+ h1 {
+ font-size: 2.5rem;
+ }
+
+ .api-grid {
+ grid-template-columns: 1fr;
+ }
+}
diff --git a/examples/vercel/index.html b/examples/vercel/index.html
new file mode 100644
index 0000000..a505b9d
--- /dev/null
+++ b/examples/vercel/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Vercel Edge Functions with srvx + Vite
+
+
+
+
+
+
diff --git a/examples/vercel/package.json b/examples/vercel/package.json
new file mode 100644
index 0000000..70e22f4
--- /dev/null
+++ b/examples/vercel/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "srvx-vite-vercel-example",
+ "version": "0.1.0",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build && vite build --mode server",
+ "preview": "vercel dev"
+ },
+ "dependencies": {
+ "srvx": "^0.9.7"
+ },
+ "devDependencies": {
+ "@types/node": "^22.10.5",
+ "typescript": "^5.7.3",
+ "vite": "^6.0.5",
+ "vite-plugin-srvx": "workspace:*"
+ }
+}
diff --git a/examples/vercel/src/server.ts b/examples/vercel/src/server.ts
new file mode 100644
index 0000000..34e7341
--- /dev/null
+++ b/examples/vercel/src/server.ts
@@ -0,0 +1,95 @@
+export default {
+ async fetch(request: Request): Promise {
+ const url = new URL(request.url);
+
+ // API endpoint - returns JSON
+ if (url.pathname === "/api/hello") {
+ return Response.json({
+ message: "Hello from Vercel Edge Functions!",
+ timestamp: new Date().toISOString(),
+ powered_by: "srvx + Vite + Vercel Edge",
+ runtime: "edge",
+ });
+ }
+
+ // Time API endpoint
+ if (url.pathname === "/api/time") {
+ return Response.json({
+ time: new Date().toLocaleTimeString(),
+ date: new Date().toLocaleDateString(),
+ unix: Date.now(),
+ });
+ }
+
+ // User agent endpoint
+ if (url.pathname === "/api/user-agent") {
+ const userAgent = request.headers.get("user-agent") || "Unknown";
+ return Response.json({
+ userAgent,
+ headers: Object.fromEntries(request.headers.entries()),
+ });
+ }
+
+ // About page - returns HTML
+ if (url.pathname === "/about") {
+ return new Response(
+ `
+
+
+
+
+ About - Vercel Edge Example
+
+
+
+ About This Example
+
+ This is a demonstration of srvx (Universal Server)
+ deployed as a Vercel Edge Function , with
+ Vite powering the development and build process.
+
+
+ ⚡ Vite
+ 🌐 srvx
+ ▲ Vercel Edge
+
+ ← Back to home
+
+`,
+ {
+ headers: {
+ "Content-Type": "text/html",
+ },
+ }
+ );
+ }
+
+ // For all other routes, return 404
+ return new Response("Not Found", { status: 404 });
+ },
+};
diff --git a/examples/vercel/tsconfig.json b/examples/vercel/tsconfig.json
new file mode 100644
index 0000000..c51b7df
--- /dev/null
+++ b/examples/vercel/tsconfig.json
@@ -0,0 +1,23 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src", "frontend"]
+}
diff --git a/examples/vercel/vercel.json b/examples/vercel/vercel.json
new file mode 100644
index 0000000..7d5c195
--- /dev/null
+++ b/examples/vercel/vercel.json
@@ -0,0 +1,9 @@
+{
+ "buildCommand": "pnpm build",
+ "outputDirectory": "dist/public",
+ "functions": {
+ "dist/api/**": {
+ "runtime": "edge"
+ }
+ }
+}
diff --git a/examples/vercel/vite.config.ts b/examples/vercel/vite.config.ts
new file mode 100644
index 0000000..563432b
--- /dev/null
+++ b/examples/vercel/vite.config.ts
@@ -0,0 +1,11 @@
+import { defineConfig } from "vite";
+import srvx from "vite-plugin-srvx";
+
+export default defineConfig({
+ plugins: [
+ ...srvx({
+ entry: "./src/server.ts",
+ framework: "vercel", // Enable Vercel Edge Functions
+ }),
+ ],
+});
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..d8f416d
--- /dev/null
+++ b/package.json
@@ -0,0 +1,44 @@
+{
+ "name": "vite-plugin-srvx",
+ "version": "0.1.0",
+ "description": "Vite plugin for srvx - Universal Server integration",
+ "type": "module",
+ "main": "./dist/index.js",
+ "module": "./dist/index.js",
+ "types": "./dist/index.d.ts",
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.js"
+ }
+ },
+ "files": [
+ "dist"
+ ],
+ "scripts": {
+ "build": "tsup",
+ "dev": "tsup --watch",
+ "typecheck": "tsc --noEmit"
+ },
+ "keywords": [
+ "vite",
+ "vite-plugin",
+ "srvx",
+ "server",
+ "ssr"
+ ],
+ "author": "",
+ "license": "MIT",
+ "peerDependencies": {
+ "srvx": ">=0.9.0",
+ "vite": "^5.0.0 || ^6.0.0"
+ },
+ "devDependencies": {
+ "@types/node": "^22.10.5",
+ "srvx": "^0.9.7",
+ "tsup": "^8.3.5",
+ "typescript": "^5.7.3",
+ "vite": "^6.0.5"
+ },
+ "packageManager": "pnpm@10.27.0+sha512.72d699da16b1179c14ba9e64dc71c9a40988cbdc65c264cb0e489db7de917f20dcf4d64d8723625f2969ba52d4b7e2a1170682d9ac2a5dcaeaab732b7e16f04a"
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..f33e82c
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,1309 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ devDependencies:
+ '@types/node':
+ specifier: ^22.10.5
+ version: 22.19.3
+ srvx:
+ specifier: ^0.9.7
+ version: 0.9.8
+ tsup:
+ specifier: ^8.3.5
+ version: 8.5.1(postcss@8.5.6)(typescript@5.9.3)
+ typescript:
+ specifier: ^5.7.3
+ version: 5.9.3
+ vite:
+ specifier: ^6.0.5
+ version: 6.4.1(@types/node@22.19.3)
+
+ examples/basic:
+ dependencies:
+ srvx:
+ specifier: ^0.9.7
+ version: 0.9.8
+ devDependencies:
+ '@types/node':
+ specifier: ^22.10.5
+ version: 22.19.3
+ typescript:
+ specifier: ^5.7.3
+ version: 5.9.3
+ vite:
+ specifier: ^6.0.5
+ version: 6.4.1(@types/node@22.19.3)
+ vite-plugin-srvx:
+ specifier: workspace:*
+ version: link:../..
+
+ examples/vercel:
+ dependencies:
+ srvx:
+ specifier: ^0.9.7
+ version: 0.9.8
+ devDependencies:
+ '@types/node':
+ specifier: ^22.10.5
+ version: 22.19.3
+ typescript:
+ specifier: ^5.7.3
+ version: 5.9.3
+ vite:
+ specifier: ^6.0.5
+ version: 6.4.1(@types/node@22.19.3)
+ vite-plugin-srvx:
+ specifier: workspace:*
+ version: link:../..
+
+packages:
+
+ '@esbuild/aix-ppc64@0.25.12':
+ resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/aix-ppc64@0.27.2':
+ resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.25.12':
+ resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm64@0.27.2':
+ resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.25.12':
+ resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-arm@0.27.2':
+ resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.25.12':
+ resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/android-x64@0.27.2':
+ resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.25.12':
+ resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-arm64@0.27.2':
+ resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.25.12':
+ resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.27.2':
+ resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.25.12':
+ resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-arm64@0.27.2':
+ resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.25.12':
+ resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.27.2':
+ resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.25.12':
+ resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm64@0.27.2':
+ resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.25.12':
+ resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.27.2':
+ resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.25.12':
+ resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.27.2':
+ resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.25.12':
+ resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.27.2':
+ resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.25.12':
+ resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.27.2':
+ resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.25.12':
+ resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.27.2':
+ resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.25.12':
+ resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.27.2':
+ resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.25.12':
+ resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.27.2':
+ resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.25.12':
+ resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.27.2':
+ resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-arm64@0.25.12':
+ resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-arm64@0.27.2':
+ resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.25.12':
+ resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.27.2':
+ resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.25.12':
+ resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-arm64@0.27.2':
+ resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.25.12':
+ resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.27.2':
+ resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openharmony-arm64@0.25.12':
+ resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@esbuild/openharmony-arm64@0.27.2':
+ resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@esbuild/sunos-x64@0.25.12':
+ resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/sunos-x64@0.27.2':
+ resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.25.12':
+ resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-arm64@0.27.2':
+ resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.25.12':
+ resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.27.2':
+ resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.25.12':
+ resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.27.2':
+ resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
+ '@jridgewell/gen-mapping@0.3.13':
+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/sourcemap-codec@1.5.5':
+ resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+
+ '@rollup/rollup-android-arm-eabi@4.55.1':
+ resolution: {integrity: sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.55.1':
+ resolution: {integrity: sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.55.1':
+ resolution: {integrity: sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.55.1':
+ resolution: {integrity: sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.55.1':
+ resolution: {integrity: sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.55.1':
+ resolution: {integrity: sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.55.1':
+ resolution: {integrity: sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.55.1':
+ resolution: {integrity: sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.55.1':
+ resolution: {integrity: sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.55.1':
+ resolution: {integrity: sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loong64-gnu@4.55.1':
+ resolution: {integrity: sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loong64-musl@4.55.1':
+ resolution: {integrity: sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-ppc64-gnu@4.55.1':
+ resolution: {integrity: sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-ppc64-musl@4.55.1':
+ resolution: {integrity: sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.55.1':
+ resolution: {integrity: sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-musl@4.55.1':
+ resolution: {integrity: sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.55.1':
+ resolution: {integrity: sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.55.1':
+ resolution: {integrity: sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.55.1':
+ resolution: {integrity: sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-openbsd-x64@4.55.1':
+ resolution: {integrity: sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@rollup/rollup-openharmony-arm64@4.55.1':
+ resolution: {integrity: sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rollup/rollup-win32-arm64-msvc@4.55.1':
+ resolution: {integrity: sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.55.1':
+ resolution: {integrity: sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-gnu@4.55.1':
+ resolution: {integrity: sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==}
+ cpu: [x64]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.55.1':
+ resolution: {integrity: sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==}
+ cpu: [x64]
+ os: [win32]
+
+ '@types/estree@1.0.8':
+ resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+
+ '@types/node@22.19.3':
+ resolution: {integrity: sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==}
+
+ acorn@8.15.0:
+ resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
+ any-promise@1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+
+ bundle-require@5.1.0:
+ resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ peerDependencies:
+ esbuild: '>=0.18'
+
+ cac@6.7.14:
+ resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
+ engines: {node: '>=8'}
+
+ chokidar@4.0.3:
+ resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
+ engines: {node: '>= 14.16.0'}
+
+ commander@4.1.1:
+ resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+ engines: {node: '>= 6'}
+
+ confbox@0.1.8:
+ resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
+
+ consola@3.4.2:
+ resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
+ engines: {node: ^14.18.0 || >=16.10.0}
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ esbuild@0.25.12:
+ resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ esbuild@0.27.2:
+ resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ fix-dts-default-cjs-exports@1.0.1:
+ resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==}
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ joycon@3.1.1:
+ resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
+ engines: {node: '>=10'}
+
+ lilconfig@3.1.3:
+ resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
+ engines: {node: '>=14'}
+
+ lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+
+ load-tsconfig@0.2.5:
+ resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ magic-string@0.30.21:
+ resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
+ mlly@1.8.0:
+ resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ mz@2.7.0:
+ resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+
+ nanoid@3.3.11:
+ resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ pathe@2.0.3:
+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@4.0.3:
+ resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+ engines: {node: '>=12'}
+
+ pirates@4.0.7:
+ resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
+ engines: {node: '>= 6'}
+
+ pkg-types@1.3.1:
+ resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
+
+ postcss-load-config@6.0.1:
+ resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ jiti: '>=1.21.0'
+ postcss: '>=8.0.9'
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ jiti:
+ optional: true
+ postcss:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ postcss@8.5.6:
+ resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ readdirp@4.1.2:
+ resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
+ engines: {node: '>= 14.18.0'}
+
+ resolve-from@5.0.0:
+ resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
+ engines: {node: '>=8'}
+
+ rollup@4.55.1:
+ resolution: {integrity: sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ source-map@0.7.6:
+ resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
+ engines: {node: '>= 12'}
+
+ srvx@0.9.8:
+ resolution: {integrity: sha512-RZaxTKJEE/14HYn8COLuUOJAt0U55N9l1Xf6jj+T0GoA01EUH1Xz5JtSUOI+EHn+AEgPCVn7gk6jHJffrr06fQ==}
+ engines: {node: '>=20.16.0'}
+ hasBin: true
+
+ sucrase@3.35.1:
+ resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+
+ thenify-all@1.6.0:
+ resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+ engines: {node: '>=0.8'}
+
+ thenify@3.3.1:
+ resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+
+ tinyexec@0.3.2:
+ resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
+
+ tinyglobby@0.2.15:
+ resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
+ engines: {node: '>=12.0.0'}
+
+ tree-kill@1.2.2:
+ resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+ hasBin: true
+
+ ts-interface-checker@0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+
+ tsup@8.5.1:
+ resolution: {integrity: sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==}
+ engines: {node: '>=18'}
+ hasBin: true
+ peerDependencies:
+ '@microsoft/api-extractor': ^7.36.0
+ '@swc/core': ^1
+ postcss: ^8.4.12
+ typescript: '>=4.5.0'
+ peerDependenciesMeta:
+ '@microsoft/api-extractor':
+ optional: true
+ '@swc/core':
+ optional: true
+ postcss:
+ optional: true
+ typescript:
+ optional: true
+
+ typescript@5.9.3:
+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ ufo@1.6.1:
+ resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==}
+
+ undici-types@6.21.0:
+ resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+
+ vite@6.4.1:
+ resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ jiti: '>=1.21.0'
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+snapshots:
+
+ '@esbuild/aix-ppc64@0.25.12':
+ optional: true
+
+ '@esbuild/aix-ppc64@0.27.2':
+ optional: true
+
+ '@esbuild/android-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/android-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/android-arm@0.25.12':
+ optional: true
+
+ '@esbuild/android-arm@0.27.2':
+ optional: true
+
+ '@esbuild/android-x64@0.25.12':
+ optional: true
+
+ '@esbuild/android-x64@0.27.2':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/darwin-x64@0.25.12':
+ optional: true
+
+ '@esbuild/darwin-x64@0.27.2':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.25.12':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.27.2':
+ optional: true
+
+ '@esbuild/linux-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/linux-arm@0.25.12':
+ optional: true
+
+ '@esbuild/linux-arm@0.27.2':
+ optional: true
+
+ '@esbuild/linux-ia32@0.25.12':
+ optional: true
+
+ '@esbuild/linux-ia32@0.27.2':
+ optional: true
+
+ '@esbuild/linux-loong64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-loong64@0.27.2':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.25.12':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.27.2':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.27.2':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.27.2':
+ optional: true
+
+ '@esbuild/linux-s390x@0.25.12':
+ optional: true
+
+ '@esbuild/linux-s390x@0.27.2':
+ optional: true
+
+ '@esbuild/linux-x64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-x64@0.27.2':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.25.12':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.27.2':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.25.12':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.27.2':
+ optional: true
+
+ '@esbuild/openharmony-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/openharmony-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/sunos-x64@0.25.12':
+ optional: true
+
+ '@esbuild/sunos-x64@0.27.2':
+ optional: true
+
+ '@esbuild/win32-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/win32-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/win32-ia32@0.25.12':
+ optional: true
+
+ '@esbuild/win32-ia32@0.27.2':
+ optional: true
+
+ '@esbuild/win32-x64@0.25.12':
+ optional: true
+
+ '@esbuild/win32-x64@0.27.2':
+ optional: true
+
+ '@jridgewell/gen-mapping@0.3.13':
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/sourcemap-codec@1.5.5': {}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ '@rollup/rollup-android-arm-eabi@4.55.1':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.55.1':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.55.1':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.55.1':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.55.1':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.55.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.55.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.55.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.55.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.55.1':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-gnu@4.55.1':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-musl@4.55.1':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-gnu@4.55.1':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-musl@4.55.1':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.55.1':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.55.1':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.55.1':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.55.1':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.55.1':
+ optional: true
+
+ '@rollup/rollup-openbsd-x64@4.55.1':
+ optional: true
+
+ '@rollup/rollup-openharmony-arm64@4.55.1':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.55.1':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.55.1':
+ optional: true
+
+ '@rollup/rollup-win32-x64-gnu@4.55.1':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.55.1':
+ optional: true
+
+ '@types/estree@1.0.8': {}
+
+ '@types/node@22.19.3':
+ dependencies:
+ undici-types: 6.21.0
+
+ acorn@8.15.0: {}
+
+ any-promise@1.3.0: {}
+
+ bundle-require@5.1.0(esbuild@0.27.2):
+ dependencies:
+ esbuild: 0.27.2
+ load-tsconfig: 0.2.5
+
+ cac@6.7.14: {}
+
+ chokidar@4.0.3:
+ dependencies:
+ readdirp: 4.1.2
+
+ commander@4.1.1: {}
+
+ confbox@0.1.8: {}
+
+ consola@3.4.2: {}
+
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
+ esbuild@0.25.12:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.25.12
+ '@esbuild/android-arm': 0.25.12
+ '@esbuild/android-arm64': 0.25.12
+ '@esbuild/android-x64': 0.25.12
+ '@esbuild/darwin-arm64': 0.25.12
+ '@esbuild/darwin-x64': 0.25.12
+ '@esbuild/freebsd-arm64': 0.25.12
+ '@esbuild/freebsd-x64': 0.25.12
+ '@esbuild/linux-arm': 0.25.12
+ '@esbuild/linux-arm64': 0.25.12
+ '@esbuild/linux-ia32': 0.25.12
+ '@esbuild/linux-loong64': 0.25.12
+ '@esbuild/linux-mips64el': 0.25.12
+ '@esbuild/linux-ppc64': 0.25.12
+ '@esbuild/linux-riscv64': 0.25.12
+ '@esbuild/linux-s390x': 0.25.12
+ '@esbuild/linux-x64': 0.25.12
+ '@esbuild/netbsd-arm64': 0.25.12
+ '@esbuild/netbsd-x64': 0.25.12
+ '@esbuild/openbsd-arm64': 0.25.12
+ '@esbuild/openbsd-x64': 0.25.12
+ '@esbuild/openharmony-arm64': 0.25.12
+ '@esbuild/sunos-x64': 0.25.12
+ '@esbuild/win32-arm64': 0.25.12
+ '@esbuild/win32-ia32': 0.25.12
+ '@esbuild/win32-x64': 0.25.12
+
+ esbuild@0.27.2:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.27.2
+ '@esbuild/android-arm': 0.27.2
+ '@esbuild/android-arm64': 0.27.2
+ '@esbuild/android-x64': 0.27.2
+ '@esbuild/darwin-arm64': 0.27.2
+ '@esbuild/darwin-x64': 0.27.2
+ '@esbuild/freebsd-arm64': 0.27.2
+ '@esbuild/freebsd-x64': 0.27.2
+ '@esbuild/linux-arm': 0.27.2
+ '@esbuild/linux-arm64': 0.27.2
+ '@esbuild/linux-ia32': 0.27.2
+ '@esbuild/linux-loong64': 0.27.2
+ '@esbuild/linux-mips64el': 0.27.2
+ '@esbuild/linux-ppc64': 0.27.2
+ '@esbuild/linux-riscv64': 0.27.2
+ '@esbuild/linux-s390x': 0.27.2
+ '@esbuild/linux-x64': 0.27.2
+ '@esbuild/netbsd-arm64': 0.27.2
+ '@esbuild/netbsd-x64': 0.27.2
+ '@esbuild/openbsd-arm64': 0.27.2
+ '@esbuild/openbsd-x64': 0.27.2
+ '@esbuild/openharmony-arm64': 0.27.2
+ '@esbuild/sunos-x64': 0.27.2
+ '@esbuild/win32-arm64': 0.27.2
+ '@esbuild/win32-ia32': 0.27.2
+ '@esbuild/win32-x64': 0.27.2
+
+ fdir@6.5.0(picomatch@4.0.3):
+ optionalDependencies:
+ picomatch: 4.0.3
+
+ fix-dts-default-cjs-exports@1.0.1:
+ dependencies:
+ magic-string: 0.30.21
+ mlly: 1.8.0
+ rollup: 4.55.1
+
+ fsevents@2.3.3:
+ optional: true
+
+ joycon@3.1.1: {}
+
+ lilconfig@3.1.3: {}
+
+ lines-and-columns@1.2.4: {}
+
+ load-tsconfig@0.2.5: {}
+
+ magic-string@0.30.21:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ mlly@1.8.0:
+ dependencies:
+ acorn: 8.15.0
+ pathe: 2.0.3
+ pkg-types: 1.3.1
+ ufo: 1.6.1
+
+ ms@2.1.3: {}
+
+ mz@2.7.0:
+ dependencies:
+ any-promise: 1.3.0
+ object-assign: 4.1.1
+ thenify-all: 1.6.0
+
+ nanoid@3.3.11: {}
+
+ object-assign@4.1.1: {}
+
+ pathe@2.0.3: {}
+
+ picocolors@1.1.1: {}
+
+ picomatch@4.0.3: {}
+
+ pirates@4.0.7: {}
+
+ pkg-types@1.3.1:
+ dependencies:
+ confbox: 0.1.8
+ mlly: 1.8.0
+ pathe: 2.0.3
+
+ postcss-load-config@6.0.1(postcss@8.5.6):
+ dependencies:
+ lilconfig: 3.1.3
+ optionalDependencies:
+ postcss: 8.5.6
+
+ postcss@8.5.6:
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ readdirp@4.1.2: {}
+
+ resolve-from@5.0.0: {}
+
+ rollup@4.55.1:
+ dependencies:
+ '@types/estree': 1.0.8
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.55.1
+ '@rollup/rollup-android-arm64': 4.55.1
+ '@rollup/rollup-darwin-arm64': 4.55.1
+ '@rollup/rollup-darwin-x64': 4.55.1
+ '@rollup/rollup-freebsd-arm64': 4.55.1
+ '@rollup/rollup-freebsd-x64': 4.55.1
+ '@rollup/rollup-linux-arm-gnueabihf': 4.55.1
+ '@rollup/rollup-linux-arm-musleabihf': 4.55.1
+ '@rollup/rollup-linux-arm64-gnu': 4.55.1
+ '@rollup/rollup-linux-arm64-musl': 4.55.1
+ '@rollup/rollup-linux-loong64-gnu': 4.55.1
+ '@rollup/rollup-linux-loong64-musl': 4.55.1
+ '@rollup/rollup-linux-ppc64-gnu': 4.55.1
+ '@rollup/rollup-linux-ppc64-musl': 4.55.1
+ '@rollup/rollup-linux-riscv64-gnu': 4.55.1
+ '@rollup/rollup-linux-riscv64-musl': 4.55.1
+ '@rollup/rollup-linux-s390x-gnu': 4.55.1
+ '@rollup/rollup-linux-x64-gnu': 4.55.1
+ '@rollup/rollup-linux-x64-musl': 4.55.1
+ '@rollup/rollup-openbsd-x64': 4.55.1
+ '@rollup/rollup-openharmony-arm64': 4.55.1
+ '@rollup/rollup-win32-arm64-msvc': 4.55.1
+ '@rollup/rollup-win32-ia32-msvc': 4.55.1
+ '@rollup/rollup-win32-x64-gnu': 4.55.1
+ '@rollup/rollup-win32-x64-msvc': 4.55.1
+ fsevents: 2.3.3
+
+ source-map-js@1.2.1: {}
+
+ source-map@0.7.6: {}
+
+ srvx@0.9.8: {}
+
+ sucrase@3.35.1:
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ commander: 4.1.1
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.7
+ tinyglobby: 0.2.15
+ ts-interface-checker: 0.1.13
+
+ thenify-all@1.6.0:
+ dependencies:
+ thenify: 3.3.1
+
+ thenify@3.3.1:
+ dependencies:
+ any-promise: 1.3.0
+
+ tinyexec@0.3.2: {}
+
+ tinyglobby@0.2.15:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+
+ tree-kill@1.2.2: {}
+
+ ts-interface-checker@0.1.13: {}
+
+ tsup@8.5.1(postcss@8.5.6)(typescript@5.9.3):
+ dependencies:
+ bundle-require: 5.1.0(esbuild@0.27.2)
+ cac: 6.7.14
+ chokidar: 4.0.3
+ consola: 3.4.2
+ debug: 4.4.3
+ esbuild: 0.27.2
+ fix-dts-default-cjs-exports: 1.0.1
+ joycon: 3.1.1
+ picocolors: 1.1.1
+ postcss-load-config: 6.0.1(postcss@8.5.6)
+ resolve-from: 5.0.0
+ rollup: 4.55.1
+ source-map: 0.7.6
+ sucrase: 3.35.1
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.15
+ tree-kill: 1.2.2
+ optionalDependencies:
+ postcss: 8.5.6
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - jiti
+ - supports-color
+ - tsx
+ - yaml
+
+ typescript@5.9.3: {}
+
+ ufo@1.6.1: {}
+
+ undici-types@6.21.0: {}
+
+ vite@6.4.1(@types/node@22.19.3):
+ dependencies:
+ esbuild: 0.25.12
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.55.1
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 22.19.3
+ fsevents: 2.3.3
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..471ec4b
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,3 @@
+packages:
+ - '.'
+ - 'examples/*'
diff --git a/src/build.ts b/src/build.ts
new file mode 100644
index 0000000..8ec2e59
--- /dev/null
+++ b/src/build.ts
@@ -0,0 +1,85 @@
+import path from 'path'
+import type { Plugin, UserConfig } from 'vite'
+
+export interface BuildOptions {
+ entry?: string
+ outDir?: string
+ serverOutFile?: string
+ framework?: 'vercel' // Target framework for deployment
+}
+
+export const defaultBuildOptions: Partial = {
+ entry: './src/server.ts',
+ outDir: 'dist',
+ serverOutFile: 'server.js',
+}
+
+export function srvxBuild(options?: BuildOptions): Plugin {
+ const mergedOptions = { ...defaultBuildOptions, ...options }
+
+ // Auto-detect Vercel or use explicit framework option
+ const isVercel = mergedOptions.framework === 'vercel' || process.env.VERCEL === '1'
+
+ return {
+ name: 'vite-plugin-srvx-server-build',
+
+ // Only apply during server builds (not client builds)
+ apply(_config, { command, mode }) {
+ return command === 'build' && mode === 'server'
+ },
+
+ config(): UserConfig {
+ // For Vercel, output to dist/api/index.js
+ // For standard builds, use configured options
+ const serverOutDir = isVercel
+ ? path.join(mergedOptions.outDir || 'dist', 'api')
+ : (mergedOptions.outDir || 'dist')
+ const serverOutFile = isVercel ? 'index.js' : (mergedOptions.serverOutFile || 'server.js')
+
+ return {
+ build: {
+ ssr: true,
+ outDir: serverOutDir,
+ copyPublicDir: false, // Don't copy public assets during server build
+ rollupOptions: {
+ input: mergedOptions.entry,
+ output: {
+ entryFileNames: serverOutFile,
+ format: 'esm',
+ },
+ },
+ emptyOutDir: false,
+ },
+ }
+ },
+
+ buildEnd() {
+ const serverOutDir = isVercel
+ ? path.join(mergedOptions.outDir || 'dist', 'api')
+ : (mergedOptions.outDir || 'dist')
+ const serverOutFile = isVercel ? 'index.js' : (mergedOptions.serverOutFile || 'server.js')
+ const serverPath = path.join(serverOutDir, serverOutFile)
+
+ console.log('\n✅ Server built successfully!')
+ console.log(`📦 Server output: ${serverPath}`)
+
+ if (isVercel) {
+ console.log('\n🚀 Deploy to Vercel:')
+ console.log(' 1. Configure vercel.json with:')
+ console.log(' {')
+ console.log(' "functions": {')
+ console.log(' "dist/api/**": { "runtime": "edge" }')
+ console.log(' }')
+ console.log(' }')
+ console.log(' 2. Run: vercel deploy\n')
+ console.log('💡 Output structure:')
+ console.log(' dist/api/index.js - Edge Function')
+ console.log(' dist/public/ - Static assets')
+ } else {
+ console.log('\n🚀 Run your app with:')
+ console.log(` srvx ${serverPath}\n`)
+ console.log('💡 Tip: srvx will automatically serve static files from dist/public/')
+ }
+ },
+ }
+}
diff --git a/src/client-build.ts b/src/client-build.ts
new file mode 100644
index 0000000..10d129b
--- /dev/null
+++ b/src/client-build.ts
@@ -0,0 +1,34 @@
+import path from 'path'
+import type { Plugin, UserConfig } from 'vite'
+
+export interface ClientBuildOptions {
+ outDir?: string
+}
+
+export const defaultClientBuildOptions: Required = {
+ outDir: 'dist',
+}
+
+export function clientBuild(options?: ClientBuildOptions): Plugin {
+ const mergedOptions = { ...defaultClientBuildOptions, ...options }
+
+ return {
+ name: 'vite-plugin-srvx-client-build',
+
+ // Only apply during client builds (not server builds)
+ apply(_config, { command, mode }) {
+ return command === 'build' && mode !== 'server'
+ },
+
+ config(): UserConfig {
+ // Output to 'dist/public' (or custom outDir/public)
+ const clientOutDir = path.join(mergedOptions.outDir, 'public')
+
+ return {
+ build: {
+ outDir: clientOutDir,
+ },
+ }
+ },
+ }
+}
diff --git a/src/dev-server.ts b/src/dev-server.ts
new file mode 100644
index 0000000..85d298b
--- /dev/null
+++ b/src/dev-server.ts
@@ -0,0 +1,199 @@
+import type { Plugin, ViteDevServer } from 'vite'
+import type { IncomingMessage, ServerResponse } from 'http'
+import fs from 'fs'
+import path from 'path'
+
+export interface DevServerOptions {
+ entry?: string
+ exclude?: (string | RegExp)[]
+ injectClientScript?: boolean
+ loadModule?: (server: ViteDevServer, entry: string) => Promise
+}
+
+export const defaultOptions: Partial = {
+ entry: './src/server.ts',
+ exclude: [
+ /.*\.tsx?$/,
+ /.*\.ts$/,
+ /.*\.jsx?$/,
+ /.*\.css$/,
+ /.*\.scss$/,
+ /.*\.sass$/,
+ /.*\.less$/,
+ /.*\.styl$/,
+ /.*\.png$/,
+ /.*\.jpg$/,
+ /.*\.jpeg$/,
+ /.*\.gif$/,
+ /.*\.svg$/,
+ /.*\.webp$/,
+ /^\/@.+$/,
+ /^\/node_modules\/.*/,
+ /\?import$/,
+ ],
+ injectClientScript: true,
+}
+
+interface SrvxApp {
+ fetch: (request: Request) => Response | Promise
+}
+
+function createMiddleware(server: ViteDevServer, options: DevServerOptions) {
+ return async (
+ req: IncomingMessage,
+ res: ServerResponse,
+ next: () => void
+ ) => {
+ const config = server.config
+ const base = config.base === '/' ? '' : config.base
+
+ if (req.url === '/' || req.url === base || req.url === `${base}/`) {
+ const indexPath = path.join(config.root, 'index.html')
+ if (fs.existsSync(indexPath)) {
+ const html = await server.transformIndexHtml(
+ req.url,
+ fs.readFileSync(indexPath, 'utf-8')
+ )
+ res.statusCode = 200
+ res.setHeader('Content-Type', 'text/html')
+ res.setHeader('Content-Length', Buffer.byteLength(html))
+ res.end(html)
+ return
+ }
+ }
+
+ const exclude = options.exclude ?? defaultOptions.exclude ?? []
+
+ for (const pattern of exclude) {
+ if (req.url) {
+ if (pattern instanceof RegExp) {
+ if (pattern.test(req.url)) {
+ return next()
+ }
+ } else if (typeof pattern === 'string') {
+ if (req.url.startsWith(pattern)) {
+ return next()
+ }
+ }
+ }
+ }
+
+ if (req.url?.startsWith(base)) {
+ const publicDir = config.publicDir
+ if (publicDir && fs.existsSync(publicDir)) {
+ const filePath = path.join(publicDir, req.url.replace(base, ''))
+ if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
+ return next()
+ }
+ }
+ }
+
+ let app: SrvxApp | undefined
+
+ try {
+ const loadModule = options.loadModule ?? ((server, entry) => server.ssrLoadModule(entry))
+ const module = await loadModule(server, options.entry!)
+
+ if ('default' in module) {
+ app = module.default as SrvxApp
+ } else {
+ app = module as SrvxApp
+ }
+
+ if (!app?.fetch) {
+ throw new Error('No fetch handler found in the entry module')
+ }
+ } catch (e) {
+ return next()
+ }
+
+ const protocol = (req.socket as any).encrypted ? 'https' : 'http'
+ const host = req.headers.host || 'localhost'
+ const url = `${protocol}://${host}${req.url}`
+
+ const headers = new Headers()
+ for (const [key, value] of Object.entries(req.headers)) {
+ if (value !== undefined) {
+ if (Array.isArray(value)) {
+ for (const v of value) {
+ headers.append(key, v)
+ }
+ } else {
+ headers.set(key, value)
+ }
+ }
+ }
+
+ const body = req.method !== 'GET' && req.method !== 'HEAD' ? req : undefined
+
+ const request = new Request(url, {
+ method: req.method,
+ headers,
+ body: body as any,
+ })
+
+ const response = await app.fetch(request)
+
+ res.statusCode = response.status
+ response.headers.forEach((value, key) => {
+ res.setHeader(key, value)
+ })
+
+ if (options.injectClientScript !== false) {
+ const contentType = response.headers.get('content-type')
+ if (contentType?.includes('text/html')) {
+ const body = await response.text()
+
+ let script = ``
+
+ const nonce = response.headers.get('content-security-policy-nonce')
+ if (nonce) {
+ script = ``
+ }
+
+ const injectedBody = body.replace('', `${script}`)
+
+ res.setHeader('content-length', Buffer.byteLength(injectedBody))
+ res.end(injectedBody)
+ return
+ }
+ }
+
+ if (response.body) {
+ const reader = response.body.getReader()
+ const stream = async () => {
+ try {
+ while (true) {
+ const { done, value } = await reader.read()
+ if (done) break
+ res.write(value)
+ }
+ res.end()
+ } catch (error) {
+ res.end()
+ }
+ }
+ await stream()
+ } else {
+ res.end()
+ }
+ }
+}
+
+export function devServer(options?: DevServerOptions): Plugin {
+ const entry = options?.entry ?? defaultOptions.entry
+
+ return {
+ name: 'vite-plugin-srvx-dev',
+ apply: 'serve',
+ configureServer(server) {
+ const mergedOptions: DevServerOptions = {
+ ...defaultOptions,
+ ...options,
+ entry,
+ }
+
+ server.middlewares.use(createMiddleware(server, mergedOptions))
+ },
+ }
+}
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 0000000..883ed93
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,15 @@
+import { srvx } from "./srvx";
+
+export type { BuildOptions } from "./build";
+export { defaultBuildOptions, srvxBuild } from "./build";
+export type { ClientBuildOptions } from "./client-build";
+export { clientBuild, defaultClientBuildOptions } from "./client-build";
+export type { DevServerOptions } from "./dev-server";
+// Individual plugins (for advanced use cases)
+export { defaultOptions, devServer } from "./dev-server";
+export type { SrvxOptions } from "./srvx";
+// Unified plugin (recommended)
+export { defaultSrvxOptions, srvx } from "./srvx";
+
+// Default export is the unified plugin
+export default srvx;
diff --git a/src/srvx.ts b/src/srvx.ts
new file mode 100644
index 0000000..88417cd
--- /dev/null
+++ b/src/srvx.ts
@@ -0,0 +1,44 @@
+import type { Plugin } from "vite";
+import { srvxBuild } from "./build";
+import { clientBuild } from "./client-build";
+import { type DevServerOptions, devServer } from "./dev-server";
+
+export interface SrvxOptions extends DevServerOptions {
+ // Build-specific options
+ outDir?: string;
+ serverOutFile?: string;
+ framework?: "vercel"; // Target framework for deployment
+}
+
+export const defaultSrvxOptions: Partial = {
+ entry: "./src/server.ts",
+ outDir: "dist",
+ serverOutFile: "server.js",
+};
+
+export function srvx(options?: SrvxOptions): Plugin[] {
+ const mergedOptions = { ...defaultSrvxOptions, ...options };
+
+ return [
+ // Development server plugin
+ devServer({
+ entry: mergedOptions.entry,
+ exclude: mergedOptions.exclude,
+ injectClientScript: mergedOptions.injectClientScript,
+ loadModule: mergedOptions.loadModule,
+ }),
+
+ // Client build plugin
+ clientBuild({
+ outDir: mergedOptions.outDir,
+ }),
+
+ // Server build plugin
+ srvxBuild({
+ entry: mergedOptions.entry,
+ outDir: mergedOptions.outDir,
+ serverOutFile: mergedOptions.serverOutFile,
+ framework: mergedOptions.framework,
+ }),
+ ];
+}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..f538874
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "ESNext",
+ "lib": ["ES2022"],
+ "moduleResolution": "bundler",
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "declaration": true,
+ "declarationMap": true,
+ "outDir": "./dist",
+ "rootDir": "./src"
+ },
+ "include": ["src"],
+ "exclude": ["node_modules", "dist", "example"]
+}
diff --git a/tsup.config.ts b/tsup.config.ts
new file mode 100644
index 0000000..3e10e4f
--- /dev/null
+++ b/tsup.config.ts
@@ -0,0 +1,10 @@
+import { defineConfig } from 'tsup'
+
+export default defineConfig({
+ entry: ['src/index.ts'],
+ format: ['esm'],
+ dts: true,
+ clean: true,
+ sourcemap: true,
+ splitting: false,
+})