Adds Fastify Middleware for v2 (#1536)

Co-authored-by: Felix Weinberger <fweinberger@anthropic.com>
Co-authored-by: Konstantin Konstantinov <KKonstantinov@users.noreply.github.com>
Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com>
This commit is contained in:
Andy Fleming 2026-03-31 06:51:14 -07:00 • committed by GitHub
commit 81e4b2a412
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 937 additions and 1 deletions

View file

@ -0,0 +1,5 @@
---
'@modelcontextprotocol/fastify': minor
---
Add Fastify middleware adapter for MCP servers, following the same pattern as the Express and Hono adapters.

View file

@ -40,4 +40,4 @@ jobs:
- name: Publish preview packages
run:
pnpm dlx pkg-pr-new publish --packageManager=npm --pnpm './packages/server' './packages/client'
'./packages/middleware/express' './packages/middleware/hono' './packages/middleware/node'
'./packages/middleware/express' './packages/middleware/fastify' './packages/middleware/hono' './packages/middleware/node'

View file

@ -0,0 +1,70 @@
# `@modelcontextprotocol/fastify`
Fastify adapters for the MCP TypeScript server SDK.
This package is a thin Fastify integration layer for [`@modelcontextprotocol/server`](https://github.com/modelcontextprotocol/typescript-sdk/tree/main/packages/server).
It does **not** implement MCP itself. Instead, it helps you:
- create a Fastify app with sensible defaults for MCP servers
- add DNS rebinding protection via Host header validation (recommended for localhost servers)
## Install
```bash
npm install @modelcontextprotocol/server @modelcontextprotocol/fastify fastify
# For MCP Streamable HTTP over Node.js (IncomingMessage/ServerResponse):
npm install @modelcontextprotocol/node
```
## Exports
- `createMcpFastifyApp(options?)`
- `hostHeaderValidation(allowedHostnames)`
- `localhostHostValidation()`
## Usage
### Create a Fastify app (localhost DNS rebinding protection by default)
```ts
import { createMcpFastifyApp } from '@modelcontextprotocol/fastify';
const app = createMcpFastifyApp(); // default host is 127.0.0.1; protection enabled
```
### Streamable HTTP endpoint (Fastify)
```ts
import { createMcpFastifyApp } from '@modelcontextprotocol/fastify';
import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node';
import { McpServer } from '@modelcontextprotocol/server';
const app = createMcpFastifyApp();
const mcpServer = new McpServer({ name: 'my-server', version: '1.0.0' });
app.post('/mcp', async (request, reply) => {
// Stateless example: create a transport per request.
// For stateful mode (sessions), keep a transport instance around and reuse it.
const transport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: undefined });
await mcpServer.connect(transport);
// Clean up when the client closes the connection (e.g. during SSE streaming).
reply.raw.on('close', () => {
transport.close();
});
await transport.handleRequest(request.raw, reply.raw, request.body);
});
```
If you create a new `McpServer` per request in stateless mode, also call `mcpServer.close()` in the `close` handler. To reject non-POST requests with 405 Method Not Allowed, add routes for GET and DELETE that send a JSON-RPC error response.
### Host header validation (DNS rebinding protection)
```ts
import { hostHeaderValidation } from '@modelcontextprotocol/fastify';
app.addHook('onRequest', hostHeaderValidation(['localhost', '127.0.0.1', '[::1]']));
```

View file

@ -0,0 +1,12 @@
// @ts-check
import baseConfig from '@modelcontextprotocol/eslint-config';
export default [
...baseConfig,
{
settings: {
'import/internal-regex': '^@modelcontextprotocol/(server|core)'
}
}
];

View file

@ -0,0 +1,67 @@
{
"name": "@modelcontextprotocol/fastify",
"private": false,
"version": "2.0.0-alpha.0",
"description": "Fastify adapters for the Model Context Protocol TypeScript server SDK - Fastify middleware",
"license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)",
"homepage": "https://modelcontextprotocol.io",
"bugs": "https://github.com/modelcontextprotocol/typescript-sdk/issues",
"type": "module",
"repository": {
"type": "git",
"url": "git+https://github.com/modelcontextprotocol/typescript-sdk.git"
},
"engines": {
"node": ">=20",
"pnpm": ">=10.24.0"
},
"packageManager": "pnpm@10.24.0",
"keywords": [
"modelcontextprotocol",
"mcp",
"fastify",
"middleware"
],
"exports": {
".": {
"types": "./dist/index.d.mts",
"import": "./dist/index.mjs"
}
},
"files": [
"dist"
],
"scripts": {
"typecheck": "tsgo -p tsconfig.json --noEmit",
"build": "tsdown",
"build:watch": "tsdown --watch",
"prepack": "npm run build",
"lint": "eslint src/ && prettier --ignore-path ../../../.prettierignore --check .",
"lint:fix": "eslint src/ --fix && prettier --ignore-path ../../../.prettierignore --write .",
"check": "npm run typecheck && npm run lint",
"test": "vitest run",
"test:watch": "vitest"
},
"dependencies": {},
"peerDependencies": {
"@modelcontextprotocol/server": "workspace:^",
"fastify": "catalog:runtimeServerOnly"
},
"devDependencies": {
"@modelcontextprotocol/server": "workspace:^",
"@modelcontextprotocol/tsconfig": "workspace:^",
"@modelcontextprotocol/vitest-config": "workspace:^",
"@modelcontextprotocol/eslint-config": "workspace:^",
"@eslint/js": "catalog:devTools",
"@typescript/native-preview": "catalog:devTools",
"eslint": "catalog:devTools",
"eslint-config-prettier": "catalog:devTools",
"eslint-plugin-n": "catalog:devTools",
"prettier": "catalog:devTools",
"tsdown": "catalog:devTools",
"typescript": "catalog:devTools",
"typescript-eslint": "catalog:devTools",
"vitest": "catalog:devTools"
}
}

View file

@ -0,0 +1,41 @@
/**
* Type-checked examples for `fastify.ts`.
*
* These examples are synced into JSDoc comments via the sync-snippets script.
* Each function's region markers define the code snippet that appears in the docs.
*
* @module
*/
import { createMcpFastifyApp } from './fastify.js';
/**
* Example: Basic usage with default DNS rebinding protection.
*/
function createMcpFastifyApp_default() {
//#region createMcpFastifyApp_default
const app = createMcpFastifyApp();
//#endregion createMcpFastifyApp_default
return app;
}
/**
* Example: Custom host binding with and without DNS rebinding protection.
*/
function createMcpFastifyApp_customHost() {
//#region createMcpFastifyApp_customHost
const appOpen = createMcpFastifyApp({ host: '0.0.0.0' }); // No automatic DNS rebinding protection
const appLocal = createMcpFastifyApp({ host: 'localhost' }); // DNS rebinding protection enabled
//#endregion createMcpFastifyApp_customHost
return { appOpen, appLocal };
}
/**
* Example: Custom allowed hosts for non-localhost binding.
*/
function createMcpFastifyApp_allowedHosts() {
//#region createMcpFastifyApp_allowedHosts
const app = createMcpFastifyApp({ host: '0.0.0.0', allowedHosts: ['myapp.local', 'localhost'] });
//#endregion createMcpFastifyApp_allowedHosts
return app;
}

View file

@ -0,0 +1,82 @@
import type { FastifyInstance } from 'fastify';
import Fastify from 'fastify';
import { hostHeaderValidation, localhostHostValidation } from './middleware/hostHeaderValidation.js';
/**
* Options for creating an MCP Fastify application.
*/
export interface CreateMcpFastifyAppOptions {
/**
* The hostname to bind to. Defaults to `'127.0.0.1'`.
* When set to `'127.0.0.1'`, `'localhost'`, or `'::1'`, DNS rebinding protection is automatically enabled.
*/
host?: string;
/**
* List of allowed hostnames for DNS rebinding protection.
* If provided, host header validation will be applied using this list.
* For IPv6, provide addresses with brackets (e.g., `'[::1]'`).
*
* This is useful when binding to `'0.0.0.0'` or `'::'` but still wanting
* to restrict which hostnames are allowed.
*/
allowedHosts?: string[];
}
/**
* Creates a Fastify application pre-configured for MCP servers.
*
* When the host is `'127.0.0.1'`, `'localhost'`, or `'::1'` (the default is `'127.0.0.1'`),
* DNS rebinding protection is automatically applied via an onRequest hook to protect against
* DNS rebinding attacks on localhost servers.
*
* Fastify parses JSON request bodies by default, so no additional middleware is required
* for MCP Streamable HTTP endpoints.
*
* @param options - Configuration options
* @returns A configured Fastify application
*
* @example Basic usage - defaults to 127.0.0.1 with DNS rebinding protection
* ```ts source="./fastify.examples.ts#createMcpFastifyApp_default"
* const app = createMcpFastifyApp();
* ```
*
* @example Custom host - DNS rebinding protection only applied for localhost hosts
* ```ts source="./fastify.examples.ts#createMcpFastifyApp_customHost"
* const appOpen = createMcpFastifyApp({ host: '0.0.0.0' }); // No automatic DNS rebinding protection
* const appLocal = createMcpFastifyApp({ host: 'localhost' }); // DNS rebinding protection enabled
* ```
*
* @example Custom allowed hosts for non-localhost binding
* ```ts source="./fastify.examples.ts#createMcpFastifyApp_allowedHosts"
* const app = createMcpFastifyApp({ host: '0.0.0.0', allowedHosts: ['myapp.local', 'localhost'] });
* ```
*/
export function createMcpFastifyApp(options: CreateMcpFastifyAppOptions = {}): FastifyInstance {
const { host = '127.0.0.1', allowedHosts } = options;
const app = Fastify();
// Fastify parses JSON by default - no middleware needed
// If allowedHosts is explicitly provided, use that for validation
if (allowedHosts) {
app.addHook('onRequest', hostHeaderValidation(allowedHosts));
} else {
// Apply DNS rebinding protection automatically for localhost hosts
const localhostHosts = ['127.0.0.1', 'localhost', '::1'];
if (localhostHosts.includes(host)) {
app.addHook('onRequest', localhostHostValidation());
} else if (host === '0.0.0.0' || host === '::') {
// Warn when binding to all interfaces without DNS rebinding protection
app.log.warn(
`Server is binding to ${host} without DNS rebinding protection. ` +
'Consider using the allowedHosts option to restrict allowed hosts, ' +
'or use authentication to protect your server.'
);
}
}
return app;
}

View file

@ -0,0 +1,2 @@
export * from './fastify.js';
export * from './middleware/hostHeaderValidation.js';

View file

@ -0,0 +1,30 @@
/**
* Type-checked examples for `hostHeaderValidation.ts`.
*
* These examples are synced into JSDoc comments via the sync-snippets script.
* Each function's region markers define the code snippet that appears in the docs.
*
* @module
*/
import type { FastifyInstance } from 'fastify';
import { hostHeaderValidation, localhostHostValidation } from './hostHeaderValidation.js';
/**
* Example: Using hostHeaderValidation hook with custom allowed hosts.
*/
function hostHeaderValidation_basicUsage(app: FastifyInstance) {
//#region hostHeaderValidation_basicUsage
app.addHook('onRequest', hostHeaderValidation(['localhost', '127.0.0.1', '[::1]']));
//#endregion hostHeaderValidation_basicUsage
}
/**
* Example: Using localhostHostValidation convenience hook.
*/
function localhostHostValidation_basicUsage(app: FastifyInstance) {
//#region localhostHostValidation_basicUsage
app.addHook('onRequest', localhostHostValidation());
//#endregion localhostHostValidation_basicUsage
}

View file

@ -0,0 +1,49 @@
import { localhostAllowedHostnames, validateHostHeader } from '@modelcontextprotocol/server';
import type { FastifyReply, FastifyRequest } from 'fastify';
/**
* Fastify onRequest hook for DNS rebinding protection.
* Validates `Host` header hostname (port-agnostic) against an allowed list.
*
* This is particularly important for servers without authorization or HTTPS,
* such as localhost servers or development servers. DNS rebinding attacks can
* bypass same-origin policy by manipulating DNS to point a domain to a
* localhost address, allowing malicious websites to access your local server.
*
* @param allowedHostnames - List of allowed hostnames (without ports).
* For IPv6, provide the address with brackets (e.g., `[::1]`).
* @returns Fastify onRequest hook handler
*
* @example
* ```ts source="./hostHeaderValidation.examples.ts#hostHeaderValidation_basicUsage"
* app.addHook('onRequest', hostHeaderValidation(['localhost', '127.0.0.1', '[::1]']));
* ```
*/
export function hostHeaderValidation(allowedHostnames: string[]) {
return async (request: FastifyRequest, reply: FastifyReply): Promise<void> => {
const result = validateHostHeader(request.headers.host, allowedHostnames);
if (!result.ok) {
await reply.code(403).send({
jsonrpc: '2.0',
error: {
code: -32_000,
message: result.message
},
id: null
});
}
};
}
/**
* Convenience hook for localhost DNS rebinding protection.
* Allows only `localhost`, `127.0.0.1`, and `[::1]` (IPv6 localhost) hostnames.
*
* @example
* ```ts source="./hostHeaderValidation.examples.ts#localhostHostValidation_basicUsage"
* app.addHook('onRequest', localhostHostValidation());
* ```
*/
export function localhostHostValidation() {
return hostHeaderValidation(localhostAllowedHostnames());
}

View file

@ -0,0 +1,209 @@
import Fastify from 'fastify';
import { createMcpFastifyApp } from '../src/fastify.js';
import { hostHeaderValidation, localhostHostValidation } from '../src/middleware/hostHeaderValidation.js';
describe('@modelcontextprotocol/fastify', () => {
describe('hostHeaderValidation', () => {
test('should block invalid Host header', async () => {
const app = Fastify();
app.addHook('onRequest', hostHeaderValidation(['localhost']));
app.get('/health', async () => ({ ok: true }));
const res = await app.inject({
method: 'GET',
url: '/health',
headers: { host: 'evil.com:3000' }
});
expect(res.statusCode).toBe(403);
expect(res.json()).toEqual(
expect.objectContaining({
jsonrpc: '2.0',
error: expect.objectContaining({
code: -32_000
}),
id: null
})
);
});
test('should allow valid Host header', async () => {
const app = Fastify();
app.addHook('onRequest', hostHeaderValidation(['localhost']));
app.get('/health', async () => 'ok');
const res = await app.inject({
method: 'GET',
url: '/health',
headers: { host: 'localhost:3000' }
});
expect(res.statusCode).toBe(200);
expect(res.body).toBe('ok');
});
test('should handle multiple allowed hostnames', async () => {
const app = Fastify();
app.addHook('onRequest', hostHeaderValidation(['localhost', '127.0.0.1', 'myapp.local']));
app.get('/health', async () => 'ok');
const res1 = await app.inject({
method: 'GET',
url: '/health',
headers: { host: '127.0.0.1:8080' }
});
const res2 = await app.inject({
method: 'GET',
url: '/health',
headers: { host: 'myapp.local' }
});
expect(res1.statusCode).toBe(200);
expect(res2.statusCode).toBe(200);
});
});
describe('localhostHostValidation', () => {
test('should allow localhost', async () => {
const app = Fastify();
app.addHook('onRequest', localhostHostValidation());
app.get('/health', async () => 'ok');
const res = await app.inject({
method: 'GET',
url: '/health',
headers: { host: 'localhost:3000' }
});
expect(res.statusCode).toBe(200);
});
test('should allow 127.0.0.1', async () => {
const app = Fastify();
app.addHook('onRequest', localhostHostValidation());
app.get('/health', async () => 'ok');
const res = await app.inject({
method: 'GET',
url: '/health',
headers: { host: '127.0.0.1:3000' }
});
expect(res.statusCode).toBe(200);
});
test('should allow [::1] (IPv6 localhost)', async () => {
const app = Fastify();
app.addHook('onRequest', localhostHostValidation());
app.get('/health', async () => 'ok');
const res = await app.inject({
method: 'GET',
url: '/health',
headers: { host: '[::1]:3000' }
});
expect(res.statusCode).toBe(200);
});
test('should block non-localhost hosts', async () => {
const app = Fastify();
app.addHook('onRequest', localhostHostValidation());
app.get('/health', async () => 'ok');
const res = await app.inject({
method: 'GET',
url: '/health',
headers: { host: 'evil.com:3000' }
});
expect(res.statusCode).toBe(403);
});
});
describe('createMcpFastifyApp', () => {
test('should enable localhost DNS rebinding protection by default', async () => {
const app = createMcpFastifyApp();
app.get('/health', async () => 'ok');
const bad = await app.inject({
method: 'GET',
url: '/health',
headers: { host: 'evil.com:3000' }
});
expect(bad.statusCode).toBe(403);
const good = await app.inject({
method: 'GET',
url: '/health',
headers: { host: 'localhost:3000' }
});
expect(good.statusCode).toBe(200);
});
test('should apply DNS rebinding protection for localhost host', () => {
const app = createMcpFastifyApp({ host: 'localhost' });
expect(app).toBeDefined();
expect(typeof app.addHook).toBe('function');
expect(typeof app.get).toBe('function');
expect(typeof app.post).toBe('function');
});
test('should apply DNS rebinding protection for ::1 host', () => {
const app = createMcpFastifyApp({ host: '::1' });
expect(app).toBeDefined();
});
test('should use allowedHosts when provided', async () => {
const app = createMcpFastifyApp({ host: '0.0.0.0', allowedHosts: ['myapp.local'] });
app.get('/health', async () => 'ok');
const bad = await app.inject({
method: 'GET',
url: '/health',
headers: { host: 'evil.com:3000' }
});
expect(bad.statusCode).toBe(403);
const good = await app.inject({
method: 'GET',
url: '/health',
headers: { host: 'myapp.local:3000' }
});
expect(good.statusCode).toBe(200);
});
test('should log warning when binding to 0.0.0.0 without allowedHosts', () => {
const app = createMcpFastifyApp({ host: '0.0.0.0' });
expect(app).toBeDefined();
expect(app.log).toBeDefined();
});
test('should log warning when binding to :: without allowedHosts', () => {
const app = createMcpFastifyApp({ host: '::' });
expect(app).toBeDefined();
expect(app.log).toBeDefined();
});
test('should not log warning for 0.0.0.0 when allowedHosts is provided', () => {
const app = createMcpFastifyApp({ host: '0.0.0.0', allowedHosts: ['myapp.local'] });
expect(app).toBeDefined();
});
test('should not apply host validation for 0.0.0.0 without allowedHosts', async () => {
const app = createMcpFastifyApp({ host: '0.0.0.0' });
app.get('/health', async () => 'ok');
const res = await app.inject({
method: 'GET',
url: '/health',
headers: { host: 'evil.com:3000' }
});
expect(res.statusCode).toBe(200);
});
test('should not apply host validation for non-localhost hosts without allowedHosts', () => {
const app = createMcpFastifyApp({ host: '192.168.1.1' });
expect(app).toBeDefined();
});
});
});

View file

@ -0,0 +1,15 @@
{
"extends": "@modelcontextprotocol/tsconfig",
"include": ["./"],
"exclude": ["node_modules", "dist"],
"compilerOptions": {
"paths": {
"*": ["./*"],
"@modelcontextprotocol/server": ["./node_modules/@modelcontextprotocol/server/src/index.ts"],
"@modelcontextprotocol/server/_shims": ["./node_modules/@modelcontextprotocol/server/src/shimsNode.ts"],
"@modelcontextprotocol/core": [
"./node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/src/index.ts"
]
}
}
}

View file

@ -0,0 +1,21 @@
import { defineConfig } from 'tsdown';
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
outDir: 'dist',
clean: true,
sourcemap: true,
target: 'esnext',
platform: 'node',
shims: true,
dts: {
resolver: 'tsc',
compilerOptions: {
baseUrl: '.',
paths: {
'@modelcontextprotocol/server': ['../server/src/index.ts']
}
}
}
});

