@h-ai/cli 0.1.0-alpha5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +167 -0
  3. package/dist/chunk-2H7UOFLK.js +10 -0
  4. package/dist/chunk-2H7UOFLK.js.map +1 -0
  5. package/dist/chunk-LANIDJC7.js +659 -0
  6. package/dist/chunk-LANIDJC7.js.map +1 -0
  7. package/dist/chunk-YV7WPUI6.js +206 -0
  8. package/dist/chunk-YV7WPUI6.js.map +1 -0
  9. package/dist/config-templates-S5RI2MC6.js +5 -0
  10. package/dist/config-templates-S5RI2MC6.js.map +1 -0
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.js +1645 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/skill-templates-N5DU5FNX.js +5 -0
  15. package/dist/skill-templates-N5DU5FNX.js.map +1 -0
  16. package/dist/src-XJ6YXNAF.js +15030 -0
  17. package/dist/src-XJ6YXNAF.js.map +1 -0
  18. package/package.json +59 -0
  19. package/templates/README.md +126 -0
  20. package/templates/apps/admin/messages/en-US.json +33 -0
  21. package/templates/apps/admin/messages/zh-CN.json +33 -0
  22. package/templates/apps/admin/src/routes/+layout.svelte.hbs +30 -0
  23. package/templates/apps/admin/src/routes/+page.svelte.hbs +35 -0
  24. package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +44 -0
  25. package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +45 -0
  26. package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +37 -0
  27. package/templates/apps/admin/src/routes/api/health/+server.ts +12 -0
  28. package/templates/apps/android-app/.env.hbs +3 -0
  29. package/templates/apps/android-app/capacitor.config.ts.hbs +12 -0
  30. package/templates/apps/android-app/messages/en-US.json +24 -0
  31. package/templates/apps/android-app/messages/zh-CN.json +24 -0
  32. package/templates/apps/android-app/src/lib/api.ts.hbs +30 -0
  33. package/templates/apps/android-app/src/lib/capacitor.ts +21 -0
  34. package/templates/apps/android-app/src/routes/+layout.svelte.hbs +42 -0
  35. package/templates/apps/android-app/src/routes/+layout.ts +7 -0
  36. package/templates/apps/android-app/src/routes/+page.svelte.hbs +27 -0
  37. package/templates/apps/api/src/routes/+layout.svelte +14 -0
  38. package/templates/apps/api/src/routes/+page.svelte +11 -0
  39. package/templates/apps/api/src/routes/api/v1/health/+server.ts +14 -0
  40. package/templates/apps/api/src/routes/api/v1/items/+server.ts +37 -0
  41. package/templates/apps/api/src/routes/api/v1/items/[id]/+server.ts +30 -0
  42. package/templates/apps/h5/messages/en-US.json +37 -0
  43. package/templates/apps/h5/messages/zh-CN.json +37 -0
  44. package/templates/apps/h5/src/routes/+layout.svelte.hbs +57 -0
  45. package/templates/apps/h5/src/routes/+page.svelte.hbs +27 -0
  46. package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +27 -0
  47. package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +27 -0
  48. package/templates/apps/website/messages/en-US.json +32 -0
  49. package/templates/apps/website/messages/zh-CN.json +32 -0
  50. package/templates/apps/website/src/routes/+layout.svelte.hbs +66 -0
  51. package/templates/apps/website/src/routes/+page.svelte.hbs +33 -0
  52. package/templates/apps/website/src/routes/about/+page.svelte.hbs +27 -0
  53. package/templates/apps/website/src/routes/api/health/+server.ts +12 -0
  54. package/templates/apps/website/src/routes/contact/+page.svelte.hbs +59 -0
  55. package/templates/apps/website/src/routes/services/+page.svelte.hbs +63 -0
  56. package/templates/base/e2e/helpers.ts +49 -0
  57. package/templates/base/package.json.hbs +67 -0
  58. package/templates/base/playwright.config.ts +32 -0
  59. package/templates/base/src/app.css +2 -0
  60. package/templates/base/src/app.d.ts.hbs +18 -0
  61. package/templates/base/src/app.html.hbs +16 -0
  62. package/templates/base/src/hooks.server.ts.hbs +123 -0
  63. package/templates/base/src/lib/server/init.ts.hbs +190 -0
  64. package/templates/base/svelte.config.js.hbs +30 -0
  65. package/templates/base/tsconfig.json +8 -0
  66. package/templates/base/vite.config.ts.hbs +27 -0
  67. package/templates/features/ai/routes/api/chat/+server.ts +26 -0
  68. package/templates/features/datapipe/routes/api/datapipe/pipeline/+server.ts +41 -0
  69. package/templates/features/iam/routes-admin/(auth)/+layout.svelte.hbs +21 -0
  70. package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +98 -0
  71. package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +124 -0
  72. package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +98 -0
  73. package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +114 -0
  74. package/templates/features/iam/routes-shared/api/auth/login/+server.ts +32 -0
  75. package/templates/features/iam/routes-shared/api/auth/logout/+server.ts +15 -0
  76. package/templates/features/iam/routes-shared/api/auth/me/+server.ts +12 -0
  77. package/templates/features/iam/routes-shared/api/auth/register/+server.ts +26 -0
  78. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +30 -0
  79. package/templates/features/payment/routes/api/v1/payment/notify/[provider]/+server.ts +42 -0
  80. package/templates/features/payment/routes/api/v1/payment/query/[orderNo]/+server.ts +25 -0
  81. package/templates/features/storage/routes/api/upload/+server.ts +35 -0
  82. package/templates/features/vecdb/routes/api/vecdb/search/+server.ts +36 -0
  83. package/templates/i18n/project.inlang/settings.json +11 -0
  84. package/templates/skills/AGENTS.md +26 -0
  85. package/templates/skills/CLAUDE.md +12 -0
  86. package/templates/skills/copilot-instructions.md +61 -0
  87. package/templates/skills/hai-ai/SKILL.md +659 -0
  88. package/templates/skills/hai-api-client/SKILL.md +346 -0
  89. package/templates/skills/hai-app-create/SKILL.md +371 -0
  90. package/templates/skills/hai-app-review/SKILL.md +156 -0
  91. package/templates/skills/hai-app-tests/SKILL.md +468 -0
  92. package/templates/skills/hai-audit/SKILL.md +141 -0
  93. package/templates/skills/hai-build/SKILL.md +319 -0
  94. package/templates/skills/hai-cache/SKILL.md +184 -0
  95. package/templates/skills/hai-capacitor/SKILL.md +389 -0
  96. package/templates/skills/hai-core/SKILL.md +544 -0
  97. package/templates/skills/hai-crypto/SKILL.md +183 -0
  98. package/templates/skills/hai-datapipe/SKILL.md +214 -0
  99. package/templates/skills/hai-deploy/SKILL.md +210 -0
  100. package/templates/skills/hai-iam/SKILL.md +355 -0
  101. package/templates/skills/hai-kit/SKILL.md +319 -0
  102. package/templates/skills/hai-payment/SKILL.md +289 -0
  103. package/templates/skills/hai-reach/SKILL.md +325 -0
  104. package/templates/skills/hai-reldb/SKILL.md +459 -0
  105. package/templates/skills/hai-scheduler/SKILL.md +242 -0
  106. package/templates/skills/hai-storage/SKILL.md +230 -0
  107. package/templates/skills/hai-ui/SKILL.md +275 -0
  108. package/templates/skills/hai-vecdb/SKILL.md +273 -0
  109. package/templates/skills/opencode.json +11 -0
