@h-ai/cli 0.1.0-alpha.13 → 0.1.0-alpha.16

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.
@@ -1,484 +1,157 @@
1
1
  ---
2
2
  name: hai-kit
3
- description: 使用 @h-ai/kit 构建 SvelteKit 请求管道与 API 安全边界(handle/guard/middleware/handler/validate/response/fromContract)。当需求涉及 hooks.server.ts、hooks.client.ts、权限守卫、限流、统一响应、Bearer Token 认证、契约处理、CORS 配置、svelte.config.js 或 playwright.config.ts 时使用。
3
+ description: 使用 @h-ai/kit 构建 SvelteKit 请求管道、认证守卫、统一响应、Zod 校验、浏览器端 apiFetch、A2A 与双构建适配;当需求涉及 hooks.server.ts、权限守卫、CORS、限流、同源 transport 或 SvelteKit API endpoint 时使用。
4
4
  ---
5
5
 
6
6
  # hai-kit
7
7
 
8
- `@h-ai/kit` 是 hai-framework 的 SvelteKit 集成层。它把请求处理中的"通用横切能力"收敛到统一命名空间 `kit`:
8
+ > `@h-ai/kit` 只负责 SvelteKit 集成:Handle Hook、guard、response、validate、client、auth、crud、A2A。公共跨端 HTTP API 契约统一使用 `@h-ai/api-contract` + `@h-ai/serv`,不要在 kit 中定义业务 API contract。
9
9
 
10
- - 请求入口:`createHandle` / `sequence`
11
- - 安全边界:`guard` / `middleware`
12
- - API 工具:`handler` / `response` / `validate`
13
- - Bearer Token 认证:从 `Authorization` header 解析,SSR 端通过 `hai_token` Cookie 透传
14
- - 契约处理:`fromContract(endpoint, fn)` — 基于 EndpointDef 的类型安全 handler
15
- - 双构建模式:`createAdapter()` 根据环境变量选择 adapter-node 或 adapter-static
16
-
17
- ## 模块概述
18
-
19
- 当任务涉及以下关键词时,优先使用本 Skill:
20
-
21
- - `hooks.server.ts` / `hooks.client.ts`
22
- - `svelte.config.js` / `vite.config.ts` / `playwright.config.ts`
23
- - `kit.createHandle` / `kit.sequence`
24
- - `kit.guard.*`(`require` / `check`)
25
- - `kit.handler` / `kit.response` / `kit.validate`
26
- - `kit.fromContract(endpoint, fn)` — 契约到 SvelteKit handler
27
- - `kit.client.create()` — 浏览器端统一 API 客户端(`apiFetch`)
28
- - `kit.auth.createTokenStore()` — 浏览器端 Token 存储
29
- - `kit.auth.createHandleFetch()` — `hooks.client.ts` 自动附加 Token
30
- - Bearer Token / `Authorization` header
31
- - CORS 配置(含 Capacitor Origin 预设)
32
- - 传输加密(key exchange / `X-Client-Id`)
33
-
34
- > **重要变更**:Cookie Session 和 CSRF 中间件已移除。统一使用 Bearer Token 认证。
35
-
36
- ## 依赖
37
-
38
- | 模块 | 用途 | 是否必需 | 初始化要求 |
39
- | --- | --- | --- | --- |
40
- | `@h-ai/iam` | 身份认证与授权(A2A 认证) | 可选 | 使用 A2A 功能时需在 kit 使用前初始化 |
41
- | `@h-ai/crypto` | 加密(传输加密 / Cookie 加密) | 可选 | 启用加密时需在 kit 使用前初始化 |
42
-
43
- ---
44
-
45
- ## 项目配置(从 npm 安装)
46
-
47
- > 以下示例面向通过 `npm install @h-ai/kit` 引用发布包的项目。monorepo 内部使用 `workspace:*` 时路径略有不同。
48
-
49
- ### 1. 安装依赖
50
-
51
- ```bash
52
- # 核心包
53
- npm install @h-ai/kit
54
-
55
- # 必须的对等依赖
56
- npm install svelte @sveltejs/kit
57
- npm install -D @sveltejs/vite-plugin-svelte vite
58
-
59
- # 可选:双构建 adapter
60
- npm install -D @sveltejs/adapter-node @sveltejs/adapter-static
61
-
62
- # API 校验
63
- npm install zod
64
- ```
65
-
66
- ### 2. svelte.config.js
67
-
68
- ```js
69
- import adapter from '@sveltejs/adapter-auto'
70
- import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
71
-
72
- /** @type {import('@sveltejs/kit').Config} */
73
- const config = {
74
- preprocess: [vitePreprocess()],
75
- compilerOptions: {
76
- runes: true,
77
- },
78
- kit: {
79
- adapter: adapter(),
80
- // 如需双构建模式(SSR/SSG 按环境切换):
81
- // import { createAdapter } from '@h-ai/kit/adapter'
82
- // adapter: createAdapter(),
83
- csrf: {
84
- // E2E 测试时信任本地域名
85
- trustedOrigins: process.env.HAI_E2E === '1'
86
- ? ['http://localhost:4173', 'http://127.0.0.1:4173']
87
- : [],
88
- },
89
- alias: {
90
- $components: './src/lib/components',
91
- $stores: './src/lib/stores',
92
- },
93
- },
94
- }
95
-
96
- export default config
97
- ```
98
-
99
- > 若同时使用 `@h-ai/ui`,在 `preprocess` 数组前方加 `autoImportHaiUi()`(详见 hai-ui Skill)。
100
-
101
- ### 3. vite.config.ts
102
-
103
- ```ts
104
- import process from 'node:process'
105
- import { sveltekit } from '@sveltejs/kit/vite'
106
- import tailwindcss from '@tailwindcss/vite'
107
- import { defineConfig, loadEnv } from 'vite'
108
-
109
- export default defineConfig(({ mode }) => {
110
- const env = loadEnv(mode, process.cwd(), '')
111
- Object.assign(process.env, env)
112
-
113
- return {
114
- plugins: [
115
- sveltekit(),
116
- tailwindcss(),
117
- // 如使用 Paraglide i18n:
118
- // paraglideVitePlugin({ project: './project.inlang', outdir: './src/lib/paraglide', strategy: ['cookie', 'baseLocale'] }),
119
- ],
120
- optimizeDeps: {
121
- exclude: ['bits-ui'], // bits-ui 使用 Svelte 虚拟模块
122
- },
123
- ssr: {
124
- // @h-ai 包为 ESM,需 Vite 在 SSR 时处理
125
- noExternal: [/@h-ai\//],
126
- },
127
- server: {
128
- port: 5173,
129
- },
130
- }
131
- })
132
- ```
10
+ ## 使用步骤
133
11
 