View file

@ -0,0 +1,10 @@
{
"$schema": "https://typedoc.org/schema.json",
"entryPoints": ["src"],
"entryPointStrategy": "expand",
"exclude": ["**/*.test.ts"],
"navigation": {
"includeGroups": true,
"includeCategories": true
}
}

View file

@ -0,0 +1,3 @@
import baseConfig from '@modelcontextprotocol/vitest-config';
export default baseConfig;

319
pnpm-lock.yaml generated
View file

@ -104,6 +104,9 @@ catalogs:
express:
specifier: ^5.2.1
version: 5.2.1
fastify:
specifier: ^5.2.0
version: 5.8.4
hono:
specifier: ^4.11.4
version: 4.12.9
@ -700,6 +703,55 @@ importers:
specifier: catalog:devTools
version: 4.1.2(@opentelemetry/api@1.9.1)(@types/node@25.5.0)(vite@7.3.0(@types/node@25.5.0)(tsx@4.21.0)(yaml@2.8.3))
packages/middleware/fastify:
dependencies:
fastify:
specifier: catalog:runtimeServerOnly
version: 5.8.4
devDependencies:
'@eslint/js':
specifier: catalog:devTools
version: 9.39.4
'@modelcontextprotocol/eslint-config':
specifier: workspace:^
version: link:../../../common/eslint-config
'@modelcontextprotocol/server':
specifier: workspace:^
version: link:../../server
'@modelcontextprotocol/tsconfig':
specifier: workspace:^
version: link:../../../common/tsconfig
'@modelcontextprotocol/vitest-config':
specifier: workspace:^
version: link:../../../common/vitest-config
'@typescript/native-preview':
specifier: catalog:devTools
version: 7.0.0-dev.20260327.2
eslint:
specifier: catalog:devTools
version: 9.39.4
eslint-config-prettier:
specifier: catalog:devTools
version: 10.1.8(eslint@9.39.4)
eslint-plugin-n:
specifier: catalog:devTools
version: 17.24.0(eslint@9.39.4)(typescript@5.9.3)
prettier:
specifier: catalog:devTools
version: 3.6.2
tsdown:
specifier: catalog:devTools
version: 0.18.4(@typescript/native-preview@7.0.0-dev.20260327.2)(typescript@5.9.3)
typescript:
specifier: catalog:devTools
version: 5.9.3
typescript-eslint:
specifier: catalog:devTools
version: 8.57.2(eslint@9.39.4)(typescript@5.9.3)
vitest:
specifier: catalog:devTools
version: 4.1.2(@opentelemetry/api@1.9.1)(@types/node@25.5.0)(vite@7.3.0(@types/node@25.5.0)(tsx@4.21.0)(yaml@2.8.3))
packages/middleware/hono:
dependencies:
hono:
@ -1581,6 +1633,24 @@ packages:
resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@fastify/ajv-compiler@4.0.5':
resolution: {integrity: sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A==}
'@fastify/error@4.2.0':
resolution: {integrity: sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==}
'@fastify/fast-json-stringify-compiler@5.0.3':
resolution: {integrity: sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ==}
'@fastify/forwarded@3.0.1':
resolution: {integrity: sha512-JqDochHFqXs3C3Ml3gOY58zM7OqO9ENqPo0UqAjAjH8L01fRZqwX9iLeX34//kiJubF7r2ZQHtBRU36vONbLlw==}
'@fastify/merge-json-schemas@0.2.1':
resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==}
'@fastify/proxy-addr@5.1.0':
resolution: {integrity: sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw==}
'@gerrit0/mini-shiki@3.23.0':
resolution: {integrity: sha512-bEMORlG0cqdjVyCEuU0cDQbORWX+kYCeo0kV1lbxF5bt4r7SID2l9bqsxJEM0zndaxpOUT7riCyIVEuqq/Ynxg==}
@ -1903,6 +1973,9 @@ packages:
'@paralleldrive/cuid2@2.3.1':
resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==}
'@pinojs/redact@0.4.0':
resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==}
'@poppinss/colors@4.1.6':
resolution: {integrity: sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==}
@ -2585,6 +2658,9 @@ packages:
'@vitest/utils@4.1.2':
resolution: {integrity: sha512-xw2/TiX82lQHA06cgbqRKFb5lCAy3axQ4H4SoUFhUsg+wztiet+co86IAMDtF6Vm1hc7J6j09oh/rgDn+JdKIQ==}
abstract-logging@2.0.1:
resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==}
accepts@2.0.0:
resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
engines: {node: '>= 0.6'}
@ -2687,10 +2763,17 @@ packages:
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
atomic-sleep@1.0.0:
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
engines: {node: '>=8.0.0'}
available-typed-arrays@1.0.7:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
avvio@9.2.0:
resolution: {integrity: sha512-2t/sy01ArdHHE0vRH5Hsay+RtCZt3dLPji7W7/MMOCEgze5b7SNDC4j5H6FnVgPkI1MTNFGzHdHrVXDDl7QSSQ==}
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@ -3014,6 +3097,10 @@ packages:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
detect-indent@6.1.0:
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
engines: {node: '>=8'}
@ -3322,6 +3409,9 @@ packages:
fast-content-type-parse@3.0.0:
resolution: {integrity: sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==}
fast-decode-uri-component@1.0.1:
resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==}
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
@ -3332,15 +3422,24 @@ packages:
fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
fast-json-stringify@6.3.0:
resolution: {integrity: sha512-oRCntNDY/329HJPlmdNLIdogNtt6Vyjb1WuT01Soss3slIdyUp8kAcDU3saQTOquEK8KFVfwIIF7FebxUAu+yA==}
fast-levenshtein@2.0.6:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
fast-querystring@1.1.2:
resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==}
fast-safe-stringify@2.1.1:
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
fast-uri@3.1.0:
resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
fastify@5.8.4:
resolution: {integrity: sha512-sa42J1xylbBAYUWALSBoyXKPDUvM3OoNOibIefA+Oha57FryXKKCZarA1iDntOCWp3O35voZLuDg2mdODXtPzQ==}
fastq@1.20.1:
resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
@ -3368,6 +3467,10 @@ packages:
resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==}
engines: {node: '>= 18.0.0'}
find-my-way@9.5.0:
resolution: {integrity: sha512-VW2RfnmscZO5KgBY5XVyKREMW5nMZcxDy+buTOsL+zIPnBlbKm+00sgzoQzq1EVh4aALZLfKdwv6atBGcjvjrQ==}
engines: {node: '>=20'}
find-up-simple@1.0.1:
resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==}
engines: {node: '>=18'}
@ -3588,6 +3691,10 @@ packages:
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
engines: {node: '>= 0.10'}
ipaddr.js@2.3.0:
resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==}
engines: {node: '>= 10'}
is-array-buffer@3.0.5:
resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
engines: {node: '>= 0.4'}
@ -3749,6 +3856,9 @@ packages:
json-buffer@3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
json-schema-ref-resolver@3.0.0:
resolution: {integrity: sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==}
json-schema-to-ts@3.1.1:
resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==}
engines: {node: '>=16'}
@ -3844,6 +3954,9 @@ packages:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
light-my-request@6.6.0:
resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==}
linkify-it@5.0.0:
resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
@ -4019,6 +4132,10 @@ packages:
obug@2.1.1:
resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
on-exit-leak-free@2.1.2:
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
engines: {node: '>=14.0.0'}
on-finished@2.4.1:
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
engines: {node: '>= 0.8'}
@ -4119,6 +4236,16 @@ packages:
resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
engines: {node: '>=6'}
pino-abstract-transport@3.0.0:
resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==}
pino-std-serializers@7.1.0:
resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==}
pino@10.3.1:
resolution: {integrity: sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==}
hasBin: true
pkce-challenge@5.0.1:
resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==}
engines: {node: '>=16.20.0'}
@ -4159,6 +4286,12 @@ packages:
engines: {node: '>=14'}
hasBin: true
process-warning@4.0.1:
resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==}
process-warning@5.0.0:
resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==}
proxy-addr@2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
@ -4187,6 +4320,9 @@ packages:
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
quick-format-unescaped@4.0.4:
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
range-parser@1.2.1:
resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
engines: {node: '>= 0.6'}
@ -4207,6 +4343,10 @@ packages:
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
engines: {node: '>= 6'}
real-require@0.2.0:
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
engines: {node: '>= 12.13.0'}
reflect.getprototypeof@1.0.10:
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
engines: {node: '>= 0.4'}
@ -4243,10 +4383,17 @@ packages:
engines: {node: '>= 0.4'}
hasBin: true
ret@0.5.0:
resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==}
engines: {node: '>=10'}
reusify@1.1.0:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
rfdc@1.4.1:
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
rolldown-plugin-dts@0.20.0:
resolution: {integrity: sha512-cLAY1kN2ilTYMfZcFlGWbXnu6Nb+8uwUBsi+Mjbh4uIx7IN8uMOmJ7RxrrRgPsO4H7eSz3E+JwGoL1gyugiyUA==}
engines: {node: '>=20.19.0'}
@ -4310,9 +4457,20 @@ packages:
resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
engines: {node: '>= 0.4'}
safe-regex2@5.1.0:
resolution: {integrity: sha512-pNHAuBW7TrcleFHsxBr5QMi/Iyp0ENjUKz7GCcX1UO7cMh+NmVK6HxQckNL1tJp1XAJVjG6B8OKIPqodqj9rtw==}
hasBin: true
safe-stable-stringify@2.5.0:
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
engines: {node: '>=10'}
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
secure-json-parse@4.1.0:
resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==}
semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
@ -4330,6 +4488,9 @@ packages:
resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==}
engines: {node: '>= 18'}
set-cookie-parser@2.7.2:
resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
set-cookie-parser@3.1.0:
resolution: {integrity: sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==}
@ -4393,6 +4554,9 @@ packages:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
sonic-boom@4.2.1:
resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==}
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
@ -4400,6 +4564,10 @@ packages:
spawndamnit@3.0.1:
resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==}
split2@4.2.0:
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
engines: {node: '>= 10.x'}
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
@ -4491,6 +4659,10 @@ packages:
resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==}
engines: {node: '>=8'}
thread-stream@4.0.0:
resolution: {integrity: sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==}
engines: {node: '>=20'}
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
@ -4510,6 +4682,10 @@ packages:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
toad-cache@3.7.0:
resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==}
engines: {node: '>=12'}
toidentifier@1.0.1:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
@ -5373,6 +5549,29 @@ snapshots:
'@eslint/core': 0.17.0
levn: 0.4.1
'@fastify/ajv-compiler@4.0.5':
dependencies:
ajv: 8.18.0
ajv-formats: 3.0.1(ajv@8.18.0)
fast-uri: 3.1.0
'@fastify/error@4.2.0': {}
'@fastify/fast-json-stringify-compiler@5.0.3':
dependencies:
fast-json-stringify: 6.3.0
'@fastify/forwarded@3.0.1': {}
'@fastify/merge-json-schemas@0.2.1':
dependencies:
dequal: 2.0.3
'@fastify/proxy-addr@5.1.0':
dependencies:
'@fastify/forwarded': 3.0.1
ipaddr.js: 2.3.0
'@gerrit0/mini-shiki@3.23.0':
dependencies:
'@shikijs/engine-oniguruma': 3.23.0
@ -5680,6 +5879,8 @@ snapshots:
dependencies:
'@noble/hashes': 1.8.0
'@pinojs/redact@0.4.0': {}
'@poppinss/colors@4.1.6':
dependencies:
kleur: 4.1.5
@ -6229,6 +6430,8 @@ snapshots:
convert-source-map: 2.0.0
tinyrainbow: 3.1.0
abstract-logging@2.0.1: {}
accepts@2.0.0:
dependencies:
mime-types: 3.0.2
@ -6349,10 +6552,17 @@ snapshots:
asynckit@0.4.0: {}
atomic-sleep@1.0.0: {}
available-typed-arrays@1.0.7:
dependencies:
possible-typed-array-names: 1.1.0
avvio@9.2.0:
dependencies:
'@fastify/error': 4.2.0
fastq: 1.20.1
balanced-match@1.0.2: {}
balanced-match@4.0.4: {}
@ -6619,6 +6829,8 @@ snapshots:
depd@2.0.0: {}
dequal@2.0.3: {}
detect-indent@6.1.0: {}
detect-libc@2.1.2: {}
@ -7082,6 +7294,8 @@ snapshots:
fast-content-type-parse@3.0.0: {}
fast-decode-uri-component@1.0.1: {}
fast-deep-equal@3.1.3: {}
fast-glob@3.3.3:
@ -7094,12 +7308,43 @@ snapshots:
fast-json-stable-stringify@2.1.0: {}
fast-json-stringify@6.3.0:
dependencies:
'@fastify/merge-json-schemas': 0.2.1
ajv: 8.18.0
ajv-formats: 3.0.1(ajv@8.18.0)
fast-uri: 3.1.0
json-schema-ref-resolver: 3.0.0
rfdc: 1.4.1
fast-levenshtein@2.0.6: {}
fast-querystring@1.1.2:
dependencies:
fast-decode-uri-component: 1.0.1
fast-safe-stringify@2.1.1: {}
fast-uri@3.1.0: {}
fastify@5.8.4:
dependencies:
'@fastify/ajv-compiler': 4.0.5
'@fastify/error': 4.2.0
'@fastify/fast-json-stringify-compiler': 5.0.3
'@fastify/proxy-addr': 5.1.0
abstract-logging: 2.0.1
avvio: 9.2.0
fast-json-stringify: 6.3.0
find-my-way: 9.5.0
light-my-request: 6.6.0
pino: 10.3.1
process-warning: 5.0.0
rfdc: 1.4.1
secure-json-parse: 4.1.0
semver: 7.7.4
toad-cache: 3.7.0
fastq@1.20.1:
dependencies:
reusify: 1.1.0
@ -7129,6 +7374,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
find-my-way@9.5.0:
dependencies:
fast-deep-equal: 3.1.3
fast-querystring: 1.1.2
safe-regex2: 5.1.0
find-up-simple@1.0.1: {}
find-up@4.1.0:
@ -7342,6 +7593,8 @@ snapshots:
ipaddr.js@1.9.1: {}
ipaddr.js@2.3.0: {}
is-array-buffer@3.0.5:
dependencies:
call-bind: 1.0.8
@ -7497,6 +7750,10 @@ snapshots:
json-buffer@3.0.1: {}
json-schema-ref-resolver@3.0.0:
dependencies:
dequal: 2.0.3
json-schema-to-ts@3.1.1:
dependencies:
'@babel/runtime': 7.29.2
@ -7576,6 +7833,12 @@ snapshots:
prelude-ls: 1.2.1
type-check: 0.4.0
light-my-request@6.6.0:
dependencies:
cookie: 1.1.1
process-warning: 4.0.1
set-cookie-parser: 2.7.2
linkify-it@5.0.0:
dependencies:
uc.micro: 2.1.0
@ -7729,6 +7992,8 @@ snapshots:
obug@2.1.1: {}
on-exit-leak-free@2.1.2: {}
on-finished@2.4.1:
dependencies:
ee-first: 1.1.1
@ -7819,6 +8084,26 @@ snapshots:
pify@4.0.1: {}
pino-abstract-transport@3.0.0:
dependencies:
split2: 4.2.0
pino-std-serializers@7.1.0: {}
pino@10.3.1:
dependencies:
'@pinojs/redact': 0.4.0
atomic-sleep: 1.0.0
on-exit-leak-free: 2.1.2
pino-abstract-transport: 3.0.0
pino-std-serializers: 7.1.0
process-warning: 5.0.0
quick-format-unescaped: 4.0.4
real-require: 0.2.0
safe-stable-stringify: 2.5.0
sonic-boom: 4.2.1
thread-stream: 4.0.0
pkce-challenge@5.0.1: {}
pluralize@8.0.0: {}
@ -7854,6 +8139,10 @@ snapshots:
prettier@3.6.2: {}
process-warning@4.0.1: {}
process-warning@5.0.0: {}
proxy-addr@2.0.7:
dependencies:
forwarded: 0.2.0
@ -7878,6 +8167,8 @@ snapshots:
queue-microtask@1.2.3: {}
quick-format-unescaped@4.0.4: {}
range-parser@1.2.1: {}
raw-body@3.0.2:
@ -7907,6 +8198,8 @@ snapshots:
string_decoder: 1.3.0
util-deprecate: 1.0.2
real-require@0.2.0: {}
reflect.getprototypeof@1.0.10:
dependencies:
call-bind: 1.0.8
@ -7947,8 +8240,12 @@ snapshots:
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
ret@0.5.0: {}
reusify@1.1.0: {}
rfdc@1.4.1: {}
rolldown-plugin-dts@0.20.0(@typescript/native-preview@7.0.0-dev.20260327.2)(rolldown@1.0.0-beta.57)(typescript@5.9.3):
dependencies:
'@babel/generator': 7.29.1
@ -8076,8 +8373,16 @@ snapshots:
es-errors: 1.3.0
is-regex: 1.2.1
safe-regex2@5.1.0:
dependencies:
ret: 0.5.0
safe-stable-stringify@2.5.0: {}
safer-buffer@2.1.2: {}
secure-json-parse@4.1.0: {}
semver@6.3.1: {}
semver@7.7.4: {}
@ -8107,6 +8412,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
set-cookie-parser@2.7.2: {}
set-cookie-parser@3.1.0: {}
set-function-length@1.2.2:
@ -8212,6 +8519,10 @@ snapshots:
slash@3.0.0: {}
sonic-boom@4.2.1:
dependencies:
atomic-sleep: 1.0.0
source-map-js@1.2.1: {}
spawndamnit@3.0.1:
@ -8219,6 +8530,8 @@ snapshots:
cross-spawn: 7.0.6
signal-exit: 4.1.0
split2@4.2.0: {}
sprintf-js@1.0.3: {}
stable-hash-x@0.2.0: {}
@ -8322,6 +8635,10 @@ snapshots:
term-size@2.2.1: {}
thread-stream@4.0.0:
dependencies:
real-require: 0.2.0
tinybench@2.9.0: {}
tinyexec@1.0.4: {}
@ -8337,6 +8654,8 @@ snapshots:
dependencies:
is-number: 7.0.0
toad-cache@3.7.0: {}
toidentifier@1.0.1: {}
tr46@0.0.3: {}

View file

@ -41,6 +41,7 @@ catalogs:
content-type: ^1.0.5
cors: ^2.8.5
express: ^5.2.1
fastify: ^5.2.0
hono: ^4.11.4
raw-body: ^3.0.0
runtimeShared: