mirror of
https://github.com/34892002/edgeKey.git
synced 2026-05-07 07:39:23 +08:00
16 KiB
16 KiB
EdgeKey 项目开发规范指南
本指南为AI助手提供EdgeKey项目开发迭代的标准流程和规范要求,确保代码质量和项目一致性。
项目架构概览
技术栈
- 前端框架: Vue 3 + Vike(文件路由 + SSR)
- 服务端: Hono(路由与中间件)
- 运行时: Cloudflare Workers
- 数据库: Cloudflare D1(原生SQLite)
- ORM: Prisma(Cloudflare适配器)
- UI框架: Tailwind CSS + daisyUI
- 构建工具: Vite + Bun
- 认证: Auth.js(管理员账号密码登录)
- 数据变更: Telefunc(前后端同构RPC)
核心约束
-
Cloudflare Workers环境限制:
- 禁止依赖
node:fs、node:path等Node.js原生模块 - 使用Web Crypto API(
crypto.subtle)处理签名,避免第三方加密库 - 脚本体积限制(免费版3MB),引入新依赖必须经过批准
- 禁止依赖
-
数据库特殊性:
- 使用Cloudflare D1(SQLite),非传统数据库
- 开发环境使用本地D1模拟器,生产环境使用远程D1
- 禁止使用
prisma migrate dev,必须使用特定迁移工作流
开发流程规范
1. 环境准备
# 安装依赖(推荐使用Bun)
bun install
# 生成Prisma客户端(必须)
bun run db:generate
# 初始化本地数据库
bun run db:migrations:local
bun run db:seed
# 启动开发服务器
bun run dev
2. 数据库变更流程
重要: 修改数据库表结构时必须遵循以下流程:
步骤1: 修改Schema并生成迁移SQL
# 修改 prisma/schema.prisma 后,使用prisma migrate diff生成SQL
bunx prisma migrate diff \
--from-migrations prisma/migrations \
--to-schema prisma/schema.prisma \
--script > prisma/migrations/000X_描述.sql
步骤2: 同步到本地开发环境
bun run db:migrations:local
步骤3: 部署前同步到生产环境
bun run db:migrations:remote
禁止操作:
- ❌ 使用
prisma migrate dev - ❌ 反复覆盖初始化迁移文件
0001_init.sql - ❌ 假设
bun dev使用的是prisma/db.sqlite
3. 代码提交与部署
# 构建项目
bun run build
# 本地预览构建结果
bun run preview
# 部署到Cloudflare Workers
bun run deploy
# 或等效命令
bun run up
代码规范
1. 文件组织
- 页面文件:
pages/目录,遵循Vike文件路由约定 - 组件:
components/目录,通用组件 - 业务逻辑:
lib/目录 - 功能模块:
modules/目录 - 服务端:
server/目录 - 数据库:
prisma/目录 - 静态资源:
assets/目录
2. 命名规范
- Vue组件: PascalCase(如
AppButton.vue) - TypeScript文件: camelCase(如
order-utils.ts) - 数据库模型: PascalCase(如
Admin、Order) - 数据库字段: camelCase(如
createdAt、paymentStatus)
3. 组件开发规范
- 使用
<script setup>语法 - Props定义必须包含类型和默认值
- 事件使用
emit函数触发 - 样式优先使用Tailwind CSS类,必要时使用daisyUI组件
4. Telefunc使用规范
- Telefunc函数放在对应页面目录下,以
.telefunc.ts结尾 - 函数命名:
on[Action](如onCreateOrder、onUpdateProduct) - 返回类型必须明确声明
5. 日志规范
使用项目内置的logger模块:
import { logger } from '@/lib/logger';
// 信息日志
logger.info('操作成功', { userId: 123, action: 'create_order' });
// 警告日志
logger.warn('库存不足', { productId: 456, stock: 2 });
// 错误日志
logger.error('支付失败', error, { orderId: 'ORD001' });
// 创建子日志记录器(带默认上下文)
const orderLogger = logger.child({ module: 'order', service: 'create' });
orderLogger.info('订单创建开始', { orderNo: 'ORD001' });
日志级别使用原则:
info: 业务流程关键节点、重要操作记录warn: 可恢复的异常、资源不足、配置问题error: 不可恢复的错误、系统异常
Cloudflare Workers限制:
console.debug不会出现在Cloudflare Dashboard中- 统一使用
info、warn、error三个级别
日志上下文自动注入:
- 请求上下文(requestId、method、path、cfRay)自动注入
- 错误对象自动序列化(包含name、message、stack、code、statusCode、details)
- 支持AppError和普通Error的序列化
日志格式示例:
{
"timestamp": "2024-01-01T00:00:00.000Z",
"level": "error",
"requestId": "abc123",
"method": "POST",
"path": "/api/orders",
"cfRay": "xyz789",
"message": "支付失败",
"error": {
"name": "AppError",
"message": "支付网关返回错误",
"stack": "...",
"code": "PAYMENT_GATEWAY_ERROR",
"statusCode": 400,
"details": { "provider": "bepusdt", "orderId": "ORD001" }
},
"module": "payment",
"service": "verify"
}
架构设计规范
1. 中间件使用
- 请求上下文: 通过
createRequestContext和runWithRequestContext管理 - 数据库注入: 通过
prismaMiddleware注入Prisma实例 - 认证: 通过
authjsSessionMiddleware处理会话 - API路由: 独立的Hono子应用,优先于页面路由
2. 错误处理
使用项目内置的错误处理机制:
import { AppError, toAppError, badRequestError, notFoundError, conflictError, unauthorizedError } from '@/lib/app-error';
// 使用预定义的错误工厂函数
throw notFoundError('订单不存在', 'ORDER_NOT_FOUND');
throw badRequestError('购买数量不合法', 'ORDER_QUANTITY_INVALID');
throw conflictError('数据已存在,请检查是否重复', 'UNIQUE_CONSTRAINT');
throw unauthorizedError('请先登录管理员账号');
// 或使用通用AppError
throw new AppError('自定义错误消息', {
code: 'CUSTOM_ERROR',
statusCode: 400,
details: { field: 'value' }
});
// 转换未知错误(自动处理Prisma错误、Telefunc错误等)
try {
// 业务逻辑
} catch (error) {
const appError = toAppError(error);
logger.error('操作失败', appError);
throw appError;
}
// 断言条件
assertCondition(order != null, notFoundError('订单不存在'));
// 获取错误消息(兼容字符串、Error、AppError)
const message = getErrorMessage(error, '未知错误');
错误工厂函数:
badRequestError(): 400 - 请求参数错误unauthorizedError(): 401 - 未授权forbiddenError(): 403 - 禁止访问notFoundError(): 404 - 资源不存在conflictError(): 409 - 数据冲突rateLimitError(): 429 - 请求过于频繁externalServiceError(): 502 - 外部服务错误internalServerError(): 500 - 服务器内部错误
错误转换规则:
- Prisma P2002错误 → 冲突错误(唯一约束冲突)
- Telefunc Abort错误 → 自动提取错误信息
- "Unauthorized"错误 → 未授权错误
- 其他错误 → 内部服务器错误
错误响应格式:
// toErrorResponsePayload() 返回标准格式
{
message: string; // 用户友好的错误消息(expose为false时返回通用消息)
code?: string; // 错误代码
statusCode: number; // HTTP状态码
}
3. 实用工具函数
项目提供多个实用工具函数:
import { formatMoney, parseMoney } from '@/lib/utils/money';
import { getOrderStatusLabel, getOrderStatusType } from '@/lib/utils/order-status';
import { formatDate, formatRelativeTime } from '@/lib/utils/time';
import { generateOrderNo, generateQueryToken } from '@/lib/utils/order';
import { hashPassword, verifyPassword } from '@/lib/utils/crypto';
import { detectDeviceType } from '@/lib/utils/device';
// 金额处理(单位:分)
const formatted = formatMoney(1000); // '10.00'
const cents = parseMoney('10.00'); // 1000
// 订单状态标签
const label = getOrderStatusLabel('PAID'); // '已支付'
const type = getOrderStatusType('PAID'); // 'success'
// 时间格式化
const dateStr = formatDate(new Date()); // '2024-01-01'
const relative = formatRelativeTime(new Date()); // '刚刚'
// 订单号生成
const orderNo = generateOrderNo(); // 'ORD20240101001'
const queryToken = generateQueryToken(); // 32位随机字符串
// 密码处理(使用bcrypt)
const hash = await hashPassword('password123');
const isValid = await verifyPassword('password123', hash);
// 设备检测
const device = detectDeviceType(request); // 'mobile' | 'desktop'
4. 常量和类型定义
项目定义的常量和类型:
// 常量定义
import { PAYMENT_PROVIDERS } from '@/lib/constants/payment';
import { ORDER_QUERY_TOKEN_LENGTH } from '@/lib/constants/order';
import { PRODUCT_STATUS, ORDER_STATUS } from '@/lib/constants/product';
// 类型定义
import type { Order, OrderStatus, PaymentStatus } from '@/lib/types/order';
import type { Product, ProductStatus } from '@/lib/types/product';
import type { SiteSetting } from '@/lib/types/site';
import type { CommonResponse, PaginatedResponse } from '@/lib/types/common';
数据库枚举类型:
AdminStatus: ACTIVE, DISABLEDCategoryStatus: ACTIVE, DISABLEDProductStatus: DRAFT, ACTIVE, INACTIVEProductDeliveryType: CARD_AUTO, MANUALProductStockMode: FINITE, UNLIMITEDCardStatus: UNUSED, LOCKED, SOLD, DISABLEDContactType: EMAIL, QQ, TELEGRAM, OTHEROrderStatus: PENDING, PAID, DELIVERED, CLOSED, FAILEDPaymentStatus: UNPAID, PAID, FAILEDDeliveryStatus: NOT_DELIVERED, DELIVERED, FAILEDEmailChannel: API, SMTP, CLOUDFLAREEmailScene: TEST, ORDER_PAID, DELIVERY_SUCCESS, DELIVERY_FAILED
5. 重要项目文件
以下是开发时需要了解的关键文件:
核心配置文件:
package.json: 项目依赖和脚本命令vite.config.ts: Vite构建配置(包含Vike、Vue、Tailwind、Telefunc插件)wrangler.jsonc: Cloudflare Workers部署配置(包含D1数据库绑定)prisma/schema.prisma: 数据库模型定义
服务端入口:
server/entry.ts: 服务端主入口(Hono应用、中间件链)server/authjs-handler.ts: Auth.js认证处理器server/prisma-middleware.ts: Prisma D1注入中间件server/telefunc-handler.ts: Telefunc RPC处理器
核心库文件:
lib/logger.ts: 日志模块(自动注入请求上下文、错误序列化)lib/app-error.ts: 错误处理模块(AppError类、错误工厂函数)lib/request-context.ts: 请求上下文管理(AsyncLocalStorage)
业务模块:
modules/payment/: 支付相关(适配器、服务、路由)modules/email/: 邮件相关(模板、发送、日志)modules/order/: 订单管理modules/inventory/: 库存管理
前端页面:
pages/: Vike文件路由目录components/: 通用Vue组件assets/: 静态资源
6. Telefunc使用模式
Telefunc提供前后端同构的数据变更RPC:
// pages/admin/orders/createOrder.telefunc.ts
import { getContext } from 'telefunc';
import type { PrismaClient } from '../../generated/prisma/client';
import { badRequestError } from '../../lib/app-error';
import { logger } from '../../lib/logger';
import { validateOrderInput } from '../../lib/validators/order';
export async function onCreateOrder(input: {
productId: number;
quantity: number;
contactValue: string;
}) {
// 获取上下文(自动包含Prisma实例)
const { prisma } = getContext() as { prisma: PrismaClient };
// 验证输入
const validated = validateOrderInput(input);
// 业务逻辑
const order = await prisma.order.create({
data: {
orderNo: generateOrderNo(),
productId: input.productId,
quantity: validated.quantity,
contactValue: validated.contactValue,
// ... 其他字段
}
});
logger.info('订单创建成功', { orderNo: order.orderNo });
return { orderNo: order.orderNo };
}
Telefunc约定:
- 函数放在页面目录下,以
.telefunc.ts结尾 - 命名规范:
on[Action](如onCreateOrder、onUpdateProduct) - 通过
getContext()获取请求上下文(包含prisma实例) - 返回值自动序列化为JSON
- 错误会自动转换为Telefunc Abort格式
本地开发与生产环境差异:
- 本地开发: 使用Wrangler D1模拟器
- 生产环境: 使用Cloudflare远程D1
- 数据库绑定:
env.DB在两个环境中都可用 - Prisma配置: 运行时使用
env.DB,CLI使用DATABASE_URL
文档维护
1. 更新README.md
重大功能变更后,更新README.md中的功能特性和项目截图。
2. 更新组件文档
新增或修改公共组件时,更新docs/components.md。
3. 更新支付网关文档
新增支付网关时,更新docs/payment-gateway-guide.md。
代码审查要点
1. 安全性
- 密码是否使用bcrypt加密
- API密钥是否硬编码
- SQL注入防护(Prisma自动处理)
2. 性能
- 数据库查询是否优化
- 是否有N+1查询问题
- 静态资源是否优化
3. 可维护性
- 代码是否有适当注释
- 是否遵循项目架构规范
- 是否有重复代码
参考资源
-
项目文档:
README.md: 项目概述和快速开始docs/components.md: 组件使用指南docs/payment-gateway-guide.md: 支付网关开发指南
-
官方文档:
- Vike: 文件路由框架
- Vue 3: 前端框架
- Hono: 服务端框架
- Prisma: ORM框架
- Cloudflare Workers: 运行时环境
-
工具文档:
重要提醒: 在进行任何修改前,请确保理解项目架构和约束条件。对于不确定的操作,建议先在开发环境测试,确认无误后再部署到生产环境。
快速参考
常用命令
# 开发
bun install # 安装依赖
bun run dev # 启动开发服务器
bun run build # 构建项目
bun run preview # 预览构建结果
# 数据库
bun run db:generate # 生成Prisma客户端
bun run db:migrations:local # 应用迁移到本地D1
bun run db:migrations:remote # 应用迁移到远程D1
bun run db:seed # 本地种子数据
bun run db:seed:remote # 远程种子数据
bun run db:studio # Prisma Studio
# 部署
bun run deploy # 部署到Cloudflare Workers
bun run up # 构建并部署
bun run types # 生成Wrangler类型
常见模式
// 1. 日志记录
import { logger } from '@/lib/logger';
logger.info('操作成功', { key: 'value' });
logger.error('操作失败', error);
// 2. 错误处理
import { notFoundError, badRequestError } from '@/lib/app-error';
throw notFoundError('资源不存在');
// 3. 输入验证
import { validateOrderInput } from '@/lib/validators/order';
const data = validateOrderInput(input);
// 4. Telefunc函数
import { getContext } from 'telefunc';
const { prisma } = getContext() as { prisma: PrismaClient };
// 5. 数据库查询
const orders = await prisma.order.findMany({
where: { status: 'PAID' },
include: { product: true },
skip: 0,
take: 20
});
项目结构速查
edgeKey/
├── pages/ # Vike页面路由
├── components/ # Vue组件
├── lib/ # 核心库(logger、error、utils)
├── modules/ # 业务模块(payment、email、order)
├── server/ # 服务端(Hono、中间件)
├── prisma/ # 数据库模型和迁移
├── assets/ # 静态资源
└── docs/ # 文档
关键约束速查
- ❌ 禁止使用
node:fs、node:path等Node.js原生模块 - ❌ 禁止使用
prisma migrate dev - ✅ 使用Web Crypto API处理签名
- ✅ 使用项目内置的logger模块
- ✅ 遵循数据库迁移工作流
- ✅ 生产环境必须配置AUTH_SECRET