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:
parent
5f32a90f0d
commit
81e4b2a412
17 changed files with 937 additions and 1 deletions
5
.changeset/add-fastify-middleware.md
Normal file
5
.changeset/add-fastify-middleware.md
Normal 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.
|
||||
2
.github/workflows/publish.yml
vendored
2
.github/workflows/publish.yml
vendored
|
|
@ -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'
|
||||
|
|
|
|||
70
packages/middleware/fastify/README.md
Normal file
70
packages/middleware/fastify/README.md
Normal 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]']));
|
||||
```
|
||||
12
packages/middleware/fastify/eslint.config.mjs
Normal file
12
packages/middleware/fastify/eslint.config.mjs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// @ts-check
|
||||
|
||||
import baseConfig from '@modelcontextprotocol/eslint-config';
|
||||
|
||||
export default [
|
||||
...baseConfig,
|
||||
{
|
||||
settings: {
|
||||
'import/internal-regex': '^@modelcontextprotocol/(server|core)'
|
||||
}
|
||||
}
|
||||
];
|
||||
67
packages/middleware/fastify/package.json
Normal file
67
packages/middleware/fastify/package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
41
packages/middleware/fastify/src/fastify.examples.ts
Normal file
41
packages/middleware/fastify/src/fastify.examples.ts
Normal 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;
|
||||
}
|
||||
82
packages/middleware/fastify/src/fastify.ts
Normal file
82
packages/middleware/fastify/src/fastify.ts
Normal 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;
|
||||
}
|
||||
2
packages/middleware/fastify/src/index.ts
Normal file
2
packages/middleware/fastify/src/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export * from './fastify.js';
|
||||
export * from './middleware/hostHeaderValidation.js';
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
209
packages/middleware/fastify/test/fastify.test.ts
Normal file
209
packages/middleware/fastify/test/fastify.test.ts
Normal 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();
|
||||
});
|
||||
});
|
||||
});
|
||||
15
packages/middleware/fastify/tsconfig.json
Normal file
15
packages/middleware/fastify/tsconfig.json
Normal 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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
21
packages/middleware/fastify/tsdown.config.ts
Normal file
21
packages/middleware/fastify/tsdown.config.ts
Normal 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']
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
10
packages/middleware/fastify/typedoc.json
Normal file
10
packages/middleware/fastify/typedoc.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"$schema": "https://typedoc.org/schema.json",
|
||||
"entryPoints": ["src"],
|
||||
"entryPointStrategy": "expand",
|
||||
"exclude": ["**/*.test.ts"],
|
||||
"navigation": {
|
||||
"includeGroups": true,
|
||||
"includeCategories": true
|
||||
}
|
||||
}
|
||||
3
packages/middleware/fastify/vitest.config.js
Normal file
3
packages/middleware/fastify/vitest.config.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import baseConfig from '@modelcontextprotocol/vitest-config';
|
||||
|
||||
export default baseConfig;
|
||||
319
pnpm-lock.yaml
generated
319
pnpm-lock.yaml
generated
|
|
@ -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: {}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in a new issue