134
- ### 4. src/hooks.server.ts — 请求管道
12
+ ### 1. 请求管道
135
13
 
136
14
  ```ts
137
15
  import type { Handle } from '@sveltejs/kit'
138
16
  import { kit } from '@h-ai/kit'
139
17
 
140
- // ─── 模块初始化(延迟 + 并发安全) ─── //
141
- let initPromise: Promise<void> | null = null
142
-
143
- async function ensureInit() {
144
- if (!initPromise) {
145
- initPromise = initModules().catch((err) => {
146
- initPromise = null // 失败清除,允许重试
147
- throw err
148
- })
149
- }
150
- await initPromise
151
- }
152
-
153
- async function initModules() {
154
- // 按需初始化 reldb、iam、cache 等模块
155
- }
156
-
157
- // ─── 初始化 Handle ─── //
158
- const initHandle: Handle = async ({ event, resolve }) => {
159
- await ensureInit()
160
- return resolve(event)
161
- }
162
-
163
- // ─── 认证 Handle ─── //
164
18
  const haiHandle = kit.createHandle({
165
19
  auth: {
166
- verifyToken: async (token) => {
167
- // 验证 Bearer Token,返回 SessionData 或 null
168
- return token ? { userId: 'u_1', roles: ['admin'], permissions: ['user:read'] } : null
169
- },
20
+ verifyToken: async token => token ? { userId: 'u_1', roles: ['admin'], permissions: ['user:read'] } : null,
170
21
  loginUrl: '/auth/login',
171
- protectedPaths: ['/admin/*', '/api/*'],
172
- publicPaths: ['/api/auth/*', '/api/public/*'],
22
+ protectedPaths: ['/admin/*'],
173
23
  },
174
24
  rateLimit: { windowMs: 60_000, maxRequests: 100 },
175
25
  logging: true,
176
- cors: {
177
- origins: ['https://example.com'],
178
- capacitor: true, // 自动允许 Capacitor 原生 App WebView Origin
179
- credentials: true,
180
- },
181
26
  })
182
27
 
183
- export const handle: Handle = kit.sequence(initHandle, haiHandle)
28
+ export const handle: Handle = haiHandle
184
29
  ```
