@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,389 @@
1
+ ---
2
+ name: hai-capacitor
3
+ description: 使用 @h-ai/capacitor 桥接 Capacitor 原生能力(Token 安全存储、设备信息、推送通知、相机、状态栏),构建 Android/iOS 原生应用;当需求涉及原生 App 开发、Capacitor 集成、安全存储或原生设备功能时使用。
4
+ ---
5
+
6
+ # hai-capacitor
7
+
8
+ > `@h-ai/capacitor` 是 hai-framework 的 Capacitor 原生桥接模块,封装常用原生能力为统一 API,返回 `HaiResult<T>`。与 `@h-ai/api-client` 配合实现 App 端 Token 安全存储。
9
+
10
+ ---
11
+
12
+ ## 适用场景
13
+
14
+ - Android/iOS 原生应用开发(SvelteKit + Capacitor)
15
+ - Token 安全存储(Capacitor Preferences → SharedPreferences / UserDefaults)
16
+ - 设备信息获取(平台、型号、版本)
17
+ - 推送通知注册与监听(FCM / APNs)
18
+ - 原生相机拍照 / 相册选取
19
+ - 状态栏配置(沉浸式、颜色、样式)
20
+
21
+ ---
22
+
23
+ ## 模块结构
24
+
25
+ ```
26
+ packages/capacitor/src/
27
+ index.ts # export * 聚合
28
+ capacitor-main.ts # 服务对象(export const capacitor)
29
+ capacitor-types.ts # 公共类型(CapacitorFunctions / CapacitorError / 业务类型)
30
+ capacitor-config.ts # 错误码(HaiCapacitorError as const)
31
+ capacitor-i18n.ts # i18n 消息获取器
32
+ capacitor-token-storage.ts # Token 存储(TokenStorage 实现 + safe* 工具)
33
+ capacitor-device.ts # 设备信息
34
+ capacitor-camera.ts # 相机/相册
35
+ capacitor-push.ts # 推送通知
36
+ capacitor-status-bar.ts # 状态栏
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 使用步骤
42
+
43
+ ### 1. 初始化与关闭
44
+
45
+ ```typescript
46
+ import { capacitor } from '@h-ai/capacitor'
47
+
48
+ // 应用启动时初始化(检测 Capacitor 环境可用性)
49
+ const result = await capacitor.init()
50
+ if (!result.success) {
51
+ // result.error.code === HaiCapacitorError.NOT_AVAILABLE.code
52
+ // 非 Capacitor 环境(纯 Web)
53
+ }
54
+
55
+ // 检查状态
56
+ capacitor.isInitialized // boolean
57
+ capacitor.getPlatform() // 'android' | 'ios' | 'web'
58
+ capacitor.isNative() // true = 原生 App
59
+
60
+ // 关闭模块(重置状态)
61
+ await capacitor.close()
62
+ ```
63
+
64
+ ### 2. Token 安全存储(与 api-client 配合)
65
+
66
+ ```typescript
67
+ import { api } from '@h-ai/api-client'
68
+ import { createCapacitorTokenStorage } from '@h-ai/capacitor'
69
+
70
+ await api.init({
71
+ baseUrl: import.meta.env.PUBLIC_API_BASE,
72
+ auth: {
73
+ storage: createCapacitorTokenStorage(),
74
+ refreshUrl: '/api/v1/auth/refresh',
75
+ },
76
+ })
77
+ ```
78
+
79
+ `createCapacitorTokenStorage()` 返回 `TokenStorage` 实例(兼容 `@h-ai/api-client`),底层使用 `@capacitor/preferences`:
80
+
81
+ - Android → SharedPreferences(应用沙盒)
82
+ - iOS → UserDefaults
83
+ - Web → localStorage(退化,建议仅原生端使用)
84
+
85
+ 所有方法内置 try-catch,Preferences 异常时 get 返回 `null`、set/clear 静默失败并记录日志。
86
+
87
+ #### Preferences 子操作
88
+
89
+ ```typescript
90
+ import { capacitor } from '@h-ai/capacitor'
91
+
92
+ // 返回 HaiResult<string | null>
93
+ const result = await capacitor.preferences.get('my_key')
94
+ if (result.success) {
95
+ // result.data — 值或 null
96
+ }
97
+
98
+ await capacitor.preferences.set('my_key', 'value')
99
+ await capacitor.preferences.remove('my_key')
100
+ ```
101
+
102
+ ### 3. 设备信息
103
+
104
+ ```typescript
105
+ import { capacitor } from '@h-ai/capacitor'
106
+
107
+ const info = await capacitor.device.getInfo()
108
+ if (info.success) {
109
+ info.data.platform // 'android' | 'ios' | 'web'
110
+ info.data.model // 'Pixel 7'
111
+ info.data.osVersion // '14'
112
+ info.data.manufacturer // 'Google'
113
+ info.data.isVirtual // false
114
+ }
115
+
116
+ const version = await capacitor.device.getAppVersion()
117
+ if (version.success) {
118
+ version.data.version // '1.0.0'
119
+ version.data.build // '42'
120
+ }
121
+ ```
122
+
123
+ ### 4. 推送通知
124
+
125
+ ```typescript
126
+ import { capacitor } from '@h-ai/capacitor'
127
+
128
+ // 注册推送(请求权限 + 获取设备 Token)
129
+ const reg = await capacitor.push.register()
130
+ if (reg.success) {
131
+ // 将 reg.data.token 上报给后端
132
+ await api.post('/push/register', { token: reg.data.token })
133
+ }
134
+
135
+ // 监听推送事件(返回 HaiResult 包裹的 async 清理函数)
136
+ const listenResult = await capacitor.push.listen({
137
+ onReceived: (notification) => {
138
+ // 前台收到推送
139
+ // notification: { id, title?, body?, data? }
140
+ },
141
+ onActionPerformed: (notification) => {
142
+ // 用户点击推送
143
+ },
144
+ })
145
+
146
+ // 停止监听
147
+ if (listenResult.success) {
148
+ await listenResult.data()
149
+ }
150
+ ```
151
+
152
+ ### 5. 相机
153
+
154
+ ```typescript
155
+ import { capacitor } from '@h-ai/capacitor'
156
+
157
+ const photo = await capacitor.camera.takePhoto({
158
+ quality: 80, // 0-100
159
+ source: 'camera', // 'camera' | 'photos' | 'prompt'
160
+ resultType: 'base64', // 'uri' | 'base64' | 'dataUrl'
161
+ width: 800, // 最大宽度(可选)
162
+ height: 600, // 最大高度(可选)
163
+ })
164
+
165
+ if (photo.success) {
166
+ const imgSrc = `data:image/${photo.data.format};base64,${photo.data.data}`
167
+ }
168
+ ```
169
+
170
+ ### 6. 状态栏
171
+
172
+ ```typescript
173
+ import { capacitor } from '@h-ai/capacitor'
174
+
175
+ await capacitor.statusBar.configure({
176
+ backgroundColor: '#ffffff',
177
+ style: 'dark', // 'dark' | 'light' | 'default'(文字颜色)
178
+ overlay: true, // 沉浸式
179
+ })
180
+
181
+ await capacitor.statusBar.hide()
182
+ await capacitor.statusBar.show()
183
+ ```
184
+
185
+ ---
186
+
187
+ ## 核心 API
188
+
189
+ | API | 用途 | 返回值 |
190
+ | --- | --- | --- |
191
+ | `capacitor.init()` | 初始化模块(检测环境) | `HaiResult<void>` |
192
+ | `capacitor.close()` | 关闭模块,重置状态 | `Promise<void>` |
193
+ | `capacitor.getPlatform()` | 获取当前平台 | `'android' \| 'ios' \| 'web'` |
194
+ | `capacitor.isNative()` | 是否为原生环境 | `boolean` |
195
+ | `capacitor.isInitialized` | 是否已初始化 | `boolean` |
196
+ | `createCapacitorTokenStorage()` | 创建 Token 存储 | `TokenStorage`(兼容 api-client) |
197
+ | `capacitor.preferences.get(key)` | 安全读取 Preference | `HaiResult<string \| null>` |
198
+ | `capacitor.preferences.set(key, value)` | 安全写入 Preference | `HaiResult<void>` |
199
+ | `capacitor.preferences.remove(key)` | 安全删除 Preference | `HaiResult<void>` |
200
+ | `capacitor.device.getInfo()` | 设备信息 | `HaiResult<DeviceInfo>` |
201
+ | `capacitor.device.getAppVersion()` | 应用版本 | `HaiResult<{ version, build }>` |
202
+ | `capacitor.push.register()` | 注册推送 | `HaiResult<PushRegistration>` |
203
+ | `capacitor.push.listen(callbacks)` | 监听推送事件 | `HaiResult<() => Promise<void>>`(async 清理函数) |
204
+ | `capacitor.camera.takePhoto(options?)` | 拍照 / 选取图片 | `HaiResult<PhotoResult>` |
205
+ | `capacitor.statusBar.configure(config)` | 配置状态栏 | `HaiResult<void>` |
206
+ | `capacitor.statusBar.show()` | 显示状态栏 | `HaiResult<void>` |
207
+ | `capacitor.statusBar.hide()` | 隐藏状态栏 | `HaiResult<void>` |
208
+
209
+ ---
210
+
211
+ ## 错误码 — `HaiCapacitorError`
212
+
213
+ | 错误码 | code | 说明 |
214
+ | -------------------------------------------- | ---------------------- | -------------------- |
215
+ | `HaiCapacitorError.INIT_FAILED` | `hai:capacitor:001` | 初始化失败 |
216
+ | `HaiCapacitorError.NOT_AVAILABLE` | `hai:capacitor:002` | Capacitor 不可用 |
217
+ | `HaiCapacitorError.INIT_IN_PROGRESS` | `hai:capacitor:003` | 正在初始化中 |
218
+ | `HaiCapacitorError.NOT_INITIALIZED` | `hai:capacitor:010` | 模块未初始化 |
219
+ | `HaiCapacitorError.PREFERENCES_GET_FAILED` | `hai:capacitor:011` | Preferences 读取失败 |
220
+ | `HaiCapacitorError.PREFERENCES_SET_FAILED` | `hai:capacitor:012` | Preferences 写入失败 |
221
+ | `HaiCapacitorError.PREFERENCES_REMOVE_FAILED`| `hai:capacitor:013` | Preferences 删除失败 |
222
+ | `HaiCapacitorError.DEVICE_INFO_FAILED` | `hai:capacitor:020` | 获取设备信息失败 |
223
+ | `HaiCapacitorError.PUSH_REGISTER_FAILED` | `hai:capacitor:030` | 推送注册失败 |
224
+ | `HaiCapacitorError.PUSH_LISTEN_FAILED` | `hai:capacitor:031` | 推送监听失败 |
225
+ | `HaiCapacitorError.CAMERA_FAILED` | `hai:capacitor:040` | 拍照/相册失败 |
226
+ | `HaiCapacitorError.STATUS_BAR_FAILED` | `hai:capacitor:050` | 状态栏配置失败 |
227
+
228
+ ---
229
+
230
+ ## 常见模式
231
+
232
+ ### Android 应用标准初始化
233
+
234
+ ```typescript
235
+ // src/lib/capacitor.ts
236
+ import { capacitor } from '@h-ai/capacitor'
237
+
238
+ export async function initCapacitor() {
239
+ const result = await capacitor.init()
240
+ if (!result.success) {
241
+ return
242
+ }
243
+
244
+ if (capacitor.isNative()) {
245
+ await capacitor.statusBar.configure({
246
+ backgroundColor: '#ffffff',
247
+ style: 'light',
248
+ overlay: false,
249
+ })
250
+ }
251
+ }
252
+ ```
253
+
254
+ ```svelte
255
+ <!-- src/routes/+layout.svelte -->
256
+ <script lang="ts">
257
+ import { onMount } from 'svelte'
258
+ import { initCapacitor } from '$lib/capacitor'
259
+
260
+ onMount(() => { initCapacitor() })
261
+ </script>
262
+ ```
263
+
264
+ ### SPA 模式配置(必需)
265
+
266
+ Capacitor 应用必须使用 SPA 模式:
267
+
268
+ ```typescript
269
+ // src/routes/+layout.ts
270
+ export const prerender = true
271
+ export const ssr = false
272
+ ```
273
+
274
+ ```javascript
275
+ // svelte.config.js
276
+ import adapter from '@sveltejs/adapter-static'
277
+
278
+ const config = {
279
+ kit: {
280
+ adapter: adapter({
281
+ pages: 'build',
282
+ assets: 'build',
283
+ fallback: 'index.html',
284
+ }),
285
+ },
286
+ }
287
+ ```
288
+
289
+ ### Token 存储 + 认证流程
290
+
291
+ ```typescript
292
+ // src/lib/api.ts
293
+ import { api } from '@h-ai/api-client'
294
+ import { createCapacitorTokenStorage } from '@h-ai/capacitor'
295
+
296
+ export async function initApi() {
297
+ return api.init({
298
+ baseUrl: `${import.meta.env.PUBLIC_API_BASE}/api/v1`,
299
+ auth: {
300
+ storage: createCapacitorTokenStorage(),
301
+ refreshUrl: '/auth/refresh',
302
+ },
303
+ })
304
+ }
305
+
306
+ export { api }
307
+ ```
308
+
309
+ ### 推送通知完整流程
310
+
311
+ ```typescript
312
+ import { capacitor } from '@h-ai/capacitor'
313
+
314
+ export async function setupPush() {
315
+ if (!capacitor.isNative()) {
316
+ return
317
+ }
318
+
319
+ const reg = await capacitor.push.register()
320
+ if (!reg.success) {
321
+ return
322
+ }
323
+
324
+ // 上报 Token 给后端
325
+ await api.post('/push/register', {
326
+ token: reg.data.token,
327
+ platform: capacitor.getPlatform(),
328
+ })
329
+
330
+ // 监听推送
331
+ const listenResult = await capacitor.push.listen({
332
+ onReceived: (n) => {
333
+ // 前台通知处理
334
+ },
335
+ onActionPerformed: (n) => {
336
+ // 用户点击跳转
337
+ },
338
+ })
339
+ }
340
+ ```
341
+
342
+ ### 拍照上传
343
+
344
+ ```typescript
345
+ import { capacitor } from '@h-ai/capacitor'
346
+
347
+ async function captureAndUpload() {
348
+ const photo = await capacitor.camera.takePhoto({
349
+ source: 'camera',
350
+ resultType: 'base64',
351
+ quality: 80,
352
+ width: 1024,
353
+ })
354
+
355
+ if (!photo.success) {
356
+ return
357
+ }
358
+
359
+ // 上传 base64 给后端
360
+ await api.post('/files/upload', {
361
+ data: photo.data.data,
362
+ format: photo.data.format,
363
+ })
364
+ }
365
+ ```
366
+
367
+ ---
368
+
369
+ ## 插件依赖
370
+
371
+ | 插件 | 类型 | 用于 |
372
+ | --- | --- | --- |
373
+ | `@capacitor/core` | peerDependency(必需) | 核心运行时 |
374
+ | `@capacitor/preferences` | peerDependency(必需) | Token 存储 |
375
+ | `@capacitor/device` | 可选 | `getDeviceInfo()` |
376
+ | `@capacitor/app` | 可选 | `getAppVersion()` |
377
+ | `@capacitor/push-notifications` | 可选 | `registerPush()` / `listenPush()` |
378
+ | `@capacitor/camera` | 可选 | `takePhoto()` |
379
+ | `@capacitor/status-bar` | 可选 | `configureStatusBar()` / `show/hide` |
380
+
381
+ 可选插件未安装时,对应 API 调用会返回 `err`(动态 import 失败被 catch)。
382
+
383
+ ---
384
+
385
+ ## 相关 Skills
386
+
387
+ - `hai-api-client`:HTTP 客户端(Token 管理依赖 capacitor 存储)
388
+ - `hai-iam`:认证流程(登录获取 Token → 存储到 Capacitor)
389
+ - `hai-ui`:移动端 UI 组件(SafeArea、BottomNav 等)