UNPKG

autosnippet

Version:

Extract code patterns into a knowledge base for AI coding assistants

189 lines (188 loc) 7.91 kB
/** * FastAPI Enhancement Pack * 条件: { languages: ['python'], frameworks: ['fastapi'] } * * 覆盖 FastAPI 全栈生态: * - 路由装饰器 + Pydantic 模型 * - Depends() 依赖注入 * - Middleware / CORS / BackgroundTask * - WebSocket * - SQLAlchemy / Tortoise ORM 集成模式 */ import { EnhancementPack } from './EnhancementPack.js'; class FastAPIEnhancement extends EnhancementPack { get id() { return 'fastapi'; } get displayName() { return 'FastAPI Enhancement'; } get conditions() { return { languages: ['python'], frameworks: ['fastapi'] }; } getExtraDimensions() { return [ { id: 'fastapi-route-scan', label: 'FastAPI 路由分析', guide: 'Route 装饰器(@app.get/post/put/delete)、APIRouter 分组、Pydantic Model/Schema、DI (Depends())、路由参数声明', tierHint: 2, knowledgeTypes: ['architecture', 'code-pattern'], skillWorthy: true, dualOutput: true, skillMeta: { name: 'project-fastapi-routes', description: 'FastAPI route definitions, Pydantic schemas and dependency injection (auto-generated by enhancement)', }, }, { id: 'fastapi-middleware-scan', label: 'FastAPI 中间件分析', guide: 'FastAPI Middleware 分析 — @app.middleware("http") 自定义中间件、CORS 配置、Trusted Host、GZip、BackgroundTasks 使用模式、Lifespan 事件 (startup/shutdown)', tierHint: 2, knowledgeTypes: ['architecture', 'code-pattern'], skillWorthy: true, dualOutput: true, skillMeta: { name: 'project-fastapi-middleware', description: 'FastAPI middleware stack, CORS config, lifespan events and background tasks (auto-generated by enhancement)', }, }, { id: 'fastapi-orm-scan', label: 'ORM / DB 模式分析', guide: 'ORM 集成分析 — SQLAlchemy 2.0 async session 模式 / Tortoise ORM model 定义、数据库迁移 (Alembic)、Repository Pattern、Session 生命周期管理 (get_db Depends)', tierHint: 2, knowledgeTypes: ['architecture', 'code-pattern'], skillWorthy: true, dualOutput: true, skillMeta: { name: 'project-fastapi-orm', description: 'FastAPI ORM integration — SQLAlchemy async sessions, Alembic migrations and repository patterns (auto-generated by enhancement)', }, }, ]; } getGuardRules() { return [ { ruleId: 'fastapi-sync-in-async', category: 'performance', dimension: 'file', severity: 'warning', languages: ['python'], pattern: /async\s+def\s+\w+[\s\S]*?(?:time\.sleep|open\(|os\.read|subprocess\.run)/, message: 'async 路由中不应使用阻塞操作 (time.sleep/open/subprocess.run) — 使用 asyncio 版本或 run_in_executor', }, { ruleId: 'fastapi-no-response-model', category: 'style', dimension: 'file', severity: 'info', languages: ['python'], pattern: /@(?:app|router)\.(?:get|post|put|delete|patch)\s*\([^)]*\)\s*\n\s*(?:async\s+)?def\s+\w+\([^)]*\)(?!\s*->)/, message: 'FastAPI 路由建议声明 response_model 或返回类型注解 — 便于自动生成 OpenAPI 文档', }, { ruleId: 'fastapi-bare-except', category: 'correctness', dimension: 'file', severity: 'warning', languages: ['python'], pattern: /except\s*:/, message: '避免 bare except — 使用 except Exception 或具体异常类,否则会吞掉 KeyboardInterrupt/SystemExit', }, { ruleId: 'fastapi-no-star-import', category: 'style', dimension: 'file', severity: 'warning', languages: ['python'], pattern: /from\s+\w+\s+import\s+\*/, message: '避免 star import (from x import *) — 使用显式 import 以保证类型检查和 IDE 支持', }, ]; } detectPatterns(astSummary) { const patterns = []; // ── Pydantic models ── for (const cls of astSummary.classes || []) { if (cls.superclass && /BaseModel|BaseSettings/.test(cls.superclass)) { patterns.push({ type: 'pydantic-model', className: cls.name, line: cls.line, confidence: 0.9, }); } } // ── FastAPI route handlers ── for (const m of astSummary.methods || []) { if (m.decorators?.some((d) => /@(?:app|router)\.(?:get|post|put|delete|patch|options|head)/.test(d))) { patterns.push({ type: 'fastapi-route', methodName: m.name, line: m.line, confidence: 0.95, }); } } // ── Dependency injection functions ── for (const m of astSummary.methods || []) { if (!m.className) { const nameLower = m.name?.toLowerCase() || ''; if (nameLower.startsWith('get_') && (nameLower.includes('db') || nameLower.includes('session') || nameLower.includes('current_user') || nameLower.includes('settings') || nameLower.includes('service'))) { patterns.push({ type: 'fastapi-dependency', methodName: m.name, line: m.line, confidence: 0.8, }); } } } // ── SQLAlchemy models ── for (const cls of astSummary.classes || []) { if (cls.superclass && /Base$|DeclarativeBase/.test(cls.superclass)) { patterns.push({ type: 'sqlalchemy-model', className: cls.name, line: cls.line, confidence: 0.85, }); } } // ── Exception handlers ── for (const cls of astSummary.classes || []) { if (cls.superclass && /HTTPException|Exception/.test(cls.superclass)) { patterns.push({ type: 'fastapi-exception', className: cls.name, line: cls.line, confidence: 0.75, }); } } // ── FastAPI ecosystem imports ── const fastapiImports = (astSummary.imports || []).filter((imp) => imp.includes('fastapi') || imp.includes('pydantic') || imp.includes('sqlalchemy') || imp.includes('tortoise') || imp.includes('alembic') || imp.includes('uvicorn')); if (fastapiImports.length > 0) { patterns.push({ type: 'fastapi-ecosystem-usage', importCount: fastapiImports.length, confidence: 0.85, }); } return patterns; } } export const pack = new FastAPIEnhancement();