@h-ai/cli 0.1.0-alpha.54 → 0.1.0-alpha.56

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 (75) hide show
  1. package/README.md +4 -0
  2. package/dist/{chunk-FVDXJYMO.js → chunk-O3ANVICQ.js} +31 -2
  3. package/dist/chunk-O3ANVICQ.js.map +1 -0
  4. package/dist/cli-config-templates-OWBEGBZQ.js +5 -0
  5. package/dist/{cli-config-templates-WGN2I23J.js.map → cli-config-templates-OWBEGBZQ.js.map} +1 -1
  6. package/dist/index.js +3 -3
  7. package/dist/{src-6ZBWDBUB.js → src-TBIET7YU.js} +908 -127
  8. package/dist/src-TBIET7YU.js.map +1 -0
  9. package/package.json +7 -7
  10. package/templates/base/.gitignore.hbs +3 -0
  11. package/templates/base/package.json.hbs +1 -1
  12. package/templates/skills/AGENTS.md +8 -22
  13. package/templates/skills/CLAUDE.md +3 -16
  14. package/templates/skills/bridges/admin/AGENTS.md +3 -16
  15. package/templates/skills/bridges/admin/CLAUDE.md +3 -11
  16. package/templates/skills/bridges/admin/copilot-instructions.md +2 -39
  17. package/templates/skills/bridges/api/AGENTS.md +5 -18
  18. package/templates/skills/bridges/api/CLAUDE.md +3 -11
  19. package/templates/skills/bridges/api/copilot-instructions.md +3 -38
  20. package/templates/skills/bridges/fullstack/AGENTS.md.hbs +24 -59
  21. package/templates/skills/bridges/fullstack/CLAUDE.md.hbs +1 -15
  22. package/templates/skills/bridges/fullstack/copilot-instructions.md.hbs +5 -45
  23. package/templates/skills/bridges/h5/AGENTS.md +4 -17
  24. package/templates/skills/bridges/h5/CLAUDE.md +3 -11
  25. package/templates/skills/bridges/h5/copilot-instructions.md +2 -37
  26. package/templates/skills/bridges/mobile-app/AGENTS.md +5 -18
  27. package/templates/skills/bridges/mobile-app/CLAUDE.md +3 -11
  28. package/templates/skills/bridges/mobile-app/copilot-instructions.md +2 -38
  29. package/templates/skills/bridges/website/AGENTS.md +4 -17
  30. package/templates/skills/bridges/website/CLAUDE.md +3 -11
  31. package/templates/skills/bridges/website/copilot-instructions.md +2 -37
  32. package/templates/skills/copilot-instructions.md +2 -36
  33. package/templates/skills/hai-ai/SKILL.md +35 -389
  34. package/templates/skills/hai-ai/guide.md +383 -0
  35. package/templates/skills/hai-ai/reference.md +1 -1
  36. package/templates/skills/hai-api-client/SKILL.md +6 -6
  37. package/templates/skills/hai-api-contract/SKILL.md +10 -25
  38. package/templates/skills/hai-app-create/SKILL.md +29 -388
  39. package/templates/skills/hai-app-create/reference.md +350 -0
  40. package/templates/skills/hai-app-review/SKILL.md +9 -23
  41. package/templates/skills/hai-app-tests/SKILL.md +29 -494
  42. package/templates/skills/hai-app-tests/reference.md +442 -0
  43. package/templates/skills/hai-audit/SKILL.md +6 -6
  44. package/templates/skills/hai-build/SKILL.md +19 -338
  45. package/templates/skills/hai-build/reference.md +326 -0
  46. package/templates/skills/hai-cache/SKILL.md +27 -32
  47. package/templates/skills/hai-capacitor/SKILL.md +19 -366
  48. package/templates/skills/hai-capacitor/reference.md +352 -0
  49. package/templates/skills/hai-ci/SKILL.md +6 -21
  50. package/templates/skills/hai-core/SKILL.md +25 -566
  51. package/templates/skills/hai-core/reference.md +533 -0
  52. package/templates/skills/hai-crypto/SKILL.md +6 -20
  53. package/templates/skills/hai-datapipe/SKILL.md +9 -23
  54. package/templates/skills/hai-deploy/SKILL.md +63 -25
  55. package/templates/skills/hai-framework-sync/SKILL.md +8 -20
  56. package/templates/skills/hai-iam/SKILL.md +27 -371
  57. package/templates/skills/hai-iam/reference.md +343 -0
  58. package/templates/skills/hai-kit/SKILL.md +6 -6
  59. package/templates/skills/hai-payment/SKILL.md +6 -26
  60. package/templates/skills/hai-pr-review/SKILL.md +6 -22
  61. package/templates/skills/hai-reach/SKILL.md +19 -317
  62. package/templates/skills/hai-reach/reference.md +303 -0
  63. package/templates/skills/hai-reldb/SKILL.md +19 -472
  64. package/templates/skills/hai-reldb/reference.md +452 -0
  65. package/templates/skills/hai-scheduler/SKILL.md +6 -6
  66. package/templates/skills/hai-serv/SKILL.md +27 -759
  67. package/templates/skills/hai-serv/reference.md +736 -0
  68. package/templates/skills/hai-storage/SKILL.md +7 -25
  69. package/templates/skills/hai-ui/SKILL.md +29 -625
  70. package/templates/skills/hai-ui/reference.md +598 -0
  71. package/templates/skills/hai-vecdb/SKILL.md +18 -303
  72. package/templates/skills/hai-vecdb/reference.md +291 -0
  73. package/dist/chunk-FVDXJYMO.js.map +0 -1
  74. package/dist/cli-config-templates-WGN2I23J.js +0 -5
  75. package/dist/src-6ZBWDBUB.js.map +0 -1