185
30
 
186
- ### 5. src/hooks.client.ts — 客户端 Token 注入
31
+ ### 2. SvelteKit API endpoint
187
32
 
188
33
  ```ts
189
34
  import { kit } from '@h-ai/kit'
190
-
191
- // 自动将 localStorage 中的 Bearer Token 附加到 SSR fetch 请求
192
- export const handleFetch = kit.auth.createHandleFetch()
193
- ```
194
-
195
- ### 6. playwright.config.ts — E2E 测试
196
-
197
- ```ts
198
- import process from 'node:process'
199
- import { defineConfig } from '@playwright/test'
200
-
201
- const baseURL = process.env.BASE_URL || 'http://localhost:4173'
202
-
203
- export default defineConfig({
204
- testDir: './e2e',
205
- fullyParallel: false,
206
- forbidOnly: !!process.env.CI,
207
- retries: process.env.CI ? 2 : 0,
208
- workers: 2,
209
- reporter: 'list',
210
- timeout: 30_000,
211
-
212
- use: {
213
- baseURL,
214
- channel: 'chrome',
215
- extraHTTPHeaders: { Origin: baseURL },
216
- trace: 'on-first-retry',
217
- screenshot: 'only-on-failure',
218
- },
219
-
220
- webServer: {
221
- command: 'pnpm build && pnpm exec vite preview --port 4173 --strictPort',
222
- env: { HAI_E2E: '1', NODE_ENV: 'test' },
223
- url: baseURL,
224
- reuseExistingServer: false,
225
- timeout: 180_000,
226
- },
227
- })
228
- ```
229
-
230
- > `HAI_E2E=1` 与 `NODE_ENV=test` 搭配使用:提高 rateLimit 上限、信任本地 Origin。
231
-
232
- ---
233
-
234
- ## 使用步骤
235
-
236
- ### 1) API 端点使用 `kit.handler`
237
-
238
- ```typescript
239
- import { kit } from '@h-ai/kit'
240
35
  import { z } from 'zod'
241
36
 
242
- const CreateSchema = z.object({ name: z.string().min(1) })
37
+ const CreateUserSchema = z.object({ name: z.string().min(1) })
243
38
 
244
39
  export const POST = kit.handler(async ({ request, locals }) => {
245
40
  kit.guard.require(locals.session, 'user:create')
246
- const data = await kit.validate.body(request, CreateSchema)
247
- return kit.response.created(data)
41
+ const payload = await kit.validate.body(request, CreateUserSchema)
42
+ return kit.response.created(payload)
248
43
  })
249
44
  ```
250
45
 
251
- ### 2) 基于契约的类型安全 handler(推荐)
46
+ ### 3. 浏览器同源请求
252
47
 
253
- ```typescript
254
- import { iam } from '@h-ai/iam'
255
- import { iamEndpoints } from '@h-ai/iam/api'
48
+ ```ts
256
49
  import { kit } from '@h-ai/kit'
257
50
 
