| name | hai-build |
| description | 应用开发入口技能。提供项目架构总览(SSR/SPA/原生 App 多端)、TDD 开发工作流、模块初始化顺序与技能导航。当用户需要了解项目结构、查找正确的技能、或开始新任务时触发。 |
hai-build — 应用开发入口
能力契约
| 项目 | 契约 |
|---|
| 能力 | 应用开发入口技能。提供项目架构总览(SSR/SPA/原生 App 多端)、TDD 开发工作流、模块初始化顺序与技能导航。当用户需要了解项目结构、查找正确的技能、或开始新任务时触发。 |
| 适用场景 | 当任务与 hai-build 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
| 输入 | 用户目标、仓库与运行环境上下文、现有配置、授权范围和质量门禁 |
| 输出 | 与目标匹配的配置/代码/文档或审查结论,以及可复现的验证结果 |
| 限制 | 不扩张用户授权,不输出或固化密钥,不跳过失败门禁,不假定外部服务状态 |
本技能是 hai-framework 应用开发的起点。帮助理解项目结构、定位正确的技能、并遵循 TDD 驱动的标准工作流。支持 SSR Web、SPA、Android/iOS 原生 App 等多端构建。
适用场景
- 初次接触项目,需要了解整体架构与模块关系
- 不确定应使用哪个技能来完成任务
- 需要了解模块初始化顺序与依赖关系
- 需要执行跨模块操作或全局配置变更
- 多端构建切换(SSR ↔ SPA ↔ 原生 App)
项目架构
技术栈
| 层次 | 技术 |
|---|
| 框架 | SvelteKit 2 + Svelte 5 (Runes) |
| 样式 | TailwindCSS 4 + DaisyUI 5 |
| 语言 | TypeScript 5.7+ (strict) |
| 构建 | Vite + tsup |
| 包管理 | pnpm |
| 单元测试 | Vitest |
| E2E 测试 | Playwright |
| 原生 App | Capacitor 7 |
| 公共 API | oRPC contract + Hono + typed client |
| 认证 | Bearer access token + httpOnly refresh cookie(浏览器推荐) |
多端构建模式
| 模式 | Adapter | 认证方式 | 部署目标 |
|---|
| SSR Web | adapter-node | Bearer access token + Cookie | Node.js 服务器 |
| SPA | adapter-static | Bearer access token + httpOnly refresh cookie | CDN / 静态托管 |
| Android | adapter-static | Bearer access token + Capacitor secure storage | Capacitor → Android APK |
| iOS | adapter-static | Bearer access token + Capacitor secure storage | Capacitor → iOS IPA |
Adapter 切换:
import { createAdapter } from '@h-ai/kit/adapter'
const config = {
kit: {
adapter: createAdapter(),
},
}
VITE_ADAPTER=node(默认)→ adapter-node(SSR)
VITE_ADAPTER=static → adapter-static(SPA / 原生 App)
目录结构
项目根/
config/ # 模块配置(YAML)
_core.yml # Core 配置(必须)
_db.yml # DB 配置(按需)
_cache.yml # Cache 配置(按需)
_iam.yml # IAM 配置(按需)
_storage.yml # Storage 配置(按需)
_ai.yml # AI 配置(按需)
src/
app.html # HTML 入口
app.d.ts # 全局类型声明
hooks.server.ts # 服务端 Hook(模块初始化 + 请求管道)
lib/
api.ts # @h-ai/api-client 初始化(SPA / 原生 App 使用)
capacitor.ts # Capacitor 初始化(原生 App)
server/
init.ts # 模块初始化入口(单例,SSR)
procedures/ # 应用私有 oRPC procedures(仅 API Service 场景)
paraglide/ # i18n 生成文件(禁止手动修改)
components/ # 应用组件
routes/
+layout.svelte # 根布局
+page.svelte # 首页
(auth)/ # 认证相关页面组
api/ # API 端点
v1/ # API v1 版本
payment/ # 支付端点(按需)
static/ # 静态资源
messages/ # i18n 翻译文件
capacitor.config.ts # Capacitor 配置(原生 App)
模块依赖图
core(基础能力:配置、日志、i18n、HaiResult)
├── crypto(加密:SM2/SM3/SM4)
├── db(数据库:SQLite/PostgreSQL/MySQL)
├── cache(缓存:内存/Redis)
├── storage(存储:本地/S3)
├── ai(AI:LLM/MCP/Agent)
├── iam(身份管理)← 依赖 crypto + db + cache
├── payment(支付)← 依赖 db + crypto
├── api-contract(公共 HTTP API 契约)← 纯定义,依赖 core + zod + oRPC contract
├── serv(Hono + oRPC API Service)← 依赖 api-contract;features 按需依赖 iam/storage/ai
├── kit(SvelteKit 集成)← Hook / guard / validate / response,不定义公共 contract
├── api-client(typed API 客户端)← 依赖 api-contract + oRPC client
├── capacitor(原生能力)← 纯浏览器端
└── ui(UI 组件库)← 依赖 core
模块初始化顺序
SSR 模式(hooks.server.ts)
在 src/lib/server/init.ts 中按依赖顺序初始化:
import { cache } from '@h-ai/cache'
import { core } from '@h-ai/core'
import { reldb } from '@h-ai/reldb'
import { iam } from '@h-ai/iam'
import { payment } from '@h-ai/payment'
let initialized = false
export async function initModules() {
if (initialized)
return
await core.init()
await reldb.init(core.config.get('db'))
await cache.init(core.config.get('cache'))
await iam.init({ ...core.config.get('iam'), reldb, cache })
await payment.init({ ...core.config.get('payment'), reldb })
initialized = true
}
SPA / 原生 App 模式(src/lib/api.ts)
import { apiClient } from '@h-ai/api-client'
export async function initApi() {
return apiClient.init({
baseUrl: import.meta.env.VITE_API_BASE_URL,
auth: {},
timeout: 15_000,
})
}
export { apiClient }
原生 App 追加初始化(src/lib/capacitor.ts)
import { capacitor } from '@h-ai/capacitor'
export async function initCapacitor() {
await capacitor.init({ statusBar: { style: 'dark' } })
}
配置文件格式
所有模块配置使用 YAML,支持 ${ENV_VAR:default} 环境变量语法:
app:
name: ${HAI_APP_NAME:my-app}
env: ${HAI_ENV:development}
log:
level: ${HAI_LOG_LEVEL:info}
技能导航
根据任务类型选择正确的技能:
模块使用(API 与集成)
| 任务 | 技能 | 触发关键词 |
|---|
| 配置/日志/i18n/HaiResult | hai-core | core.init, core.logger, core.config, HaiResult |
| 数据库操作 | hai-reldb | reldb.init, SQL, CRUD, 事务, 分页, DDL |
| 缓存操作 | hai-cache | cache.init, cache.get/set, TTL, Redis |
| 文件存储 | hai-storage | storage.init, 上传, 下载, S3, 本地存储 |
| 加密/签名/哈希 | hai-crypto | crypto.init, SM2, SM3, SM4, 加密, 签名 |
| 身份认证/授权 | hai-iam | iam.init, 登录, 注册, RBAC, Token, Bearer |
| AI/LLM/MCP | hai-ai | ai.init, LLM, MCP, Agent, 工具调用 |
| 公共 API 契约 | hai-api-contract | apiContract.create, contract, schema, oRPC, HaiResult |
| API Service 运行时 | hai-serv | serv.createApp, Hono, procedures, OpenAPI, docs, requireAuth |
| SvelteKit 集成 | hai-kit | kit.createHandle, guard, middleware, validate, response |
| UI 组件 | hai-ui | 表单, 按钮, 表格, Modal, Toast, 移动端组件 |
| typed API 客户端 | hai-api-client | apiClient.init, typed client, Bearer, 401 refresh, custom fetch |
| 原生 App 能力 | hai-capacitor | capacitor, 相机, 推送, 状态栏, 设备信息 |
| 支付 | hai-payment | payment, 微信支付, 支付宝, Stripe, 订单 |
开发流程
| 任务 | 技能 | 触发关键词 |
|---|
| 创建页面/组件/API/模型 | hai-app-create | 新建页面, 添加组件, API 端点, 数据模型 |
| 代码审查与规范化 | hai-app-review | 审查, review, 规范, 优化 |
| 编写/补充测试 | hai-app-tests | 测试, test, 单测, 覆盖率, TDD, E2E |
| CI/CD 与质量门禁 | hai-ci | CI, CD, GitHub Actions, workflow, secret scan |
| PR / Issue 交付审查 | hai-pr-review | PR, pull request, issue, CODEOWNERS, 自动 Review, AI Review |
| hai-framework 同步 | hai-framework-sync | hai-framework, skills 同步, framework:use:local, framework:watch |
TDD 开发工作流(强制)
所有新功能开发必须遵循 TDD:先写测试 → 确认失败 → 再实现 → 确认通过 → 重构。
完整流程
需求分析 → 设计测试用例 → 编写测试(Red)→ 运行测试确认失败
→ 编写实现(Green)→ 运行测试确认通过
→ 重构优化(Refactor)→ 运行质量门禁
按阶段使用的技能
| 阶段 | 主要技能 | 说明 |
|---|
| 需求分析 + 测试设计 | hai-app-tests | 拆分测试点,确定单元测试与 E2E 测试 |
| Red:编写测试 | hai-app-tests | 编写 Vitest 单元测试 + Playwright E2E 测试 |
| Green:编写实现 | hai-app-create | 按照创建规范编写服务/路由/组件 |
| Refactor:重构审查 | hai-app-review | 代码规范审查、分层检查、日志/i18n 合规 |
快速指令
pnpm --filter <app-name> test
pnpm --filter <app-name> test:e2e
pnpm --filter <app-name> test
pnpm --filter <app-name> test:e2e
pnpm typecheck && pnpm lint && pnpm test
统一编码规范
强制规则
- 禁止
any:不确定类型用 unknown,在边界处做类型缩窄
- 禁止
console.log:使用 core.logger(trace/debug/info/warn/error/fatal)
- 禁止硬编码密钥:使用环境变量,新增变量需在
.env 中写入占位符
- 禁止硬编码用户文案:所有用户可见文本必须使用 i18n key
- 禁止修改
src/lib/paraglide 生成文件
HaiResult 模式
所有 hai 模块操作均返回 HaiResult<T> 类型:
const result = await reldb.sql.query('SELECT * FROM users')
if (!result.success) {
core.logger.error('Query failed', { error: result.error })
return kit.response.internalError()
}
return kit.response.ok(result.data)
质量门禁
每次变更后按顺序执行:
pnpm typecheck
pnpm lint
pnpm test
标准工作流
变更前:需求分析 + 测试设计
- 列出将修改的文件路径
- 确认哪些类型/接口会变
- 搜索确认引用关系(避免遗漏)
- 设计测试用例清单(单元测试 + E2E 测试)
变更中:TDD 三步走
- Red:编写单元测试(Vitest)+ E2E 测试(Playwright),运行确认全部失败
- Green:按技能指引完成功能实现,逐步让测试通过
- Refactor:审查代码规范、重构优化
变更后:验证
pnpm typecheck 通过
pnpm lint 通过
pnpm test 通过(单元测试)
pnpm --filter <app-name> test:e2e 通过(E2E 测试)
- 搜索确认所有引用点已更新