@@ -1,397 +1,38 @@
1
1
  ---
2
2
  name: hai-app-create
3
- description: 以 TDD 方式在应用中创建新功能:先编写测试定义行为,再编码实现直至测试通过;当需求涉及新增页面/路由、API、服务、数据模型、组件时使用。
3
+ description: "在 hai 应用中新增页面、路由、API、服务、模型或组件。"
4
4
  ---
5
5
 
6
- # hai-app-create — TDD 驱动的应用功能创建规范
6
+ # hai-app-create
7
7
 
8
8
  ## 能力契约
9
9
 
10
10
  | 项目 | 契约 |
11
11
  | --- | --- |
12
- | 能力 | 以 TDD 方式在应用中创建新功能:先编写测试定义行为,再编码实现直至测试通过;当需求涉及新增页面/路由、API、服务、数据模型、组件时使用。 |
13
- | 适用场景 | 当任务与 `hai-app-create` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
- | 输入 | 明确的功能需求、目标路径、现有实现、仓库规范与验收条件 |
15
- | 输出 | 最小必要的代码、类型、测试和同步文档,以及实际验证结果 |
16
- | 限制 | 不为假设需求增加抽象,不绕过生命周期/HaiResult/i18n 约定,不覆盖用户已有改动 |
17
-
18
- > 面向 AI 助手的应用功能创建指南。**必须遵循 TDD**:先写测试(Red)→ 再实现(Green)→ 再重构(Refactor)。
19
- > 若目标是纯 API service workspace,优先围绕 `apps/*-contract`、`apps/*-service` 与测试组织改动,而不是套用页面/路由脚手架。
20
-
21
- ---
22
-
23
- ## 适用场景
24
-
25
- - 新增页面(路由)
26
- - 新增 API 端点
27
- - 新增服务层模块(`$lib/server/services/`)
28
- - 新增数据库表 / 数据模型
29
- - 新增业务组件
30
-
31
- ---
32
-
33
- ## TDD 开发流程(强制)
34
-
35
- 创建任何新功能时,必须按以下顺序执行:
36
-
37
- ### Step 1:需求分析与测试设计
38
-
39
- 1. 明确功能的输入、输出、边界条件、错误场景
40
- 2. 确定需要创建的文件(服务、路由、Schema、组件等)
41
- 3. 设计测试用例清单(参照 `hai-app-tests` 技能的覆盖范围要求)
42
-
43
- ### Step 2:编写测试(Red 阶段)
44
-
45
- 1. **创建单元测试**:在 `tests/` 下为服务层、Schema 编写 Vitest 测试
46
- 2. **创建 E2E 测试**:在 `e2e/` 下为 API 端点、页面交互编写 Playwright 测试
47
- 3. **创建空的实现文件**:仅包含函数签名和类型定义,不写实际逻辑(确保 import 不报错)
48
- 4. **运行测试确认全部失败**:
49
- ```bash
50
- pnpm --filter <app-name> test # 应全部 FAIL
51
- ```
52
-
53
- ### Step 3:编写实现(Green 阶段)
54
-
55
- 按照下文的「创建指南」编写实际功能代码,每完成一个功能点立即运行测试确认通过。
56
-
57
- ### Step 4:重构与验证(Refactor 阶段)
58
-
59
- 1. 参照 `hai-app-review` 审查代码规范
60
- 2. 运行质量门禁:`pnpm typecheck && pnpm lint && pnpm test`
61
- 3. 运行 E2E:`pnpm --filter <app-name> test:e2e`
62
-
63
- ---
64
-
65
- ## 目录结构约定
66
-
67
- ```
68
- src/
69
- hooks.server.ts # `handle` hook 入口
70
- app.css # 全局样式(TailwindCSS 4)
71
- lib/
72
- server/
73
- init.ts # 应用初始化(模块 init 顺序)
74
- services/ # 业务服务层(Server-only)
75
- index.ts # 服务聚合导出
76
- user.ts # 示例:用户服务
77
- schemas/ # 请求校验 Schema(Zod)
78
- components/ # 业务组件(非 @h-ai/ui 通用组件)
79
- stores/ # 客户端 Store(Svelte 5 Runes)
80
- paraglide/ # i18n 生成文件(禁止手动修改)
81
- routes/
82
- +layout.svelte # 根布局
83
- +page.svelte # 首页
84
- (auth)/ # 认证分组路由
85
- login/+page.svelte
86
- admin/ # 管理区域
87
- users/
88
- +page.svelte # 列表页
89
- +page.server.ts # 列表数据加载
90
- [id]/
91
- +page.svelte # 详情页
92
- +page.server.ts
93
- api/ # API 端点
94
- auth/+server.ts
95
- health/+server.ts
96
- iam/
97
- users/+server.ts
98
- messages/ # i18n 消息文件
99
- en-US.json
100
- zh-CN.json
101
- config/ # 模块配置文件
102
- _core.yml
103
- _db.yml
104
- _cache.yml
105
- _iam.yml
106
- ```
107
-
108
- ---
109
-
110
- ## 创建页面
111
-
112
- ### 页面路由规则
113
-
114
- 使用 SvelteKit 文件路由,参考 `src/routes/` 约定:
115
-
116
- | 类型 | 路径示例 | 说明 |
117
- | -------- | ---------------------------------- | -------------------- |
118
- | 静态页面 | `routes/about/+page.svelte` | 常规页面 |
119
- | 动态路由 | `routes/users/[id]/+page.svelte` | URL 参数 |
120
- | 分组路由 | `routes/(auth)/login/+page.svelte` | 共享布局,不影响 URL |
121
- | API 端点 | `routes/api/users/+server.ts` | RESTful API |
122
-
123
- ### 页面文件模板
124
-
125
- ```svelte
126
- <!-- +page.svelte -->
127
- <script lang="ts">
128
- // Svelte 5 Runes 语法
129
- let { data } = $props()
130
- let loading = $state(false)
131
-
132
- async function handleAction() {
133
- loading = true
134
- try {
135
- // 业务逻辑
136
- } finally {
137
- loading = false
138
- }
139
- }
140
- </script>
141
-
142
- <div class="container mx-auto p-4">
143
- <!-- 使用 @h-ai/ui 组件 -->
144
- </div>
145
- ```
146
-
147
- ### 数据加载(+page.server.ts)
148
-
149
- ```typescript
150
- import type { PageServerLoad } from './$types'
151
- import { kit } from '@h-ai/kit'
152
-
153
- export const load: PageServerLoad = async (event) => {
154
- // 权限守卫
155
- const guard = kit.guard.requireAuth(event)
156
- if (!guard.success)
157
- return kit.response.redirect('/login')
158
-
159
- // 加载数据
160
- const result = await someService.list()
161
- if (!result.success)
162
- return kit.response.error(500, result.error.message)
163
-
164
- return { items: result.data }
165
- }
166
- ```
167
-
168
- ---
169
-
170
- ## 创建 API 端点
171
-
172
- ### RESTful 端点模板
173
-
174
- ```typescript
175
- // src/routes/api/[resource]/+server.ts
176
- import type { RequestHandler } from './$types'
177
- import { kit } from '@h-ai/kit'
178
- import { z } from 'zod'
179
-
180
- const CreateSchema = z.object({
181
- name: z.string().min(1).max(100),
182
- description: z.string().optional(),
183
- })
184
-
185
- // GET - 列表
186
- export const GET = kit.handler(async ({ locals }) => {
187
- kit.guard.requirePermission(locals.session, 'resource:read')
188
-
189
- const result = await service.list()
190
- if (!result.success)
191
- return kit.response.error(500, result.error.message)
192
- return kit.response.ok(result.data)
193
- })
194
-
195
- // POST - 创建
196
- export const POST = kit.handler(async ({ request, locals }) => {
197
- kit.guard.requirePermission(locals.session, 'resource:create')
198
-
199
- const data = await kit.validate.formOrFail(request, CreateSchema)
200
-
201
- const result = await service.create(data)
202
- if (!result.success)
203
- return kit.response.error(500, result.error.message)
204
- return kit.response.created(result.data)
205
- })
206
- ```
207
-
208
- ### 要点
209
-
210
- - 所有端点**必须**用 `kit.handler(async ({ locals, request, ... }) => { ... })` 包裹,由 handler 统一处理 throw 的 Response
211
- - 权限守卫使用 `kit.guard.requirePermission(locals.session, 'xxx:yyy')`,它本身就是 throw 模式(未通过时 throw 403 Response),**无需**检查返回值
212
- - 输入校验使用 `await kit.validate.formOrFail(request, Schema)`,校验失败时 throw 400 Response,**无需**手动判断 valid
213
- - 返回统一使用 `kit.response.*`
214
- - HaiResult 错误直接透传,不重新包装
215
- - 框架模块 API 不抛异常,不要用 `try/catch` 处理模块返回的错误,直接检查 `result.success`
216
-
217
- ---
218
-
219
- ## 创建服务层
220
-
221
- 服务层位于 `$lib/server/services/`,处理业务逻辑。
222
-
223
- ```typescript
224
- import type { HaiResult } from '@h-ai/core'
225
- // src/lib/server/services/article.ts
226
- import { core } from '@h-ai/core'
227
- import { reldb } from '@h-ai/reldb'
228
-
229
- const logger = core.logger
230
-
231
- /** 创建文章 */
232
- export async function createArticle(input: CreateArticleInput): Promise<HaiResult<Article>> {
233
- logger.debug('Creating article', { title: input.title })
234
-
235
- const result = await reldb.crud.create('articles', {
236
- id: core.id.uuid(),
237
- ...input,
238
- created_at: new Date().toISOString(),
239
- })
240
- if (!result.success)
241
- return result
242
-
243
- logger.info('Article created', { id: result.data.id })
244
- return result
245
- }
246
-
247
- /** 获取文章列表 */
248
- export async function listArticles(params: ListParams): Promise<HaiResult<PaginatedResult<Article>>> {
249
- logger.debug('Listing articles', { page: params.page })
250
- return reldb.crud.paginate('articles', params)
251
- }
252
- ```
253
-
254
- ### 服务层规则
255
-
256
- - 统一返回 `HaiResult<T>`
257
- - 写操作需 `debug`(进入)+ `info`(成功)日志
258
- - 读操作仅 `debug` 日志
259
- - 禁止 `console.log`,使用 `core.logger`
260
- - 服务层不处理 HTTP 响应格式,只返回 HaiResult
261
-
262
- ---
263
-
264
- ## 创建数据模型
265
-
266
- ### Schema 定义(SQL DDL)
267
-
268
- 数据库表 Schema 定义在 `$lib/server/init.ts` 中:
269
-
270
- ```typescript
271
- const BUSINESS_SCHEMA = `
272
- CREATE TABLE IF NOT EXISTS articles (
273
- id TEXT PRIMARY KEY,
274
- title TEXT NOT NULL,
275
- content TEXT,
276
- author_id TEXT NOT NULL,
277
- status TEXT DEFAULT 'draft',
278
- created_at TEXT DEFAULT (datetime('now')),
279
- updated_at TEXT DEFAULT (datetime('now'))
280
- );
281
-
282
- CREATE INDEX IF NOT EXISTS idx_articles_author_id ON articles(author_id);
283
- CREATE INDEX IF NOT EXISTS idx_articles_status ON articles(status);
284
- `
285
- ```
286
-
287
- ### 类型定义
288
-
289
- ```typescript
290
- // 在服务文件或独立类型文件中定义
291
- interface Article {
292
- id: string
293
- title: string
294
- content: string | null
295
- authorId: string
296
- status: 'draft' | 'published' | 'archived'
297
- createdAt: string
298
- updatedAt: string
299
- }
300
-
301
- interface CreateArticleInput {
302
- title: string
303
- content?: string
304
- authorId: string
305
- }
306
- ```
307
-
308
- ---
309
-
310
- ## 创建业务组件
311
-
312
- 业务组件放在 `$lib/components/`,通用 UI 使用 `@h-ai/ui`。
313
-
314
- ```svelte
315
- <!-- src/lib/components/ArticleCard.svelte -->
316
- <script lang="ts">
317
- import type { Article } from '$lib/server/services/article'
318
-
319
- let { article, onEdit }: { article: Article, onEdit?: () => void } = $props()
320
- </script>
321
-
322
- <div class="card bg-base-100 shadow">
323
- <div class="card-body">
324
- <h2 class="card-title">{article.title}</h2>
325
- <p>{article.content ?? ''}</p>
326
- {#if onEdit}
327
- <div class="card-actions justify-end">
328
- <button class="btn btn-primary" onclick={onEdit}>编辑</button>
329
- </div>
330
- {/if}
331
- </div>
332
- </div>
333
- ```
334
-
335
- ### 组件规则
336
-
337
- - 使用 Svelte 5 Runes 语法(`$props()`、`$state()`、`$derived()`、`$effect()`)
338
- - 事件回调通过 props 传入(非 `createEventDispatcher`)
339
- - 样式使用 TailwindCSS 4 + DaisyUI 5 class
340
- - 通用 UI 组件优先使用 `@h-ai/ui`,不重复实现
341
- - i18n 文本使用 `$lib/paraglide/messages.js` 中的 key
342
-
343
- ---
344
-
345
- ## 初始化顺序
346
-
347
- 在 `$lib/server/init.ts` 中管理模块初始化顺序:
348
-
349
- ```
350
- core.init() → reldb.init() → cache.init() → iam.init() → createBusinessTables()
351
- ```
352
-
353
- 新增模块时需在此文件中按依赖顺序添加初始化调用。
354
-
355
- ---
356
-
357
- ## 容器交付
358
-
359
- - 保持脚手架根目录 `Dockerfile`、`.dockerignore` 与 `package.json` 中 `docker:build*` / `podman:build*` 命令同步。
360
- - Podman 多阶段构建保持 `--format docker --jobs=1`;前者保留 `HEALTHCHECK`,后者避免部分 Podman 5.8/Buildah 组合在并行 stage 构建时触发内部 semaphore panic。
361
- - 先复制 lockfile 与 workspace 配置执行 `pnpm fetch`,再复制源码并离线安装、构建;避免源码变化重复下载依赖,同时兼容新增 workspace。
362
- - SvelteKit 服务使用 Node adapter;纯 Vite 前端使用带 SPA fallback 的静态镜像;fullstack 的 Service 与 Web 分别交付,Service 直接监听且不增加转发进程。
363
- - Web 的 `PUBLIC_*` 部署配置在容器启动时生成静态运行时配置,不作为 build arg 烘焙,确保同一镜像可跨环境部署。
364
- - 配置文件随镜像提供,并允许只读挂载覆盖;密钥只通过环境变量或 `--env-file` 注入。
365
- - 普通构建不携带 `data/`;只有用户明确运行 `docker:build:data` / `podman:build:data` 时才通过 named build context 嵌入 SQLite/本地存储初始快照。
366
- - 数据库和本地存储的持续写入必须落到 volume,不能依赖镜像可写层。
367
- - 完成前实际启动镜像,验证健康端点、非 root 用户、环境变量覆盖、配置挂载和预置数据读取。
368
-
369
- ---
370
-
371
- ## 检查清单
372
-
373
- - [ ] **TDD 流程已执行**:先写测试 → 确认失败 → 再实现 → 确认通过
374
- - [ ] 单元测试已编写(服务层、Schema)
375
- - [ ] E2E 测试已编写(API 端点、页面交互)
376
- - [ ] 页面使用 Svelte 5 Runes 语法
377
- - [ ] API 端点有权限守卫与输入校验
378
- - [ ] 服务层统一返回 `HaiResult<T>`
379
- - [ ] 日志级别正确(读 debug / 写 debug+info / 失败 warn|error)
380
- - [ ] 禁止 `console.log`、`any`、硬编码密钥
381
- - [ ] 用户可见文本走 i18n
382
- - [ ] Docker / Podman 镜像可启动,配置/环境变量/数据目录行为已验证
383
- - [ ] 新增表有索引定义
384
- - [ ] 组件优先使用 `@h-ai/ui`
385
- - [ ] `pnpm typecheck && pnpm lint && pnpm test` 通过
386
-
387
- ---
388
-
389
- ## 相关 Skills
390
-
391
- - `hai-build`:项目架构与模块初始化顺序
392
- - `hai-app-tests`:TDD 测试规范(Red 阶段详细指引)
393
- - `hai-app-review`:代码审查规范(Refactor 阶段参照)
394
- - `hai-kit`:SvelteKit 集成的完整 API
395
- - `hai-ui`:UI 组件库使用
396
- - `hai-reldb`:数据库操作详细 API
397
- - `hai-iam`:认证与权限管理
12
+ | 能力 | 在 hai 应用中新增页面、路由、API、服务、模型或组件 |
13
+ | 适用场景 | 已确定需求的应用功能实现 |
14
+ | 输入 | 功能需求、现有路由/contract、数据模型和验收场景 |
15
+ | 输出 | 最小实现、必要测试、i18n 与同步文档 |
16
+ | 限制 | 优先复用;TDD 仅让新增目标用例先失败,已有回归保持通过。API workspace 不生成 SvelteKit 路由。 |
17
+
18
+ ## 使用路径
19
+
20
+ - 从真实路由/contract、UI 组件和服务层扩展;API workspace、SvelteKit 和 SPA 的文件结构不能混用。
21
+ - 对新增行为先写有意义的目标用例,已有回归保持通过;同步 i18n、README 和调用方。
22
+
23
+ ## 按需参考
24
+
25
+ 详细配置、API 签名、错误码和范本在 [reference.md](reference.md)。按下列标题定位所需小节,不默认通读;用例中的业务变量需结合当前应用补齐。
26
+
27
+ - 适用场景
28
+ - TDD 开发流程(强制)
29
+ - 目录结构约定
30
+ - 创建页面
31
+ - 创建 API 端点
32
+ - 创建服务层
33
+ - 创建数据模型
34
+ - 创建业务组件
35
+ - 初始化顺序
36
+ - 容器交付
37
+ - 检查清单
38
+ - 相关 Skills