autosnippet
Version:
Extract code patterns into a knowledge base for AI coding assistants
189 lines (188 loc) • 7.91 kB
JavaScript
/**
* 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();