@faapi/schema 0.0.0-canary.0 → 0.0.0-canary.0f443f9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.js.map +1 -1
- package/package.json +16 -13
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 faapi contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schemaServer.ts","../src/routeSchema.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport type { RouteManifest, RouteInfo, FaapiPlugin, PluginContext } from '@faapi/faapi';\nimport { buildRouteSchemas } from './routeSchema
|
|
1
|
+
{"version":3,"sources":["../src/schemaServer.ts","../src/routeSchema.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport type { RouteManifest, RouteInfo, FaapiPlugin, PluginContext } from '@faapi/faapi';\nimport { buildRouteSchemas } from './routeSchema';\n\n/**\n * 判断 schema server 是否应该启用\n * - FAAPI_SCHEMA=1 强制开启\n * - FAAPI_SCHEMA=0 强制关闭\n * - 未设置时:开发环境默认开启,生产环境默认关闭\n */\nexport function isSchemaEnabled(): boolean {\n const envValue = process.env.FAAPI_SCHEMA;\n if (envValue === '1' || envValue === 'true') return true;\n if (envValue === '0' || envValue === 'false') return false;\n // 未设置时根据 NODE_ENV 判断\n return process.env.NODE_ENV !== 'production';\n}\n\n/**\n * 创建 faapi Schema Server\n * 通过 MCP 协议暴露路由信息供 LLM 查询\n */\nexport function createSchemaServer(routes: RouteManifest, rootDir: string): McpServer {\n const server = new McpServer({\n name: 'faapi-schema',\n version: '0.0.1',\n });\n\n // 缓存 route schemas\n let cachedSchemas: RouteInfo[] | null = null;\n\n function getSchemas(): RouteInfo[] {\n if (!cachedSchemas) {\n cachedSchemas = buildRouteSchemas(routes, rootDir);\n }\n return cachedSchemas;\n }\n\n // Tool: 列出所有路由\n server.tool(\n 'list_routes',\n '列出当前 faapi 应用的所有 API 路由,包括方法、路径、是否动态路由',\n {},\n () => {\n const schemas = getSchemas();\n const routesList = schemas.map((r) => ({\n method: r.method,\n path: r.path,\n isDynamic: r.isDynamic,\n filePath: r.filePath,\n }));\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(routesList, null, 2),\n },\n ],\n };\n },\n );\n\n // Tool: 获取单个路由的详细 schema\n server.tool(\n 'get_route_schema',\n '获取指定路由的详细接口信息,包括输入参数的名称、类型、是否必填',\n {\n method: z.string().describe('HTTP 方法,如 GET、POST'),\n path: z.string().describe('路由路径,如 /auth/login'),\n },\n ({ method, path }) => {\n const schemas = getSchemas();\n const route = schemas.find((r) => r.method === method.toUpperCase() && r.path === path);\n\n if (!route) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ error: `未找到路由 ${method.toUpperCase()} ${path}` }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(route, null, 2),\n },\n ],\n };\n },\n );\n\n // Tool: 获取所有路由的完整 schema(类似 OpenAPI)\n server.tool(\n 'get_api_schema',\n '获取当前应用所有接口的完整 schema,类似 OpenAPI 规范,包含每个路由的输入参数定义',\n {},\n () => {\n const schemas = getSchemas();\n const apiSchema: Record<string, unknown> = {};\n\n for (const route of schemas) {\n const key = `${route.method} ${route.path}`;\n apiSchema[key] = {\n method: route.method,\n path: route.path,\n isDynamic: route.isDynamic,\n inputs: route.inputs.map((input) => ({\n source: input.source,\n schemaName: input.schemaName,\n properties: input.properties,\n })),\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(apiSchema, null, 2),\n },\n ],\n };\n },\n );\n\n return server;\n}\n\n/**\n * 启动 Schema Server(stdio 模式)\n */\nexport async function startSchemaServer(routes: RouteManifest, rootDir: string): Promise<void> {\n const server = createSchemaServer(routes, rootDir);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\n/**\n * faapi 插件入口\n *\n * 在 faapi.config.ts 中声明:\n * ```ts\n * export default {\n * plugins: ['@faapi/schema'],\n * } satisfies FaapiConfig;\n * ```\n */\nexport default {\n name: '@faapi/schema',\n setup(ctx: PluginContext) {\n if (!isSchemaEnabled()) {\n console.log('- Schema server disabled (FAAPI_SCHEMA=0 or production mode)');\n return;\n }\n console.log('- Schema server enabled (stdio)');\n // startSchemaServer 是异步的,但不阻塞启动流程\n void startSchemaServer(ctx.routes, ctx.rootDir);\n },\n} satisfies FaapiPlugin;\n","import path from 'node:path';\nimport {\n getSchemaProperties,\n getInputTypeForMethod,\n type RouteManifest,\n type RouteInfo,\n type RouteInputSchema,\n} from '@faapi/faapi';\n\n/**\n * 从路由清单生成接口描述信息\n *\n * 复用主包 schemaRegistry 已有的类型提取结果,避免重复 AST 分析。\n *\n * @param routes 路由清单\n * @param rootDir 根目录\n */\nexport function buildRouteSchemas(routes: RouteManifest, rootDir: string): RouteInfo[] {\n return routes.map((route) => {\n const absoluteFilePath = path.resolve(rootDir, route.filePath);\n const inputs = extractInputSchemas(absoluteFilePath, route.method, route);\n\n return {\n method: route.method,\n path: route.urlPath,\n filePath: route.filePath,\n isDynamic: route.isDynamic,\n inputs,\n };\n });\n}\n\n/**\n * 提取一个路由文件的所有输入 schema\n *\n * 直接查询 schemaRegistry,复用参数校验已提取的 PropertyType,\n * 不再重复执行 AST 分析。\n */\nfunction extractInputSchemas(\n filePath: string,\n method: string,\n route: { isDynamic: boolean; paramNames: string[] },\n): RouteInputSchema[] {\n const inputs: RouteInputSchema[] = [];\n\n // 主输入(query 或 body):从 registry 查询\n const inputType = getInputTypeForMethod(method);\n const schema = getSchemaProperties(filePath, method, inputType);\n\n if (schema) {\n inputs.push({\n source: inputType,\n schemaName: schema.schemaName,\n properties: schema.properties,\n });\n } else {\n // registry 无数据(不应发生,插件 setup 时 registry 已加载)\n inputs.push({\n source: inputType,\n schemaName: null,\n properties: [],\n });\n }\n\n // 动态路由参数\n if (route.isDynamic && route.paramNames.length > 0) {\n const paramsSchema = getSchemaProperties(filePath, method, 'params');\n\n // params 有类型声明时用类型信息,否则用 paramNames 兜底\n const paramsProps =\n paramsSchema && paramsSchema.schemaName\n ? paramsSchema.properties\n : route.paramNames.map((name) => ({\n name,\n type: 'string',\n required: true,\n }));\n\n inputs.push({\n source: 'params',\n schemaName: paramsSchema?.schemaName ?? null,\n properties: paramsProps,\n });\n }\n\n return inputs;\n}\n"],"mappings":"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","names":["path"]}
|
package/package.json
CHANGED
|
@@ -1,32 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faapi/schema",
|
|
3
|
-
"version": "0.0.0-canary.
|
|
3
|
+
"version": "0.0.0-canary.0f443f9",
|
|
4
4
|
"description": "Schema introspection for faapi — expose API schema to AI assistants via MCP",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
-
"
|
|
11
|
-
"
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
15
|
"dist"
|
|
16
16
|
],
|
|
17
17
|
"engines": {
|
|
18
|
-
"node": ">=
|
|
19
|
-
},
|
|
20
|
-
"scripts": {
|
|
21
|
-
"build": "tsup",
|
|
22
|
-
"prepublishOnly": "pnpm build",
|
|
23
|
-
"test": "vitest run --passWithNoTests",
|
|
24
|
-
"typecheck": "tsc --noEmit"
|
|
18
|
+
"node": ">=24"
|
|
25
19
|
},
|
|
26
20
|
"dependencies": {
|
|
27
|
-
"@faapi/faapi": "workspace:*",
|
|
28
21
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
29
|
-
"zod": "^4.4.3"
|
|
22
|
+
"zod": "^4.4.3",
|
|
23
|
+
"@faapi/faapi": "0.0.0-canary.0f443f9"
|
|
30
24
|
},
|
|
31
25
|
"devDependencies": {
|
|
32
26
|
"@types/node": "^22.15.0",
|
|
@@ -48,5 +42,14 @@
|
|
|
48
42
|
"type": "git",
|
|
49
43
|
"url": "https://github.com/faapi/faapi.git",
|
|
50
44
|
"directory": "packages/schema"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public",
|
|
48
|
+
"provenance": true
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsup",
|
|
52
|
+
"test": "vitest run --passWithNoTests",
|
|
53
|
+
"typecheck": "tsc --noEmit"
|
|
51
54
|
}
|
|
52
|
-
}
|
|
55
|
+
}
|