258
- export const POST = kit.fromContract(iamEndpoints.login, async (input, event) => {
259
- const result = await iam.auth.login(input)
260
- if (!result.success) {
261
- return kit.response.unauthorized(result.error.message)
262
- }
263
- return kit.response.ok(result.data)
264
- })
51
+ const client = kit.client.create({ auth: true })
52
+ export const { apiFetch } = client
265
53
  ```
266
54
 
267
- ### 3) CORS + Capacitor 配置
268
-
269
- ```typescript
270
- export const handle = kit.createHandle({
271
- cors: {
272
- origins: ['https://example.com', 'https://*.example.com'],
273
- capacitor: true, // Capacitor 原生 App WebView Origin
274
- methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
275
- credentials: true,
276
- },
277
- })
278
- ```
55
+ ### 4. 同源传输加密
279
56
 
280
- ### 4) 需要传输加密时启用 `crypto` 配置
57
+ kit 不再维护本地传输加密实现;服务端和客户端都统一委托 `@h-ai/crypto` 的 `crypto.transport`。
281
58
 
282
- ```typescript
59
+ ```ts
60
+ // hooks.server.ts
283
61
  import { crypto } from '@h-ai/crypto'
284
62
  import { kit } from '@h-ai/kit'
285
63
 
286
- crypto.init()
64
+ await crypto.init()
287
65
 
288
66
  export const handle = kit.createHandle({
67
+ auth: {
68
+ verifyToken,
69
+ protectedPaths: ['/api/*'],
70
+ publicPaths: ['/api/_hai/*'],
71
+ },
289
72
  crypto: {
290
73
  crypto,
291
- transport: { requireEncryption: false },
292
- cookieEncryptionKey: process.env.HAI_KIT_COOKIE_KEY,
74
+ transport: { requireEncryption: true },
293
75
  },
294
76
  })
295
77
  ```
296
78
 
297
- ## 核心 API
298
-
299
- | API | 用途 | 关键点 |
300
- | --------------------------- | ---------------------- | --------------------------------------------- |
301
- | `kit.createHandle(config?)` | 创建 SvelteKit Handle | Bearer Token 解析、守卫、中间件、CORS |
302
- | `kit.sequence(...handles)` | 组合多个 Handle | 洋葱模型顺序执行 |
303
- | `kit.handler(fn)` | 包装 API 处理函数 | 非控制流异常统一转 500 |
304
- | `kit.fromContract(ep, fn)` | 契约到 handler | 自动 Zod 入参校验,类型安全 |
305
- | `kit.guard.*` | 权限守卫 | `require`(throw 式) / `check`(布尔) |
306
- | `kit.response.*` | 标准化响应 | 统一 `{ success, data?, error?, requestId? }` |
307
- | `kit.validate.*` | 请求体/查询/参数校验 | 失败 throw Response(SvelteKit 控制流) |
308
- | `kit.i18n.setLocale(locale)` | 设置请求级 locale | 在 handle 中调用,供服务端模块使用 |
309
- | `defineEndpoint(def)` | 定义 EndpointDef 契约 | 与 api-client 配合使用 |
310
-
311
- ### EndpointDef 契约
312
-
313
- ```typescript
314
- import { defineEndpoint } from '@h-ai/kit'
315
- import { z } from 'zod'
316
-
317
- const myEndpoint = defineEndpoint({
318
- method: 'POST',
319
- path: '/api/v1/items',
320
- input: z.object({ name: z.string() }),
321
- output: z.object({ id: z.string(), name: z.string() }),
322
- requireAuth: true,
323
- })
324
- ```
325
-
326
- ## 错误码(常见)
327
-
328
- ### API 响应错误码(`kit.response`)
329
-
330
- | code | status | 场景 |
331
- | ------------------ | ------ | ------------------ |
332
- | `BAD_REQUEST` | 400 | 参数或请求格式错误 |
333
- | `UNAUTHORIZED` | 401 | 未认证 |
334
- | `FORBIDDEN` | 403 | 无权限 |
335
- | `NOT_FOUND` | 404 | 资源不存在 |
336
- | `CONFLICT` | 409 | 资源冲突 |
337
- | `VALIDATION_ERROR` | 422 | 数据校验失败 |
338
- | `INTERNAL_ERROR` | 500 | 未处理异常 |
339
-
340
- ## API 契约范式(端到端类型安全)
341
-
342
- > `kit.fromContract` 和 `api.call` 共同消费模块 `api/` 下的 `EndpointDef`,实现服务端↔客户端的全链路类型安全 + 运行时 Zod 校验。
343
-
344
- ### 服务端流程(本模块责任)
345
-
346
- 1. 从 `@h-ai/xx/api` 导入 `xxEndpoints`
347
- 2. `kit.fromContract(xxEndpoints.xxx, handler)` → 自动 Zod 校验入参 → handler 获得类型安全的 `input`
348
- 3. 需权限时在 handler 内调用 `kit.guard.require`
349
-
350
- ### 多模块契约示例
351
-
352
- ```typescript
353
- // ─── 存储:预签名上传 ───
354
- import { storageEndpoints } from '@h-ai/storage/api'
355
- import { storage } from '$lib/server/init'
356
-
357
- export const POST = kit.fromContract(storageEndpoints.presignUpload, async (input, event) => {
358
- kit.guard.require(event.locals.session, 'storage:write')
359
- const result = await storage.presign.putUrl(input.key, input)
360
- if (!result.success) {
361
- return kit.response.internalError(result.error.message)
362
- }
363
- return kit.response.ok({ url: result.data, key: input.key })
364
- })
365
-
366
- // ─── IAM:登录 ───
367
- import { iamEndpoints } from '@h-ai/iam/api'
368
- import { iam } from '$lib/server/init'
369
-
370
- export const POST = kit.fromContract(iamEndpoints.login, async (input) => {
371
- const result = await iam.auth.login(input)
372
- if (!result.success) {
373
- return kit.response.unauthorized(result.error.message)
79
+ ```ts
80
+ // routes/+layout.svelte
81
+ <script lang='ts'>
82
+ import { browser } from '$app/environment'
83
+ import { crypto } from '@h-ai/crypto'
84
+ import { kit } from '@h-ai/kit'
85
+ import { appKitConfig } from '$lib/config/kit-config'
86
+
87
+ // 一次性安装:内部按 appKitConfig.transport 是否启用决定行为,并预热 crypto
88
+ if (browser) {
89
+ kit.client.installBrowserTransport(appKitConfig, { crypto })
374
90
  }
