Files
edgeKey/docs/development-guide.md
2026-05-21 22:41:03 +08:00

12 KiB
Raw Permalink Blame History

EdgeKey 项目开发规范指南

本指南为AI助手提供EdgeKey项目开发迭代的标准流程和规范要求确保代码质量和项目一致性。

项目架构概览

技术栈

  • 前端框架: Vue 3 + Vike文件路由 + SSR
  • 服务端: Hono路由与中间件
  • 运行时: Cloudflare Workers
  • 数据库: Cloudflare D1原生SQLite
  • ORM: PrismaCloudflare适配器
  • UI框架: Tailwind CSS + daisyUI
  • 构建工具: Vite + Bun
  • 认证: Auth.js管理员账号密码登录
  • 数据变更: Telefunc前后端同构RPC

核心约束

  1. Cloudflare Workers环境限制:

    • 禁止依赖node:fsnode:path等Node.js原生模块
    • 使用Web Crypto APIcrypto.subtle)处理签名,避免第三方加密库
    • 脚本体积限制免费版3MB引入新依赖必须经过批准
  2. 数据库特殊性:

    • 使用Cloudflare D1SQLite非传统数据库
    • 开发环境使用本地D1模拟器生产环境使用远程D1
    • 禁止使用prisma migrate dev,必须使用特定迁移工作流

项目结构

edgeKey/
├── pages/           # Vike页面路由
├── components/      # Vue组件
├── lib/             # 核心库logger、error、http-client、utils
├── modules/         # 业务模块payment、email、order
├── server/          # 服务端Hono、中间件
├── prisma/          # 数据库模型和迁移
├── assets/          # 静态资源
└── docs/            # 文档

核心库文件:

  • lib/logger.ts: 日志模块(自动注入请求上下文、错误序列化)
  • lib/app-error.ts: 错误处理模块AppError类、错误工厂函数
  • lib/http-client.ts: HTTP 客户端(统一请求封装,支持超时、重试)
  • lib/request-context.ts: 请求上下文管理AsyncLocalStorage

开发流程规范

1. 环境准备

bun install              # 安装依赖
bun run db:generate      # 生成Prisma客户端
bun run db:migrations:local  # 初始化本地数据库
bun run db:seed          # 初始化种子数据
bun run dev              # 启动开发服务器

2. 数据库变更流程

重要: 修改数据库表结构时必须遵循以下流程:

步骤1: 修改Schema并生成迁移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

3. 代码提交与部署

bun run build    # 构建项目
bun run preview  # 本地预览构建结果
bun run deploy   # 部署到Cloudflare Workers
# 或
bun run up       # 构建并部署

代码规范

文件组织

  • 页面文件: pages/目录遵循Vike文件路由约定
  • 组件: components/目录,通用组件
  • 业务逻辑: lib/目录
  • 功能模块: modules/目录
  • 服务端: server/目录
  • 数据库: prisma/目录
  • 静态资源: assets/目录

命名规范

  • Vue组件: PascalCaseAppButton.vue
  • TypeScript文件: camelCaseorder-utils.ts
  • 数据库模型: PascalCaseAdminOrder
  • 数据库字段: camelCasecreatedAtpaymentStatus

TypeScript 类型引用规范

所有类型引用必须在文件顶部使用 import type 导入,禁止在变量声明、函数参数、泛型等位置使用内联 import() 写法。

// bad禁止内联引用
function handle(data: import("./types").SomeType) { ... }
// good顶部统一导入
import type { SomeType } from "./types";
function handle(data: SomeType) { ... }

组件开发规范

优先使用全局组件:开发新功能前,先查看 docs/components.md 中是否已有可复用的组件。优先使用项目提供的全局组件,没有的才自己开发。

常用全局组件:

  • AppButton: 统一按钮,支持 loading、variant、href 等
  • SecretInput: 密码/密钥输入框,支持显示/隐藏
  • StatusTag: 状态标签
  • ConfirmDialog: 确认对话框
  • DataTable: 数据表格
  • FilePickerModal: 文件选择弹窗

开发新组件时

  • 使用<script setup>语法
  • Props定义必须包含类型和默认值
  • 事件使用emit函数触发
  • 样式优先使用Tailwind CSS类必要时使用daisyUI组件
  • 如果是通用组件,应放在 components/ 目录并更新 docs/components.md

架构设计规范

1. 中间件使用

  • 请求上下文: 通过createRequestContextrunWithRequestContext管理
  • 数据库注入: 通过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('请先登录管理员账号');

// 转换未知错误
try {
  // 业务逻辑
} catch (error) {
  const appError = toAppError(error);
  logger.error('操作失败', appError);
  throw appError;
}

错误工厂函数:

  • badRequestError(): 400 - 请求参数错误
  • unauthorizedError(): 401 - 未授权
  • forbiddenError(): 403 - 禁止访问
  • notFoundError(): 404 - 资源不存在
  • conflictError(): 409 - 数据冲突
  • rateLimitError(): 429 - 请求过于频繁
  • externalServiceError(): 502 - 外部服务错误
  • internalServerError(): 500 - 服务器内部错误

