项目模板
快速启动基于 OpenAPI 的项目开发
项目模板概览
我们提供了多种技术栈的项目模板,帮助你快速开始 API-First 开发:
使用项目生成器
安装项目生成器
bash
# 安装全局命令行工具
npm install -g @api-first/project-generator
# 或使用 npx(无需安装)
npx @api-first/project-generator create my-api交互式创建项目
bash
$ api-first create my-awesome-api
? 选择项目类型 (Use arrow keys)
❯ API 服务端
API 客户端
全栈应用
? 选择后端技术栈
❯ Java Spring Boot
Python FastAPI
Node.js Express
Go Gin
? 选择数据库
❯ PostgreSQL
MySQL
MongoDB
SQLite
? 需要哪些功能? (Press <space> to select)
❯ ◉ 用户认证 (JWT)
◉ API 文档 (Swagger/ReDoc)
◉ 数据验证
◉ 错误处理
◉ 日志记录
◉ 单元测试
◉ Docker 支持
? 初始化 Git 仓库? (Y/n) Y
正在创建项目...
✔ 下载模板
✔ 安装依赖
✔ 初始化数据库
✔ 生成示例代码
✔ 配置开发环境
项目创建成功!
开始使用:
cd my-awesome-api
npm run devJava Spring Boot 模板
项目结构
spring-boot-api-template/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/api/
│ │ │ ├── config/ # 配置类
│ │ │ ├── controller/ # REST 控制器
│ │ │ ├── service/ # 业务逻辑
│ │ │ ├── repository/ # 数据访问
│ │ │ ├── model/ # 数据模型
│ │ │ ├── dto/ # 数据传输对象
│ │ │ ├── mapper/ # 对象映射
│ │ │ ├── exception/ # 异常处理
│ │ │ ├── security/ # 安全配置
│ │ │ └── Application.java
│ │ └── resources/
│ │ ├── api/ # OpenAPI 规范
│ │ │ └── openapi.yaml
│ │ ├── application.yml # 应用配置
│ │ ├── application-dev.yml
│ │ └── application-prod.yml
│ └── test/
│ └── java/
│ └── com/example/api/
│ ├── integration/ # 集成测试
│ ├── unit/ # 单元测试
│ └── contract/ # 契约测试
├── pom.xml
├── Dockerfile
├── docker-compose.yml
├── .gitlab-ci.yml
└── README.md核心依赖配置
xml
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>
<groupId>com.example</groupId>
<artifactId>api-template</artifactId>
<version>1.0.0</version>
<properties>
<java.version>17</java.version>
<openapi-generator.version>7.1.0</openapi-generator.version>
<springdoc.version>2.2.0</springdoc.version>
<mapstruct.version>1.5.5.Final</mapstruct.version>
</properties>
<dependencies>
<!-- Spring Boot Starters -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- OpenAPI -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc.version}</version>
</dependency>
<!-- Database -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
<!-- Utilities -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- OpenAPI Generator Plugin -->
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>${openapi-generator.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/api/openapi.yaml</inputSpec>
<generatorName>spring</generatorName>
<apiPackage>com.example.api.controller</apiPackage>
<modelPackage>com.example.api.model</modelPackage>
<configOptions>
<delegatePattern>true</delegatePattern>
<useSpringBoot3>true</useSpringBoot3>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>示例代码
java
// Application.java
@SpringBootApplication
@EnableConfigurationProperties
@EnableJpaAuditing
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
// SecurityConfig.java
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/v1/auth/**").permitAll()
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
.requestMatchers("/actuator/health").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(exception -> exception
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
);
return http.build();
}
}
// GlobalExceptionHandler.java
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFound(ResourceNotFoundException ex) {
ErrorResponse error = ErrorResponse.builder()
.code("RESOURCE_NOT_FOUND")
.message(ex.getMessage())
.timestamp(LocalDateTime.now())
.build();
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
@ExceptionHandler(ValidationException.class)
public ResponseEntity<ErrorResponse> handleValidation(ValidationException ex) {
ErrorResponse error = ErrorResponse.builder()
.code("VALIDATION_ERROR")
.message("请求参数验证失败")
.details(ex.getErrors())
.timestamp(LocalDateTime.now())
.build();
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
}
}
// BaseEntity.java
@MappedSuperclass
@Getter
@Setter
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
private String id;
@CreatedDate
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
@Column(nullable = false)
private LocalDateTime updatedAt;
@Version
private Long version;
}Python FastAPI 模板
项目结构
fastapi-template/
├── app/
│ ├── api/
│ │ ├── __init__.py
│ │ ├── deps.py # 依赖注入
│ │ └── v1/
│ │ ├── __init__.py
│ │ ├── endpoints/ # API 端点
│ │ │ ├── __init__.py
│ │ │ ├── auth.py
│ │ │ └── users.py
│ │ └── router.py
│ ├── core/
│ │ ├── __init__.py
│ │ ├── config.py # 配置
│ │ ├── security.py # 安全工具
│ │ └── database.py # 数据库配置
│ ├── models/ # SQLAlchemy 模型
│ │ ├── __init__.py
│ │ ├── base.py
│ │ └── user.py
│ ├── schemas/ # Pydantic 模式
│ │ ├── __init__.py
│ │ └── user.py
│ ├── services/ # 业务逻辑
│ │ ├── __init__.py
│ │ └── user.py
│ ├── db/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ └── session.py
│ ├── tests/ # 测试
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── unit/
│ │ └── integration/
│ ├── alembic/ # 数据库迁移
│ │ └── versions/
│ ├── __init__.py
│ └── main.py # 应用入口
├── openapi/
│ └── openapi.yaml # OpenAPI 规范
├── scripts/
│ ├── generate_client.py
│ └── init_db.py
├── requirements.txt
├── requirements-dev.txt
├── Dockerfile
├── docker-compose.yml
├── .env.example
├── alembic.ini
├── pyproject.toml
└── README.md核心代码示例
python
# app/main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
import logging
from app.core.config import settings
from app.api.v1.router import api_router
from app.db.session import engine
from app.models.base import Base
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
# 启动时执行
logger.info("Starting up...")
# 创建数据库表
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield
# 关闭时执行
logger.info("Shutting down...")
app = FastAPI(
title=settings.PROJECT_NAME,
version=settings.VERSION,
openapi_url=f"{settings.API_V1_PREFIX}/openapi.json",
docs_url="/docs",
redoc_url="/redoc",
lifespan=lifespan
)
# CORS 配置
app.add_middleware(
CORSMiddleware,
allow_origins=settings.BACKEND_CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 路由
app.include_router(api_router, prefix=settings.API_V1_PREFIX)
# 健康检查
@app.get("/health")
async def health_check():
return {"status": "healthy", "version": settings.VERSION}
# app/core/config.py
from pydantic_settings import BaseSettings
from typing import List, Optional
from functools import lru_cache
class Settings(BaseSettings):
PROJECT_NAME: str = "FastAPI Template"
VERSION: str = "1.0.0"
API_V1_PREFIX: str = "/api/v1"
# 数据库配置
DATABASE_URL: str = "postgresql+asyncpg://user:pass@localhost/db"
# 安全配置
SECRET_KEY: str = "your-secret-key"
ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
# CORS
BACKEND_CORS_ORIGINS: List[str] = ["http://localhost:3000"]
# Redis
REDIS_URL: Optional[str] = None
class Config:
env_file = ".env"
case_sensitive = True
@lru_cache()
def get_settings():
return Settings()
settings = get_settings()
# app/api/deps.py
from typing import Generator, Optional
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from sqlalchemy.ext.asyncio import AsyncSession
from jose import jwt, JWTError
from app.db.session import async_session
from app.core.config import settings
from app.models.user import User
from app.services.user import UserService
oauth2_scheme = OAuth2PasswordBearer(tokenUrl=f"{settings.API_V1_PREFIX}/auth/login")
async def get_db() -> Generator:
async with async_session() as session:
try:
yield session
finally:
await session.close()
async def get_current_user(
db: AsyncSession = Depends(get_db),
token: str = Depends(oauth2_scheme)
) -> User:
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
user_id: str = payload.get("sub")
if user_id is None:
raise credentials_exception
except JWTError:
raise credentials_exception
user_service = UserService(db)
user = await user_service.get_by_id(user_id)
if user is None:
raise credentials_exception
return user
# app/models/base.py
from sqlalchemy import Column, DateTime, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import func
import uuid
Base = declarative_base()
class BaseModel(Base):
__abstract__ = True
id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now(), server_default=func.now())
# app/schemas/base.py
from pydantic import BaseModel, ConfigDict
from datetime import datetime
from typing import Optional
class BaseSchema(BaseModel):
model_config = ConfigDict(from_attributes=True)
class BaseResponseSchema(BaseSchema):
id: str
created_at: datetime
updated_at: datetimeDocker 配置
dockerfile
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
# 安装系统依赖
RUN apt-get update && apt-get install -y \
gcc \
&& rm -rf /var/lib/apt/lists/*
# 安装 Python 依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY . .
# 运行应用
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]yaml
# docker-compose.yml
version: '3.8'
services:
api:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql+asyncpg://postgres:postgres@db:5432/api_db
- REDIS_URL=redis://redis:6379
depends_on:
- db
- redis
volumes:
- ./app:/app/app
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
db:
image: postgres:15
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=api_db
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
redis:
image: redis:7-alpine
ports:
- "6379:6379"
pgadmin:
image: dpage/pgadmin4
environment:
- PGADMIN_DEFAULT_EMAIL=admin@example.com
- PGADMIN_DEFAULT_PASSWORD=admin
ports:
- "5050:80"
depends_on:
- db
volumes:
postgres_data:Node.js Express 模板
项目结构
express-api-template/
├── src/
│ ├── api/
│ │ ├── controllers/ # 控制器
│ │ ├── middlewares/ # 中间件
│ │ ├── routes/ # 路由
│ │ └── validators/ # 验证器
│ ├── config/ # 配置
│ │ ├── database.ts
│ │ ├── logger.ts
│ │ └── swagger.ts
│ ├── models/ # 数据模型
│ ├── services/ # 业务逻辑
│ ├── types/ # TypeScript 类型
│ ├── utils/ # 工具函数
│ ├── app.ts # Express 应用
│ └── server.ts # 服务器入口
├── tests/
│ ├── unit/
│ ├── integration/
│ └── fixtures/
├── openapi/
│ └── openapi.yaml
├── scripts/
│ ├── generate-types.ts
│ └── seed-db.ts
├── package.json
├── tsconfig.json
├── .eslintrc.js
├── .prettierrc
├── jest.config.js
├── Dockerfile
├── docker-compose.yml
└── README.md核心代码示例
typescript
// src/app.ts
import express, { Application } from 'express';
import cors from 'cors';
import helmet from 'helmet';
import compression from 'compression';
import morgan from 'morgan';
import swaggerUi from 'swagger-ui-express';
import { OpenAPIV3 } from 'openapi-types';
import { errorHandler } from './api/middlewares/errorHandler';
import { notFoundHandler } from './api/middlewares/notFoundHandler';
import { apiLimiter } from './api/middlewares/rateLimiter';
import routes from './api/routes';
import { logger } from './config/logger';
import { loadOpenAPISpec } from './config/swagger';
export const createApp = async (): Promise<Application> => {
const app = express();
// 基础中间件
app.use(helmet());
app.use(cors());
app.use(compression());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 日志
app.use(morgan('combined', { stream: { write: (message) => logger.info(message.trim()) } }));
// API 限流
app.use('/api/', apiLimiter);
// API 文档
const openApiSpec = await loadOpenAPISpec();
app.use('/docs', swaggerUi.serve, swaggerUi.setup(openApiSpec as OpenAPIV3.Document));
// 健康检查
app.get('/health', (req, res) => {
res.json({ status: 'healthy', timestamp: new Date().toISOString() });
});
// API 路由
app.use('/api/v1', routes);
// 错误处理
app.use(notFoundHandler);
app.use(errorHandler);
return app;
};
// src/server.ts
import { createApp } from './app';
import { connectDatabase } from './config/database';
import { logger } from './config/logger';
import { config } from './config/environment';
const startServer = async () => {
try {
// 连接数据库
await connectDatabase();
// 创建应用
const app = await createApp();
// 启动服务器
const server = app.listen(config.port, () => {
logger.info(`🚀 Server is running on port ${config.port}`);
logger.info(`📚 API Documentation available at http://localhost:${config.port}/docs`);
});
// 优雅关闭
const gracefulShutdown = async (signal: string) => {
logger.info(`${signal} received. Starting graceful shutdown...`);
server.close(() => {
logger.info('HTTP server closed');
});
// 关闭数据库连接等资源
// await closeDatabase();
process.exit(0);
};
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
} catch (error) {
logger.error('Failed to start server:', error);
process.exit(1);
}
};
startServer();
// src/api/middlewares/auth.ts
import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
import { config } from '../../config/environment';
export interface AuthRequest extends Request {
user?: {
id: string;
email: string;
roles: string[];
};
}
export const authenticate = async (
req: AuthRequest,
res: Response,
next: NextFunction
): Promise<void> => {
try {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
res.status(401).json({ error: 'Authentication required' });
return;
}
const decoded = jwt.verify(token, config.jwtSecret) as any;
req.user = {
id: decoded.sub,
email: decoded.email,
roles: decoded.roles || []
};
next();
} catch (error) {
res.status(401).json({ error: 'Invalid token' });
}
};
export const authorize = (...roles: string[]) => {
return (req: AuthRequest, res: Response, next: NextFunction): void => {
if (!req.user) {
res.status(401).json({ error: 'Authentication required' });
return;
}
const hasRole = roles.some(role => req.user!.roles.includes(role));
if (!hasRole) {
res.status(403).json({ error: 'Insufficient permissions' });
return;
}
next();
};
};
// src/api/controllers/base.controller.ts
import { Request, Response } from 'express';
import { validationResult } from 'express-validator';
export abstract class BaseController {
protected validateRequest(req: Request, res: Response): boolean {
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({
error: 'Validation failed',
details: errors.array()
});
return false;
}
return true;
}
protected success(res: Response, data: any, statusCode: number = 200): void {
res.status(statusCode).json({
success: true,
data
});
}
protected error(res: Response, message: string, statusCode: number = 500, details?: any): void {
res.status(statusCode).json({
success: false,
error: message,
...(details && { details })
});
}
}快速启动脚本
一键启动脚本
bash
#!/bin/bash
# quick-start.sh
echo "🚀 API-First 项目快速启动"
echo "========================"
# 选择模板
PS3="请选择项目模板: "
options=("Java Spring Boot" "Python FastAPI" "Node.js Express" "退出")
select opt in "${options[@]}"
do
case $opt in
"Java Spring Boot")
TEMPLATE="spring-boot"
break
;;
"Python FastAPI")
TEMPLATE="fastapi"
break
;;
"Node.js Express")
TEMPLATE="express"
break
;;
"退出")
exit 0
;;
*) echo "无效选项 $REPLY";;
esac
done
# 输入项目名称
read -p "请输入项目名称: " PROJECT_NAME
# 克隆模板
echo "📦 下载项目模板..."
git clone https://github.com/api-first/templates.git temp_template
cp -r temp_template/$TEMPLATE $PROJECT_NAME
rm -rf temp_template
cd $PROJECT_NAME
# 初始化项目
echo "🔧 初始化项目..."
case $TEMPLATE in
"spring-boot")
./mvnw clean install
;;
"fastapi")
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
;;
"express")
npm install
;;
esac
# 初始化 Git
echo "📝 初始化 Git 仓库..."
git init
git add .
git commit -m "Initial commit from API-First template"
# 启动说明
echo ""
echo "✅ 项目创建成功!"
echo ""
echo "开始开发:"
echo " cd $PROJECT_NAME"
case $TEMPLATE in
"spring-boot")
echo " ./mvnw spring-boot:run"
;;
"fastapi")
echo " source venv/bin/activate"
echo " uvicorn app.main:app --reload"
;;
"express")
echo " npm run dev"
;;
esac
echo ""
echo "查看 API 文档:"
echo " http://localhost:8080/docs"项目配置生成器
交互式配置文件生成
typescript
// scripts/generate-config.ts
import inquirer from 'inquirer';
import fs from 'fs/promises';
import yaml from 'js-yaml';
interface ProjectConfig {
projectName: string;
projectType: string;
database: string;
features: string[];
authentication: string;
deployment: string;
}
async function generateConfig() {
const answers = await inquirer.prompt<ProjectConfig>([
{
type: 'input',
name: 'projectName',
message: '项目名称:',
default: 'my-api'
},
{
type: 'list',
name: 'projectType',
message: '项目类型:',
choices: ['REST API', 'GraphQL API', 'WebSocket API', '混合']
},
{
type: 'list',
name: 'database',
message: '数据库:',
choices: ['PostgreSQL', 'MySQL', 'MongoDB', 'SQLite', 'None']
},
{
type: 'checkbox',
name: 'features',
message: '选择功能:',
choices: [
{ name: '用户认证', value: 'auth' },
{ name: '文件上传', value: 'upload' },
{ name: '邮件发送', value: 'email' },
{ name: '消息队列', value: 'queue' },
{ name: '缓存', value: 'cache' },
{ name: 'WebSocket', value: 'websocket' },
{ name: '定时任务', value: 'cron' },
{ name: '国际化', value: 'i18n' }
]
},
{
type: 'list',
name: 'authentication',
message: '认证方式:',
choices: ['JWT', 'OAuth2', 'API Key', 'Basic Auth', 'None'],
when: (answers) => answers.features.includes('auth')
},
{
type: 'list',
name: 'deployment',
message: '部署目标:',
choices: ['Docker', 'Kubernetes', 'Serverless', 'Traditional']
}
]);
// 生成配置文件
const config = generateProjectConfig(answers);
// 保存配置
await fs.writeFile('project-config.yaml', yaml.dump(config));
await fs.writeFile('project-config.json', JSON.stringify(config, null, 2));
console.log('✅ 配置文件已生成!');
console.log('\n下一步:');
console.log(' npx @api-first/generator init --config project-config.yaml');
}
function generateProjectConfig(answers: ProjectConfig) {
const config: any = {
name: answers.projectName,
type: answers.projectType,
version: '1.0.0',
features: answers.features,
database: answers.database !== 'None' ? {
type: answers.database,
host: 'localhost',
port: getDatabasePort(answers.database),
name: `${answers.projectName}_db`
} : null,
server: {
port: 8080,
cors: {
enabled: true,
origins: ['http://localhost:3000']
}
},
openapi: {
version: '3.0.3',
info: {
title: `${answers.projectName} API`,
version: '1.0.0'
}
}
};
if (answers.features.includes('auth')) {
config.authentication = {
type: answers.authentication,
secret: generateSecret(),
expiresIn: '24h'
};
}
if (answers.features.includes('cache')) {
config.cache = {
type: 'redis',
host: 'localhost',
port: 6379
};
}
if (answers.deployment === 'Docker') {
config.docker = {
registry: 'docker.io',
image: `${answers.projectName}:latest`
};
}
return config;
}
function getDatabasePort(database: string): number {
const ports: Record<string, number> = {
PostgreSQL: 5432,
MySQL: 3306,
MongoDB: 27017,
SQLite: 0
};
return ports[database] || 5432;
}
function generateSecret(): string {
return require('crypto').randomBytes(32).toString('hex');
}
// 运行生成器
generateConfig().catch(console.error);最佳实践
1. 项目初始化检查清单
- [ ] OpenAPI 规范文件已创建
- [ ] 数据库架构已设计
- [ ] 环境变量已配置
- [ ] Git 仓库已初始化
- [ ] CI/CD 配置已添加
- [ ] README 文档已更新
- [ ] 测试框架已配置
- [ ] 代码质量工具已设置
- [ ] Docker 配置已完成
- [ ] 日志系统已配置
2. 目录结构规范
project-root/
├── api/ # OpenAPI 规范
├── src/ # 源代码
├── tests/ # 测试代码
├── docs/ # 文档
├── scripts/ # 脚本
├── config/ # 配置文件
├── docker/ # Docker 相关
└── .github/ # GitHub 配置3. 命名约定
- 文件名: kebab-case (user-service.ts)
- 类名: PascalCase (UserService)
- 函数名: camelCase (getUserById)
- 常量: UPPER_SNAKE_CASE (MAX_RETRY_COUNT)
- 接口: IPascalCase (IUserService)
总结
使用项目模板的优势:
- 🚀 快速启动: 几分钟内开始开发
- 📐 最佳实践: 内置行业最佳实践
- 🔧 预配置: 所有工具已配置好
- 📚 文档齐全: 包含详细使用说明
- 🎯 专注业务: 专注于业务逻辑开发
选择合适的模板,快速开始你的 API-First 项目!