375
- return kit.response.ok(result.data)
376
- })
377
- ```
378
-
379
- ## 常见模式
380
-
381
- ### 契约模式(推荐新项目使用)
382
-
383
- 1. 在模块的 `api/` 目录定义 `EndpointDef`(Zod schema)
384
- 2. 服务端用 `kit.fromContract(endpoint, handler)` 处理
385
- 3. 客户端用 `api.call(endpoint, input)` 调用
386
- 4. 入参/出参全链路类型安全 + 运行时校验
387
-
388
- ### 双构建模式
389
-
390
- ```typescript
391
- // svelte.config.js
392
- import { createAdapter } from '@h-ai/kit/adapter'
393
-
394
- const config = {
395
- kit: {
396
- adapter: createAdapter(), // 自动选择 adapter-node 或 adapter-static
397
- },
398
- }
91
+ </script>
399
92
  ```
400
93
 
401
- ---
402
-
403
- ## 浏览器侧使用
404
-
405
- ### 创建统一 API 客户端 — `kit.client`
406
-
407
- > **所有浏览器端 API 请求必须通过 `apiFetch`,禁止直接 `fetch()`。**
408
-
409
- 在 `src/lib/utils/api.ts` 中一次性创建,全应用共享:
410
-
411
- ```typescript
412
- // src/lib/utils/api.ts
94
+ ```ts
95
+ // lib/utils/api.ts —— 业务层只看到 apiFetch
413
96
  import { kit } from '@h-ai/kit'
414
97
 
415
- const client = kit.client.create({ auth: true })
416
- export const { apiFetch } = client
98
+ export const { apiFetch } = kit.client.create({ auth: true })
417
99
  ```
418
100
 
419
- 如需传输加密:
101
+ 默认协商端点:`/api/_hai/key-exchange`。如 `keyExchangePath` 自定义,浏览器端同步设置 `keyExchangeUrl`。
420
102
 