3. HTTP 客户端

项目提供统一的 HTTP 请求封装,支持超时、重试、错误处理:

import { httpRequest, httpPost } from '@/lib/http-client';

// GET 请求
const { ok, status, data } = await httpRequest('https://api.example.com/data', {
  headers: { Authorization: 'Bearer token' },
  timeoutMs: 10000,
  retries: 2,
});

// POST 请求
const { ok, status, data } = await httpPost('https://api.example.com/send', {
  to: 'user@example.com',
  subject: 'Hello',
}, {
  headers: { 'api-key': 'xxx' },
  timeoutMs: 15000,
});

参数说明:

  • timeoutMs: 请求超时时间(默认 15000ms
  • retries: 重试次数(默认 0
  • retryDelayMs: 重试间隔(默认 1000ms
  • headers: 自定义请求头(自动包含 Content-Type 和 User-Agent

4. 日志规范

使用项目内置的logger模块:

import { logger } from '@/lib/logger';

logger.info('操作成功', { userId: 123, action: 'create_order' });
logger.warn('库存不足', { productId: 456, stock: 2 });
logger.error('支付失败', error, { orderId: 'ORD001' });

日志级别使用原则:

  • info: 业务流程关键节点、重要操作记录
  • warn: 可恢复的异常、资源不足、配置问题
  • error: 不可恢复的错误、系统异常

Telefunc 使用规范

  • Telefunc函数放在对应页面目录下.telefunc.ts结尾
  • 函数命名: on[Action](如onCreateOrderonUpdateProduct
  • 通过getContext()获取请求上下文包含prisma实例
  • 返回值自动序列化为JSON
  • 错误会自动转换为Telefunc Abort格式
import { getContext } from 'telefunc';
import type { PrismaClient } from '../../generated/prisma/client';

export async function onCreateOrder(input: { productId: number; quantity: number }) {
  const { prisma } = getContext() as { prisma: PrismaClient };
  // 业务逻辑
  return { orderNo: 'ORD001' };
}

数据库开发工作流

D1 事务限制与解决方案

Warning

Cloudflare D1 不完全支持 Prisma 的交互式事务 (prisma.$transaction(async (tx) => {...}))

本项目的解决方案补偿性事务Compensating Transaction

// 1. 先执行主操作
const order = await createOrderRecord(prisma, {...});
// 2. 尝试执行关联操作
try {
  const result = await createPaymentForOrder(order.orderNo, prisma);
  return result;
} catch (error) {
  // 3. 如果失败,执行补偿操作(删除已创建的记录)
  await prisma.order.delete({ where: { id: order.id } })
    .catch(e => logger.error("Compensating delete failed:", e));
  throw error;
}

迁移文件限制说明

  • prisma/migrations/ 中已存在的迁移文件视为历史记录,禁止修改、重命名或删除。
  • 数据库变更只能通过新增迁移文件完成,例如 0002_*.sql0003_*.sql
  • 提交前必须保证 schema.prisma 与迁移文件的职责一致,避免同一字段在多个迁移里重复定义。

当前运行方式

  • bun dev 运行在 Cloudflare 风格的本地开发环境中Prisma 会通过 env.DB 连接到本地 D1 模拟器
  • bun run up 部署后Prisma 会通过同一个 env.DB 绑定连接到远程 D1
  • .env 中的 DATABASE_URL 仅用于 Prisma CLI / 配置层,不参与当前应用运行时的数据库连接

绝对不要做的操作

  1. 不要假设 bun dev 使用的是 prisma/db.sqlite;当前它实际使用的是本地 D1 模拟器
  2. 不要使用 prisma migrate dev,这会偏离当前 D1 迁移工作流
  3. 不要反复覆盖 prisma/migrations/0001_init.sql;初始化迁移和后续增量迁移应分开维护
  4. 不要信任 Prisma 生成的迁移 SQL必须手动核查脚本重点识别并拦截非预期的 DROP TABLE全量重建逻辑
  5. 不要使用node:fsnode:path等Node.js原生模块

常用命令

# 开发
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类型

日志排查

当邮件发送异常或支付回调出现问题时,可在 Cloudflare Dashboard 查看 Workers 运行日志:

实时线上环境日志: bunx wrangler tail --format pretty

  1. 进入 dash.cloudflare.com
  2. 左侧菜单 → Workers & Pages → 点击 edgekey
  3. 顶部 tab → Observability
  4. 在搜索框输入关键词过滤日志,例如:
    • email.send.failed — 邮件发送失败
    • payment.notify.route_exception — 支付回调路由异常
    • payment.notify.diagnostic — 支付回调校验异常诊断

参考资源

项目文档:

  • README.md: 项目概述和快速开始
  • docs/components.md: 组件使用指南
  • docs/payment-gateway-guide.md: 支付网关开发指南

官方文档: