@h-ai/cli 0.1.0-alpha.53 → 0.1.0-alpha.55

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 (85) hide show
  1. package/README.md +18 -0
  2. package/dist/{chunk-U4PA632G.js → chunk-FVDXJYMO.js} +34 -67
  3. package/dist/chunk-FVDXJYMO.js.map +1 -0
  4. package/dist/cli-config-templates-WGN2I23J.js +5 -0
  5. package/dist/{cli-config-templates-GSXKLGU5.js.map → cli-config-templates-WGN2I23J.js.map} +1 -1
  6. package/dist/index.js +174 -105
  7. package/dist/index.js.map +1 -1
  8. package/dist/{src-QNEJJ3BV.js → src-6ZBWDBUB.js} +127 -87
  9. package/dist/{src-QNEJJ3BV.js.map → src-6ZBWDBUB.js.map} +1 -1
  10. package/package.json +13 -4
  11. package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +1 -0
  12. package/templates/apps/api/apps/{{projectName}}-service/package.json.hbs +1 -0
  13. package/templates/apps/api/package.json.hbs +1 -0
  14. package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +1 -0
  15. package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +1 -0
  16. package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +1 -0
  17. package/templates/apps/fullstack/package.json.hbs +1 -0
  18. package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +1 -0
  19. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +1 -0
  20. package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +1 -0
  21. package/templates/base/eslint.config.js.hbs +1 -0
  22. package/templates/base/package.json.hbs +3 -1
  23. package/templates/skills/AGENTS.md +8 -22
  24. package/templates/skills/CLAUDE.md +3 -16
  25. package/templates/skills/bridges/admin/AGENTS.md +3 -16
  26. package/templates/skills/bridges/admin/CLAUDE.md +3 -11
  27. package/templates/skills/bridges/admin/copilot-instructions.md +2 -39
  28. package/templates/skills/bridges/api/AGENTS.md +5 -18
  29. package/templates/skills/bridges/api/CLAUDE.md +3 -11
  30. package/templates/skills/bridges/api/copilot-instructions.md +3 -38
  31. package/templates/skills/bridges/fullstack/AGENTS.md.hbs +24 -59
  32. package/templates/skills/bridges/fullstack/CLAUDE.md.hbs +1 -15
  33. package/templates/skills/bridges/fullstack/copilot-instructions.md.hbs +5 -45
  34. package/templates/skills/bridges/h5/AGENTS.md +4 -17
  35. package/templates/skills/bridges/h5/CLAUDE.md +3 -11
  36. package/templates/skills/bridges/h5/copilot-instructions.md +2 -37
  37. package/templates/skills/bridges/mobile-app/AGENTS.md +5 -18
  38. package/templates/skills/bridges/mobile-app/CLAUDE.md +3 -11
  39. package/templates/skills/bridges/mobile-app/copilot-instructions.md +2 -38
  40. package/templates/skills/bridges/website/AGENTS.md +4 -17
  41. package/templates/skills/bridges/website/CLAUDE.md +3 -11
  42. package/templates/skills/bridges/website/copilot-instructions.md +2 -37
  43. package/templates/skills/copilot-instructions.md +2 -36
  44. package/templates/skills/hai-ai/SKILL.md +35 -389
  45. package/templates/skills/hai-ai/guide.md +383 -0
  46. package/templates/skills/hai-ai/reference.md +6 -2
  47. package/templates/skills/hai-api-client/SKILL.md +6 -6
  48. package/templates/skills/hai-api-contract/SKILL.md +10 -25
  49. package/templates/skills/hai-app-create/SKILL.md +29 -388
  50. package/templates/skills/hai-app-create/reference.md +350 -0
  51. package/templates/skills/hai-app-review/SKILL.md +15 -23
  52. package/templates/skills/hai-app-tests/SKILL.md +29 -494
  53. package/templates/skills/hai-app-tests/reference.md +442 -0
  54. package/templates/skills/hai-audit/SKILL.md +6 -6
  55. package/templates/skills/hai-build/SKILL.md +19 -330
  56. package/templates/skills/hai-build/reference.md +326 -0
  57. package/templates/skills/hai-cache/SKILL.md +28 -31
  58. package/templates/skills/hai-capacitor/SKILL.md +19 -364
  59. package/templates/skills/hai-capacitor/reference.md +352 -0
  60. package/templates/skills/hai-ci/SKILL.md +17 -20
  61. package/templates/skills/hai-core/SKILL.md +25 -564
  62. package/templates/skills/hai-core/reference.md +533 -0
  63. package/templates/skills/hai-crypto/SKILL.md +8 -20
  64. package/templates/skills/hai-datapipe/SKILL.md +9 -23
  65. package/templates/skills/hai-deploy/SKILL.md +18 -24
  66. package/templates/skills/hai-framework-sync/SKILL.md +8 -20
  67. package/templates/skills/hai-iam/SKILL.md +27 -365
  68. package/templates/skills/hai-iam/reference.md +343 -0
  69. package/templates/skills/hai-kit/SKILL.md +6 -6
  70. package/templates/skills/hai-payment/SKILL.md +6 -26
  71. package/templates/skills/hai-pr-review/SKILL.md +6 -22
  72. package/templates/skills/hai-reach/SKILL.md +19 -317
  73. package/templates/skills/hai-reach/reference.md +303 -0
  74. package/templates/skills/hai-reldb/SKILL.md +19 -472
  75. package/templates/skills/hai-reldb/reference.md +452 -0
  76. package/templates/skills/hai-scheduler/SKILL.md +18 -6
  77. package/templates/skills/hai-serv/SKILL.md +27 -759
  78. package/templates/skills/hai-serv/reference.md +736 -0
  79. package/templates/skills/hai-storage/SKILL.md +7 -25
  80. package/templates/skills/hai-ui/SKILL.md +29 -621
  81. package/templates/skills/hai-ui/reference.md +598 -0
  82. package/templates/skills/hai-vecdb/SKILL.md +18 -303
  83. package/templates/skills/hai-vecdb/reference.md +291 -0
  84. package/dist/chunk-U4PA632G.js.map +0 -1
  85. package/dist/cli-config-templates-GSXKLGU5.js +0 -5
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hai-cache
3
- description: 使用 @h-ai/cache 进行内存或 Redis 缓存操作(kv/hash/list/set/zset/分布式锁);当需求涉及缓存读写、TTL 管理、集合运算、排行榜、缓存一致性策略或分布式互斥锁时使用。
3
+ description: "使用 @h-ai/cache 的 Memory/Redis 缓存、TTL、集合、排行榜和锁。"
4
4
  ---
