diff --git a/README.md b/README.md
index 731ba80..2d00844 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,6 @@ more information.
This project supports:
-- Next.js 15/16
- TanStack Start with React
- Vite with React/Vue (which includes Astro, VitePress, etc)
@@ -19,154 +18,6 @@ This project can also be used through the CLI or as
## Installation
-### Next.js
-
-If you are using Next.js, install Tidewave with:
-
-```sh
-$ npx tidewave install
-# or
-$ yarn dlx tidewave install
-# or
-$ pnpm dlx tidewave install
-# or
-$ bunx tidewave install
-```
-
-And you are almost there! Now make sure
-[Tidewave is installed](https://hexdocs.pm/tidewave/installation.html) and you
-are ready to connect Tidewave to your app.
-
-In case the command above do not work, you can toggle the manual installation
-instructions below
-
-
-Show manual installation steps
-
-**1. Add Tidewave as a dependency**
-
-```sh
-$ npm install -D tidewave
-# or
-$ yarn add -D tidewave
-# or
-$ pnpm add --save-dev tidewave
-# or
-$ bun add --dev tidewave
-```
-
-**2. Create `pages/api/tidewave.ts`**
-
-Then create `pages/api/tidewave.ts` with:
-
-```typescript
-import type { NextApiRequest, NextApiResponse } from 'next';
-
-export default async function handler(
- req: NextApiRequest,
- res: NextApiResponse,
-) {
- if (process.env.NODE_ENV === 'development') {
- const { tidewaveHandler } = await import('tidewave/next-js/handler');
- const handler = await tidewaveHandler();
- return handler(req, res);
- } else {
- res.status(404).end();
- }
-}
-
-export const config = {
- runtime: 'nodejs',
- api: {
- bodyParser: false, // Tidewave already parses the body internally
- },
-};
-```
-
-**3. Create the proxy.ts or middleware.ts**
-
-If you are using Next.js 16+, then create (or modify) `proxy.ts` with:
-
-```typescript
-import { NextRequest, NextResponse } from 'next/server';
-
-export function proxy(req: NextRequest): NextResponse {
- if (req.nextUrl.pathname.startsWith('/tidewave')) {
- return NextResponse.rewrite(new URL('/api/tidewave', req.url));
- }
-
- // Here you could add your own logic or different middlewares.
- return NextResponse.next();
-}
-```
-
-For Next.js 15+ and earlier, create (or modify) `middleware.ts` with:
-
-```typescript
-import { NextRequest, NextResponse } from 'next/server';
-
-export function middleware(req: NextRequest): NextResponse {
- if (req.nextUrl.pathname.startsWith('/tidewave')) {
- return NextResponse.rewrite(new URL('/api/tidewave', req.url));
- }
-
- // Here you could add your own logic or different middlewares.
- return NextResponse.next();
-}
-
-export const config = {
- matcher: ['/tidewave/:path*'],
-};
-```
-
-**4. Create instrumentation.ts**
-
-Finally, we expose your application's spans, events, and logs to Tidewave MCP.
-First install the NodeSDK:
-
-```sh
-npm install @opentelemetry/sdk-node
-npm install -D @opentelemetry/sdk-trace-base @opentelemetry/sdk-logs
-```
-
-And then create (or modify) a custom `instrumentation.ts` file in the root
-directory of the project (or inside `src` folder if using one):
-
-```typescript
-// instrumentation.ts
-import type { SpanProcessor } from '@opentelemetry/sdk-trace-base';
-import type { LogRecordProcessor } from '@opentelemetry/sdk-logs';
-
-export async function register() {
- if (process.env.NEXT_RUNTIME === 'nodejs') {
- const { NodeSDK } = await import('@opentelemetry/sdk-node');
-
- // Add your app own processes here existing configuration
- const sdkConfig: {
- spanProcessors: SpanProcessor[];
- logRecordProcessors: LogRecordProcessor[];
- } = {
- spanProcessors: [],
- logRecordProcessors: [],
- };
-
- // Conditionally add Tidewave processors in development
- if (process.env.NODE_ENV === 'development') {
- const { TidewaveSpanProcessor, TidewaveLogRecordProcessor } =
- await import('tidewave/next-js/instrumentation');
-
- sdkConfig.spanProcessors.push(new TidewaveSpanProcessor());
- sdkConfig.logRecordProcessors.push(new TidewaveLogRecordProcessor());
- }
-
- const sdk = new NodeSDK(sdkConfig);
- sdk.start();
- }
-}
-```
-
-
-
### TanStack Start
If you are using TanStack Start with React, install Tidewave with:
@@ -255,8 +106,7 @@ features.
### Configuration
-Next.js' `tidewaveHandler` and Vite's `tidewave` accept the configuration
-options below:
+Vite's `tidewave` accepts the configuration options below:
- `allow_remote_access:` Tidewave only allows requests from localhost by
default, even if your server listens on other interfaces, for security
@@ -348,8 +198,8 @@ bun run clean # Clean dist directory
## Acknowledgements
-A thank you to [Zoey](https://github.com/zoedsoupe/) for implementing both
-Next.js and Vite integrations as well as the CLI interface.
+A thank you to [Zoey](https://github.com/zoedsoupe/) for implementing the Vite
+integration as well as the CLI interface.
## License
diff --git a/bun.lock b/bun.lock
index f964f10..431633d 100644
--- a/bun.lock
+++ b/bun.lock
@@ -1,37 +1,31 @@
{
"lockfileVersion": 1,
+ "configVersion": 0,
"workspaces": {
"": {
"name": "tidewave",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.17.4",
"body-parser": "^2.2.0",
- "chalk": "^5.3.0",
- "commander": "^12.1.0",
- "connect": "^3.7.0",
"typescript": "^5",
"zod": "3.25.76",
},
"devDependencies": {
"@eslint/js": "^9.16.0",
- "@opentelemetry/api": "^1.9.0",
- "@opentelemetry/sdk-logs": "^0.206.0",
- "@opentelemetry/sdk-trace-base": "^2.1.0",
"@types/body-parser": "^1.19.6",
"@types/bun": "latest",
- "@types/connect": "^3.4.38",
"@types/node": "^22.10.1",
"@typescript-eslint/eslint-plugin": "^8.18.0",
"@typescript-eslint/parser": "^8.18.0",
- "@vercel/otel": "^2.0.1",
"@vitest/ui": "^3.2.4",
"bun-types": "latest",
+ "chalk": "^5.3.0",
+ "commander": "^12.1.0",
"eslint": "^9.16.0",
"globals": "^15.14.0",
- "next": "^15.5.3",
"prettier": "^3.4.2",
"vite": "^7.1.5",
- "vitest": "^3.2.4",
+ "vitest": "^4.1.8",
},
"peerDependencies": {
"typescript": "^5",
@@ -39,8 +33,6 @@
},
},
"packages": {
- "@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="],
-
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.9", "", { "os": "aix", "cpu": "ppc64" }, "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA=="],
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.9", "", { "os": "android", "cpu": "arm" }, "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ=="],
@@ -119,98 +111,16 @@
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
- "@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="],
-
- "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.3" }, "os": "darwin", "cpu": "arm64" }, "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA=="],
-
- "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.3" }, "os": "darwin", "cpu": "x64" }, "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg=="],
-
- "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw=="],
-
- "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA=="],
-
- "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.3", "", { "os": "linux", "cpu": "arm" }, "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA=="],
-
- "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ=="],
-
- "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg=="],
-
- "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w=="],
-
- "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg=="],
-
- "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw=="],
-
- "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g=="],
-
- "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.3" }, "os": "linux", "cpu": "arm" }, "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA=="],
-
- "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.3" }, "os": "linux", "cpu": "arm64" }, "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ=="],
-
- "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.3" }, "os": "linux", "cpu": "ppc64" }, "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ=="],
-
- "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.3" }, "os": "linux", "cpu": "s390x" }, "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw=="],
-
- "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.3" }, "os": "linux", "cpu": "x64" }, "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A=="],
-
- "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" }, "os": "linux", "cpu": "arm64" }, "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA=="],
-
- "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.3" }, "os": "linux", "cpu": "x64" }, "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg=="],
-
- "@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.4", "", { "dependencies": { "@emnapi/runtime": "^1.5.0" }, "cpu": "none" }, "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA=="],
-
- "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA=="],
-
- "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw=="],
-
- "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.4", "", { "os": "win32", "cpu": "x64" }, "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig=="],
-
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.17.4", "", { "dependencies": { "ajv": "^6.12.6", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-zq24hfuAmmlNZvik0FLI58uE5sriN0WWsQzIlYnzSuKDAHFqJtBFrl/LfB1NLgJT5Y7dEBzaX4yAKqOPrcetaw=="],
- "@next/env": ["@next/env@15.5.3", "", {}, "sha512-RSEDTRqyihYXygx/OJXwvVupfr9m04+0vH8vyy0HfZ7keRto6VX9BbEk0J2PUk0VGy6YhklJUSrgForov5F9pw=="],
-
- "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.5.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-nzbHQo69+au9wJkGKTU9lP7PXv0d1J5ljFpvb+LnEomLtSbJkbZyEs6sbF3plQmiOB2l9OBtN2tNSvCH1nQ9Jg=="],
-
- "@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.5.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-w83w4SkOOhekJOcA5HBvHyGzgV1W/XvOfpkrxIse4uPWhYTTRwtGEM4v/jiXwNSJvfRvah0H8/uTLBKRXlef8g=="],
-
- "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.5.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-+m7pfIs0/yvgVu26ieaKrifV8C8yiLe7jVp9SpcIzg7XmyyNE7toC1fy5IOQozmr6kWl/JONC51osih2RyoXRw=="],
-
- "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.5.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-u3PEIzuguSenoZviZJahNLgCexGFhso5mxWCrrIMdvpZn6lkME5vc/ADZG8UUk5K1uWRy4hqSFECrON6UKQBbQ=="],
-
- "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.5.3", "", { "os": "linux", "cpu": "x64" }, "sha512-lDtOOScYDZxI2BENN9m0pfVPJDSuUkAD1YXSvlJF0DKwZt0WlA7T7o3wrcEr4Q+iHYGzEaVuZcsIbCps4K27sA=="],
-
- "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.5.3", "", { "os": "linux", "cpu": "x64" }, "sha512-9vWVUnsx9PrY2NwdVRJ4dUURAQ8Su0sLRPqcCCxtX5zIQUBES12eRVHq6b70bbfaVaxIDGJN2afHui0eDm+cLg=="],
-
- "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.5.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-1CU20FZzY9LFQigRi6jM45oJMU3KziA5/sSG+dXeVaTm661snQP6xu3ykGxxwU5sLG3sh14teO/IOEPVsQMRfA=="],
-
- "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.5.3", "", { "os": "win32", "cpu": "x64" }, "sha512-JMoLAq3n3y5tKXPQwCK5c+6tmwkuFDa2XAxz8Wm4+IVthdBZdZGh+lmiLUHg9f9IDwIQpUjp+ysd6OkYTyZRZw=="],
-
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
- "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
-
- "@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.206.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-yIVDu9jX//nV5wSMLZLdHdb1SKHIMj9k+wQVFtln5Flcgdldz9BkHtavvExQiJqBZg2OpEEJEZmzQazYztdz2A=="],
-
- "@opentelemetry/core": ["@opentelemetry/core@2.1.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-RMEtHsxJs/GiHHxYT58IY57UXAQTuUnZVco6ymDEqTNlJKTimM4qPUPVe8InNFyBjhHBEAx4k3Q8LtNayBsbUQ=="],
-
- "@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.206.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.206.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-anPU9GAn3vSH/0JFQZ4e626xRw8p8R21kxM7xammFk9BRhfDw1IpgqvFMllbb+1MSHHEX9EiUqYHJyWo/B6KGA=="],
-
- "@opentelemetry/resources": ["@opentelemetry/resources@2.1.0", "", { "dependencies": { "@opentelemetry/core": "2.1.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1CJjf3LCvoefUOgegxi8h6r4B/wLSzInyhGP2UmIBYNlo4Qk5CZ73e1eEyWmfXvFtm1ybkmfb2DqWvspsYLrWw=="],
-
- "@opentelemetry/sdk-logs": ["@opentelemetry/sdk-logs@0.206.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.206.0", "@opentelemetry/core": "2.1.0", "@opentelemetry/resources": "2.1.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, "sha512-SQ2yTmqe4Mw9RI3a/glVkfjWPsXh6LySvnljXubiZq4zu+UP8NMJt2j82ZsYb+KpD7Eu+/41/7qlJnjdeVjz7Q=="],
-
- "@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.1.0", "", { "dependencies": { "@opentelemetry/core": "2.1.0", "@opentelemetry/resources": "2.1.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-J9QX459mzqHLL9Y6FZ4wQPRZG4TOpMCyPOh6mkr/humxE1W2S3Bvf4i75yiMW9uyed2Kf5rxmLhTm/UK8vNkAw=="],
-
- "@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.1.0", "", { "dependencies": { "@opentelemetry/core": "2.1.0", "@opentelemetry/resources": "2.1.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-uTX9FBlVQm4S2gVQO1sb5qyBLq/FPjbp+tmGoxu4tIgtYGmBYB44+KX/725RFDe30yBSaA9Ml9fqphe1hbUyLQ=="],
-
- "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.37.0", "", {}, "sha512-JD6DerIKdJGmRp4jQyX5FlrQjA4tjOw1cvfsPAZXfOOEErMUHjPcPSICS+6WnM0nB0efSFARh0KAZss+bvExOA=="],
-
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.46.2", "", { "os": "android", "cpu": "arm" }, "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA=="],
@@ -253,7 +163,7 @@
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.46.2", "", { "os": "win32", "cpu": "x64" }, "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg=="],
- "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
+ "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"@types/body-parser": ["@types/body-parser@1.19.6", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g=="],
@@ -293,19 +203,17 @@
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.39.1", "", { "dependencies": { "@typescript-eslint/types": "8.39.1", "eslint-visitor-keys": "^4.2.1" } }, "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A=="],
- "@vercel/otel": ["@vercel/otel@2.0.1", "", { "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <2.0.0", "@opentelemetry/api-logs": ">=0.200.0 <0.300.0", "@opentelemetry/instrumentation": ">=0.200.0 <0.300.0", "@opentelemetry/resources": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-logs": ">=0.200.0 <0.300.0", "@opentelemetry/sdk-metrics": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-base": ">=2.0.0 <3.0.0" } }, "sha512-eC8F8t9Ksn6xPBXBef7w2pMVcgjXoUOMJ3gnTs4Yh/zbKSIKfvX17GjyqCODwF9FdbiiPBxLsF8aQxFOtKyiEA=="],
+ "@vitest/expect": ["@vitest/expect@4.1.9", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.9", "@vitest/utils": "4.1.9", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA=="],
- "@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="],
+ "@vitest/mocker": ["@vitest/mocker@4.1.9", "", { "dependencies": { "@vitest/spy": "4.1.9", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw=="],
- "@vitest/mocker": ["@vitest/mocker@3.2.4", "", { "dependencies": { "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ=="],
+ "@vitest/pretty-format": ["@vitest/pretty-format@4.1.9", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A=="],
- "@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="],
+ "@vitest/runner": ["@vitest/runner@4.1.9", "", { "dependencies": { "@vitest/utils": "4.1.9", "pathe": "^2.0.3" } }, "sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg=="],
- "@vitest/runner": ["@vitest/runner@3.2.4", "", { "dependencies": { "@vitest/utils": "3.2.4", "pathe": "^2.0.3", "strip-literal": "^3.0.0" } }, "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ=="],
+ "@vitest/snapshot": ["@vitest/snapshot@4.1.9", "", { "dependencies": { "@vitest/pretty-format": "4.1.9", "@vitest/utils": "4.1.9", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA=="],
- "@vitest/snapshot": ["@vitest/snapshot@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ=="],
-
- "@vitest/spy": ["@vitest/spy@3.2.4", "", { "dependencies": { "tinyspy": "^4.0.3" } }, "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw=="],
+ "@vitest/spy": ["@vitest/spy@4.1.9", "", {}, "sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA=="],
"@vitest/ui": ["@vitest/ui@3.2.4", "", { "dependencies": { "@vitest/utils": "3.2.4", "fflate": "^0.8.2", "flatted": "^3.3.3", "pathe": "^2.0.3", "sirv": "^3.0.1", "tinyglobby": "^0.2.14", "tinyrainbow": "^2.0.0" }, "peerDependencies": { "vitest": "3.2.4" } }, "sha512-hGISOaP18plkzbWEcP/QvtRW1xDXF2+96HbEX6byqQhAUbiS5oH6/9JwW+QsQCIYON2bI6QZBF+2PvOmrRZ9wA=="],
@@ -315,8 +223,6 @@
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
- "acorn-import-attributes": ["acorn-import-attributes@1.9.5", "", { "peerDependencies": { "acorn": "^8" } }, "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ=="],
-
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
@@ -325,8 +231,6 @@
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
- "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
-
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"body-parser": ["body-parser@2.2.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.0", "http-errors": "^2.0.0", "iconv-lite": "^0.6.3", "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.0", "type-is": "^2.0.0" } }, "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg=="],
@@ -339,26 +243,16 @@
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
- "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],
-
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
"call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
- "caniuse-lite": ["caniuse-lite@1.0.30001743", "", {}, "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw=="],
-
- "chai": ["chai@5.2.1", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A=="],
+ "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="],
"chalk": ["chalk@5.6.0", "", {}, "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ=="],
- "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="],
-
- "cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="],
-
- "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
-
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
@@ -367,12 +261,12 @@
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
- "connect": ["connect@3.7.0", "", { "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.2", "parseurl": "~1.3.3", "utils-merge": "1.0.1" } }, "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ=="],
-
"content-disposition": ["content-disposition@1.0.0", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg=="],
"content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
+ "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
+
"cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
"cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="],
@@ -385,14 +279,10 @@
"debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
- "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="],
-
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
"depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
- "detect-libc": ["detect-libc@2.1.0", "", {}, "sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg=="],
-
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
@@ -403,7 +293,7 @@
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
- "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="],
+ "es-module-lexer": ["es-module-lexer@2.1.0", "", {}, "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ=="],
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
@@ -437,7 +327,7 @@
"eventsource-parser": ["eventsource-parser@3.0.5", "", {}, "sha512-bSRG85ZrMdmWtm7qkF9He9TNRzc/Bm99gEJMaQoHJ9E6Kv9QBbsldh2oMj7iXmYNEAVvNgvv5vPorG6W+XtBhQ=="],
- "expect-type": ["expect-type@1.2.2", "", {}, "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA=="],
+ "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],
"express": ["express@5.1.0", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.0", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA=="],
@@ -461,7 +351,7 @@
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
- "finalhandler": ["finalhandler@1.1.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" } }, "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA=="],
+ "finalhandler": ["finalhandler@2.1.0", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q=="],
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
@@ -503,8 +393,6 @@
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
- "import-in-the-middle": ["import-in-the-middle@1.14.4", "", { "dependencies": { "acorn": "^8.14.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" } }, "sha512-eWjxh735SJLFJJDs5X82JQ2405OdJeAHDBnaoFCfdr5GVc7AWc9xU7KbrF+3Xd5F2ccP1aQFKtY+65X6EfKZ7A=="],
-
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
@@ -521,8 +409,6 @@
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
- "js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
-
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
@@ -541,7 +427,7 @@
"loupe": ["loupe@3.2.0", "", {}, "sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw=="],
- "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
+ "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
@@ -559,8 +445,6 @@
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
- "module-details-from-path": ["module-details-from-path@1.0.4", "", {}, "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w=="],
-
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
@@ -571,12 +455,12 @@
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
- "next": ["next@15.5.3", "", { "dependencies": { "@next/env": "15.5.3", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.5.3", "@next/swc-darwin-x64": "15.5.3", "@next/swc-linux-arm64-gnu": "15.5.3", "@next/swc-linux-arm64-musl": "15.5.3", "@next/swc-linux-x64-gnu": "15.5.3", "@next/swc-linux-x64-musl": "15.5.3", "@next/swc-win32-arm64-msvc": "15.5.3", "@next/swc-win32-x64-msvc": "15.5.3", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-r/liNAx16SQj4D+XH/oI1dlpv9tdKJ6cONYPwwcCC46f2NjpaRWY+EKCzULfgQYV6YKXjHBchff2IZBSlZmJNw=="],
-
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
"object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
+ "obug": ["obug@2.1.3", "", {}, "sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg=="],
+
"on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
@@ -599,15 +483,13 @@
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
- "pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="],
-
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
"pkce-challenge": ["pkce-challenge@5.0.0", "", {}, "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ=="],
- "postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
+ "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
@@ -625,12 +507,6 @@
"raw-body": ["raw-body@3.0.0", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.6.3", "unpipe": "1.0.0" } }, "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g=="],
- "react": ["react@19.1.1", "", {}, "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ=="],
-
- "react-dom": ["react-dom@19.1.1", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.1" } }, "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw=="],
-
- "require-in-the-middle": ["require-in-the-middle@8.0.0", "", { "dependencies": { "debug": "^4.3.5", "module-details-from-path": "^1.0.3" } }, "sha512-9s0pnM5tH8G4dSI3pms2GboYOs25LwOGnRMxN/Hx3TYT1K0rh6OjaWf4dI0DAQnMyaEXWoGVnSTPQasqwzTTAA=="],
-
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
@@ -645,8 +521,6 @@
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
- "scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
-
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
"send": ["send@1.2.0", "", { "dependencies": { "debug": "^4.3.5", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.0", "mime-types": "^3.0.1", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.1" } }, "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw=="],
@@ -655,8 +529,6 @@
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
- "sharp": ["sharp@0.34.4", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.0", "semver": "^7.7.2" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.4", "@img/sharp-darwin-x64": "0.34.4", "@img/sharp-libvips-darwin-arm64": "1.2.3", "@img/sharp-libvips-darwin-x64": "1.2.3", "@img/sharp-libvips-linux-arm": "1.2.3", "@img/sharp-libvips-linux-arm64": "1.2.3", "@img/sharp-libvips-linux-ppc64": "1.2.3", "@img/sharp-libvips-linux-s390x": "1.2.3", "@img/sharp-libvips-linux-x64": "1.2.3", "@img/sharp-libvips-linuxmusl-arm64": "1.2.3", "@img/sharp-libvips-linuxmusl-x64": "1.2.3", "@img/sharp-linux-arm": "0.34.4", "@img/sharp-linux-arm64": "0.34.4", "@img/sharp-linux-ppc64": "0.34.4", "@img/sharp-linux-s390x": "0.34.4", "@img/sharp-linux-x64": "0.34.4", "@img/sharp-linuxmusl-arm64": "0.34.4", "@img/sharp-linuxmusl-x64": "0.34.4", "@img/sharp-wasm32": "0.34.4", "@img/sharp-win32-arm64": "0.34.4", "@img/sharp-win32-ia32": "0.34.4", "@img/sharp-win32-x64": "0.34.4" } }, "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA=="],
-
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
@@ -679,28 +551,20 @@
"statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
- "std-env": ["std-env@3.9.0", "", {}, "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw=="],
+ "std-env": ["std-env@4.1.0", "", {}, "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ=="],
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
- "strip-literal": ["strip-literal@3.0.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA=="],
-
- "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="],
-
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
"tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
- "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
+ "tinyexec": ["tinyexec@1.2.4", "", {}, "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg=="],
"tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
- "tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="],
-
"tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="],
- "tinyspy": ["tinyspy@4.0.3", "", {}, "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A=="],
-
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
"toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
@@ -709,8 +573,6 @@
"ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="],
- "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
-
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
"type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
@@ -723,15 +585,11 @@
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
- "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="],
-
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
"vite": ["vite@7.1.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ=="],
- "vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="],
-
- "vitest": ["vitest@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", "@vitest/mocker": "3.2.4", "@vitest/pretty-format": "^3.2.4", "@vitest/runner": "3.2.4", "@vitest/snapshot": "3.2.4", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.2.4", "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A=="],
+ "vitest": ["vitest@4.1.9", "", { "dependencies": { "@vitest/expect": "4.1.9", "@vitest/mocker": "4.1.9", "@vitest/pretty-format": "4.1.9", "@vitest/runner": "4.1.9", "@vitest/snapshot": "4.1.9", "@vitest/spy": "4.1.9", "@vitest/utils": "4.1.9", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.9", "@vitest/browser-preview": "4.1.9", "@vitest/browser-webdriverio": "4.1.9", "@vitest/coverage-istanbul": "4.1.9", "@vitest/coverage-v8": "4.1.9", "@vitest/ui": "4.1.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "./vitest.mjs" } }, "sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ=="],
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
@@ -761,37 +619,37 @@
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
- "bun-types/@types/node": ["@types/node@24.3.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow=="],
+ "@vitest/expect/@vitest/utils": ["@vitest/utils@4.1.9", "", { "dependencies": { "@vitest/pretty-format": "4.1.9", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA=="],
- "connect/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+ "@vitest/expect/tinyrainbow": ["tinyrainbow@3.1.0", "", {}, "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw=="],
- "eslint/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
+ "@vitest/pretty-format/tinyrainbow": ["tinyrainbow@3.1.0", "", {}, "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw=="],
- "eslint/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
+ "@vitest/runner/@vitest/utils": ["@vitest/utils@4.1.9", "", { "dependencies": { "@vitest/pretty-format": "4.1.9", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA=="],
- "express/finalhandler": ["finalhandler@2.1.0", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q=="],
+ "@vitest/snapshot/@vitest/utils": ["@vitest/utils@4.1.9", "", { "dependencies": { "@vitest/pretty-format": "4.1.9", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA=="],
- "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
+ "@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="],
- "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+ "bun-types/@types/node": ["@types/node@24.3.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow=="],
- "finalhandler/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="],
+ "eslint/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
- "finalhandler/on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="],
+ "eslint/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
- "finalhandler/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="],
+ "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"http-errors/statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="],
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
- "vite/postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
-
"vite/tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
- "vite-node/vite": ["vite@5.4.19", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA=="],
+ "vitest/@vitest/utils": ["@vitest/utils@4.1.9", "", { "dependencies": { "@vitest/pretty-format": "4.1.9", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA=="],
- "vitest/vite": ["vite@5.4.19", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA=="],
+ "vitest/tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
+
+ "vitest/tinyrainbow": ["tinyrainbow@3.1.0", "", {}, "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw=="],
"@types/body-parser/@types/node/undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
@@ -799,110 +657,10 @@
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
- "bun-types/@types/node/undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
-
- "connect/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
-
- "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
-
- "vite-node/vite/esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
-
- "vite-node/vite/postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
-
- "vitest/vite/esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
-
- "vitest/vite/postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
-
- "vite-node/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
-
- "vite-node/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
-
- "vite-node/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
-
- "vite-node/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
-
- "vite-node/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
-
- "vite-node/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
-
- "vite-node/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
-
- "vite-node/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
-
- "vite-node/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
-
- "vite-node/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
-
- "vite-node/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
+ "@vitest/runner/@vitest/utils/tinyrainbow": ["tinyrainbow@3.1.0", "", {}, "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw=="],
- "vite-node/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
+ "@vitest/snapshot/@vitest/utils/tinyrainbow": ["tinyrainbow@3.1.0", "", {}, "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw=="],
- "vite-node/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
-
- "vite-node/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
-
- "vite-node/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
-
- "vite-node/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
-
- "vite-node/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
-
- "vite-node/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
-
- "vite-node/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
-
- "vite-node/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
-
- "vite-node/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
-
- "vite-node/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
-
- "vite-node/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
-
- "vitest/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
-
- "vitest/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
-
- "vitest/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
-
- "vitest/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
-
- "vitest/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
-
- "vitest/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
-
- "vitest/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
-
- "vitest/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
-
- "vitest/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
-
- "vitest/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
-
- "vitest/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
-
- "vitest/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
-
- "vitest/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
-
- "vitest/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
-
- "vitest/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
-
- "vitest/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
-
- "vitest/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
-
- "vitest/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
-
- "vitest/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
-
- "vitest/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
-
- "vitest/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
-
- "vitest/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
-
- "vitest/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
+ "bun-types/@types/node/undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
}
}
diff --git a/package.json b/package.json
index fa91228..d398c48 100644
--- a/package.json
+++ b/package.json
@@ -1,14 +1,13 @@
{
"name": "tidewave",
"version": "0.7.0",
- "description": "Tidewave for JavaScript (Next.js, TanStack, Vite)",
+ "description": "Tidewave for JavaScript (TanStack, Vite)",
"keywords": [
"typescript",
"documentation",
"mcp",
"cli",
"tidewave",
- "next",
"vite",
"tanstack"
],
@@ -37,16 +36,6 @@
"import": "./dist/vite-plugin.js",
"require": "./dist/vite-plugin.js"
},
- "./next-js/handler": {
- "types": "./dist/next-js/handler.d.ts",
- "import": "./dist/next-js/handler.js",
- "require": "./dist/next-js/handler.js"
- },
- "./next-js/instrumentation": {
- "types": "./dist/next-js/instrumentation.d.ts",
- "import": "./dist/next-js/instrumentation.js",
- "require": "./dist/next-js/instrumentation.js"
- },
"./tanstack": {
"types": "./dist/tanstack.d.ts",
"import": "./dist/tanstack.js",
@@ -62,7 +51,7 @@
],
"scripts": {
"dist": "bun run clean && bun run build:js && bun run build:types",
- "build:js": "bun build --outdir dist --root src --external typescript --external child_process --external module --external @opentelemetry/api --external @opentelemetry/sdk-logs --external @opentelemetry/sdk-trace-base src/next-js/handler.ts src/next-js/instrumentation.ts src/vite-plugin.ts src/tanstack.ts src/evaluation/eval_worker.ts src/cli/index.ts --target node",
+ "build:js": "bun build --outdir dist --root src --external typescript --external child_process --external module src/vite-plugin.ts src/tanstack.ts src/evaluation/eval_worker.ts src/cli/index.ts --target node",
"build:types": "tsc -p tsconfig.declarations.json",
"dev": "bun run src/cli/index.ts",
"test": "bun test",
@@ -76,29 +65,22 @@
"dependencies": {
"@modelcontextprotocol/sdk": "^1.17.4",
"body-parser": "^2.2.0",
- "connect": "^3.7.0",
"typescript": "^5",
"zod": "3.25.76"
},
"devDependencies": {
"@eslint/js": "^9.16.0",
- "@opentelemetry/api": "^1.9.0",
- "@opentelemetry/sdk-logs": "^0.206.0",
- "@opentelemetry/sdk-trace-base": "^2.1.0",
"@types/body-parser": "^1.19.6",
"@types/bun": "latest",
- "@types/connect": "^3.4.38",
"@types/node": "^22.10.1",
"@typescript-eslint/eslint-plugin": "^8.18.0",
"@typescript-eslint/parser": "^8.18.0",
- "@vercel/otel": "^2.0.1",
"@vitest/ui": "^3.2.4",
"bun-types": "latest",
"chalk": "^5.3.0",
"commander": "^12.1.0",
"eslint": "^9.16.0",
"globals": "^15.14.0",
- "next": "^15.5.3",
"prettier": "^3.4.2",
"vite": "^7.1.5",
"vitest": "^4.1.8"
diff --git a/src/cli/index.ts b/src/cli/index.ts
index b6dcd3c..815b1bc 100755
--- a/src/cli/index.ts
+++ b/src/cli/index.ts
@@ -10,7 +10,6 @@ import { isExtractError, isResolveError } from '../core';
import { name, version } from '../../package.json';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { serveMcp } from '../mcp';
-import { handleInstall } from './install';
function chdir(path: string): void {
try {
@@ -79,13 +78,6 @@ const {
source: { cli: sourceCli },
} = tools;
-program
- .command('install')
- .description('Install Tidewave in a Next.js project')
- .option('--prefix ', 'Specify the directory containing package.json')
- .option('--dry-run', 'Preview changes without creating files')
- .action(handleInstall);
-
program
.command('mcp')
.description('Starts a MCP server for tidewave (stdio)')
diff --git a/src/cli/install.ts b/src/cli/install.ts
deleted file mode 100644
index 4c27744..0000000
--- a/src/cli/install.ts
+++ /dev/null
@@ -1,408 +0,0 @@
-// src/cli/install.ts
-import * as fs from 'fs';
-import * as path from 'path';
-import * as child_process from 'child_process';
-import * as readline from 'readline';
-import chalk from 'chalk';
-
-interface InstallOptions {
- prefix?: string;
- dryRun?: boolean;
- skipDeps?: boolean;
-}
-
-interface NextJsVersion {
- major: number;
- minor: number;
- raw: string;
-}
-
-export async function handleInstall(options: InstallOptions): Promise {
- const targetDir = options.prefix || process.cwd();
- const dryRun = options.dryRun || false;
- const skipDeps = options.skipDeps || false;
-
- console.log(chalk.blue('\nš Tidewave Installer\n'));
- console.log(chalk.gray(`Target directory: ${targetDir}`));
-
- if (dryRun) {
- console.log(chalk.yellow('\nā ļø DRY RUN MODE - No files will be created\n'));
- }
-
- // Step 1: Detect Next.js version
- const nextVersion = await detectNextJsVersion(targetDir);
- if (!nextVersion) {
- console.error(chalk.red('\nā Could not find Next.js in node_modules.'));
- console.log(chalk.gray('\nThe installer only works for Next.js projects\n'));
- process.exit(1);
- }
-
- console.log(chalk.green(`ā
Detected Next.js ${nextVersion.raw} (v${nextVersion.major})`));
-
- // Step 2: Create files
- const steps: (() => Promise)[] = [
- (): Promise => createApiHandler(targetDir, dryRun),
- (): Promise => createMiddleware(targetDir, nextVersion, dryRun),
- (): Promise => createInstrumentation(targetDir, dryRun),
- ];
-
- for (const step of steps) {
- await step();
- }
-
- // Step 3: Install dependencies
- if (!skipDeps) {
- await installDependencies(targetDir, dryRun);
- }
-
- // Summary
- console.log(chalk.green('\nā
Tidewave setup complete!\n'));
- console.log(chalk.blue('Next steps:'));
- console.log(' 1. Start your Next.js dev server: npm run dev');
- console.log(' 2. Install the Tidewave app: https://hexdocs.pm/tidewave/');
- console.log(' 3. Connect to your app through Tidewave\n');
-}
-
-async function detectNextJsVersion(dir: string): Promise {
- try {
- // Get the actual installed version from node_modules
- const nextPackageJsonPath = path.join(dir, 'node_modules', 'next', 'package.json');
-
- if (!fs.existsSync(nextPackageJsonPath)) {
- return null;
- }
-
- const nextPackageJson = JSON.parse(fs.readFileSync(nextPackageJsonPath, 'utf-8'));
- const { version } = nextPackageJson;
- const match = version.match(/^(\d+)\.(\d+)\.(\d+)/);
-
- if (match) {
- return {
- major: parseInt(match[1]),
- minor: parseInt(match[2]),
- raw: version,
- };
- }
-
- return null;
- } catch {
- return null;
- }
-}
-
-function detectPackageManager(dir: string): string {
- // Check for lock files to determine package manager
- if (fs.existsSync(path.join(dir, 'bun.lockb'))) return 'bun';
- if (fs.existsSync(path.join(dir, 'pnpm-lock.yaml'))) return 'pnpm';
- if (fs.existsSync(path.join(dir, 'yarn.lock'))) return 'yarn';
- if (fs.existsSync(path.join(dir, 'package-lock.json'))) return 'npm';
- // Default to npm if no lock file found
- return 'npm';
-}
-
-async function promptUser(question: string): Promise {
- const rl = readline.createInterface({
- input: process.stdin,
- output: process.stdout,
- });
-
- return new Promise(resolve => {
- rl.question(question, answer => {
- rl.close();
- const normalized = answer.trim().toLowerCase();
- // Default to yes if empty, or explicit yes/y
- resolve(normalized === '' || normalized === 'y' || normalized === 'yes');
- });
- });
-}
-
-async function installDependencies(dir: string, dryRun: boolean): Promise {
- console.log(chalk.yellow('š¦ Installing dependencies...'));
-
- if (dryRun) {
- console.log(chalk.gray('[DRY RUN] Would install: tidewave, @opentelemetry/sdk-node'));
- return;
- }
-
- const pm = detectPackageManager(dir);
- const devDepCommands: Record = {
- npm: ['install', '-D', 'tidewave', '@opentelemetry/sdk-trace-base', '@opentelemetry/sdk-logs'],
- yarn: ['add', '-D', 'tidewave', '@opentelemetry/sdk-trace-base', '@opentelemetry/sdk-logs'],
- pnpm: [
- 'add',
- '--save-dev',
- 'tidewave',
- '@opentelemetry/sdk-trace-base',
- '@opentelemetry/sdk-logs',
- ],
- bun: ['add', '--dev', 'tidewave', '@opentelemetry/sdk-trace-base', '@opentelemetry/sdk-logs'],
- };
-
- const depCommands: Record = {
- npm: ['install', '@opentelemetry/sdk-node'],
- yarn: ['add', '@opentelemetry/sdk-node'],
- pnpm: ['add', '@opentelemetry/sdk-node'],
- bun: ['add', '@opentelemetry/sdk-node'],
- };
-
- const devCmds = devDepCommands[pm];
- const depCmds = depCommands[pm];
-
- if (!devCmds || !depCmds) {
- console.error(chalk.red(`\nā Unknown package manager: ${pm}`));
- process.exit(1);
- }
-
- try {
- // Install tidewave as dev dependency
- child_process.execSync(`${pm} ${devCmds.join(' ')}`, {
- cwd: dir,
- stdio: 'inherit',
- });
-
- // Install OpenTelemetry as regular dependency
- child_process.execSync(`${pm} ${depCmds.join(' ')}`, {
- cwd: dir,
- stdio: 'inherit',
- });
-
- console.log(chalk.green('ā
Dependencies installed'));
- } catch (_error) {
- console.error(chalk.red('\nā Failed to install dependencies'));
- console.log(
- chalk.gray(
- `\nPlease install manually:\n ${pm} ${devCmds.join(' ')}\n ${pm} ${depCmds.join(' ')}`,
- ),
- );
- }
-}
-
-async function createApiHandler(dir: string, dryRun: boolean): Promise {
- const apiDir = path.join(dir, 'pages', 'api');
- const handlerPath = path.join(apiDir, 'tidewave.ts');
-
- const handlerContent = `import type { NextApiRequest, NextApiResponse } from 'next';
-
-export default async function handler(
- req: NextApiRequest,
- res: NextApiResponse,
-) {
- if (process.env.NODE_ENV === 'development') {
- const { tidewaveHandler } = await import('tidewave/next-js/handler');
- const handler = await tidewaveHandler();
- return handler(req, res);
- } else {
- res.status(404).end();
- }
-}
-
-export const config = {
- runtime: 'nodejs',
- api: {
- bodyParser: false, // Tidewave already parses the body internally
- },
-};
-`;
-
- if (fs.existsSync(handlerPath)) {
- if (dryRun) {
- console.log(
- chalk.gray(`[DRY RUN] Would ask to overwrite: ${path.relative(dir, handlerPath)}`),
- );
- return;
- }
-
- const shouldOverwrite = await promptUser(
- chalk.yellow(`\nā ļø ${path.relative(dir, handlerPath)} already exists. Overwrite? (Y/n): `),
- );
-
- if (!shouldOverwrite) {
- console.log(chalk.gray(`āļø Skipping: ${path.relative(dir, handlerPath)}`));
- return;
- }
- }
-
- if (dryRun) {
- console.log(chalk.gray(`[DRY RUN] Would create: ${path.relative(dir, handlerPath)}`));
- return;
- }
-
- fs.mkdirSync(apiDir, { recursive: true });
- fs.writeFileSync(handlerPath, handlerContent, 'utf-8');
- console.log(chalk.green(`ā
Created: ${path.relative(dir, handlerPath)}`));
-}
-
-async function createMiddleware(
- dir: string,
- nextVersion: NextJsVersion,
- dryRun: boolean,
-): Promise {
- const isNext16Plus = nextVersion.major >= 16;
- const fileName = isNext16Plus ? 'proxy.ts' : 'middleware.ts';
- const filePath = path.join(dir, fileName);
-
- if (fs.existsSync(filePath)) {
- console.log(chalk.yellow(`āļø ${fileName} already exists`));
-
- // Check if Tidewave is already configured
- const content = fs.readFileSync(filePath, 'utf-8');
- if (content.includes('/tidewave') && content.includes('/api/tidewave')) {
- console.log(chalk.green(`ā
${fileName} already configured for Tidewave`));
- return;
- }
-
- console.log(chalk.gray(`\n Please manually add the following to your ${fileName}:\n`));
- printMiddlewareInstructions(isNext16Plus);
- return;
- }
-
- const middlewareContent = isNext16Plus
- ? `import { NextRequest, NextResponse } from 'next/server';
-
-export function proxy(req: NextRequest): NextResponse {
- if (req.nextUrl.pathname.startsWith('/tidewave')) {
- return NextResponse.rewrite(new URL('/api/tidewave', req.url));
- }
-
- // Here you could add your own logic or different middlewares.
- return NextResponse.next();
-}
-`
- : `import { NextRequest, NextResponse } from 'next/server';
-
-export function middleware(req: NextRequest): NextResponse {
- if (req.nextUrl.pathname.startsWith('/tidewave')) {
- return NextResponse.rewrite(new URL('/api/tidewave', req.url));
- }
-
- // Here you could add your own logic or different middlewares.
- return NextResponse.next();
-}
-
-export const config = {
- matcher: ['/tidewave/:path*'],
-};
-`;
-
- if (dryRun) {
- console.log(chalk.gray(`[DRY RUN] Would create: ${fileName}`));
- return;
- }
-
- fs.writeFileSync(filePath, middlewareContent, 'utf-8');
- console.log(chalk.green(`ā
Created: ${fileName}`));
-}
-
-function printMiddlewareInstructions(isNext16Plus: boolean): void {
- if (isNext16Plus) {
- console.log(
- chalk.cyan(` if (req.nextUrl.pathname.startsWith('/tidewave')) {
- return NextResponse.rewrite(new URL('/api/tidewave', req.url));
- }`),
- );
- } else {
- console.log(
- chalk.cyan(` if (req.nextUrl.pathname.startsWith('/tidewave')) {
- return NextResponse.rewrite(new URL('/api/tidewave', req.url));
- }
-
- // Also add to config.matcher:
- export const config = {
- matcher: ['/tidewave/:path*'],
- };`),
- );
- }
- console.log();
-}
-
-async function createInstrumentation(dir: string, dryRun: boolean): Promise {
- // Check both root and src directories
- const rootPath = path.join(dir, 'instrumentation.ts');
- const srcPath = path.join(dir, 'src', 'instrumentation.ts');
- const hasSrcDir = fs.existsSync(path.join(dir, 'src'));
-
- const instrumentationPath = hasSrcDir ? srcPath : rootPath;
-
- if (fs.existsSync(rootPath) || fs.existsSync(srcPath)) {
- const existingPath = fs.existsSync(rootPath) ? rootPath : srcPath;
- const existingFile = fs.existsSync(rootPath) ? 'instrumentation.ts' : 'src/instrumentation.ts';
-
- console.log(chalk.yellow(`āļø ${existingFile} already exists`));
-
- // Check if Tidewave is already configured
- const content = fs.readFileSync(existingPath, 'utf-8');
- if (
- content.includes('TidewaveSpanProcessor') &&
- content.includes('TidewaveLogRecordProcessor')
- ) {
- console.log(chalk.green(`ā
${existingFile} already configured for Tidewave`));
- return;
- }
-
- console.log(chalk.gray('\n Please manually add the following to your instrumentation.ts:\n'));
- printInstrumentationInstructions();
- return;
- }
-
- const instrumentationContent = `import type { SpanProcessor } from "@opentelemetry/sdk-trace-base";
-import type { LogRecordProcessor } from "@opentelemetry/sdk-logs";
-
-export async function register() {
- if (process.env.NEXT_RUNTIME === "nodejs") {
- const { NodeSDK } = await import("@opentelemetry/sdk-node");
-
- // Add your app own processes here existing configuration
- const sdkConfig: {
- spanProcessors: SpanProcessor[];
- logRecordProcessors: LogRecordProcessor[];
- } = {
- spanProcessors: [],
- logRecordProcessors: [],
- };
-
- // Conditionally add Tidewave processors in development
- if (process.env.NODE_ENV === "development") {
- const { TidewaveSpanProcessor, TidewaveLogRecordProcessor } = await import(
- "tidewave/next-js/instrumentation"
- );
-
- sdkConfig.spanProcessors.push(new TidewaveSpanProcessor());
- sdkConfig.logRecordProcessors.push(new TidewaveLogRecordProcessor());
- }
-
- const sdk = new NodeSDK(sdkConfig);
- sdk.start();
- }
-}
-`;
-
- if (dryRun) {
- console.log(chalk.gray(`[DRY RUN] Would create: ${path.relative(dir, instrumentationPath)}`));
- return;
- }
-
- if (hasSrcDir) {
- fs.mkdirSync(path.dirname(instrumentationPath), { recursive: true });
- }
-
- fs.writeFileSync(instrumentationPath, instrumentationContent, 'utf-8');
- console.log(chalk.green(`ā
Created: ${path.relative(dir, instrumentationPath)}`));
-}
-
-function printInstrumentationInstructions(): void {
- console.log(
- chalk.cyan(` // Inside your register() function:
- const runtime = process.env.NEXT_RUNTIME;
- const env = process.env.NODE_ENV;
-
- if (runtime === 'nodejs' && env === 'development') {
- const { TidewaveSpanProcessor, TidewaveLogRecordProcessor } = await import(
- 'tidewave/next-js/instrumentation'
- );
-
- sdkConfig.spanProcessors.push(new TidewaveSpanProcessor());
- sdkConfig.logRecordProcessors.push(new TidewaveLogRecordProcessor());
- }`),
- );
- console.log();
-}
diff --git a/src/http/handlers/config.ts b/src/http/handlers/config.ts
index 4b211a4..107df9a 100644
--- a/src/http/handlers/config.ts
+++ b/src/http/handlers/config.ts
@@ -1,21 +1,25 @@
-import { type Request, type Response, type NextFn, type Handler } from '../index';
import type { TidewaveConfig } from '../../core';
+import type { TidewaveHandler, TidewaveNext, TidewaveRequest, TidewaveResponse } from '../types';
import { default as tidewavePackage } from '../../../package.json' with { type: 'json' };
-export type LocalPortGetter = (req: Request) => number | undefined;
+export type LocalPortGetter = () => number | undefined;
export function createHandleConfig(
config: TidewaveConfig,
getLocalPort?: LocalPortGetter,
-): Handler {
- return async function handleConfig(req: Request, res: Response, next: NextFn): Promise {
+): TidewaveHandler {
+ return async function handleConfig(
+ _req: TidewaveRequest,
+ res: TidewaveResponse,
+ next: TidewaveNext,
+ ): Promise {
try {
const tidewaveConfig = {
project_name: config.projectName || 'app',
framework_type: config.framework || 'unknown',
tidewave_version: tidewavePackage.version,
team: config.team || {},
- local_port: getLocalPort?.(req),
+ local_port: getLocalPort?.(),
};
res.statusCode = 200;
diff --git a/src/http/handlers/html.ts b/src/http/handlers/html.ts
index 3092811..a7c6c6e 100644
--- a/src/http/handlers/html.ts
+++ b/src/http/handlers/html.ts
@@ -1,12 +1,17 @@
-import type { Request, Response, NextFn, Handler } from '../index';
import type { TidewaveConfig } from '../../core';
-export function createHandleHtml(config: TidewaveConfig): Handler {
- return async function handleHtml(req: Request, res: Response, next: NextFn): Promise {
+import type { TidewaveHandler, TidewaveNext, TidewaveRequest, TidewaveResponse } from '../types';
+
+export function createHandleHtml(config: TidewaveConfig): TidewaveHandler {
+ return async function handleHtml(
+ req: TidewaveRequest,
+ res: TidewaveResponse,
+ next: TidewaveNext,
+ ): Promise {
// Only handle exact /tidewave path, not sub-paths
const url = req.url || '/';
const [pathname] = url.split('?');
- // vite middleware strips the url, but next.js does not, so we check all three
+ // Different connect-style middleware stacks may strip different URL prefixes.
if (pathname !== '' && pathname !== '/' && pathname !== '/tidewave') {
return next();
}
diff --git a/src/http/handlers/mcp.ts b/src/http/handlers/mcp.ts
index 5eff29a..03b3577 100644
--- a/src/http/handlers/mcp.ts
+++ b/src/http/handlers/mcp.ts
@@ -1,8 +1,12 @@
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
-import { methodNotAllowed, originNotAllowed, type Request, type Response, type NextFn } from '..';
import { serveMcp } from '../../mcp';
+import type { TidewaveNext, TidewaveRequest, TidewaveResponse } from '../types';
-export async function handleMcp(req: Request, res: Response, next: NextFn): Promise {
+export async function handleMcp(
+ req: TidewaveRequest,
+ res: TidewaveResponse,
+ next: TidewaveNext,
+): Promise {
try {
if (req.headers.origin) {
originNotAllowed(res);
@@ -38,7 +42,7 @@ export async function handleMcp(req: Request, res: Response, next: NextFn): Prom
}
}
-function mcpErrorResponse(res: Response, err: Error | unknown): void {
+function mcpErrorResponse(res: TidewaveResponse, err: Error | unknown): void {
res.statusCode = 500;
res.setHeader('content-type', 'application/json');
res.end(
@@ -53,3 +57,17 @@ function mcpErrorResponse(res: Response, err: Error | unknown): void {
}),
);
}
+
+function methodNotAllowed(res: TidewaveResponse): void {
+ res.statusCode = 405;
+ res.setHeader('Allow', 'POST');
+ res.end();
+}
+
+function originNotAllowed(res: TidewaveResponse): void {
+ const message =
+ 'For security reasons, Tidewave does not accept requests with an origin header for this endpoint.';
+ console.warn(message);
+ res.statusCode = 403;
+ res.end(message);
+}
diff --git a/src/http/index.ts b/src/http/index.ts
index 5b0f3b9..a83af1a 100644
--- a/src/http/index.ts
+++ b/src/http/index.ts
@@ -1,79 +1,44 @@
-import type { ServerResponse } from 'http';
-import type { IncomingMessage, NextFunction, Server } from 'connect';
-import connect from 'connect';
import { checkRemoteIp } from './security';
import { handleMcp } from './handlers/mcp';
import { createHandleHtml } from './handlers/html';
import { createHandleConfig, type LocalPortGetter } from './handlers/config';
import bodyParser from 'body-parser';
import type { TidewaveConfig } from '../core';
-
-export interface Request extends IncomingMessage {
- body?: Record;
-}
-export type Response = ServerResponse;
-export type NextFn = NextFunction;
+import type {
+ TidewaveMiddlewareServer,
+ TidewaveNext,
+ TidewaveRequest,
+ TidewaveResponse,
+} from './types';
export const ENDPOINT = '/tidewave' as const;
const DEFAULT_OPTIONS: TidewaveConfig = {
allowRemoteAccess: false,
} as const;
-export type Handler = (req: Request, res: Response, next: NextFn) => Promise;
-
export interface HandlerOptions {
getLocalPort?: LocalPortGetter;
}
-function getHandlers(
- config: TidewaveConfig,
- options: HandlerOptions = {},
-): Record {
- return {
- '': createHandleHtml(config),
- config: createHandleConfig(config, options.getLocalPort),
- mcp: handleMcp,
- };
-}
-
export function configureServer(
- server: Server = connect(),
+ server: TidewaveMiddlewareServer,
config: TidewaveConfig = DEFAULT_OPTIONS,
options: HandlerOptions = {},
-): Server {
+): TidewaveMiddlewareServer {
const securityChecker = checkSecurity(config);
server.use(`${ENDPOINT}`, securityChecker);
- server.use(`${ENDPOINT}`, bodyParser.json());
-
- const handlers = getHandlers(config, options);
- for (const [path, handler] of Object.entries(handlers)) {
- server.use(ENDPOINT + '/' + path, handler);
- }
+ server.use(`${ENDPOINT}/`, createHandleHtml(config));
+ server.use(`${ENDPOINT}/config`, createHandleConfig(config, options.getLocalPort));
+ server.use(`${ENDPOINT}/mcp`, bodyParser.json());
+ server.use(`${ENDPOINT}/mcp`, handleMcp);
return server;
}
-export function checkSecurity(config: TidewaveConfig) {
- return (req: Request, res: Response, next: NextFn): void => {
+function checkSecurity(config: TidewaveConfig) {
+ return (req: TidewaveRequest, res: TidewaveResponse, next: TidewaveNext): void => {
if (!checkRemoteIp(req, res, config)) return;
next();
};
}
-
-export function methodNotAllowed(res: Response): void {
- res.statusCode = 405;
- res.setHeader('Allow', 'POST');
- res.end();
-}
-
-export function originNotAllowed(res: Response): void {
- const message =
- 'For security reasons, Tidewave does not accept requests with an origin header for this endpoint.';
- console.warn(message);
- res.statusCode = 403;
- res.end(message);
-}
-
-// Export for use by framework integrations
-export { getHandlers };
diff --git a/src/http/security.ts b/src/http/security.ts
index 168448f..86006a5 100644
--- a/src/http/security.ts
+++ b/src/http/security.ts
@@ -1,21 +1,30 @@
import type { TidewaveConfig } from '../core';
-import type { Request, Response } from './index';
+import type { TidewaveRequest, TidewaveResponse } from './types';
-function fetchRemoteIp(req: Request): string | null {
+function fetchRemoteIp(req: TidewaveRequest): string | null {
const remote = req.socket.remoteAddress;
if (remote) return remote;
- const ip = (req.headers['x-real-ip'] && req.headers['x-forwarded-for']) || null;
+ const realIp = firstHeaderValue(req.headers['x-real-ip']);
+ if (realIp) return realIp;
- if (Array.isArray(ip)) {
- return ip.join();
- }
+ const forwardedFor = firstHeaderValue(req.headers['x-forwarded-for']);
+ if (forwardedFor) return forwardedFor.split(',')[0]?.trim() || null;
- return ip;
+ return null;
}
-export function checkRemoteIp(req: Request, res: Response, config: TidewaveConfig): boolean {
+function firstHeaderValue(value: string | string[] | undefined): string | null {
+ if (Array.isArray(value)) return value[0] || null;
+ return value || null;
+}
+
+export function checkRemoteIp(
+ req: TidewaveRequest,
+ res: TidewaveResponse,
+ config: TidewaveConfig,
+): boolean {
const ip = fetchRemoteIp(req);
if (!ip) return false;
diff --git a/src/http/types.ts b/src/http/types.ts
new file mode 100644
index 0000000..e7ed8a8
--- /dev/null
+++ b/src/http/types.ts
@@ -0,0 +1,17 @@
+import type { IncomingMessage, ServerResponse } from 'node:http';
+
+export interface TidewaveRequest extends IncomingMessage {
+ body?: Record;
+}
+
+export type TidewaveResponse = ServerResponse;
+export type TidewaveNext = (err?: unknown) => void;
+export type TidewaveHandler = (
+ req: TidewaveRequest,
+ res: TidewaveResponse,
+ next: TidewaveNext,
+) => Promise;
+
+export interface TidewaveMiddlewareServer {
+ use(route: string, handler: unknown): void;
+}
diff --git a/src/logger/tidewave-log-record-processor.ts b/src/logger/tidewave-log-record-processor.ts
deleted file mode 100644
index fa21426..0000000
--- a/src/logger/tidewave-log-record-processor.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import type { LogRecordProcessor, SdkLogRecord } from '@opentelemetry/sdk-logs';
-import type { Context } from '@opentelemetry/api';
-import { tidewaveLogger } from './tidewave-logger';
-
-/**
- * Custom LogRecordProcessor that captures OpenTelemetry logger logs
- * and writes them directly to the tidewave logger.
- *
- * This is opt-in for users who want to capture actual logger logs
- * (not console.log, which is handled separately by console patching).
- */
-export class TidewaveLogRecordProcessor implements LogRecordProcessor {
- /**
- * Called when a log record is emitted.
- */
- onEmit(logRecord: SdkLogRecord, _context?: Context): void {
- try {
- const body = String(logRecord.body || '');
-
- tidewaveLogger.addLog({
- timestamp: new Date(
- logRecord.hrTime[0] * 1000 + logRecord.hrTime[1] / 1_000_000,
- ).toISOString(),
- severityText: logRecord.severityText || 'INFO',
- body,
- attributes: logRecord.attributes,
- });
- } catch (_error) {
- // Silently fail to avoid breaking logging
- }
- }
-
- async forceFlush(): Promise {
- // No-op: we process log records synchronously
- }
-
- async shutdown(): Promise {
- // No-op: no resources to clean up
- }
-}
diff --git a/src/logger/tidewave-span-processor.ts b/src/logger/tidewave-span-processor.ts
deleted file mode 100644
index d620e94..0000000
--- a/src/logger/tidewave-span-processor.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-import type { SpanProcessor } from '@opentelemetry/sdk-trace-base';
-import type { ReadableSpan } from '@opentelemetry/sdk-trace-base';
-import type { Span, Context } from '@opentelemetry/api';
-import { tidewaveLogger } from './tidewave-logger';
-
-/**
- * Custom SpanProcessor that converts OpenTelemetry spans to logs and writes them
- * directly to the tidewave logger.
- * This is used to capture Next.js HTTP request/response spans and
- * make them available via the get_logs tool.
- */
-export class TidewaveSpanProcessor implements SpanProcessor {
- /**
- * Called when a span is started. We don't need to do anything here.
- */
- onStart(_span: Span, _parentContext: Context): void {
- // No-op: we only care about completed spans
- }
-
- /**
- * Called when a span ends. This is where we convert the span to a log entry
- * and write it directly to the tidewave logger.
- */
- onEnd(span: ReadableSpan): void {
- try {
- const spanType = span.attributes['next.span_type'];
- const httpMethod = span.attributes['http.method'];
-
- // Only log certain span types to avoid noise
- const relevantSpanTypes = [
- 'BaseServer.handleRequest',
- 'AppRender.getBodyResult',
- 'AppRouteRouteHandlers.runHandler',
- ];
-
- if (!spanType || !relevantSpanTypes.includes(spanType as string)) {
- return;
- }
-
- // Extract relevant information
- const route = span.attributes['next.route'] || span.attributes['http.route'];
- const httpUrl = span.attributes['http.url'];
- const httpTarget = span.attributes['http.target'];
- const httpStatusCode = span.attributes['http.status_code'];
-
- // Filter out /tidewave paths
- const path = route || httpTarget || httpUrl || 'unknown';
- if (typeof path === 'string' && path.startsWith('/tidewave')) {
- return;
- }
-
- const durationMs = this.calculateDuration(span);
-
- let message = '';
- let severity = 'INFO';
-
- if (spanType === 'BaseServer.handleRequest') {
- const method = httpMethod || 'UNKNOWN';
- const status = httpStatusCode || 'unknown';
- message = `${method} ${path} ${status} ${durationMs.toFixed(2)}ms`;
-
- if (typeof httpStatusCode === 'number') {
- if (httpStatusCode >= 500) severity = 'ERROR';
- else if (httpStatusCode >= 400) severity = 'WARN';
- }
- } else if (spanType === 'AppRender.getBodyResult') {
- message = `Rendered route: ${route || 'unknown'} (${durationMs.toFixed(2)}ms)`;
- } else if (spanType === 'AppRouteRouteHandlers.runHandler') {
- message = `API route: ${route || 'unknown'} (${durationMs.toFixed(2)}ms)`;
- }
-
- // Write directly to tidewave logger
- tidewaveLogger.addLog({
- timestamp: new Date(span.endTime[0] * 1000 + span.endTime[1] / 1_000_000).toISOString(),
- severityText: severity,
- body: message,
- attributes: {
- 'log.origin': 'opentelemetry-span',
- 'span.name': span.name,
- 'span.kind': span.kind,
- 'span.type': spanType,
- 'http.method': httpMethod,
- 'http.route': route,
- 'http.status_code': httpStatusCode,
- 'duration.ms': durationMs,
- },
- });
- } catch (_error) {
- // Silently fail to avoid breaking tracing
- }
- }
-
- /**
- * Calculate span duration in milliseconds from high-resolution time
- */
- private calculateDuration(span: ReadableSpan): number {
- const startTimeMs = span.startTime[0] * 1000 + span.startTime[1] / 1_000_000;
- const endTimeMs = span.endTime[0] * 1000 + span.endTime[1] / 1_000_000;
- return endTimeMs - startTimeMs;
- }
-
- async forceFlush(): Promise {
- // No-op: we process spans synchronously
- }
-
- async shutdown(): Promise {
- // No-op: no resources to clean up
- }
-}
diff --git a/src/next-js/handler.ts b/src/next-js/handler.ts
deleted file mode 100644
index d283c7c..0000000
--- a/src/next-js/handler.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-import type { NextApiRequest, NextApiResponse } from 'next';
-import { checkSecurity, type Request, type Response } from '../http';
-import bodyParser from 'body-parser';
-import type { TidewaveConfig } from '../core';
-import { getProjectName } from '../core';
-import type { AddressInfo } from 'node:net';
-
-const DEFAULT_CONFIG: TidewaveConfig = {};
-
-type NextJsHandler = (_req: NextApiRequest, _res: NextApiResponse) => Promise;
-
-type NextHandler = () => ValueOrPromise;
-
-/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
-export type FunctionLike = (...args: any[]) => unknown;
-
-export type Nextable = (
- ...args: [...Parameters, NextHandler]
-) => ValueOrPromise; /* eslint-disable-line @typescript-eslint/no-explicit-any */
-
-export type ValueOrPromise = T | Promise;
-
-type NextFunction = (err?: unknown) => void;
-
-type ExpressRequestHandler = (req: Req, res: Res, next: NextFunction) => void;
-
-export type RequestHandler = (
- req: Req,
- res: Res,
-) => ValueOrPromise;
-
-function connectWrapper(
- fn: ExpressRequestHandler,
-): Nextable> {
- return (req, res, next) =>
- new Promise((resolve, reject) => {
- fn(req, res, err => (err ? reject(err) : resolve()));
- }).then(next);
-}
-
-function isAddressInfo(address: ReturnType): address is AddressInfo {
- return typeof address === 'object' && address !== null && 'port' in address;
-}
-
-export function getRequestLocalPort(request: Request): number | undefined {
- const address = request.socket.address();
-
- if (isAddressInfo(address)) return address.port;
-
- return request.socket.localPort;
-}
-
-export async function tidewaveHandler(
- config: TidewaveConfig = DEFAULT_CONFIG,
-): Promise {
- const env = process.env['NODE_ENV'];
-
- if (!(env === 'development')) {
- throw Error(
- `[Tidewave] tidewave is designed to only work on development environment, got: ${env}`,
- );
- }
-
- if (process.env['NEXT_RUNTIME'] !== 'edge') {
- // Import instrumentation to automatically patch console
- const { patchConsole } = await import('../logger/console-patch');
- patchConsole();
- }
-
- // Set framework and projectName upfront
- config.framework = 'nextjs';
- config.projectName = config.projectName || (await getProjectName('next_app'));
-
- return async function handler(req: NextApiRequest, res: NextApiResponse): Promise {
- const origin = req.headers.host;
- const url = new URL(req.url ?? '', `http://${origin}`);
- const segments = url.pathname.split('/').filter(Boolean);
- const [_tidewave, endpoint] = segments;
-
- if (!url.pathname.startsWith('/tidewave')) {
- return res.status(404).json({ message: 'This route only works when accessed at /tidewave' });
- }
-
- const next: () => void = () => {};
- const securityMiddleware = checkSecurity(config);
- await connectWrapper(securityMiddleware)(req, res, next);
- await connectWrapper(bodyParser.json())(req, res, next);
-
- const { getHandlers } = await import('../http');
- const handlers = getHandlers(config, {
- getLocalPort: getRequestLocalPort,
- });
-
- const handler = handlers[endpoint || ''];
- if (handler) return await connectWrapper(handler)(req, res, next);
-
- return res.status(404).json({ message: `Route not found: ${req.method} ${req.url}` });
- };
-}
diff --git a/src/next-js/instrumentation.ts b/src/next-js/instrumentation.ts
deleted file mode 100644
index 9e0af0f..0000000
--- a/src/next-js/instrumentation.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { patchConsole } from '../logger/console-patch';
-
-export { TidewaveSpanProcessor } from '../logger/tidewave-span-processor';
-export { TidewaveLogRecordProcessor } from '../logger/tidewave-log-record-processor';
-
-patchConsole();
diff --git a/test/fixtures/next15/node_modules/next/package.json b/test/fixtures/next15/node_modules/next/package.json
deleted file mode 100644
index 25824f9..0000000
--- a/test/fixtures/next15/node_modules/next/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "next",
- "version": "15.5.3"
-}
diff --git a/test/fixtures/next15/package.json b/test/fixtures/next15/package.json
deleted file mode 100644
index eb800fe..0000000
--- a/test/fixtures/next15/package.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "name": "test-next15",
- "version": "1.0.0",
- "dependencies": {
- "next": "^15.0.0"
- }
-}
diff --git a/test/fixtures/next16/node_modules/next/package.json b/test/fixtures/next16/node_modules/next/package.json
deleted file mode 100644
index 1315665..0000000
--- a/test/fixtures/next16/node_modules/next/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "next",
- "version": "16.0.0"
-}
diff --git a/test/fixtures/next16/package.json b/test/fixtures/next16/package.json
deleted file mode 100644
index 5c267d3..0000000
--- a/test/fixtures/next16/package.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "name": "test-next16",
- "version": "1.0.0",
- "dependencies": {
- "next": "^16.0.0"
- }
-}
diff --git a/test/http/index.test.ts b/test/http/index.test.ts
index 6aad560..64e3f56 100644
--- a/test/http/index.test.ts
+++ b/test/http/index.test.ts
@@ -1,11 +1,10 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
-import { methodNotAllowed } from '../../src/http';
-import type { Request, Response } from '../../src/http';
+import type { TidewaveRequest, TidewaveResponse } from '../../src/http/types';
import { handleMcp } from '../../src/http/handlers/mcp';
import { createHandleConfig } from '../../src/http/handlers/config';
// Mock request/response helpers
-const createMockRequest = (headers: Record = {}): Partial => ({
+const createMockRequest = (headers: Record = {}): Partial => ({
socket: { remoteAddress: '127.0.0.1' } as any,
headers,
});
@@ -21,7 +20,7 @@ const createMockResponse = () => {
setHeader: mockSetHeader,
headersSent: false,
destroyed: false,
- } as Partial,
+ } as Partial,
mockEnd,
mockSetHeader,
};
@@ -34,37 +33,29 @@ describe('HTTP Utilities', () => {
console.error = vi.fn();
});
- describe('methodNotAllowed', () => {
- it('should set correct status code and headers', () => {
- const { res, mockEnd, mockSetHeader } = createMockResponse();
-
- methodNotAllowed(res as Response);
-
- expect(res.statusCode).toBe(405);
- expect(mockSetHeader).toHaveBeenCalledWith('Allow', 'POST');
- expect(mockEnd).toHaveBeenCalled();
- });
-
- it('should return undefined', () => {
- const { res } = createMockResponse();
-
- const result = methodNotAllowed(res as Response);
-
- expect(result).toBeUndefined();
- });
- });
-
describe('handleMcp', () => {
it('should return 403 if origin header is set', async () => {
const req = createMockRequest({ origin: 'http://localhost:4000' });
const { res, mockEnd } = createMockResponse();
const next = vi.fn();
- await handleMcp(req as Request, res as Response, next);
+ await handleMcp(req as TidewaveRequest, res as TidewaveResponse, next);
expect(res.statusCode).toBe(403);
expect(mockEnd).toHaveBeenCalledWith(expect.stringContaining('origin'));
});
+
+ it('should return 405 for non-POST requests', async () => {
+ const req = { ...createMockRequest(), method: 'GET' };
+ const { res, mockEnd, mockSetHeader } = createMockResponse();
+ const next = vi.fn();
+
+ await handleMcp(req as TidewaveRequest, res as TidewaveResponse, next);
+
+ expect(res.statusCode).toBe(405);
+ expect(mockSetHeader).toHaveBeenCalledWith('Allow', 'POST');
+ expect(mockEnd).toHaveBeenCalled();
+ });
});
describe('handleConfig', () => {
@@ -80,7 +71,7 @@ describe('HTTP Utilities', () => {
},
() => 5173,
);
- await handler(req as Request, res as Response, next);
+ await handler(req as TidewaveRequest, res as TidewaveResponse, next);
expect(res.statusCode).toBe(200);
expect(mockSetHeader).toHaveBeenCalledWith('Content-Type', 'application/json');
diff --git a/test/http/security.test.ts b/test/http/security.test.ts
index 9f74010..2796086 100644
--- a/test/http/security.test.ts
+++ b/test/http/security.test.ts
@@ -1,10 +1,10 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { checkRemoteIp, isLocalIp } from '../../src/http/security';
-import type { Request, Response } from '../../src/http';
+import type { TidewaveRequest, TidewaveResponse } from '../../src/http/types';
import type { TidewaveConfig } from '../../src/core';
// Mock request/response helpers
-const createMockRequest = (remoteAddress = '127.0.0.1'): Partial => ({
+const createMockRequest = (remoteAddress = '127.0.0.1'): Partial => ({
socket: { remoteAddress } as any,
headers: {},
});
@@ -20,7 +20,7 @@ const createMockResponse = () => {
setHeader: mockSetHeader,
headersSent: false,
destroyed: false,
- } as Partial,
+ } as Partial,
mockEnd,
mockSetHeader,
};
@@ -70,7 +70,7 @@ describe('HTTP Security', () => {
const { res } = createMockResponse();
const config: TidewaveConfig = {};
- const result = checkRemoteIp(req as Request, res as Response, config);
+ const result = checkRemoteIp(req as TidewaveRequest, res as TidewaveResponse, config);
expect(result).toBe(true);
expect(res.statusCode).toBe(200);
@@ -81,7 +81,7 @@ describe('HTTP Security', () => {
const { res, mockEnd } = createMockResponse();
const config: TidewaveConfig = {};
- const result = checkRemoteIp(req as Request, res as Response, config);
+ const result = checkRemoteIp(req as TidewaveRequest, res as TidewaveResponse, config);
expect(result).toBe(false);
expect(res.statusCode).toBe(403);
@@ -93,7 +93,7 @@ describe('HTTP Security', () => {
const { res } = createMockResponse();
const config: TidewaveConfig = { allowRemoteAccess: true };
- const result = checkRemoteIp(req as Request, res as Response, config);
+ const result = checkRemoteIp(req as TidewaveRequest, res as TidewaveResponse, config);
expect(result).toBe(true);
expect(res.statusCode).toBe(200);
diff --git a/test/install.test.ts b/test/install.test.ts
deleted file mode 100644
index 1c95200..0000000
--- a/test/install.test.ts
+++ /dev/null
@@ -1,225 +0,0 @@
-import { describe, test, expect, beforeEach, afterEach } from 'vitest';
-import * as fs from 'fs';
-import * as path from 'path';
-import { handleInstall } from '../src/cli/install';
-
-const TEST_FIXTURES = path.join(__dirname, 'fixtures');
-const NEXT15_FIXTURE = path.join(TEST_FIXTURES, 'next15');
-const NEXT16_FIXTURE = path.join(TEST_FIXTURES, 'next16');
-
-// Helper to clean up created files
-function cleanupFiles(dir: string) {
- const filesToRemove = [
- path.join(dir, 'pages/api/tidewave.ts'),
- path.join(dir, 'middleware.ts'),
- path.join(dir, 'proxy.ts'),
- path.join(dir, 'instrumentation.ts'),
- path.join(dir, 'src/instrumentation.ts'),
- ];
-
- for (const file of filesToRemove) {
- if (fs.existsSync(file)) {
- fs.unlinkSync(file);
- }
- }
-
- // Clean up directories if empty
- const dirsToRemove = [
- path.join(dir, 'pages/api'),
- path.join(dir, 'pages'),
- path.join(dir, 'src'),
- ];
-
- for (const dirPath of dirsToRemove) {
- if (fs.existsSync(dirPath)) {
- try {
- fs.rmdirSync(dirPath);
- } catch {
- // Directory not empty, skip
- }
- }
- }
-}
-
-describe('install command', () => {
- describe('Next.js 15', () => {
- beforeEach(() => {
- cleanupFiles(NEXT15_FIXTURE);
- });
-
- afterEach(() => {
- cleanupFiles(NEXT15_FIXTURE);
- });
-
- test('should create middleware.ts for Next.js 15', async () => {
- await handleInstall({
- prefix: NEXT15_FIXTURE,
- skipDeps: true,
- });
-
- const middlewarePath = path.join(NEXT15_FIXTURE, 'middleware.ts');
- expect(fs.existsSync(middlewarePath)).toBe(true);
-
- const content = fs.readFileSync(middlewarePath, 'utf-8');
- expect(content).toContain('export function middleware');
- expect(content).toContain('/tidewave');
- expect(content).toContain('/api/tidewave');
- expect(content).toContain("matcher: ['/tidewave/:path*']");
- });
-
- test('should create pages/api/tidewave.ts', async () => {
- await handleInstall({
- prefix: NEXT15_FIXTURE,
- skipDeps: true,
- });
-
- const handlerPath = path.join(NEXT15_FIXTURE, 'pages/api/tidewave.ts');
- expect(fs.existsSync(handlerPath)).toBe(true);
-
- const content = fs.readFileSync(handlerPath, 'utf-8');
- expect(content).toContain('tidewaveHandler');
- expect(content).toContain('NextApiRequest');
- expect(content).toContain('NextApiResponse');
- expect(content).toContain('bodyParser: false');
- });
-
- test('should create instrumentation.ts', async () => {
- await handleInstall({
- prefix: NEXT15_FIXTURE,
- skipDeps: true,
- });
-
- const instrumentationPath = path.join(NEXT15_FIXTURE, 'instrumentation.ts');
- expect(fs.existsSync(instrumentationPath)).toBe(true);
-
- const content = fs.readFileSync(instrumentationPath, 'utf-8');
- expect(content).toContain('export async function register');
- expect(content).toContain('TidewaveSpanProcessor');
- expect(content).toContain('TidewaveLogRecordProcessor');
- expect(content).toContain('NodeSDK');
- });
- });
-
- describe('Next.js 16', () => {
- beforeEach(() => {
- cleanupFiles(NEXT16_FIXTURE);
- });
-
- afterEach(() => {
- cleanupFiles(NEXT16_FIXTURE);
- });
-
- test('should create proxy.ts for Next.js 16', async () => {
- await handleInstall({
- prefix: NEXT16_FIXTURE,
- skipDeps: true,
- });
-
- const proxyPath = path.join(NEXT16_FIXTURE, 'proxy.ts');
- expect(fs.existsSync(proxyPath)).toBe(true);
-
- const content = fs.readFileSync(proxyPath, 'utf-8');
- expect(content).toContain('export function proxy');
- expect(content).toContain('/tidewave');
- expect(content).toContain('/api/tidewave');
- // Next.js 16 proxy should NOT have matcher config
- expect(content).not.toContain('matcher');
- });
-
- test('should create pages/api/tidewave.ts', async () => {
- await handleInstall({
- prefix: NEXT16_FIXTURE,
- skipDeps: true,
- });
-
- const handlerPath = path.join(NEXT16_FIXTURE, 'pages/api/tidewave.ts');
- expect(fs.existsSync(handlerPath)).toBe(true);
-
- const content = fs.readFileSync(handlerPath, 'utf-8');
- expect(content).toContain('tidewaveHandler');
- });
-
- test('should create instrumentation.ts', async () => {
- await handleInstall({
- prefix: NEXT16_FIXTURE,
- skipDeps: true,
- });
-
- const instrumentationPath = path.join(NEXT16_FIXTURE, 'instrumentation.ts');
- expect(fs.existsSync(instrumentationPath)).toBe(true);
-
- const content = fs.readFileSync(instrumentationPath, 'utf-8');
- expect(content).toContain('export async function register');
- expect(content).toContain('TidewaveSpanProcessor');
- expect(content).toContain('TidewaveLogRecordProcessor');
- });
- });
-
- describe('Existing files', () => {
- beforeEach(() => {
- cleanupFiles(NEXT16_FIXTURE);
- });
-
- afterEach(() => {
- cleanupFiles(NEXT16_FIXTURE);
- });
-
- test('should skip existing middleware files if already configured', async () => {
- // Create a proxy.ts that's already configured
- const proxyPath = path.join(NEXT16_FIXTURE, 'proxy.ts');
- fs.writeFileSync(
- proxyPath,
- `import { NextRequest, NextResponse } from 'next/server';
-
-export function proxy(req: NextRequest): NextResponse {
- if (req.nextUrl.pathname.startsWith('/tidewave')) {
- return NextResponse.rewrite(new URL('/api/tidewave', req.url));
- }
- return NextResponse.next();
-}
-`,
- 'utf-8',
- );
-
- await handleInstall({
- prefix: NEXT16_FIXTURE,
- skipDeps: true,
- });
-
- // File should still exist and be unchanged
- const content = fs.readFileSync(proxyPath, 'utf-8');
- expect(content).toContain('export function proxy');
- expect(content).toContain('/tidewave');
- });
-
- test('should skip existing instrumentation files if already configured', async () => {
- // Create an instrumentation.ts that's already configured
- const instrumentationPath = path.join(NEXT16_FIXTURE, 'instrumentation.ts');
- fs.writeFileSync(
- instrumentationPath,
- `import { NodeSDK } from '@opentelemetry/sdk-node';
-import { TidewaveSpanProcessor, TidewaveLogRecordProcessor } from 'tidewave/next-js/instrumentation';
-
-export async function register() {
- const sdk = new NodeSDK({
- spanProcessors: [new TidewaveSpanProcessor()],
- logRecordProcessors: [new TidewaveLogRecordProcessor()],
- });
- sdk.start();
-}
-`,
- 'utf-8',
- );
-
- await handleInstall({
- prefix: NEXT16_FIXTURE,
- skipDeps: true,
- });
-
- // File should still exist and be unchanged
- const content = fs.readFileSync(instrumentationPath, 'utf-8');
- expect(content).toContain('TidewaveSpanProcessor');
- expect(content).toContain('TidewaveLogRecordProcessor');
- });
- });
-});
diff --git a/test/next-js-handler.test.ts b/test/next-js-handler.test.ts
deleted file mode 100644
index fe78745..0000000
--- a/test/next-js-handler.test.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { describe, expect, it } from 'vitest';
-import { getRequestLocalPort } from '../src/next-js/handler';
-import type { Request } from '../src/http';
-
-describe('Tidewave Next.js Handler', () => {
- it('should use the request socket port in config responses', () => {
- const req = {
- headers: {
- host: 'localhost:3000',
- origin: 'http://localhost:9999',
- },
- socket: {
- remoteAddress: '127.0.0.1',
- localPort: 1234,
- address: () => ({ address: '127.0.0.1', family: 'IPv4', port: 4321 }),
- },
- };
-
- expect(getRequestLocalPort(req as unknown as Request)).toBe(4321);
- });
-});
diff --git a/test/vite-plugin.test.ts b/test/vite-plugin.test.ts
index b431792..d2753bc 100644
--- a/test/vite-plugin.test.ts
+++ b/test/vite-plugin.test.ts
@@ -72,7 +72,7 @@ describe('Tidewave Vite Plugin', () => {
const middlewareUse = (mockServer as any)._middlewareUse;
- // Should register 5 middleware: security + decode body + html + config + mcp routes
+ // Should register 5 middleware: security + html + config + MCP body parser + MCP routes
expect(middlewareUse).toHaveBeenCalledTimes(5);
// Global security middleware
@@ -109,7 +109,7 @@ describe('Tidewave Vite Plugin', () => {
await (plugin.configureServer as any)(mockServer);
- const configHandler = (mockServer as any)._middlewareUse.mock.calls[3][1];
+ const configHandler = (mockServer as any)._middlewareUse.mock.calls[2][1];
const req = {
socket: { remoteAddress: '127.0.0.1' },
headers: {
@@ -208,16 +208,16 @@ describe('Tidewave Vite Plugin', () => {
expect(calls[0][0]).toBe('/tidewave');
expect(typeof calls[0][1]).toBe('function');
- // Second call should be decode body middleware
- expect(calls[1][0]).toBe('/tidewave');
+ // Second call should be HTML endpoint (empty string = '/')
+ expect(calls[1][0]).toBe('/tidewave/');
expect(typeof calls[1][1]).toBe('function');
- // Third call should be HTML endpoint (empty string = '/')
- expect(calls[2][0]).toBe('/tidewave/');
+ // Third call should be config endpoint
+ expect(calls[2][0]).toBe('/tidewave/config');
expect(typeof calls[2][1]).toBe('function');
- // Fourth call should be config endpoint
- expect(calls[3][0]).toBe('/tidewave/config');
+ // Fourth call should parse JSON only for the MCP endpoint
+ expect(calls[3][0]).toBe('/tidewave/mcp');
expect(typeof calls[3][1]).toBe('function');
// Fifth call should be MCP endpoint