@@ -0,0 +1,319 @@
1
+ ---
2
+ name: hai-build
3
+ description: 应用开发入口技能。提供项目架构总览(SSR/SPA/原生 App 多端)、TDD 开发工作流、模块初始化顺序与技能导航。当用户需要了解项目结构、查找正确的技能、或开始新任务时触发。
4
+ ---
5
+
6
+ # hai-build — 应用开发入口
7
+
8
+ > 本技能是 hai-framework 应用开发的起点。帮助理解项目结构、定位正确的技能、并遵循 **TDD 驱动的标准工作流**。支持 SSR Web、SPA、Android/iOS 原生 App 等多端构建。
9
+
10
+ ---
11
+
12
+ ## 适用场景
13
+
14
+ - 初次接触项目,需要了解整体架构与模块关系
15
+ - 不确定应使用哪个技能来完成任务
16
+ - 需要了解模块初始化顺序与依赖关系
17
+ - 需要执行跨模块操作或全局配置变更
18
+ - 多端构建切换(SSR ↔ SPA ↔ 原生 App)
19
+
20
+ ---
21
+
22
+ ## 项目架构
23
+
24
+ ### 技术栈
25
+
26
+ | 层次 | 技术 |
27
+ | -------- | ------------------------------ |
28
+ | 框架 | SvelteKit 2 + Svelte 5 (Runes) |
29
+ | 样式 | TailwindCSS 4 + DaisyUI 5 |
30
+ | 语言 | TypeScript 5.7+ (strict) |
31
+ | 构建 | Vite + tsup |
32
+ | 包管理 | pnpm |
33
+ | 单元测试 | Vitest |
34
+ | E2E 测试 | Playwright |
35
+ | 原生 App | Capacitor 7 |
36
+ | 认证 | Bearer Token(统一) |
37
+
38
+ ### 多端构建模式
39
+
40
+ | 模式 | Adapter | 认证方式 | 部署目标 |
41
+ | ------- | -------------- | --------------------- | ----------------------- |
42
+ | SSR Web | adapter-node | Bearer Token + Cookie | Node.js 服务器 |
43
+ | SPA | adapter-static | Bearer Token | CDN / 静态托管 |
44
+ | Android | adapter-static | Bearer Token | Capacitor → Android APK |
45
+ | iOS | adapter-static | Bearer Token | Capacitor → iOS IPA |
46
+
47
+ **Adapter 切换**:
48
+
49
+ ```typescript
50
+ // svelte.config.js — 使用 kit 提供的 createAdapter
51
+ import { createAdapter } from '@h-ai/kit/adapter'
52
+
53
+ const config = {
54
+ kit: {
55
+ adapter: createAdapter(), // 根据 VITE_ADAPTER 环境变量自动选择
56
+ },
57
+ }
58
+ ```
59
+
60
+ - `VITE_ADAPTER=node`(默认)→ adapter-node(SSR)
61
+ - `VITE_ADAPTER=static` → adapter-static(SPA / 原生 App)
62
+
63
+ ### 目录结构
64
+
65
+ ```
66
+ 项目根/
67
+ config/ # 模块配置(YAML)
68
+ _core.yml # Core 配置(必须)
69
+ _db.yml # DB 配置(按需)
70
+ _cache.yml # Cache 配置(按需)
71
+ _iam.yml # IAM 配置(按需)
72
+ _storage.yml # Storage 配置(按需)
73
+ _ai.yml # AI 配置(按需)
74
+ src/
75
+ app.html # HTML 入口
76
+ app.d.ts # 全局类型声明
77
+ hooks.server.ts # 服务端 Hook(模块初始化 + 请求管道)
78
+ lib/
79
+ api.ts # API Client 初始化(SPA / 原生 App 使用)
80
+ capacitor.ts # Capacitor 初始化(原生 App)
81
+ server/
82
+ init.ts # 模块初始化入口(单例,SSR)
83
+ paraglide/ # i18n 生成文件(禁止手动修改)
84
+ components/ # 应用组件
85
+ routes/
86
+ +layout.svelte # 根布局
87
+ +page.svelte # 首页
88
+ (auth)/ # 认证相关页面组
89
+ api/ # API 端点
90
+ v1/ # API v1 版本
91
+ payment/ # 支付端点(按需)
92
+ static/ # 静态资源
93
+ messages/ # i18n 翻译文件
94
+ capacitor.config.ts # Capacitor 配置(原生 App)
95
+ ```
96
+
97
+ ### 模块依赖图
98
+
99
+ ```
100
+ core(基础能力:配置、日志、i18n、HaiResult)
101
+ ├── crypto(加密:SM2/SM3/SM4)
102
+ ├── db(数据库:SQLite/PostgreSQL/MySQL)
103
+ ├── cache(缓存:内存/Redis)
104
+ ├── storage(存储:本地/S3)
105
+ ├── ai(AI:LLM/MCP/Agent)
106
+ ├── iam(身份管理)← 依赖 crypto + db + cache
107
+ ├── payment(支付)← 依赖 db + crypto
108
+ ├── kit(SvelteKit 集成)← 依赖 iam + cache + storage + crypto
109
+ ├── api-client(HTTP 客户端)← 纯浏览器端,依赖 iam/api(类型)
110
+ ├── capacitor(原生能力)← 纯浏览器端
111
+ └── ui(UI 组件库)← 依赖 core
112
+ ```
113
+
114
+ ### 模块初始化顺序
115
+
116
+ #### SSR 模式(hooks.server.ts)
117
+
118
+ 在 `src/lib/server/init.ts` 中按依赖顺序初始化:
119
+
120
+ ```typescript
121
+ import { cache } from '@h-ai/cache'
122
+ import { core } from '@h-ai/core'
123
+ import { reldb } from '@h-ai/reldb'
124
+ import { iam } from '@h-ai/iam'
125
+ import { payment } from '@h-ai/payment' // 按需
126
+
127
+ let initialized = false
128
+
129
+ export async function initModules() {
130
+ if (initialized)
131
+ return
132
+
133
+ // 1. Core 必须最先初始化(加载配置、日志、i18n)
134
+ await core.init()
135
+
136
+ // 2. 基础设施层(无相互依赖,可任意顺序)
137
+ await reldb.init(core.config.get('db'))
138
+ await cache.init(core.config.get('cache'))
139
+
140
+ // 3. 业务层(依赖基础设施)
141
+ await iam.init({ ...core.config.get('iam'), reldb, cache })
142
+ // 支付模块(按需)
143
+ await payment.init({ ...core.config.get('payment'), reldb })
144
+
145
+ // 4. 集成层
146
+ // kit 无需 init,通过 createHandle 配置
147
+
148
+ initialized = true
149
+ }
150
+ ```
151
+
152
+ #### SPA / 原生 App 模式(src/lib/api.ts)
153
+
154
+ ```typescript
155
+ import { api } from '@h-ai/api-client'
156
+
157
+ export async function initApi() {
158
+ return api.init({
159
+ baseUrl: import.meta.env.VITE_API_BASE_URL,
160
+ timeout: 15_000,
161
+ })
162
+ }
163
+
164
+ export { api }
165
+ ```
166
+
167
+ #### 原生 App 追加初始化(src/lib/capacitor.ts)
168
+
169
+ ```typescript
170
+ import { capacitor } from '@h-ai/capacitor'
171
+
172
+ export async function initCapacitor() {
173
+ await capacitor.init({ statusBar: { style: 'dark' } })
174
+ }
175
+ ```
176
+
177
+ ### 配置文件格式
178
+
179
+ 所有模块配置使用 YAML,支持 `${ENV_VAR:default}` 环境变量语法:
180
+
181
+ ```yaml
182
+ # config/_core.yml
183
+ app:
184
+ name: ${HAI_APP_NAME:my-app}
185
+ env: ${HAI_ENV:development}
186
+ log:
187
+ level: ${HAI_LOG_LEVEL:info}
188
+ ```
189
+
190
+ ---
191
+
192
+ ## 技能导航
193
+
194
+ 根据任务类型选择正确的技能:
195
+
196
+ ### 模块使用(API 与集成)
197
+
198
+ | 任务 | 技能 | 触发关键词 |
199
+ | --------------------- | ---------------- | ------------------------------------------------- |
200
+ | 配置/日志/i18n/HaiResult | `hai-core` | core.init, core.logger, core.config, HaiResult |
201
+ | 数据库操作 | `hai-reldb` | reldb.init, SQL, CRUD, 事务, 分页, DDL |
202
+ | 缓存操作 | `hai-cache` | cache.init, cache.get/set, TTL, Redis |
203
+ | 文件存储 | `hai-storage` | storage.init, 上传, 下载, S3, 本地存储 |
204
+ | 加密/签名/哈希 | `hai-crypto` | crypto.init, SM2, SM3, SM4, 加密, 签名 |
205
+ | 身份认证/授权 | `hai-iam` | iam.init, 登录, 注册, RBAC, Token, Bearer |
206
+ | AI/LLM/MCP | `hai-ai` | ai.init, LLM, MCP, Agent, 工具调用 |
207
+ | SvelteKit 集成 | `hai-kit` | kit.createHandle, guard, fromContract, middleware |
208
+ | UI 组件 | `hai-ui` | 表单, 按钮, 表格, Modal, Toast, 移动端组件 |
209
+ | HTTP 客户端 | `hai-api-client` | api.call, api.get, api.post, Bearer, 拦截器 |
210
+ | 原生 App 能力 | `hai-capacitor` | capacitor, 相机, 推送, 状态栏, 设备信息 |
211
+ | 支付 | `hai-payment` | payment, 微信支付, 支付宝, Stripe, 订单 |
212
+
213
+ ### 开发流程
214
+
215
+ | 任务 | 技能 | 触发关键词 |
216
+ | ---------------------- | ---------------- | -------------------------------------- |
217
+ | 创建页面/组件/API/模型 | `hai-app-create` | 新建页面, 添加组件, API 端点, 数据模型 |
218
+ | 代码审查与规范化 | `hai-app-review` | 审查, review, 规范, 优化 |
219
+ | 编写/补充测试 | `hai-app-tests` | 测试, test, 单测, 覆盖率, TDD, E2E |
220
+
221
+ ---
222
+
223
+ ## TDD 开发工作流(强制)
224
+
225
+ > 所有新功能开发必须遵循 TDD:**先写测试 → 确认失败 → 再实现 → 确认通过 → 重构**。
226
+
227
+ ### 完整流程
228
+
229
+ ```
230
+ 需求分析 → 设计测试用例 → 编写测试(Red)→ 运行测试确认失败
231
+ → 编写实现(Green)→ 运行测试确认通过
232
+ → 重构优化(Refactor)→ 运行质量门禁
233
+ ```
234
+
235
+ ### 按阶段使用的技能
236
+
237
+ | 阶段 | 主要技能 | 说明 |
238
+ | ------------------- | ---------------- | ------------------------------------------ |
239
+ | 需求分析 + 测试设计 | `hai-app-tests` | 拆分测试点,确定单元测试与 E2E 测试 |
240
+ | Red:编写测试 | `hai-app-tests` | 编写 Vitest 单元测试 + Playwright E2E 测试 |
241
+ | Green:编写实现 | `hai-app-create` | 按照创建规范编写服务/路由/组件 |
242
+ | Refactor:重构审查 | `hai-app-review` | 代码规范审查、分层检查、日志/i18n 合规 |
243
+
244
+ ### 快速指令
245
+
246
+ ```bash
247
+ # Red:运行测试确认全部失败
248
+ pnpm --filter <app-name> test
249
+ pnpm --filter <app-name> test:e2e
250
+
251
+ # Green:运行测试确认全部通过
252
+ pnpm --filter <app-name> test
253
+ pnpm --filter <app-name> test:e2e
254
+
255
+ # Refactor:质量门禁
256
+ pnpm typecheck && pnpm lint && pnpm test
257
+ ```
258
+
259
+ ---
260
+
261
+ ## 统一编码规范
262
+
263
+ ### 强制规则
264
+
265
+ - **禁止 `any`**:不确定类型用 `unknown`,在边界处做类型缩窄
266
+ - **禁止 `console.log`**:使用 `core.logger`(trace/debug/info/warn/error/fatal)
267
+ - **禁止硬编码密钥**:使用环境变量,新增变量需在 `.env` 中写入占位符
268
+ - **禁止硬编码用户文案**:所有用户可见文本必须使用 i18n key
269
+ - **禁止修改 `src/lib/paraglide`** 生成文件
270
+
271
+ ### HaiResult 模式
272
+
273
+ 所有 hai 模块操作均返回 `HaiResult<T>` 类型:
274
+
275
+ ```typescript
276
+ const result = await reldb.sql.query('SELECT * FROM users')
277
+ if (!result.success) {
278
+ // result.error: { code, message, details? }
279
+ core.logger.error('Query failed', { error: result.error })
280
+ return kit.response.internalError()
281
+ }
282
+ // result.data 可安全使用
283
+ return kit.response.ok(result.data)
284
+ ```
285
+
286
+ ### 质量门禁
287
+
288
+ 每次变更后按顺序执行:
289
+
290
+ ```bash
291
+ pnpm typecheck # TypeScript 类型检查
292
+ pnpm lint # ESLint 检查
293
+ pnpm test # Vitest 单元测试
294
+ ```
295
+
296
+ ---
297
+
298
+ ## 标准工作流
299
+
300
+ ### 变更前:需求分析 + 测试设计
301
+
302
+ 1. 列出将修改的文件路径
303
+ 2. 确认哪些类型/接口会变
304
+ 3. 搜索确认引用关系(避免遗漏)
305
+ 4. **设计测试用例清单**(单元测试 + E2E 测试)
306
+
307
+ ### 变更中:TDD 三步走
308
+
309
+ 1. **Red**:编写单元测试(Vitest)+ E2E 测试(Playwright),运行确认全部失败
310
+ 2. **Green**:按技能指引完成功能实现,逐步让测试通过
311
+ 3. **Refactor**:审查代码规范、重构优化
312
+
313
+ ### 变更后:验证
314
+
315
+ 1. `pnpm typecheck` 通过
316
+ 2. `pnpm lint` 通过
317
+ 3. `pnpm test` 通过(单元测试)
318
+ 4. `pnpm --filter <app-name> test:e2e` 通过(E2E 测试)
319
+ 5. 搜索确认所有引用点已更新
@@ -0,0 +1,184 @@
1
+ ---
2
+ name: hai-cache
3
+ description: 使用 @h-ai/cache 进行内存或 Redis 缓存操作(kv/hash/list/set/zset/分布式锁);当需求涉及缓存读写、TTL 管理、集合运算、排行榜、缓存一致性策略或分布式互斥锁时使用。
4
+ ---
5
+
6
+ # hai-cache
7
+
8
+ > `@h-ai/cache` 提供统一缓存接口,支持 Memory 与 Redis 后端,包含 KV / Hash / List / Set / ZSet / 分布式锁 六类操作。
9
+
10
+ ---
11
+
12
+ ## 适用场景
13
+
14
+ - 缓存热点数据减少数据库查询
15
+ - 会话存储(配合 IAM)
16
+ - 分布式缓存(Redis)与本地测试缓存(Memory)
17
+ - 集合操作(权限缓存、标签集合)
18
+ - 排行榜(ZSet)与队列(List)
19
+ - 分布式锁(多节点部署互斥控制)
20
+
21
+ ---
22
+
23
+ ## 使用步骤
24
+
25
+ ### 1. 配置
26
+
27
+ ```yaml
28
+ # config/_cache.yml
29
+ type: ${HAI_CACHE_TYPE:memory} # memory | redis
30
+ # Redis 配置(type=redis 时生效):
31
+ # host: ${HAI_CACHE_REDIS_HOST:localhost}
32
+ # port: ${HAI_CACHE_REDIS_PORT:6379}
33
+ # password: ${HAI_CACHE_REDIS_PASSWORD:}
34
+ # db: ${HAI_CACHE_REDIS_DB:0}
35
+ # keyPrefix: ${HAI_CACHE_KEY_PREFIX:hai:}
36
+ ```
37
+
38
+ ### 2. 初始化与关闭
39
+
40
+ ```typescript
41
+ import { cache } from '@h-ai/cache'
42
+
43
+ await cache.init(core.config.get('cache'))
44
+ // 使用后关闭
45
+ await cache.close()
46
+ ```
47
+
48
+ ---
49
+
50
+ ## 核心 API
51
+
52
+ ### KV 操作(`cache.kv`)
53
+
54
+ | 方法 | 说明 |
55
+ | ----------------------------------- | -------------------- |
56
+ | `get / set / del / exists` | 基础读写与存在性判断 |
57
+ | `expire / expireAt / ttl / persist` | TTL 管理 |
58
+ | `incr / incrBy / decr / decrBy` | 计数器操作 |
59
+ | `mget / mset` | 批量读写 |
60
+ | `scan / keys / type` | Key 检索与类型判断 |
61
+
62
+ ```typescript
63
+ await cache.kv.set('user:123', { name: '张三' }, { ex: 3600 })
64
+ const result = await cache.kv.get<{ name: string }>('user:123')
65
+ if (result.success && result.data) {
66
+ // result.data.name === '张三'
67
+ }
68
+
69
+ await cache.kv.del('user:123')
70
+ ```
71
+
72
+ ### Hash/List/Set/ZSet(`cache.hash/list/set_/zset`)
73
+
74
+ - `cache.hash`:对象字段读写(如用户 profile 局部更新)
75
+ - `cache.list`:队列/消息顺序处理
76
+ - `cache.set_`:去重集合(成员关系、权限集合)
77
+ - `cache.zset`:分数排序(排行榜、权重调度)
78
+
79
+ ```typescript
80
+ await cache.hash.hset('profile:1', { nickname: 'alice' })
81
+ await cache.list.lpush('queue:jobs', 'job-1', 'job-2')
82
+ await cache.set_.sadd('role:admin:perms', 'user.read', 'user.write')
83
+ await cache.zset.zadd('rank:daily', { member: 'u1', score: 100 })
84
+ ```
85
+
86
+ ### 分布式锁(`cache.lock`)
87
+
88
+ | 方法 | 说明 |
89
+ | ---------- | ------------------------------------------ |
90
+ | `acquire` | 尝试获锁(SET NX EX),返回 true/false |
91
+ | `release` | 释放锁(支持 owner 验证,防止误释放) |
92
+ | `isLocked` | 检查锁是否被持有 |
93
+ | `extend` | 续期锁 TTL(支持 owner 验证) |
94
+
95
+ ```typescript
96
+ // 获锁(TTL 30 秒,owner 用于标识持有者)
97
+ const acquired = await cache.lock.acquire('my-lock', { ttl: 30, owner: 'node-1' })
98
+ if (acquired.success && acquired.data) {
99
+ try {
100
+ // 受保护的操作
101
+ }
102
+ finally {
103
+ await cache.lock.release('my-lock', 'node-1')
104
+ }
105
+ }
106
+
107
+ // 续期
108
+ await cache.lock.extend('my-lock', 60, 'node-1')
109
+
110
+ // 检查
111
+ const locked = await cache.lock.isLocked('my-lock')
112
+ ```
113
+
114
+ **最佳实践:**
115
+
116
+ - `owner` 使用稳定的节点标识(如 `nodeId`),不要每次随机生成
117
+ - 释放锁时传入 `owner` 防止误释放他人锁
118
+ - Memory 后端适合开发/测试;Redis 后端用 Lua 脚本保证 release/extend 原子性
119
+
120
+ ---
121
+
122
+ ## 错误码 — `HaiCacheError`
123
+
124
+ | 错误码 | code | 说明 |
125
+ |--------|------|------|
126
+ | `HaiCacheError.CONNECTION_FAILED` | `hai:cache:001` | 连接失败 |
127
+ | `HaiCacheError.OPERATION_FAILED` | `hai:cache:002` | 操作失败 |
128
+ | `HaiCacheError.SERIALIZATION_FAILED` | `hai:cache:003` | 序列化失败 |
129
+ | `HaiCacheError.DESERIALIZATION_FAILED` | `hai:cache:004` | 反序列化失败 |
130
+ | `HaiCacheError.KEY_NOT_FOUND` | `hai:cache:005` | 键不存在 |
131
+ | `HaiCacheError.TIMEOUT` | `hai:cache:006` | 超时 |
132
+ | `HaiCacheError.NOT_INITIALIZED` | `hai:cache:010` | 未初始化 |
133
+ | `HaiCacheError.UNSUPPORTED_TYPE` | `hai:cache:011` | 不支持的缓存类型 |
134
+ | `HaiCacheError.CONFIG_ERROR` | `hai:cache:012` | 配置错误 |
135
+
136
+ ---
137
+
138
+ ## 常见模式
139
+
140
+ ### 缓存穿透保护
141
+
142
+ ```typescript
143
+ async function getUserCached(userId: string) {
144
+ const cached = await cache.kv.get<User>(`user:${userId}`)
145
+ if (cached.success && cached.data)
146
+ return cached.data
147
+
148
+ const user = await userRepo.findById(userId)
149
+ if (user.success && user.data) {
150
+ await cache.kv.set(`user:${userId}`, user.data, { ex: 3600 })
151
+ return user.data
152
+ }
153
+ return null
154
+ }
155
+ ```
156
+
157
+ ### 分布式锁保护共享资源
158
+
159
+ ```typescript
160
+ const lockKey = 'batch:import'
161
+ const acquired = await cache.lock.acquire(lockKey, { ttl: 60, owner: nodeId })
162
+ if (acquired.success && acquired.data) {
163
+ try {
164
+ await runBatchImport()
165
+ }
166
+ finally {
167
+ await cache.lock.release(lockKey, nodeId)
168
+ }
169
+ }
170
+ else {
171
+ logger.info('Another node is running the import')
172
+ }
173
+ ```
174
+
175
+ ---
176
+
177
+ ## 相关 Skills
178
+
179
+ - `hai-build`:模块初始化顺序(cache 在 db 之后、iam 之前)
180
+ - `hai-core`:配置与 HaiResult 模型
181
+ - `hai-iam`:会话存储与权限缓存(底层使用 cache)
182
+ - `hai-scheduler`:定时任务分布式锁(底层使用 cache.lock)
183
+ - `hai-reach`:消息发送互斥锁(底层使用 cache.lock)
184
+ - `hai-kit`:SvelteKit 集成层