5
5
 
6
6
  # hai-cache
@@ -9,22 +9,20 @@ description: 使用 @h-ai/cache 进行内存或 Redis 缓存操作(kv/hash/lis
9
9
 
10
10
  | 项目 | 契约 |
11
11
  | --- | --- |
12
- | 能力 | 使用 @h-ai/cache 进行内存或 Redis 缓存操作(kv/hash/list/set/zset/分布式锁);当需求涉及缓存读写、TTL 管理、集合运算、排行榜、缓存一致性策略或分布式互斥锁时使用。 |
13
- | 适用场景 | 当任务与 `hai-cache` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
- | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
- | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
- | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
12
+ | 能力 | 使用 @h-ai/cache 的 Memory/Redis 缓存、TTL、集合、排行榜和锁 |
13
+ | 适用场景 | 缓存读写、过期策略或共享资源互斥 |
14
+ | 输入 | CacheConfigInput、key/value、TTL、每次获锁的唯一 owner |
15
+ | 输出 | 缓存和锁操作的 HaiResult,获锁 data 为 boolean |
16
+ | 限制 | 仅服务端;Memory 不跨节点。release/extend 携带本次 owner,避免锁过期后误操作新持有者。 |
17
17
 
18
18
  > `@h-ai/cache` 提供统一缓存接口,支持 Memory 与 Redis 后端,包含 KV / Hash / List / Set / ZSet / 分布式锁 六类操作。
19
19
 
20
- ---
20
+ 内存 KV 在到期时间点即失效。整数计数器拒绝 null/boolean/array、非整数增量和安全整数溢出,失败不修改原值;Hash 的 `__proto__` / `constructor` 名称按普通字段保留。
21
21
 
22
22
  ## 运行环境
23
23
 
24
24
  > ⚠️ **服务端模块(Node.js only)。** 浏览器端无需直接操作缓存,由服务端模块(如 IAM、Scheduler)内部使用。
25
25
 
26
- ---
27
-
28
26
  ## 适用场景
29
27
 
30
28
  - 缓存热点数据减少数据库查询
@@ -34,8 +32,6 @@ description: 使用 @h-ai/cache 进行内存或 Redis 缓存操作(kv/hash/lis
34
32
  - 排行榜(ZSet)与队列(List)
35
33
  - 分布式锁(多节点部署互斥控制)
36
34
 
37
- ---
38
-
39
35
  ## 使用步骤
40
36
 
41
37
  ### 1. 配置
@@ -66,8 +62,6 @@ await cache.close()
66
62
 
67
63
  `cache.config` 返回的是脱敏后的配置快照;Redis `password` / `url` 等敏感值不会原样暴露给日志或调试输出。
68
64
 
69
- ---
70
-
71
65
  ## 核心 API
72
66
 
73
67
  ### KV 操作(`cache.kv`)
@@ -114,32 +108,35 @@ await cache.zset.zadd('rank:daily', { member: 'u1', score: 100 })
114
108
  | `extend` | 续期锁 TTL(支持 owner 验证) |
115
109
 
116
110
  ```typescript
117
- // 获锁(TTL 30 秒,owner 用于标识持有者)
118
- const acquired = await cache.lock.acquire('my-lock', { ttl: 30, owner: 'node-1' })
111
+ // 每次尝试生成唯一 owner,后续释放/续期复用同一个值
112
+ const owner = core.id.generate()
113
+ const acquired = await cache.lock.acquire('my-lock', { ttl: 30, owner })
119
114
  if (acquired.success && acquired.data) {
120
115
  try {
121
- // 受保护的操作
116
+ // 长任务仅在仍持有锁时续期;失败或 data=false 时停止依赖锁的后续操作
117
+ const extended = await cache.lock.extend('my-lock', 60, owner)
118
+ if (!extended.success || !extended.data) {
119
+ logger.warn('Lock extension failed; protected work cancelled')
120
+ }
121
+ else {
122
+ // 受保护的操作
123
+ }
122
124
  }
123
125
  finally {
124
- await cache.lock.release('my-lock', 'node-1')
126
+ await cache.lock.release('my-lock', owner)
125
127
  }
126
128
  }
127
129
 
128
- // 续期
129
- await cache.lock.extend('my-lock', 60, 'node-1')
130
-
131
130
  // 检查
132
131
  const locked = await cache.lock.isLocked('my-lock')
133
132
  ```
134
133
 
135
134
  **最佳实践:**
136
135
 
137
- - `owner` 使用稳定的节点标识(如 `nodeId`),不要每次随机生成
136
+ - `owner` 每次获锁尝试唯一,释放/续期复用该值;仅用 nodeId 会使同节点旧任务误释放过期后重新获得的锁
138
137
  - 释放锁时传入 `owner` 防止误释放他人锁
139
138
  - Memory 后端适合开发/测试;Redis 后端用 Lua 脚本保证 release/extend 原子性
140
139
 
141
- ---
142
-
143
140
  ## 错误码 — `HaiCacheError`
144
141
 
145
142
  | 错误码 | code | 说明 |
@@ -154,11 +151,9 @@ const locked = await cache.lock.isLocked('my-lock')
154
151
  | `HaiCacheError.UNSUPPORTED_TYPE` | `hai:cache:011` | 不支持的缓存类型 |
155
152
  | `HaiCacheError.CONFIG_ERROR` | `hai:cache:012` | 配置错误 |
156
153
 
157
- ---
158
-
159
154
  ## 常见模式
160
155
 
161
- ### 缓存穿透保护
156
+ ### 缓存命中与回源(未缓存空值,不防穿透)
162
157
 
163
158
  ```typescript
164
159
  async function getUserCached(userId: string) {
@@ -179,22 +174,24 @@ async function getUserCached(userId: string) {
179
174
 
180
175
  ```typescript
181
176
  const lockKey = 'batch:import'
182
- const acquired = await cache.lock.acquire(lockKey, { ttl: 60, owner: nodeId })
177
+ const owner = core.id.generate()
178
+ const acquired = await cache.lock.acquire(lockKey, { ttl: 60, owner })
183
179
  if (acquired.success && acquired.data) {
184
180
  try {
185
181
  await runBatchImport()
186
182
  }
187
183
  finally {
188
- await cache.lock.release(lockKey, nodeId)
184
+ await cache.lock.release(lockKey, owner)
189
185
  }
190
186
  }
191
- else {
187
+ else if (acquired.success) {
192
188
  logger.info('Another node is running the import')
193
189
  }
190
+ else {
191
+ logger.error('Lock acquisition failed', { code: acquired.error.code })
192
+ }
194
193
  ```
195
194
 
196
- ---
197
-
198
195
  ## 相关 Skills
199
196
 
200
197
  - `hai-build`:模块初始化顺序(cache 在 db 之后、iam 之前)
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hai-capacitor
3
- description: 使用 @h-ai/capacitor 桥接 Capacitor 原生能力(Token 安全存储、设备信息、推送通知、相机、状态栏),构建 Android/iOS 原生应用;当需求涉及原生 App 开发、Capacitor 集成、安全存储或原生设备功能时使用。
3
+ description: "使用 @h-ai/capacitor 接入原生设备、相机、推送、状态栏和安全 Token 存储。"
4
4
  ---
5
5
 
6
6
  # hai-capacitor
@@ -9,371 +9,26 @@ description: 使用 @h-ai/capacitor 桥接 Capacitor 原生能力(Token 安全
9
9
 
10
10
  | 项目 | 契约 |
11
11
  | --- | --- |
12
- | 能力 | 使用 @h-ai/capacitor 桥接 Capacitor 原生能力(Token 安全存储、设备信息、推送通知、相机、状态栏),构建 Android/iOS 原生应用;当需求涉及原生 App 开发、Capacitor 集成、安全存储或原生设备功能时使用。 |
13
- | 适用场景 | 当任务与 `hai-capacitor` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
- | 输入 | 用户目标、仓库与运行环境上下文、现有配置、授权范围和质量门禁 |
15
- | 输出 | 与目标匹配的配置/代码/文档或审查结论,以及可复现的验证结果 |
16
- | 限制 | 不扩张用户授权,不输出或固化密钥,不跳过失败门禁,不假定外部服务状态 |
12
+ | 能力 | 使用 @h-ai/capacitor 接入原生设备、相机、推送、状态栏和安全 Token 存储 |
13
+ | 适用场景 | Android/iOS 原生壳集成与平台差异处理 |
14
+ | 输入 | Capacitor 配置、原生插件、设备权限和平台状态 |
15
+ | 输出 | 原生操作结果及 TokenStorage 适配器 |
16
+ | 限制 | 区分浏览器与 Android/iOS;安全存储需原生插件,Web 不降级到 localStorage。H5 验证不能代替真机验证。 |
17
17
 
18
- > `@h-ai/capacitor` 是 hai-framework 的 Capacitor 原生桥接模块,封装常用原生能力为统一 API,返回 `HaiResult<T>`。与 `@h-ai/api-client` 配合时,Token 仅存于原生安全存储,不回退到 Web `localStorage`。
18
+ ## 使用路径
19
19
 
20
- ---
21
-
22
- ## 运行环境
23
-
24
- > **浏览器端 / 原生 App 专用。** 在 Capacitor 原生环境(Android/iOS)中提供完整能力;`createCapacitorTokenStorage()` 仅在原生环境持久化 token,纯 Web 不做不安全回退。`capacitor.preferences` 仍可用于普通偏好数据。
25
-
26
- ---
27
-
28
- ## 适用场景
29
-
30
- - Android/iOS 原生应用开发(Svelte 5 + Vite + Capacitor)
31
- - Token 安全存储(`@aparajita/capacitor-secure-storage`)
32
- - 设备信息获取(平台、型号、版本)
33
- - 推送通知注册与监听(FCM / APNs)
34
- - 原生相机拍照 / 相册选取
35
- - 状态栏配置(沉浸式、颜色、样式)
36
-
37
- ---
38
-
39
- ## 使用步骤
40
-
41
- ### 1. 初始化与关闭
42
-
43
- ```typescript
44
- import { capacitor } from '@h-ai/capacitor'
45
-
46
- // 应用启动时初始化(检测 Capacitor 环境可用性)
47
- const result = await capacitor.init()
48
- if (!result.success) {
49
- // result.error.code === HaiCapacitorError.NOT_AVAILABLE.code
50
- // 非 Capacitor 环境(纯 Web)
51
- }
52
-
53
- // 检查状态
54
- capacitor.isInitialized // boolean
55
- capacitor.getPlatform() // 'android' | 'ios' | 'web'
56
- capacitor.isNative() // true = 原生 App
57
-
58
- // 关闭模块(重置状态)
59
- await capacitor.close()
60
- ```
61
-
62
- ### 2. Token 安全存储(与 api-client 配合)
63
-
64
- ```typescript
65
- import { apiClient } from '@h-ai/api-client'
66
- import { createCapacitorTokenStorage } from '@h-ai/capacitor'
67
-
68
- await apiClient.init({
69
- baseUrl: import.meta.env.PUBLIC_API_BASE,
70
- auth: {
71
- storage: createCapacitorTokenStorage(),
72
- },
73
- })
74
- ```
75
-
76
- `createCapacitorTokenStorage()` 返回 `TokenStorage` 实例(兼容 `@h-ai/api-client`),底层使用 `@aparajita/capacitor-secure-storage`:
77
-
78
- - Android → Android KeyStore + 加密 SharedPreferences
79
- - iOS → Keychain
80
- - Web → **不回退到 localStorage**;`get*()` 返回 `null`,`set*()` / `clear()` 为 no-op
81
-
82
- 所有方法内置 try-catch;原生安全存储异常时 get 返回 `null`、set/clear 静默失败并记录日志。
83
-
84
- #### Preferences 子操作
20
+ - 先判断平台和插件可用性,复用已有 SPA 入口;原生 UI 变化验证权限拒绝、取消和返回路径。
21
+ - TokenStorage 在原生端使用安全插件;Web 下不伪造持久化成功。
85
22
 
86
- ```typescript
87
- import { capacitor } from '@h-ai/capacitor'
88
-
89
- // 返回 HaiResult<string | null>
90
- const result = await capacitor.preferences.get('my_key')
91
- if (result.success) {
92
- // result.data — 值或 null
93
- }
94
-
95
- await capacitor.preferences.set('my_key', 'value')
96
- await capacitor.preferences.remove('my_key')
97
- ```
98
-
99
- ### 3. 设备信息
100
-
101
- ```typescript
102
- import { capacitor } from '@h-ai/capacitor'
103
-
104
- const info = await capacitor.device.getInfo()
105
- if (info.success) {
106
- info.data.platform // 'android' | 'ios' | 'web'
107
- info.data.model // 'Pixel 7'
108
- info.data.osVersion // '14'
109
- info.data.manufacturer // 'Google'
110
- info.data.isVirtual // false
111
- }
112
-
113
- const version = await capacitor.device.getAppVersion()
114
- if (version.success) {
115
- version.data.version // '1.0.0'
116
- version.data.build // '42'
117
- }
118
- ```
119
-
120
- ### 4. 推送通知
121
-
122
- ```typescript
123
- import { capacitor } from '@h-ai/capacitor'
124
-
125
- // 注册推送(请求权限 + 获取设备 Token)
126
- const reg = await capacitor.push.register()
127
- if (reg.success) {
128
- // 将 reg.data.token 上报给后端
129
- await api.post('/push/register', { token: reg.data.token })
130
- }
131
-
132
- // 监听推送事件(返回 HaiResult 包裹的 async 清理函数)
133
- const listenResult = await capacitor.push.listen({
134
- onReceived: (notification) => {
135
- // 前台收到推送
136
- // notification: { id, title?, body?, data? }
137
- },
138
- onActionPerformed: (notification) => {
139
- // 用户点击推送
140
- },
141
- })
142
-
143
- // 停止监听
144
- if (listenResult.success) {
145
- await listenResult.data()
146
- }
147
- ```
148
-
149
- ### 5. 相机
150
-
151
- ```typescript
152
- import { capacitor } from '@h-ai/capacitor'
153
-
154
- const photo = await capacitor.camera.takePhoto({
155
- quality: 80, // 0-100
156
- source: 'camera', // 'camera' | 'photos' | 'prompt'
157
- resultType: 'base64', // 'uri' | 'base64' | 'dataUrl'
158
- width: 800, // 最大宽度(可选)
159
- height: 600, // 最大高度(可选)
160
- })
161
-
162
- if (photo.success) {
163
- const imgSrc = `data:image/${photo.data.format};base64,${photo.data.data}`
164
- }
165
- ```
166
-
167
- ### 6. 状态栏
168
-
169
- ```typescript
170
- import { capacitor } from '@h-ai/capacitor'
171
-
172
- await capacitor.statusBar.configure({
173
- backgroundColor: '#ffffff',
174
- style: 'dark', // 'dark' | 'light' | 'default'(文字颜色)
175
- overlay: true, // 沉浸式
176
- })
177
-
178
- await capacitor.statusBar.hide()
179
- await capacitor.statusBar.show()
180
- ```
181
-
182
- ---
183
-
184
- ## 核心 API
185
-
186
- | API | 用途 | 返回值 |
187
- | --- | --- | --- |
188
- | `capacitor.init()` | 初始化模块(检测环境) | `HaiResult<void>` |
189
- | `capacitor.close()` | 关闭模块,重置状态 | `Promise<void>` |
190
- | `capacitor.getPlatform()` | 获取当前平台 | `'android' \| 'ios' \| 'web'` |
191
- | `capacitor.isNative()` | 是否为原生环境 | `boolean` |
192
- | `capacitor.isInitialized` | 是否已初始化 | `boolean` |
193
- | `createCapacitorTokenStorage()` | 创建 Token 存储 | `TokenStorage`(兼容 api-client) |
194
- | `capacitor.preferences.get(key)` | 安全读取 Preference | `HaiResult<string \| null>` |
195
- | `capacitor.preferences.set(key, value)` | 安全写入 Preference | `HaiResult<void>` |
196
- | `capacitor.preferences.remove(key)` | 安全删除 Preference | `HaiResult<void>` |
197
- | `capacitor.device.getInfo()` | 设备信息 | `HaiResult<DeviceInfo>` |
198
- | `capacitor.device.getAppVersion()` | 应用版本 | `HaiResult<{ version, build }>` |
199
- | `capacitor.push.register()` | 注册推送 | `HaiResult<PushRegistration>` |
200
- | `capacitor.push.listen(callbacks)` | 监听推送事件 | `HaiResult<() => Promise<void>>`(async 清理函数) |
201
- | `capacitor.camera.takePhoto(options?)` | 拍照 / 选取图片 | `HaiResult<PhotoResult>` |
202
- | `capacitor.statusBar.configure(config)` | 配置状态栏 | `HaiResult<void>` |
203
- | `capacitor.statusBar.show()` | 显示状态栏 | `HaiResult<void>` |
204
- | `capacitor.statusBar.hide()` | 隐藏状态栏 | `HaiResult<void>` |
205
-
206
- ---
207
-
208
- ## 错误码 — `HaiCapacitorError`
209
-
210
- | 错误码 | code | 说明 |
211
- | -------------------------------------------- | ---------------------- | -------------------- |
212
- | `HaiCapacitorError.INIT_FAILED` | `hai:capacitor:001` | 初始化失败 |
213
- | `HaiCapacitorError.NOT_AVAILABLE` | `hai:capacitor:002` | Capacitor 不可用 |
214
- | `HaiCapacitorError.INIT_IN_PROGRESS` | `hai:capacitor:003` | 正在初始化中 |
215
- | `HaiCapacitorError.NOT_INITIALIZED` | `hai:capacitor:010` | 模块未初始化 |
216
- | `HaiCapacitorError.PREFERENCES_GET_FAILED` | `hai:capacitor:011` | Preferences 读取失败 |
217
- | `HaiCapacitorError.PREFERENCES_SET_FAILED` | `hai:capacitor:012` | Preferences 写入失败 |
218
- | `HaiCapacitorError.PREFERENCES_REMOVE_FAILED`| `hai:capacitor:013` | Preferences 删除失败 |
219
- | `HaiCapacitorError.DEVICE_INFO_FAILED` | `hai:capacitor:020` | 获取设备信息失败 |
220
- | `HaiCapacitorError.APP_VERSION_FAILED` | `hai:capacitor:021` | 获取应用版本失败 |
221
- | `HaiCapacitorError.PUSH_REGISTER_FAILED` | `hai:capacitor:030` | 推送注册失败 |
222
- | `HaiCapacitorError.PUSH_LISTEN_FAILED` | `hai:capacitor:031` | 推送监听失败 |
223
- | `HaiCapacitorError.CAMERA_FAILED` | `hai:capacitor:040` | 拍照/相册失败 |
224
- | `HaiCapacitorError.STATUS_BAR_FAILED` | `hai:capacitor:050` | 状态栏配置失败 |
225
-
226
- ---
227
-
228
- ## 常见模式
229
-
230
- ### Mobile App 标准初始化
231
-
232
- ```typescript
233
- // src/lib/capacitor.ts
234
- import { capacitor } from '@h-ai/capacitor'
235
-
236
- export async function initCapacitor() {
237
- const result = await capacitor.init()
238
- if (!result.success) {
239
- return
240
- }
241
-
242
- if (capacitor.isNative()) {
243
- await capacitor.statusBar.configure({
244
- backgroundColor: '#ffffff',
245
- style: 'light',
246
- overlay: false,
247
- })
248
- }
249
- }
250
- ```
251
-
252
- ```svelte
253
- <!-- src/App.svelte -->
254
- <script lang='ts'>
255
- import { onMount } from 'svelte'
256
- import { initCapacitor } from './lib/capacitor'
257
-
258
- onMount(() => { initCapacitor() })
259
- </script>
260
- ```
261
-
262
- ### SPA 模式配置(必需)
263
-
264
- Capacitor 应用使用 Vite 构建 SPA,并让原生壳读取 `dist`:
265
-
266
- ```typescript
267
- // capacitor.config.ts
268
- import type { CapacitorConfig } from '@capacitor/cli'
269
-
270
- const config: CapacitorConfig = {
271
- appId: 'com.example.app',
272
- appName: 'Example App',
273
- webDir: 'dist',
274
- }
275
-
276
- export default config
277
- ```
278
-
279
- ### Token 存储 + 认证流程
280
-
281
- ```typescript
282
- // src/lib/api.ts
283
- import { apiClient } from '@h-ai/api-client'
284
- import { createCapacitorTokenStorage } from '@h-ai/capacitor'
285
-
286
- export async function initApi() {
287
- return apiClient.init({
288
- baseUrl: `${import.meta.env.PUBLIC_API_BASE}/api/v1`,
289
- auth: {
290
- storage: createCapacitorTokenStorage(),
291
- },
292
- })
293
- }
294
-
295
- export { apiClient }
296
- ```
297
-
298
- ### 推送通知完整流程
299
-
300
- ```typescript
301
- import { capacitor } from '@h-ai/capacitor'
302
-
303
- export async function setupPush() {
304
- if (!capacitor.isNative()) {
305
- return
306
- }
307
-
308
- const reg = await capacitor.push.register()
309
- if (!reg.success) {
310
- return
311
- }
312
-
313
- // 上报 Token 给后端
314
- await api.post('/push/register', {
315
- token: reg.data.token,
316
- platform: capacitor.getPlatform(),
317
- })
318
-
319
- // 监听推送
320
- const listenResult = await capacitor.push.listen({
321
- onReceived: (n) => {
322
- // 前台通知处理
323
- },
324
- onActionPerformed: (n) => {
325
- // 用户点击跳转
326
- },
327
- })
328
- }
329
- ```
330
-
331
- ### 拍照上传
332
-
333
- ```typescript
334
- import { capacitor } from '@h-ai/capacitor'
335
-
336
- async function captureAndUpload() {
337
- const photo = await capacitor.camera.takePhoto({
338
- source: 'camera',
339
- resultType: 'base64',
340
- quality: 80,
341
- width: 1024,
342
- })
343
-
344
- if (!photo.success) {
345
- return
346
- }
347
-
348
- // 上传 base64 给后端
349
- await api.post('/files/upload', {
350
- data: photo.data.data,
351
- format: photo.data.format,
352
- })
353
- }
354
- ```
355
-
356
- ---
357
-
358
- ## 插件依赖
359
-
360
- | 插件 | 类型 | 用于 |
361
- | --- | --- | --- |
362
- | `@capacitor/core` | peerDependency(必需) | 核心运行时 |
363
- | `@aparajita/capacitor-secure-storage` | 可选 peerDependency(原生 token 存储必需) | `createCapacitorTokenStorage()` |
364
- | `@capacitor/preferences` | peerDependency(必需) | `capacitor.preferences.*` 普通偏好数据 |
365
- | `@capacitor/device` | 可选 | `getDeviceInfo()` |
366
- | `@capacitor/app` | 可选 | `getAppVersion()` |
367
- | `@capacitor/push-notifications` | 可选 | `registerPush()` / `listenPush()` |
368
- | `@capacitor/camera` | 可选 | `takePhoto()` |
369
- | `@capacitor/status-bar` | 可选 | `configureStatusBar()` / `show/hide` |
370
-
371
- 可选插件未安装时,对应 API 调用会返回 `err`(动态 import 失败被 catch)。
372
-
373
- ---
23
+ ## 按需参考
374
24
 
375
- ## 相关 Skills
25
+ 详细配置、API 签名、错误码和范本在 [reference.md](reference.md)。按下列标题定位所需小节,不默认通读;用例中的业务变量需结合当前应用补齐。
376
26
 
377
- - `hai-api-client`:HTTP 客户端(Token 管理依赖 capacitor 存储)
378
- - `hai-iam`:认证流程(登录获取 Token → 存储到 Capacitor)
379
- - `hai-ui`:移动端 UI 组件(SafeArea、BottomNav 等)
27
+ - 运行环境
28
+ - 适用场景
29
+ - 使用步骤
30
+ - 核心 API
31
+ - 错误码 — `HaiCapacitorError`
32
+ - 常见模式
33
+ - 插件依赖
34
+ - 相关 Skills