421
- ```typescript
422
- import { crypto } from '@h-ai/crypto'
423
- import { kit } from '@h-ai/kit'
424
-
425
- if (typeof window !== 'undefined') {
426
- crypto.init()
427
- }
428
-
429
- const client = kit.client.create({
430
- transport: { crypto },
431
- auth: true,
432
- })
103
+ transport 默认保护同源 `/api/*` endpoint 与 SvelteKit `__data.json` 页面数据请求;页面文档、静态资源与 `multipart/form-data` 上传请求保持明文透传。
433
104
 
434
- export const { apiFetch } = client
435
- ```
105
+ 安全策略默认 fail-closed:`requireEncryption: true` 时,受保护路径缺少 `X-Client-Id` 必须返回 400;服务端 transport 管理器不可用、响应体无法加密或超过单次加密上限时返回错误,禁止明文业务响应回退。`requireEncryption: false` 只适合迁移期灰度。
436
106
 
437
- `apiFetch` 自动处理:
438
- - **CSRF**:写方法自动读取 `hai_csrf` Cookie 并设置 `X-CSRF-Token`
439
- - **Bearer Token**:自动从 localStorage 读取并注入 `Authorization` header
440
- - **传输加密**:可选,首次写请求时自动密钥交换
107
+ ### 5. 使用 `_kit.yml` 统一 transport 配置
441
108
 
442
- ### Token 存储 — `kit.auth.createTokenStore`
443
-
444
- ```typescript
445
- import { kit } from '@h-ai/kit'
109
+ `@h-ai/kit` 现在提供 `KitConfigSchema` / `resolveKitConfig()`,适合同一份 `_kit.yml`
110
+ 同时驱动 `hooks.server.ts` 与浏览器端 `kit.client.installBrowserTransport()`:
446
111
 
447
- const tokenStore = kit.auth.createTokenStore('hai_access_token')
448
- tokenStore.set(tokens.accessToken)
449
- tokenStore.get()
450
- tokenStore.clear()
112
+ ```yml
113
+ transport:
114
+ keyExchangePath: /api/_hai/key-exchange
115
+ requireEncryption: true
116
+ encryptResponse: true
117
+ excludePaths:
118
+ - /api/storage
119
+ - /api/public
120
+ - /api/auth/profile/avatar
121
+ maxClients: 10000
451
122
  ```
452
123
 
453
- ### 选择指南:kit.client vs api-client
454
-
455
- | 场景 | 推荐 | 原因 |
456
- |------|------|------|
457
- | SSR SvelteKit 应用(同源请求) | `kit.client.create().apiFetch` | 自动 CSRF、同源 Cookie 透传、传输加密 |
458
- | SPA / 原生 App(跨域请求) | `api.init()` + `api.call()` | 完整 Token 管理、401 自动刷新 |
459
- | 服务端 `+page.server.ts` | 直接调用模块 API | 无需 HTTP 自环 |
460
- | 契约调用(类型安全) | `api.call(endpoint, input)` | EndpointDef 双向 Zod 校验 |
124
+ ```ts
125
+ import { resolveKitConfig } from '@h-ai/kit'
126
+ import { parse } from 'yaml'
127
+ import rawKitConfig from '../config/_kit.yml?raw'
461
128
 
462
- ---
129
+ export const appKitConfig = resolveKitConfig(parse(rawKitConfig) ?? {})
130
+ ```
463
131
 
464
- ## 导出路径
132
+ `_kit.yml` 只放公开的 transport 路径/开关,不放密钥;如自定义 `keyExchangePath`,浏览器端必须同步映射为 `keyExchangeUrl`。
465
133
 
466
- | 路径 | 用途 |
467
- | ------------------- | ------------------------------------------------ |
468
- | `@h-ai/kit` | 主入口:`kit` 命名空间、类型、`defineEndpoint` |
469
- | `@h-ai/kit/client` | 浏览器端客户端(单独引用时) |
470
- | `@h-ai/kit/adapter` | 双构建 adapter(`createAdapter()`) |
471
- | `@h-ai/kit/vite` | Vite 插件 |
472
- | `@h-ai/kit/a2a` | A2A 协议集成 |
473
- | `@h-ai/kit/crypto` | 加密模块集成 |
134
+ ## 核心 API
474
135
 
475
- ---
136
+ | API | 用途 |
137
+ | --- | --- |
138
+ | `kit.createHandle()` | 创建 SvelteKit Handle |
139
+ | `kit.sequence()` | 组合多个 Handle |
140
+ | `kit.handler()` | API endpoint 错误边界 |
141
+ | `kit.guard.require()` | 权限守卫 |
142
+ | `kit.response.*` | 统一响应工厂 |
143
+ | `kit.validate.*` | Zod 请求校验 |
144
+ | `kit.auth.*` | Cookie / Token 辅助 |
145
+ | `kit.client.create()` | 浏览器端同源 apiFetch |
146
+ | `kit.client.installBrowserTransport(config, { crypto })` | 推荐入口:按解析后的 `_kit.yml` 一键安装浏览器端传输加密 |
147
+ | `kit.client.installBrowserTransportFetch()` | 底层入口:直接传 transport 配置安装浏览器全局 fetch 包装 |
148
+ | `kit.crud.define()` | 声明式 CRUD 资源 |
476
149
 
477
- ## 相关 Skills
150
+ ## 常见模式
478
151
 
479
- - `hai-ui`:UI 组件库(svelte.config.js / app.css 配置)
480
- - `hai-core`:全局配置、日志、HaiResult 基础能力
481
- - `hai-iam`:Token 认证、角色权限模型
482
- - `hai-api-client`:客户端契约调用(SPA / 原生 App 场景)
483
- - `hai-crypto`:传输加密与密钥管理能力
484
- - `hai-capacitor`:原生 App CORS 场景
152
+ - SvelteKit 应用内同源请求用 `kit.client.create().apiFetch`。
153
+ - SvelteKit 应用启用 transport 时,在 `+layout.svelte` 的 `if (browser)` 分支调用一次 `kit.client.installBrowserTransport(appKitConfig, { crypto })`,无需重复连线 `keyExchangeUrl` / `excludePaths`。
154
+ - Web/App/小程序跨域访问公共 API 用 `@h-ai/api-client` typed client。
155
+ - 传输加密只通过 `crypto.transport` 间接装配,不在 kit 中新增本地加密工厂或鸭子类型。
156
+ - 服务端业务模块直接调用模块 API,不通过 HTTP 自环。
157
+ - API endpoint 必须用 Zod 校验用户输入,并设置认证/权限边界。
@@ -203,17 +203,15 @@ const payResult = await invokePayment(orderResult.data)
203
203
 
204
204
  自定义 Provider 通过 `payment.registerProvider(provider)` 注册。
205
205
 
206
- ### API 契约
206
+ ### HTTP API 契约
207
207
 
208
208
  ```typescript
209
- import { paymentEndpoints } from '@h-ai/payment/api'
210
-
211
- // paymentEndpoints.createOrder — POST /payment/create
212
- // paymentEndpoints.queryOrder — GET /payment/query
213
- // paymentEndpoints.notifyWechat — POST /payment/notify/wechat
214
- // paymentEndpoints.notifyAlipay — POST /payment/notify/alipay
215
- // paymentEndpoints.notifyStripe — POST /payment/notify/stripe
216
- // paymentEndpoints.refund — POST /payment/refund
209
+ import { apiContract } from '@h-ai/api-contract'
210
+
211
+ // apiContract.payment.orders.create — POST /payment/orders
212
+ // apiContract.payment.orders.get — GET /payment/orders/{orderNo}
213
+ // apiContract.payment.orders.refund — POST /payment/orders/{orderNo}/refunds
214
+ // apiContract.payment.notifications.wechat — POST /payment/notifications/wechat
217
215
  ```
218
216
 
219
217
  ---
@@ -249,7 +247,7 @@ export const POST = kit.handler(async ({ request, locals }) => {
249
247
  ### 完整支付流程
250
248
 
251
249
  ```
252
- 1. 客户端 → 服务端:创建订单(api.call(paymentEndpoints.createOrder, {...}))
250
+ 1. 客户端 → 服务端:创建订单(api.payment.orders.create({...}))
253
251
  2. 服务端 → 支付平台:调用 Provider 创建预支付
254
252
  3. 服务端 → 客户端:返回 providerData(含调起参数)
255
253
  4. 客户端:invokePayment(providerData) 调起支付