@h-ai/kit 1.0.0-beta.2 → 1.0.0-beta.21

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 (43) hide show
  1. package/README.en.md +190 -110
  2. package/README.ja.md +192 -112
  3. package/README.md +195 -114
  4. package/dist/adapter/index.d.ts +8 -7
  5. package/dist/adapter/index.js.map +1 -1
  6. package/dist/browser.d.ts +9 -26
  7. package/dist/browser.js +4 -4
  8. package/dist/browser.js.map +1 -1
  9. package/dist/{chunk-JRQPMPQC.js → chunk-BCEBXG4X.js} +2 -2
  10. package/dist/chunk-BCEBXG4X.js.map +1 -0
  11. package/dist/{chunk-7EH47MTW.js → chunk-BVGXHIXR.js} +30 -9
  12. package/dist/chunk-BVGXHIXR.js.map +1 -0
  13. package/dist/{chunk-5VWPH7DO.js → chunk-GQZCU6PC.js} +14 -6
  14. package/dist/chunk-GQZCU6PC.js.map +1 -0
  15. package/dist/{chunk-YKJRQCWR.js → chunk-JL2C5ZGQ.js} +54 -20
  16. package/dist/chunk-JL2C5ZGQ.js.map +1 -0
  17. package/dist/{chunk-3OHUSKHI.js → chunk-WYGIKXHE.js} +23 -8
  18. package/dist/chunk-WYGIKXHE.js.map +1 -0
  19. package/dist/client/index.d.ts +6 -5
  20. package/dist/client/index.js +5 -5
  21. package/dist/client/index.js.map +1 -1
  22. package/dist/index.d.ts +18 -711
  23. package/dist/index.js +266 -149
  24. package/dist/index.js.map +1 -1
  25. package/dist/{kit-a2a-types-4dapztu2.d.ts → kit-a2a-types-sw7sI-ZT.d.ts} +3 -2
  26. package/dist/kit-config-BQKQnu8Y.d.ts +182 -0
  27. package/dist/kit-crypto-types-CqFENBqm.d.ts +47 -0
  28. package/dist/kit-types-Cr1cnB3M.d.ts +2051 -0
  29. package/dist/modules/a2a/index.d.ts +9 -5
  30. package/dist/modules/a2a/index.js +1 -1
  31. package/dist/modules/crypto/index.d.ts +8 -105
  32. package/dist/modules/crypto/index.js +3 -149
  33. package/dist/modules/crypto/index.js.map +1 -1
  34. package/package.json +22 -22
  35. package/dist/chunk-3OHUSKHI.js.map +0 -1
  36. package/dist/chunk-5VWPH7DO.js.map +0 -1
  37. package/dist/chunk-7EH47MTW.js.map +0 -1
  38. package/dist/chunk-JRQPMPQC.js.map +0 -1
  39. package/dist/chunk-YKJRQCWR.js.map +0 -1
  40. package/dist/kit-client-auth-BnhrkzZF.d.ts +0 -422
  41. package/dist/kit-crypto-types-CXr888wf.d.ts +0 -200
  42. package/dist/kit-i18n-EBzZKYN-.d.ts +0 -502
  43. package/dist/kit-types-BkNdyKj8.d.ts +0 -822
@@ -0,0 +1,2051 @@
1
+ import { HaiResult, HaiError, TrustedProxies, RequestAccessConfigInput, core } from '@h-ai/core';
2
+ import { CryptoFunctions, TransportServerKeyRing, TransportKeyStore } from '@h-ai/crypto';
3
+ import { IamFunctions, AuthnOperations, PasswordCredentials, AuthRequestContext, AuthResult, OtpCredentials, LdapCredentials, ApiKeyCredentials, RegisterOptions } from '@h-ai/iam';
4
+ import * as _sveltejs_kit from '@sveltejs/kit';
5
+ import { RequestEvent, RequestHandler } from '@sveltejs/kit';
6
+ import { IamCreateCaptchaInputSchema, IamPublicConfig, IamLoginInput, IamRegisterInput } from '@h-ai/api-contract';
7
+ import { Handle } from '@sveltejs/kit/hooks';
8
+ import { FeedbackFunctions, FeedbackContext } from '@h-ai/feedback';
9
+ import { z } from 'zod';
10
+
11
+ /**
12
+ * @h-ai/kit — Bearer 认证工具
13
+ *
14
+ * 提供服务端认证 Cookie 管理(login / logout)与浏览器端 Token 存储工具。
15
+ * @module kit-auth
16
+ */
17
+
18
+ /**
19
+ * 浏览器 Token 存储器;使用页面内存或平台安全存储,禁止写入 Web Storage。
20
+ * @example 模块内部上下文
21
+ * ```ts
22
+ * const store: BrowserTokenStore = getDefaultBrowserTokenStore()
23
+ * store.clear() // 当前页面内存状态;不持有服务端会话真值。
24
+ * ```
25
+ */
26
+ interface BrowserTokenStore {
27
+ get: () => string | null;
28
+ set: (token: string) => void;
29
+ clear: () => void;
30
+ }
31
+
32
+ /**
33
+ * @h-ai/kit — 统一客户端
34
+ *
35
+ * 将 CSRF Token 附加与可选传输加密封装为统一 `apiFetch`。
36
+ * 应用层只需调用一次 `createKitClient()`,后续 API 调用即可复用同一套安全能力。
37
+ * @module kit-client
38
+ */
39
+
40
+ /**
41
+ * 传输加密客户端配置
42
+ * @example
43
+ * ```ts
44
+ * import type { ClientTransportConfig } from '@h-ai/kit'
45
+ * import { crypto } from '@h-ai/crypto'
46
+ *
47
+ * function configAfterInit(): ClientTransportConfig { return { crypto, excludePaths: ['/api/health'] } }
48
+ * ```
49
+ */
50
+ interface ClientTransportConfig {
51
+ /** 宿主构建挂载目录,默认空字符串;SvelteKit 使用 paths.relative=false 时的 resolve('/').replace(/\/$/, '')。 */
52
+ basePath?: string;
53
+ /** 可选本地明文上限;缺省跟随服务端握手。 */
54
+ maxPlaintextBytes?: number;
55
+ /** @h-ai/crypto 服务实例 */
56
+ crypto: CryptoFunctions;
57
+ /** 密钥交换端点 URL(默认 `'/api/_hai/key-exchange'`) */
58
+ keyExchangeUrl?: string;
59
+ /** 排除路径(命中后强制走明文),需与服务端 transport.excludePaths 保持一致 */
60
+ excludePaths?: readonly string[];
61
+ }
62
+ /**
63
+ * Kit 客户端配置
64
+ * @example
65
+ * ```ts
66
+ * import type { KitClientConfig } from '@h-ai/kit'
67
+ *
68
+ * const value: KitClientConfig = { auth: true }
69
+ * void value
70
+ * ```
71
+ */
72
+ interface KitClientConfig {
73
+ /** 标准鉴别明确失效时原地登录原用户;成功才对被拒绝的请求重试一次。 */
74
+ recoverSession?: () => Promise<boolean>;
75
+ /** 会话终端分组,默认web;服务端按终端与全局配额共同限制。 */
76
+ terminalType?: 'web' | 'app' | 'desktop' | 'api';
77
+ /**
78
+ * 传输加密配置。
79
+ * - 不提供 / undefined:不启用传输加密,仅 CSRF
80
+ * - 提供对象:启用传输加密
81
+ */
82
+ transport?: ClientTransportConfig;
83
+ /** CSRF Cookie 名称(默认 `'hai_csrf'`) */
84
+ csrfCookieName?: string;
85
+ /** CSRF Header 名称(默认 `'X-CSRF-Token'`) */
86
+ csrfHeaderName?: string;
87
+ /**
88
+ * 认证配置:自动从浏览器存储读取 Access Token 并注入请求头。
89
+ * - `true`:使用默认页面内存存储(由 `kit.auth.setBrowserToken()` 写入,不读写 localStorage)
90
+ * - `BrowserTokenStore`:使用自定义存储
91
+ * - 不提供 / `false`:不自动注入
92
+ */
93
+ auth?: boolean | BrowserTokenStore;
94
+ }
95
+ /**
96
+ * Kit 客户端实例
97
+ * @example
98
+ * ```ts
99
+ * import type { KitClient } from '@h-ai/kit'
100
+ *
101
+ * async function read(client: KitClient) {
102
+ * const response = await client.apiFetch('/api/health')
103
+ * if (!response.ok) throw new Error('Request failed')
104
+ * return response.json()
105
+ * }
106
+ * ```
107
+ */
108
+ interface KitClient {
109
+ /** 统一 API fetch(写请求自动附加 CSRF,启用 transport 时自动加解密) */
110
+ apiFetch: (input: RequestInfo | URL, init?: RequestInit, options?: {
111
+ recoverSession?: boolean;
112
+ reauthorize?: () => Promise<string | null | undefined>;
113
+ }) => Promise<Response>;
114
+ /** 传输加密是否就绪(未启用传输加密时始终为 true) */
115
+ readonly ready: boolean;
116
+ /**
117
+ * 手动触发密钥交换(transport 启用时)。
118
+ *
119
+ * 注意:本方法是 Client 形态的合规例外,密钥协商失败时 `throw`(与 `@h-ai/api-client` 一致),
120
+ * 调用方需自行 `try/catch`,不返回 `HaiResult`。
121
+ */
122
+ init: () => Promise<void>;
123
+ /** 销毁密钥状态 */
124
+ destroy: () => void;
125
+ }
126
+ /**
127
+ * 在浏览器启动时安装同源 transport fetch 包装。
128
+ *
129
+ * 该包装作用于同源 `/api/*` 与 SvelteKit `__data.json` 请求,页面文档、
130
+ * 静态资源以及 multipart/form-data 等上传请求保持原样。应用只需安装一次,
131
+ * 后续 `fetch` / SvelteKit 内部 data fetch / `kit.client.create()` 明文发送路径
132
+ * 都会共用这层传输加密能力。
133
+ * @param transportConfig - 已初始化 crypto、同源密钥交换路径及排除路径;省略时不安装包装。
134
+ * @example
135
+ * ```ts
136
+ * import { kit } from '@h-ai/kit'
137
+ *
138
+ * // 不传配置时不安装全局包装;启用时应传已初始化 crypto 与同源端点。
139
+ * kit.client.installBrowserTransportFetch()
140
+ * ```
141
+ */
142
+ declare function installBrowserTransportFetch(transportConfig?: ClientTransportConfig): void;
143
+ /**
144
+ * 用 `config/_kit.yml` 解析后的 {@link KitPublicConfig} 公共投影 一次性安装浏览器端传输加密。
145
+ *
146
+ * 行为:
147
+ * - `config.transport === false` 时直接返回(不启用传输加密);
148
+ * - 否则启动 {@link installBrowserTransportFetch},并预热 {@link CryptoFunctions} 模块。
149
+ *
150
+ * 应用层(SvelteKit `+layout.svelte` 或浏览器入口)只需调用此函数一次,
151
+ * 之后宿主 basePath 下的同源 `/api/*` 与 `__data.json` 请求都会自动走传输加密。
152
+ *
153
+ * @param config 已解析的 kit 公共传输配置
154
+ * @param deps 外部依赖
155
+ * @param deps.crypto `@h-ai/crypto` 模块实例
156
+ * @param deps.basePath 宿主构建挂载目录,默认空字符串;SvelteKit 使用 paths.relative=false 时的 resolve('/').replace(/\/$/, '')。
157
+ * @example
158
+ * ```ts
159
+ * import { kit } from '@h-ai/kit'
160
+ *
161
+ * import { crypto } from '@h-ai/crypto'
162
+ *
163
+ * function installAfterCryptoInit() {
164
+ * kit.client.installBrowserTransport({ transport: { keyExchangePath: '/api/_hai/key-exchange', excludePaths: ['/api/health'] } }, { crypto })
165
+ * }
166
+ * ```
167
+ */
168
+ declare function installBrowserTransport(config: KitPublicConfig, deps: {
169
+ crypto: CryptoFunctions;
170
+ basePath?: string;
171
+ }): void;
172
+ /**
173
+ * 创建 Kit 客户端
174
+ *
175
+ * 返回统一的 `apiFetch`,内部自动完成:
176
+ * 1. CSRF Token 附加(写方法自动读取 Cookie + 设置 Header)
177
+ * 2. 密钥交换(首次写请求时 lazy init,transport 启用时)
178
+ * 3. 请求体加密(transport 启用时)
179
+ * 4. 响应体解密(transport 启用时)
180
+ *
181
+ * @param config - 客户端配置
182
+ * @returns KitClient 实例
183
+ * @example
184
+ * ```ts
185
+ * import { kit } from '@h-ai/kit'
186
+ *
187
+ * const client = kit.client.create({ auth: true })
188
+ * try {
189
+ * await client.init() // Client API 使用 Promise 拒绝;不是 HaiResult。
190
+ * const response = await client.apiFetch('/api/health')
191
+ * if (!response.ok) throw new Error('Request failed')
192
+ * } finally {
193
+ * client.destroy()
194
+ * }
195
+ * ```
196
+ */
197
+ declare function createKitClient(config?: KitClientConfig): KitClient;
198
+
199
+ /** 与标准 Kit 认证端点配套的表单动作;复用已有 CSRF/transport fetch。 */
200
+
201
+ /**
202
+ * 创建标准 Cookie 认证表单动作;复用可选 apiFetch 以保留 CSRF 和传输配置。
203
+ * @param options - 可复用的 apiFetch 和标准认证端点 basePath。
204
+ * @param options.apiFetch - 已装配 CSRF/transport 的 fetch;省略时使用默认 Kit 客户端。
205
+ * @param options.basePath - 同源认证端点前缀,默认 /api/auth。
206
+ * @returns 标准表单动作;业务和已认证的时间错误返回 HaiResult,网络/格式错误会拒绝 Promise。
207
+ * @example
208
+ * ```ts
209
+ * import { kit } from '@h-ai/kit'
210
+ *
211
+ * const actions = kit.client.createAuthActions({ basePath: '/api/auth' })
212
+ * void actions
213
+ * ```
214
+ */
215
+ declare function createKitAuthActions(options?: {
216
+ apiFetch?: KitClient['apiFetch'];
217
+ basePath?: string;
218
+ }): {
219
+ bindPageExit(options?: {
220
+ enabled?: boolean;
221
+ }): () => void;
222
+ createCaptcha(input: z.input<typeof IamCreateCaptchaInputSchema>): Promise<HaiResult<{
223
+ id: string;
224
+ challenge: {
225
+ parameters: {
226
+ algorithm: "PBKDF2/SHA-256";
227
+ nonce: string;
228
+ salt: string;
229
+ cost: number;
230
+ keyLength: number;
231
+ keyPrefix: string;
232
+ keySignature?: string | undefined;
233
+ data?: Record<string, string | number | boolean | null> | undefined;
234
+ };
235
+ signature?: string | undefined;
236
+ };
237
+ }>>;
238
+ publicConfig(): Promise<HaiResult<IamPublicConfig | null>>;
239
+ login(input: IamLoginInput & {
240
+ method?: "password" | "ldap" | "email" | "sms";
241
+ code?: string;
242
+ }): Promise<HaiResult<unknown>>;
243
+ register: (input: IamRegisterInput) => Promise<HaiResult<unknown>>;
244
+ sendOtp: (identifier: string, options?: {
245
+ captcha?: string;
246
+ }) => Promise<HaiResult<unknown>>;
247
+ requestPasswordReset: (identifier: string, options?: {
248
+ captcha?: string;
249
+ }) => Promise<HaiResult<unknown>>;
250
+ confirmPasswordReset: (token: string, newPassword: string) => Promise<HaiResult<unknown>>;
251
+ renewPassword: (input: {
252
+ identifier: string;
253
+ password: string;
254
+ newPassword: string;
255
+ captcha?: string;
256
+ }) => Promise<HaiResult<unknown>>;
257
+ reauthenticate(password: string, operation: string): Promise<HaiResult<{
258
+ ticket: string;
259
+ expiresAt: number;
260
+ }>>;
261
+ };
262
+
263
+ /**
264
+ * @h-ai/kit — CRUD 类型定义
265
+ *
266
+ * 声明式 CRUD 资源定义所需的全部类型。
267
+ * @module kit-crud-types
268
+ */
269
+ /**
270
+ * 支持的字段类型
271
+ * @example
272
+ * ```ts
273
+ * import type { CrudFieldType } from '@h-ai/kit'
274
+ *
275
+ * const value: CrudFieldType = 'date-range'
276
+ * void value
277
+ * ```
278
+ */
279
+ type CrudFieldType = 'string' | 'number' | 'boolean' | 'date' | 'date-range' | 'datetime' | 'email' | 'url' | 'tel' | 'password' | 'textarea' | 'select' | 'multi-select' | 'radio' | 'checkbox' | 'custom';
280
+ /**
281
+ * 字段校验规则
282
+ * @example
283
+ * ```ts
284
+ * import type { CrudFieldValidation } from '@h-ai/kit'
285
+ *
286
+ * const value: CrudFieldValidation = { required: true, max: 120 }
287
+ * void value
288
+ * ```
289
+ */
290
+ interface CrudFieldValidation {
291
+ /** 是否必填 */
292
+ required?: boolean;
293
+ /** 最小值(number)或 最小长度(string) */
294
+ min?: number;
295
+ /** 最大值(number)或 最大长度(string) */
296
+ max?: number;
297
+ /** 正则表达式 */
298
+ pattern?: string;
299
+ /** 自定义错误提示 */
300
+ message?: CrudText;
301
+ }
302
+ /**
303
+ * 选项项(用于 select/radio 等)
304
+ * @example
305
+ * ```ts
306
+ * import type { CrudFieldOption } from '@h-ai/kit'
307
+ *
308
+ * const value: CrudFieldOption = { label: 'Published', value: 'published' }
309
+ * void value
310
+ * ```
311
+ */
312
+ interface CrudFieldOption {
313
+ label: string;
314
+ value: string | number | boolean;
315
+ }
316
+ /**
317
+ * 选项来源:静态数组或动态工厂函数
318
+ * @example
319
+ * ```ts
320
+ * import type { CrudFieldOptions } from '@h-ai/kit'
321
+ *
322
+ * const value: CrudFieldOptions = [{ label: 'Published', value: 'published' }]
323
+ * void value
324
+ * ```
325
+ */
326
+ type CrudFieldOptions = CrudFieldOption[] | (() => CrudFieldOption[]);
327
+ /**
328
+ * 可解析为字符串的文本值(支持 i18n)
329
+ * @example
330
+ * ```ts
331
+ * import type { CrudText } from '@h-ai/kit'
332
+ *
333
+ * const value: CrudText = () => 'Articles'
334
+ * void value
335
+ * ```
336
+ */
337
+ type CrudText = string | (() => string);
338
+ /**
339
+ * 字段定义
340
+ * @example
341
+ * ```ts
342
+ * import type { CrudFieldDef } from '@h-ai/kit'
343
+ *
344
+ * const value: CrudFieldDef = { id: 'title', label: 'Title', type: 'string', validation: { required: true } }
345
+ * void value
346
+ * ```
347
+ */
348
+ interface CrudFieldDef {
349
+ /** 字段 ID(对应数据对象的 key) */
350
+ id: string;
351
+ /** 显示名称(支持 i18n 函数) */
352
+ label: CrudText;
353
+ /** 字段类型 */
354
+ type: CrudFieldType;
355
+ /** 是否在列表中显示(默认 true) */
356
+ inList?: boolean;
357
+ /** 是否是过滤项(默认 false) */
358
+ filterable?: boolean;
359
+ /** 是否只读(编辑时不可修改,默认 false) */
360
+ readonly?: boolean;
361
+ /** 是否在新建表单中显示(默认 true) */
362
+ inCreate?: boolean;
363
+ /** 是否在编辑表单中显示(默认 true) */
364
+ inEdit?: boolean;
365
+ /** 是否在详情中显示(默认 true) */
366
+ inDetail?: boolean;
367
+ /** 选项列表(select/radio/checkbox/multi-select) */
368
+ options?: CrudFieldOptions;
369
+ /** 校验规则 */
370
+ validation?: CrudFieldValidation;
371
+ /** 双列表单中的占用列数;auto 按控件类型判断,默认 auto。 */
372
+ colSpan?: 'auto' | 1 | 2;
373
+ /** 列宽(列表模式) */
374
+ width?: string;
375
+ /** 列对齐方式 */
376
+ align?: 'left' | 'center' | 'right';
377
+ /** 自定义列表渲染 */
378
+ render?: (value: unknown, item: Record<string, unknown>) => string;
379
+ /** 占位符 */
380
+ placeholder?: CrudText;
381
+ /** 日期范围起始值的查询参数名;仅 date-range 字段使用,默认 `${id}Start` */
382
+ startKey?: string;
383
+ /** 日期范围结束值的查询参数名;仅 date-range 字段使用,默认 `${id}End` */
384
+ endKey?: string;
385
+ /** 默认值(新建时) */
386
+ defaultValue?: unknown;
387
+ /** 排列权重(数值越小越靠前) */
388
+ order?: number;
389
+ }
390
+ /**
391
+ * 分页参数
392
+ * @example
393
+ * ```ts
394
+ * import type { CrudPaginationParams } from '@h-ai/kit'
395
+ *
396
+ * const value: CrudPaginationParams = { page: 1, pageSize: 20 }
397
+ * void value
398
+ * ```
399
+ */
400
+ interface CrudPaginationParams {
401
+ page: number;
402
+ pageSize: number;
403
+ }
404
+ /**
405
+ * 过滤参数(搜索 + 自定义过滤字段)
406
+ * @example
407
+ * ```ts
408
+ * import type { CrudFilterParams } from '@h-ai/kit'
409
+ *
410
+ * const value: CrudFilterParams = { search: 'example', status: 'published' }
411
+ * void value
412
+ * ```
413
+ */
414
+ interface CrudFilterParams {
415
+ search?: string;
416
+ [key: string]: unknown;
417
+ }
418
+ /**
419
+ * 分页结果
420
+ * @example
421
+ * ```ts
422
+ * import type { CrudPaginatedResult } from '@h-ai/kit'
423
+ *
424
+ * const value: CrudPaginatedResult<{ id: string }> = { items: [], total: 0, page: 1, pageSize: 20 }
425
+ * void value
426
+ * ```
427
+ */
428
+ interface CrudPaginatedResult<T> {
429
+ items: T[];
430
+ total: number;
431
+ page: number;
432
+ pageSize: number;
433
+ }
434
+ /**
435
+ * CRUD API 接口定义
436
+ * @example
437
+ * ```ts
438
+ * import type { CrudApiDef } from '@h-ai/kit'
439
+ *
440
+ * // 应用适配层把持久化查询结果转为此结构,失败应拒绝 Promise。
441
+ * function listAdapter(list: CrudApiDef<{ id: string }>['list']): CrudApiDef<{ id: string }> { return { list } }
442
+ * ```
443
+ */
444
+ interface CrudApiDef<T = Record<string, unknown>> {
445
+ /** 获取分页列表 */
446
+ list: (params: CrudPaginationParams & CrudFilterParams) => Promise<CrudPaginatedResult<T>>;
447
+ /** 获取单条记录 */
448
+ get?: (id: string) => Promise<T | null>;
449
+ /** 新建记录 */
450
+ create?: (data: Partial<T>) => Promise<T>;
451
+ /** 更新记录(patch) */
452
+ update?: (id: string, data: Partial<T>) => Promise<T>;
453
+ /** 删除记录 */
454
+ remove?: (id: string) => Promise<void>;
455
+ }
456
+ /**
457
+ * CRUD 资源定义
458
+ * @example
459
+ * ```ts
460
+ * import type { CrudApiDef, CrudResourceDef } from '@h-ai/kit'
461
+ *
462
+ * function articles(api: CrudApiDef<{ id: string, title: string }>): CrudResourceDef<{ id: string, title: string }> {
463
+ * return { name: 'article', label: 'Articles', fields: [{ id: 'title', label: 'Title', type: 'string' }], api }
464
+ * }
465
+ * ```
466
+ */
467
+ interface CrudResourceDef<T = Record<string, unknown>> {
468
+ /** 资源名称(如 'user', 'role'),用于 URL 路由 */
469
+ name: string;
470
+ /** 显示名称(面包屑、标题用,支持 i18n) */
471
+ label: CrudText;
472
+ /** 主键字段名(默认 'id') */
473
+ keyField?: string;
474
+ /** 字段列表 */
475
+ fields: CrudFieldDef[];
476
+ /** API 接口 */
477
+ api: CrudApiDef<T>;
478
+ /** 默认分页大小(默认 20) */
479
+ defaultPageSize?: number;
480
+ /** 是否支持搜索(默认 true) */
481
+ searchable?: boolean;
482
+ /** 搜索占位符 */
483
+ searchPlaceholder?: CrudText;
484
+ }
485
+ /**
486
+ * DataTable 列配置(适配 @h-ai/ui DataTable)
487
+ * @example
488
+ * ```ts
489
+ * import type { CrudTableColumn } from '@h-ai/kit'
490
+ *
491
+ * const value: CrudTableColumn = { key: 'title', label: 'Title' }
492
+ * void value
493
+ * ```
494
+ */
495
+ interface CrudTableColumn {
496
+ key: string;
497
+ label: string;
498
+ width?: string;
499
+ align?: 'left' | 'center' | 'right';
500
+ render?: (item: Record<string, unknown>) => string;
501
+ }
502
+ /**
503
+ * CRUD 操作对象(由 defineCrud 返回)
504
+ * @example
505
+ * ```ts
506
+ * import type { CrudOperations } from '@h-ai/kit'
507
+ *
508
+ * function columns(resource: CrudOperations<{ id: string }>) { return resource.toTableColumns() }
509
+ * ```
510
+ */
511
+ interface CrudOperations<T = Record<string, unknown>> {
512
+ /** 资源元信息 */
513
+ resource: CrudResourceDef<T>;
514
+ /** 获取列表列字段(inList=true) */
515
+ getListFields: () => CrudFieldDef[];
516
+ /** 获取过滤字段(filterable=true) */
517
+ getFilterFields: () => CrudFieldDef[];
518
+ /** 获取新建表单字段(inCreate=true) */
519
+ getCreateFields: () => CrudFieldDef[];
520
+ /** 获取编辑表单字段(inEdit=true) */
521
+ getEditFields: () => CrudFieldDef[];
522
+ /** 获取详情字段(inDetail=true) */
523
+ getDetailFields: () => CrudFieldDef[];
524
+ /** 构建 DataTable 列配置 */
525
+ toTableColumns: () => CrudTableColumn[];
526
+ /** 构建新建时的默认值 */
527
+ getDefaultValues: () => Record<string, unknown>;
528
+ /** API 操作代理 */
529
+ api: CrudApiDef<T>;
530
+ }
531
+
532
+ /**
533
+ * @h-ai/kit — CRUD 操作定义
534
+ *
535
+ * 声明式 CRUD 资源定义工厂函数。
536
+ * @module kit-crud
537
+ */
538
+
539
+ /**
540
+ * 解析 CrudText 为字符串
541
+ */
542
+ declare function resolveText(text: CrudText): string;
543
+ /**
544
+ * 解析选项列表
545
+ */
546
+ declare function resolveOptions(options: CrudFieldOptions | undefined): Array<{
547
+ label: string;
548
+ value: string | number | boolean;
549
+ }>;
550
+ /**
551
+ * 定义 CRUD 资源
552
+ *
553
+ * 返回 CrudOperations 对象,包含字段过滤、列构建和 API 代理等能力。
554
+ * 与 @h-ai/ui 的 CrudPage 组件配合使用。
555
+ *
556
+ * @param resource - 资源定义
557
+ * @returns CRUD 操作对象
558
+ * @example
559
+ * ```ts
560
+ * import { kit } from '@h-ai/kit'
561
+ *
562
+ * import type { CrudApiDef } from '@h-ai/kit'
563
+ *
564
+ * function articleResource(api: CrudApiDef<{ id: string, title: string }>) {
565
+ * return kit.crud.define({ name: 'article', label: 'Articles', fields: [{ id: 'title', label: 'Title', type: 'string' }], api })
566
+ * }
567
+ * ```
568
+ */
569
+ declare function defineCrud<T = Record<string, unknown>>(resource: CrudResourceDef<T>): CrudOperations<T>;
570
+
571
+ /**
572
+ * @h-ai/kit — 权限守卫
573
+ *
574
+ * 验证用户是否具有指定权限。
575
+ * @module kit-permission
576
+ */
577
+
578
+ /**
579
+ * 权限守卫配置
580
+ * @example
581
+ * ```ts
582
+ * import type { PermissionGuardConfig } from '@h-ai/kit'
583
+ *
584
+ * const value: PermissionGuardConfig = { permissions: ['article:read'] }
585
+ * void value
586
+ * ```
587
+ */
588
+ interface PermissionGuardConfig {
589
+ /** 需要的权限列表(默认 OR 逻辑,满足任一即通过) */
590
+ permissions: string[];
591
+ /** 为 `true` 时要求用户拥有 **全部** 权限(AND 逻辑) */
592
+ requireAll?: boolean;
593
+ /** 无权限时重定向 URL(默认 `'/403'`) */
594
+ forbiddenUrl?: string;
595
+ /** 为 `true` 时返回 JSON 403 而非重定向 */
596
+ apiMode?: boolean;
597
+ }
598
+ /**
599
+ * 匹配权限
600
+ *
601
+ * 支持通配符:
602
+ * - `admin:*` 匹配 `admin:read`、`admin:write` 等
603
+ * - `*` 匹配所有权限
604
+ *
605
+ * @param required - 需要的权限码
606
+ * @param userPermissions - 用户已有的权限列表
607
+ * @returns 是否匹配
608
+ * @example
609
+ * ```ts
610
+ * import { matchPermission } from '@h-ai/kit'
611
+ *
612
+ * const allowed = matchPermission('article:read', ['article:*'])
613
+ * void allowed
614
+ * ```
615
+ */
616
+ declare function matchPermission(required: string, userPermissions: string[]): boolean;
617
+ /**
618
+ * 检查会话是否具有指定权限(布尔判断)
619
+ *
620
+ * 适用于条件分支场景(如菜单过滤、按钮显示等)。
621
+ *
622
+ * @param session - 当前会话数据,null/undefined 视为无权限
623
+ * @param permission - 需要的权限码,如 `user:read`
624
+ * @returns 是否拥有权限
625
+ * @example
626
+ * ```ts
627
+ * import { kit } from '@h-ai/kit'
628
+ *
629
+ * const allowed = kit.guard.check({ userId: 'user_1', roles: ['editor'], permissions: ['article:read'] }, 'article:read')
630
+ * void allowed
631
+ * ```
632
+ */
633
+ declare function hasPermission(session: SessionLike | null | undefined, permission: string): boolean;
634
+ /**
635
+ * 要求会话具有指定权限,不满足时 throw Response
636
+ *
637
+ * throw 的 Response 对象由 kit.handler 捕获并直接作为 API 响应返回。
638
+ * 搭配 `kit.handler()` 使用时,无需手动检查返回值。
639
+ *
640
+ * @param session - 当前会话数据,null/undefined 视为未认证
641
+ * @param permission - 需要的权限码,如 `user:create`
642
+ * @throws Response - 未认证 401 / 无权限 403
643
+ * @example
644
+ * ```ts
645
+ * import { kit } from '@h-ai/kit'
646
+ *
647
+ * kit.guard.require({ userId: 'user_1', roles: ['editor'], permissions: ['article:read'] }, 'article:read') // 拒绝时抛出 Response,由 kit.handler 传递。
648
+ * ```
649
+ */
650
+ declare function requirePermission(session: SessionLike | null | undefined, permission: string): void;
651
+
652
+ /** 可选敏感操作再鉴别;由操作入口在现有权限/资源检查之后调用。 */
653
+
654
+ /**
655
+ * 要求选定操作携带短期单次再鉴别票据;失败抛出 Response,由 kit.handler 返回。
656
+ * 不替代已有认证、权限与资源范围守卫;操作 ID 必须由服务端指定。
657
+ * @param iam - 已初始化的 IAM 服务。
658
+ * @param event - 当前请求与 Cookie,不能跨请求保存。
659
+ * @param operation - 当前服务端操作 ID。
660
+ * @returns 策略关闭、未选操作或证明校验成功时无返回值。
661
+ * @example
662
+ * ```ts
663
+ * import { iam } from '@h-ai/iam'
664
+ * import type { SessionLike } from '@h-ai/kit'
665
+ * import type { RequestEvent } from '@sveltejs/kit'
666
+ * import { kit } from '@h-ai/kit'
667
+ * // session 由应用在当前请求完成鉴别后传入,不在跨请求闭包中保存。
668
+ * async function remove(event: Pick<RequestEvent, 'request' | 'cookies'>, session: SessionLike) {
669
+ * kit.guard.require(session, 'user:delete')
670
+ * await kit.guard.requireSensitive(iam, event, 'iam.users.delete')
671
+ * return kit.response.ok({ allowed: true })
672
+ * }
673
+ * ```
674
+ */
675
+ declare function requireSensitiveOperation(iam: IamFunctions, event: Pick<RequestEvent, 'request' | 'cookies'>, operation: string): Promise<void>;
676
+
677
+ /**
678
+ * @h-ai/kit — SvelteKit Handle Hook
679
+ *
680
+ * 创建 SvelteKit Handle Hook,集成请求 ID 生成、会话验证、Cookie 加密代理、
681
+ * 路由守卫、中间件链与可选传输加密;同时提供 `sequence()` 组合多个 Handle。
682
+ * @module kit-handle
683
+ */
684
+
685
+ /**
686
+ * 创建 hai handle hook
687
+ *
688
+ * 整合会话解析、路由守卫、中间件链与统一错误处理的 SvelteKit Handle 工厂。
689
+ *
690
+ * 执行顺序:
691
+ * 1. 生成 `requestId` 并写入 `event.locals`
692
+ * 2. 根据 `auth` 配置从 Bearer / Cookie 解析会话
693
+ * 3. 根据 `auth.protectedPaths` 自动执行路由守卫 + 额外自定义守卫
694
+ * 4. 构建中间件链(内置 logging / rateLimit + 自定义)并执行
695
+ * 5. 调用 `resolve(event)` 获取业务响应
696
+ * 6. 附加 `X-Request-Id` 响应头
697
+ *
698
+ * @param config - Handle 配置(均有合理默认值,可零配置使用)
699
+ * @returns SvelteKit Handle 函数
700
+ * @example
701
+ * ```ts
702
+ * import { kit } from '@h-ai/kit'
703
+ *
704
+ * const handle = kit.createHandle({ auth: { verifyToken: async () => null, protectedPaths: ['/admin/**'] } })
705
+ * void handle
706
+ * ```
707
+ */
708
+ declare function createHandle(config?: HandleConfig): Handle;
709
+ /**
710
+ * 组合多个 SvelteKit handle 为单一 handle
711
+ *
712
+ * 洋葱模型:`sequence(a, b, c)` 执行顺序为 a → b → c → resolve → c → b → a。
713
+ *
714
+ * @param handles - 待组合的 handle 函数列表
715
+ * @returns 组合后的单一 Handle 函数
716
+ * @example
717
+ * ```ts
718
+ * import { kit } from '@h-ai/kit'
719
+ *
720
+ * const handle = kit.sequence(kit.createHandle({ logging: true }), kit.createHandle())
721
+ * void handle
722
+ * ```
723
+ */
724
+ declare function sequence(...handles: Handle[]): Handle;
725
+
726
+ /**
727
+ * 应用路由直接导出对应 handler;认证 ops 仍由 createHandle 注入。
728
+ * @param iam - 已由应用初始化的 IAM 服务对象。
729
+ * @returns 标准认证端点的 RequestHandler 集合。
730
+ * @example 模块内部上下文
731
+ * ```ts
732
+ * function build(iam: IamFunctions) {
733
+ * return createAuthApi(iam) // 调用方负责初始化 IAM;工厂只装配 handler。
734
+ * }
735
+ * ```
736
+ */
737
+ declare function createAuthApi(iam: IamFunctions): {
738
+ closeSession: _sveltejs_kit.RequestHandler;
739
+ createCaptcha: _sveltejs_kit.RequestHandler;
740
+ reauthenticate: _sveltejs_kit.RequestHandler;
741
+ publicConfig: _sveltejs_kit.RequestHandler;
742
+ renewPassword: _sveltejs_kit.RequestHandler;
743
+ login: _sveltejs_kit.RequestHandler;
744
+ loginWithLdap: _sveltejs_kit.RequestHandler;
745
+ loginWithOtp: _sveltejs_kit.RequestHandler;
746
+ register: _sveltejs_kit.RequestHandler;
747
+ sendOtp: _sveltejs_kit.RequestHandler;
748
+ requestPasswordReset: _sveltejs_kit.RequestHandler;
749
+ confirmPasswordReset: _sveltejs_kit.RequestHandler;
750
+ };
751
+
752
+ /** 可直接挂到 SvelteKit catch-all 路由的反馈适配,无 serv 或 Svelte UI 依赖。 */
753
+
754
+ /**
755
+ * 反馈服务及可信范围解析。resolveContext 必须使用已验证 session/宿主策略。
756
+ * @example
757
+ * ```ts
758
+ * import type { FeedbackHandlerOptions } from '@h-ai/kit'
759
+ * import { feedback } from '@h-ai/feedback'
760
+ * const options: FeedbackHandlerOptions = { feedback, resolveContext: () => null }
761
+ * // 应用实现真实 session 映射;null 拒绝访问,不能从 JSON 取得身份。
762
+ * ```
763
+ */
764
+ interface FeedbackHandlerOptions {
765
+ readonly feedback: FeedbackFunctions;
766
+ readonly resolveContext: (event: RequestEvent) => FeedbackContext | null | Promise<FeedbackContext | null>;
767
+ readonly basePath?: string;
768
+ }
769
+ /**
770
+ * 装配反馈 REST 路由;默认路径 /api/feedback,由宿主 handle 保持 CSRF、认证和传输加密。
771
+ * @param options - 已初始化服务与可信范围映射。
772
+ * @returns 可赋值给 catch-all 路由 GET/POST/PATCH 的同一 handler。
773
+ * @example
774
+ * ```ts
775
+ * import { kit } from '@h-ai/kit'
776
+ * import { feedback } from '@h-ai/feedback'
777
+ * const handler = kit.createFeedbackHandler({ feedback, resolveContext: () => null })
778
+ * // 路由 export const GET = handler;真实应用从受信 session 返回范围,null 默认拒绝。
779
+ * ```
780
+ */
781
+ declare function createFeedbackHandler(options: FeedbackHandlerOptions): RequestHandler;
782
+
783
+ /**
784
+ * @h-ai/kit — API Handler 包装器
785
+ *
786
+ * 统一封装 SvelteKit API Handler 的错误处理逻辑。
787
+ * @module kit-handler
788
+ */
789
+
790
+ /**
791
+ * 创建 API Handler 包装器
792
+ *
793
+ * 将业务逻辑包裹在统一的异常边界中:
794
+ * 1. 正常执行 `fn(event)` 返回 Response
795
+ * 2. 若 `fn` throw 了 `Response`(如 `kit.guard.require` / `kit.validate.body`),直接返回该 Response
796
+ * 3. 若 `fn` throw 了 SvelteKit 控制流(`redirect()` / `error()`),继续抛出
797
+ * 4. 其他异常:记录日志 → 返回 `kit.response.internalError()`
798
+ *
799
+ * @param fn - 业务处理函数
800
+ * @returns SvelteKit RequestHandler
801
+ * @example
802
+ * ```ts
803
+ * import { kit } from '@h-ai/kit'
804
+ *
805
+ * const GET = kit.handler(() => kit.response.ok({ healthy: true }))
806
+ * void GET
807
+ * ```
808
+ */
809
+ declare function handler(fn: (event: RequestEvent) => Promise<Response> | Response): RequestHandler;
810
+
811
+ /**
812
+ * @h-ai/kit — API 响应工具
813
+ *
814
+ * 标准化 API 响应工具集,统一 `{ success, data?, error?, requestId? }` 结构。
815
+ * 提供成功响应(ok / created / noContent)、错误响应
816
+ * (badRequest / unauthorized / forbidden / notFound / conflict / validationError / internalError)
817
+ * 以及重定向响应。
818
+ * @module kit-response
819
+ */
820
+
821
+ /**
822
+ * 创建 200 成功响应
823
+ *
824
+ * @param data - 响应数据,序列化为 JSON
825
+ * @param requestId - 可选请求 ID,用于链路追踪
826
+ * @returns `{ success: true, data, requestId }` 格式的 JSON Response
827
+ * @example
828
+ * ```ts
829
+ * import { kit } from '@h-ai/kit'
830
+ *
831
+ * const response = kit.response.ok({ id: 'article_1' })
832
+ * void response.status
833
+ * ```
834
+ */
835
+ declare function ok<T>(data: T, requestId?: string): Response;
836
+ /**
837
+ * 创建 201 资源创建成功响应
838
+ *
839
+ * @param data - 新创建的资源数据
840
+ * @param requestId - 可选请求 ID
841
+ * @returns `{ success: true, data }` 格式的 JSON Response(status 201)
842
+ * @example
843
+ * ```ts
844
+ * import { kit } from '@h-ai/kit'
845
+ *
846
+ * const response = kit.response.created({ id: 'article_1' })
847
+ * void response.status
848
+ * ```
849
+ */
850
+ declare function created<T>(data: T, requestId?: string): Response;
851
+ /**
852
+ * 创建 204 无内容响应
853
+ *
854
+ * 通常用于 DELETE 成功或无返回值的更新操作。
855
+ *
856
+ * @returns 空 body、status 204 的 Response
857
+ * @example
858
+ * ```ts
859
+ * import { kit } from '@h-ai/kit'
860
+ *
861
+ * const response = kit.response.noContent()
862
+ * void response.status
863
+ * ```
864
+ */
865
+ declare function noContent(): Response;
866
+ /**
867
+ * 创建自定义错误响应
868
+ *
869
+ * @param code - 错误码(如 `'CUSTOM_ERROR'`)
870
+ * @param message - 人可读错误消息
871
+ * @param status - HTTP 状态码,默认 400
872
+ * @param requestId - 可选请求 ID
873
+ * @param details - 显式公开的业务详情;不要传原始异常、SQL、输入值或内部上下文
874
+ * @returns `{ success: false, error: { code, message, details } }` 格式的 JSON Response
875
+ * @example
876
+ * ```ts
877
+ * import { kit } from '@h-ai/kit'
878
+ *
879
+ * const response = kit.response.error('ARTICLE_MISSING', 'Article missing', 404)
880
+ * void response.status
881
+ * ```
882
+ */
883
+ declare function error(code: HaiError['code'], message: string, status?: number, requestId?: string, details?: unknown): Response;
884
+ /**
885
+ * 创建 400 Bad Request 响应
886
+ *
887
+ * @param message - 错误消息
888
+ * @param requestId - 可选请求 ID
889
+ * @param details - 可选额外详情
890
+ * @returns error code 为 `HaiCommonError.INVALID_REQUEST.code` 的 JSON Response
891
+ * @example
892
+ * ```ts
893
+ * import { kit } from '@h-ai/kit'
894
+ *
895
+ * const response = kit.response.badRequest('Invalid article')
896
+ * void response.status
897
+ * ```
898
+ */
899
+ declare function badRequest(message: string, requestId?: string, details?: unknown): Response;
900
+ /**
901
+ * 创建 401 Unauthorized 响应
902
+ *
903
+ * @param message - 错误消息,默认 `'Authentication required'`
904
+ * @param requestId - 可选请求 ID
905
+ * @returns error code 为 `HaiCommonError.UNAUTHORIZED.code` 的 JSON Response
906
+ * @example
907
+ * ```ts
908
+ * import { kit } from '@h-ai/kit'
909
+ *
910
+ * const response = kit.response.unauthorized()
911
+ * void response.status
912
+ * ```
913
+ */
914
+ declare function unauthorized(message?: string, requestId?: string): Response;
915
+ /**
916
+ * 创建 403 Forbidden 响应
917
+ *
918
+ * @param message - 错误消息,默认 `'Access denied'`
919
+ * @param requestId - 可选请求 ID
920
+ * @returns error code 为 `HaiCommonError.FORBIDDEN.code` 的 JSON Response
921
+ * @example
922
+ * ```ts
923
+ * import { kit } from '@h-ai/kit'
924
+ *
925
+ * const response = kit.response.forbidden()
926
+ * void response.status
927
+ * ```
928
+ */
929
+ declare function forbidden(message?: string, requestId?: string): Response;
930
+ /**
931
+ * 创建 404 Not Found 响应
932
+ *
933
+ * @param message - 错误消息,默认 `'Resource not found'`
934
+ * @param requestId - 可选请求 ID
935
+ * @returns error code 为 `HaiCommonError.NOT_FOUND.code` 的 JSON Response
936
+ * @example
937
+ * ```ts
938
+ * import { kit } from '@h-ai/kit'
939
+ *
940
+ * const response = kit.response.notFound()
941
+ * void response.status
942
+ * ```
943
+ */
944
+ declare function notFound(message?: string, requestId?: string): Response;
945
+ /**
946
+ * 创建 409 Conflict 响应
947
+ *
948
+ * @param message - 冲突描述(如重复创建等)
949
+ * @param requestId - 可选请求 ID
950
+ * @returns error code 为 `HaiCommonError.CONFLICT.code` 的 JSON Response
951
+ * @example
952
+ * ```ts
953
+ * import { kit } from '@h-ai/kit'
954
+ *
955
+ * const response = kit.response.conflict('Already updated')
956
+ * void response.status
957
+ * ```
958
+ */
959
+ declare function conflict(message: string, requestId?: string): Response;
960
+ /**
961
+ * 创建 422 Unprocessable Entity 响应(验证错误)
962
+ *
963
+ * @param errors - 字段级别的验证错误列表
964
+ * @param requestId - 可选请求 ID
965
+ * @returns error code 为 `HaiCommonError.VALIDATION_ERROR.code`,cause 仅包含 field/message
966
+ * @example
967
+ * ```ts
968
+ * import { kit } from '@h-ai/kit'
969
+ *
970
+ * const response = kit.response.validationError([{ field: 'title', message: 'Title is required' }])
971
+ * void response.status
972
+ * ```
973
+ */
974
+ declare function validationError(errors: Array<{
975
+ field: string;
976
+ message: string;
977
+ }>, requestId?: string): Response;
978
+ /**
979
+ * 创建 500 Internal Server Error 响应
980
+ *
981
+ * @param message - 错误消息,默认 `'Internal server error'`
982
+ * @param requestId - 可选请求 ID
983
+ * @returns error code 为 `HaiCommonError.INTERNAL_ERROR.code` 的 JSON Response
984
+ * @example
985
+ * ```ts
986
+ * import { kit } from '@h-ai/kit'
987
+ *
988
+ * const response = kit.response.internalError()
989
+ * void response.status
990
+ * ```
991
+ */
992
+ declare function internalError(message?: string, requestId?: string): Response;
993
+ /**
994
+ * 创建重定向响应
995
+ *
996
+ * @param url - 目标 URL
997
+ * @param status - HTTP 状态码,默认 302;常用 303(POST 后重定向)
998
+ * @returns 带 `Location` 头的空 body Response
999
+ * @example
1000
+ * ```ts
1001
+ * import { kit } from '@h-ai/kit'
1002
+ *
1003
+ * const response = kit.response.redirect('/articles', 303)
1004
+ * void response.status
1005
+ * ```
1006
+ */
1007
+ declare function redirect(url: string, status?: 301 | 302 | 303 | 307 | 308): Response;
1008
+ /**
1009
+ * 将 HaiResult<T> 转换为标准 API Response
1010
+ *
1011
+ * 成功时返回 200 ok(data),失败时从 error 对象中提取 code、message,
1012
+ * 并根据 httpStatusMap 或错误定义映射 HTTP 状态码;未知状态按 500 安全处理。
1013
+ *
1014
+ * @param result - core HaiResult 对象({ success, data } 或 { success: false, error })
1015
+ * @param httpStatusMap - 模块导出的错误码 → HTTP 状态码映射表(如 IamErrorHttpStatus)
1016
+ * @param requestId - 可选请求 ID,用于链路追踪
1017
+ * @returns 标准化 JSON Response
1018
+ * @example
1019
+ * ```ts
1020
+ * import { err, HaiCommonError, type HaiResult } from '@h-ai/core'
1021
+ * import { kit } from '@h-ai/kit'
1022
+ *
1023
+ * function respond(result: HaiResult<{ id: string }>): Response {
1024
+ * return kit.response.fromResult(result)
1025
+ * }
1026
+ * const response = kit.response.fromResult(err(HaiCommonError.NOT_FOUND, 'Article missing'))
1027
+ * void response.status
1028
+ * ```
1029
+ */
1030
+ declare function fromResult<T>(result: HaiResult<T>, httpStatusMap?: Record<number | string, number>, requestId?: string): Response;
1031
+ /**
1032
+ * 按模块错误的 HTTP 状态构建安全的统一 API 错误响应。
1033
+ * @param haiError - 包含 code、message 和可选 httpStatus 的模块错误。
1034
+ * @param requestId - 可选的请求追踪标识。
1035
+ * @returns 包含统一错误结构和对应 HTTP 状态的 Response。
1036
+ * @example
1037
+ * ```ts
1038
+ * import { kit } from '@h-ai/kit'
1039
+ *
1040
+ * const response = kit.response.fromError({ code: 'app:articles:001', message: 'Article missing', httpStatus: 404 })
1041
+ * void response.status
1042
+ * ```
1043
+ */
1044
+ declare function fromError(haiError: HaiError, requestId?: string): Response;
1045
+
1046
+ /**
1047
+ * @h-ai/kit — 请求数据验证
1048
+ *
1049
+ * 基于 Zod 的请求数据验证工具,支持表单/JSON Body、URL 查询参数与路由参数。
1050
+ * Zod 默认错误消息的本地化规则委托给 `core.zodValidation`,避免 kit / serv
1051
+ * 等模块重复维护同一套 issue 解析与消息映射逻辑;模块前缀映射也统一交给
1052
+ * `core.zodValidation.createPrefixedZodMessageGetter()` 处理。
1053
+ * 每种数据源都提供两类 API:
1054
+ * - 安全返回:`FormValidationResult`
1055
+ * - 失败抛出:`OrFail`(抛出 `Response`,由 kit.handler 作为 API 控制流处理)
1056
+ * @module kit-validation
1057
+ */
1058
+
1059
+ /**
1060
+ * 从 Request 解析并验证表单数据,失败时 throw Response
1061
+ *
1062
+ * 与 `validateForm` 功能相同,但校验失败时 throw 400 Response(SvelteKit 控制流),
1063
+ * 搭配 `kit.handler()` 使用可精简 handler 代码。
1064
+ *
1065
+ * @param request - SvelteKit 请求对象
1066
+ * @param schema - Zod Schema
1067
+ * @returns 校验通过的数据(类型安全)
1068
+ * @throws Response - 400 BadRequest(含首条错误消息)
1069
+ * @example 模块内部上下文
1070
+ * ```ts
1071
+ * const schema = zod.object({ title: zod.string().min(1) })
1072
+ * const result = await validateFormOrFail(new Request('https://app.example.com/api', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: 'Example' }) }), schema)
1073
+ * // 校验失败抛出 Response,由框架错误边界透传。
1074
+ * void result.title
1075
+ * ```
1076
+ */
1077
+ declare function validateFormOrFail<T extends z.ZodType>(request: Request, schema: T): Promise<z.infer<T>>;
1078
+ /**
1079
+ * 从 URL 查询参数验证,失败时 throw Response
1080
+ *
1081
+ * @param url - 请求 URL 对象
1082
+ * @param schema - Zod Schema
1083
+ * @returns 校验通过的数据
1084
+ * @throws Response - 400 BadRequest
1085
+ * @example 模块内部上下文
1086
+ * ```ts
1087
+ * const schema = zod.object({ title: zod.string().min(1) })
1088
+ * const result = validateQueryOrFail(new URL('https://app.example.com/articles?title=Example'), schema)
1089
+ * // 校验失败抛出 Response,由框架错误边界透传。
1090
+ * void result.title
1091
+ * ```
1092
+ */
1093
+ declare function validateQueryOrFail<T extends z.ZodType>(url: URL, schema: T): z.infer<T>;
1094
+ /**
1095
+ * 验证路径参数,失败时 throw Response
1096
+ *
1097
+ * @param params - SvelteKit 路由参数
1098
+ * @param schema - Zod Schema
1099
+ * @returns 校验通过的数据
1100
+ * @throws Response - 400 BadRequest
1101
+ * @example 模块内部上下文
1102
+ * ```ts
1103
+ * const schema = zod.object({ title: zod.string().min(1) })
1104
+ * const result = validateParamsOrFail({ title: 'Example' }, schema)
1105
+ * // 校验失败抛出 Response,由框架错误边界透传。
1106
+ * void result.title
1107
+ * ```
1108
+ */
1109
+ declare function validateParamsOrFail<T extends z.ZodType>(params: Record<string, string>, schema: T): z.infer<T>;
1110
+ /**
1111
+ * 路径参数 id 校验 Schema
1112
+ *
1113
+ * 验证 `event.params.id` 为非空字符串。
1114
+ * @example
1115
+ * ```ts
1116
+ * import { IdParamSchema } from '@h-ai/kit'
1117
+ *
1118
+ * const value = IdParamSchema.parse({ id: 'article_1' })
1119
+ * void value
1120
+ * ```
1121
+ */
1122
+ declare const IdParamSchema: z.ZodObject<{
1123
+ id: z.ZodString;
1124
+ }, z.core.$strip>;
1125
+ /**
1126
+ * 通用分页查询参数 Schema
1127
+ *
1128
+ * 包含 page(默认 1)、pageSize(默认 20,上限 100)、search(可选)。
1129
+ * 可通过 `.extend()` 扩展业务字段。
1130
+ * @example
1131
+ * ```ts
1132
+ * import { PaginationQuerySchema } from '@h-ai/kit'
1133
+ *
1134
+ * const value = PaginationQuerySchema.parse({ page: '1', pageSize: '20' })
1135
+ * void value
1136
+ * ```
1137
+ */
1138
+ declare const PaginationQuerySchema: z.ZodObject<{
1139
+ page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
1140
+ pageSize: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
1141
+ search: z.ZodOptional<z.ZodString>;
1142
+ }, z.core.$strip>;
1143
+
1144
+ /**
1145
+ * @h-ai/kit — 速率限制中间件
1146
+ *
1147
+ * 以首个成功请求为起点的固定窗口限流;后续计数不延长窗口。
1148
+ * 内置内存存储(`MemoryRateLimitStore`),并支持通过 `RateLimitStore` 接入
1149
+ * Redis 等外部存储后端。
1150
+ * @module kit-ratelimit
1151
+ */
1152
+
1153
+ /**
1154
+ * 速率限制存储条目
1155
+ * @example
1156
+ * ```ts
1157
+ * import type { RateLimitEntry } from '@h-ai/kit'
1158
+ *
1159
+ * const value: RateLimitEntry = { count: 1, resetAt: Date.now() + 60_000 }
1160
+ * void value
1161
+ * ```
1162
+ */
1163
+ interface RateLimitEntry {
1164
+ /** 当前窗口内的请求次数 */
1165
+ count: number;
1166
+ /** 窗口重置时间戳(ms) */
1167
+ resetAt: number;
1168
+ }
1169
+ /**
1170
+ * 原子固定窗口计数器;故障抛错由中间件转为503,禁止读改写回退。
1171
+ * @example
1172
+ * ```ts
1173
+ * import type { RateLimitStore } from '@h-ai/kit'
1174
+ *
1175
+ * async function count(store: RateLimitStore) {
1176
+ * return store.increment('client_1', 60_000)
1177
+ * }
1178
+ * ```
1179
+ */
1180
+ interface RateLimitStore {
1181
+ /** shared要求共享后端;memory仅限显式开发/测试。 */
1182
+ readonly scope: 'shared' | 'memory';
1183
+ /** 原子计数并保留首次请求的窗口,返回提交后的计数/重置点。 */
1184
+ increment: (key: string, windowMs: number) => Promise<RateLimitEntry> | RateLimitEntry;
1185
+ }
1186
+ /**
1187
+ * 共享缓存的最小结构契约;使用其单键CAS与服务端TTL,不使用锁或客户端到期清零。
1188
+ * @example
1189
+ * ```ts
1190
+ * import type { RateLimitCache } from '@h-ai/kit'
1191
+ * import { cache } from '@h-ai/cache'
1192
+ *
1193
+ * const backend: RateLimitCache = cache
1194
+ * void backend
1195
+ * ```
1196
+ */
1197
+ interface RateLimitCache {
1198
+ readonly config: {
1199
+ type: string;
1200
+ } | null;
1201
+ readonly kv: {
1202
+ get: <T>(key: string) => Promise<HaiResult<T | null>>;
1203
+ compareAndSwap: (key: string, expected: RateLimitEntry | undefined, value: RateLimitEntry, options: {
1204
+ px?: number;
1205
+ keepTtl?: boolean;
1206
+ }) => Promise<HaiResult<boolean>>;
1207
+ };
1208
+ }
1209
+ /**
1210
+ * 内存速率限制存储
1211
+ *
1212
+ * 基于 Map 实现,仅用于单进程开发/测试;每次请求最多扫描 64 项过期窗口,
1213
+ * 不持有定时器。最多 10000 项,容量耗尽时拒绝新 key,不驱逐有效计数以免绕过限流。
1214
+ * @example
1215
+ * ```ts
1216
+ * import { kit } from '@h-ai/kit'
1217
+ *
1218
+ * // 仅开发/测试;丢弃引用即可回收,无内部定时器。
1219
+ * const store = kit.middleware.createMemoryRateLimitStore()
1220
+ * void store.increment('client_1', 60_000)
1221
+ * ```
1222
+ */
1223
+ declare class MemoryRateLimitStore implements RateLimitStore {
1224
+ readonly scope: "memory";
1225
+ private store;
1226
+ private cleanupCursor;
1227
+ /**
1228
+ * 有界惰性回收;保留迭代位置,避免每次从头扫描使尾部过期项永久滞留。
1229
+ * @param now - 当前请求时间,等于 resetAt 时窗口已经失效。
1230
+ */
1231
+ private prune;
1232
+ /**
1233
+ * 原子自增(内存实现为同步操作,天然原子)
1234
+ *
1235
+ * @param key - 限流键
1236
+ * @param windowMs - 窗口时长
1237
+ * @returns 自增后的快照,修改返回对象不会改变已保存的计数。
1238
+ * @throws 新 key 超出容量或期限非法;中间件将其转换为 503。
1239
+ * @example store.increment('client', 60_000)
1240
+ */
1241
+ increment(key: string, windowMs: number): RateLimitEntry;
1242
+ }
1243
+
1244
+ /**
1245
+ * @h-ai/kit — 类型定义
1246
+ *
1247
+ * SvelteKit 集成相关类型
1248
+ * @module kit-types
1249
+ */
1250
+
1251
+ /**
1252
+ * 当前请求的认证 Cookie 写入契约;不持有跨请求状态。
1253
+ * @example
1254
+ * ```ts
1255
+ * import type { AuthCookieWriter } from '@h-ai/kit'
1256
+ * import { kit } from '@h-ai/kit'
1257
+ *
1258
+ * async function signOut(cookies: AuthCookieWriter) {
1259
+ * const result = await kit.auth.logout(cookies)
1260
+ * return result.success
1261
+ * }
1262
+ * ```
1263
+ */
1264
+ interface AuthCookieWriter {
1265
+ set: (name: string, value: string, options: {
1266
+ path: string;
1267
+ httpOnly: boolean;
1268
+ sameSite: 'lax' | 'strict' | 'none';
1269
+ secure: boolean;
1270
+ maxAge?: number;
1271
+ }) => void;
1272
+ delete: (name: string, options: {
1273
+ path: string;
1274
+ }) => void;
1275
+ }
1276
+ /**
1277
+ * Kit 服务端公开命名空间;消费者声明只引用公开类型,不暴露内部函数入口。
1278
+ * @example
1279
+ * ```ts
1280
+ * import type { KitFunctions } from '@h-ai/kit'
1281
+ * import { kit } from '@h-ai/kit'
1282
+ *
1283
+ * const runtime: KitFunctions = kit
1284
+ * const response = runtime.response.ok({ ready: true })
1285
+ * void response.status
1286
+ * ```
1287
+ */
1288
+ interface KitFunctions {
1289
+ createFeedbackHandler: typeof createFeedbackHandler;
1290
+ middleware: {
1291
+ rateLimit: (config: RateLimitConfig) => Middleware;
1292
+ createCacheRateLimitStore: (backend: RateLimitCache, options: {
1293
+ namespace: string;
1294
+ allowMemory?: boolean;
1295
+ }) => RateLimitStore;
1296
+ createMemoryRateLimitStore: () => MemoryRateLimitStore;
1297
+ };
1298
+ createHandle: typeof createHandle;
1299
+ sequence: typeof sequence;
1300
+ handler: typeof handler;
1301
+ guard: {
1302
+ requireSensitive: typeof requireSensitiveOperation;
1303
+ require: typeof requirePermission;
1304
+ check: typeof hasPermission;
1305
+ };
1306
+ response: {
1307
+ ok: typeof ok;
1308
+ created: typeof created;
1309
+ noContent: typeof noContent;
1310
+ error: typeof error;
1311
+ badRequest: typeof badRequest;
1312
+ unauthorized: typeof unauthorized;
1313
+ forbidden: typeof forbidden;
1314
+ notFound: typeof notFound;
1315
+ conflict: typeof conflict;
1316
+ validationError: typeof validationError;
1317
+ internalError: typeof internalError;
1318
+ redirect: typeof redirect;
1319
+ fromResult: typeof fromResult;
1320
+ fromError: typeof fromError;
1321
+ };
1322
+ validate: {
1323
+ body: typeof validateFormOrFail;
1324
+ query: typeof validateQueryOrFail;
1325
+ params: typeof validateParamsOrFail;
1326
+ IdParamSchema: typeof IdParamSchema;
1327
+ PaginationQuerySchema: typeof PaginationQuerySchema;
1328
+ };
1329
+ client: {
1330
+ create: typeof createKitClient;
1331
+ createAuthActions: typeof createKitAuthActions;
1332
+ installBrowserTransport: typeof installBrowserTransport;
1333
+ installBrowserTransportFetch: typeof installBrowserTransportFetch;
1334
+ };
1335
+ auth: {
1336
+ publicPaths: string[];
1337
+ createApi: typeof createAuthApi;
1338
+ login: (cookies: AuthCookieWriter, credentials: PasswordCredentials, context?: AuthRequestContext) => Promise<HaiResult<AuthResult>>;
1339
+ loginWithOtp: (cookies: AuthCookieWriter, credentials: OtpCredentials, context?: AuthRequestContext) => Promise<HaiResult<AuthResult>>;
1340
+ loginWithLdap: (cookies: AuthCookieWriter, credentials: LdapCredentials, context?: AuthRequestContext) => Promise<HaiResult<AuthResult>>;
1341
+ loginWithApiKey: (cookies: AuthCookieWriter, credentials: ApiKeyCredentials, context?: AuthRequestContext) => Promise<HaiResult<AuthResult>>;
1342
+ registerAndLogin: (cookies: AuthCookieWriter, options: RegisterOptions, context?: AuthRequestContext) => Promise<HaiResult<AuthResult>>;
1343
+ logout: (cookies: AuthCookieWriter, accessToken?: string | null) => Promise<HaiResult<void>>;
1344
+ setBrowserToken: (token: string) => void;
1345
+ clearBrowserToken: () => void;
1346
+ };
1347
+ crud: {
1348
+ define: typeof defineCrud;
1349
+ };
1350
+ i18n: {
1351
+ setLocale: (locale: string) => void;
1352
+ runWithLocale: typeof core.i18n.runWithLocale;
1353
+ };
1354
+ }
1355
+ /**
1356
+ * 浏览器实际可用的 Kit 命名空间;不含服务端认证、Hook 或中间件。
1357
+ * @example
1358
+ * ```ts
1359
+ * import type { BrowserKitFunctions } from '@h-ai/kit'
1360
+ * import { kit } from '@h-ai/kit'
1361
+ *
1362
+ * const browser: BrowserKitFunctions = kit
1363
+ * browser.auth.clearBrowserToken()
1364
+ * ```
1365
+ */
1366
+ interface BrowserKitFunctions {
1367
+ client: {
1368
+ create: typeof createKitClient;
1369
+ createAuthActions: typeof createKitAuthActions;
1370
+ installBrowserTransport: typeof installBrowserTransport;
1371
+ installBrowserTransportFetch: typeof installBrowserTransportFetch;
1372
+ };
1373
+ crud: {
1374
+ define: typeof defineCrud;
1375
+ };
1376
+ auth: {
1377
+ setBrowserToken: (token: string) => void;
1378
+ clearBrowserToken: () => void;
1379
+ };
1380
+ i18n: {
1381
+ setLocale: (locale: string) => void;
1382
+ };
1383
+ }
1384
+ /**
1385
+ * 服务器监听配置(对应 `config/_kit.yml` 的 `server`)。
1386
+ * @example
1387
+ * ```ts
1388
+ * import type { KitServerConfig } from '@h-ai/kit'
1389
+ *
1390
+ * const value: KitServerConfig = { host: '127.0.0.1', port: 3000 }
1391
+ * void value
1392
+ * ```
1393
+ */
1394
+ interface KitServerConfig {
1395
+ readonly host: string;
1396
+ readonly port: number;
1397
+ }
1398
+ /**
1399
+ * `config/_kit.yml` 中的服务器监听输入类型。
1400
+ * @example
1401
+ * ```ts
1402
+ * import type { KitServerConfigInput } from '@h-ai/kit'
1403
+ *
1404
+ * const value: KitServerConfigInput = { port: 4000 }
1405
+ * void value
1406
+ * ```
1407
+ */
1408
+ type KitServerConfigInput = Partial<KitServerConfig>;
1409
+ /**
1410
+ * `config/_kit.yml` 中的 transport 配置。
1411
+ * @example
1412
+ * ```ts
1413
+ * import type { KitTransportConfig } from '@h-ai/kit'
1414
+ *
1415
+ * const value: KitTransportConfig = { keyExchangePath: '/api/_hai/key-exchange', excludePaths: ['/api/health'] }
1416
+ * void value
1417
+ * ```
1418
+ */
1419
+ interface KitTransportConfig {
1420
+ /** 双向明文 UTF-8 字节上限;省略使用 1 MiB,范围 1 KiB~64 MiB。 */
1421
+ readonly maxPlaintextBytes?: number;
1422
+ /** 请求时间允许领先服务器的秒数,默认 30,整数范围 0~300。 */
1423
+ readonly maxFutureSkewSeconds?: number;
1424
+ /** 请求从签发起的有效秒数,默认 300,整数范围 1~600。 */
1425
+ readonly maxRequestAgeSeconds?: number;
1426
+ /** 按完整路径段匹配的明文容量;* 匹配单段。 */
1427
+ readonly routePlaintextBytes?: Readonly<Record<string, number>>;
1428
+ readonly keyExchangePath: `/${string}`;
1429
+ readonly excludePaths: readonly `/${string}`[];
1430
+ }
1431
+ /**
1432
+ * `config/_kit.yml` 的顶层配置结构。
1433
+ * @example
1434
+ * ```ts
1435
+ * import type { KitConfig } from '@h-ai/kit'
1436
+ *
1437
+ * const value: KitConfig = { server: { host: '127.0.0.1', port: 3000 }, transport: false, trustedProxies: 'auto', access: false }
1438
+ * void value
1439
+ * ```
1440
+ */
1441
+ interface KitConfig {
1442
+ readonly server: KitServerConfig;
1443
+ readonly transport: false | KitTransportConfig;
1444
+ /** auto 仅在受管私有容器入口采用容器网段;普通宿主忽略转发头。 */
1445
+ readonly trustedProxies: TrustedProxies;
1446
+ /** 每次请求的地址/时间/路径限制,默认 false;不会限制由静态服务器直接提供的资源。 */
1447
+ readonly access: RequestAccessConfigInput;
1448
+ }
1449
+ /**
1450
+ * `config/_kit.yml` 中的 transport 输入类型。
1451
+ * @example
1452
+ * ```ts
1453
+ * import type { KitTransportConfigInput } from '@h-ai/kit'
1454
+ *
1455
+ * const value: KitTransportConfigInput = { excludePaths: ['/api/health'] }
1456
+ * void value
1457
+ * ```
1458
+ */
1459
+ type KitTransportConfigInput = Partial<{
1460
+ readonly maxPlaintextBytes: number | 'auto';
1461
+ readonly maxFutureSkewSeconds: number;
1462
+ readonly maxRequestAgeSeconds: number;
1463
+ readonly routePlaintextBytes: Readonly<Record<string, number>>;
1464
+ readonly keyExchangePath: `/${string}`;
1465
+ readonly excludePaths: readonly `/${string}`[];
1466
+ }>;
1467
+ /**
1468
+ * `config/_kit.yml` 的顶层输入类型。
1469
+ * @example
1470
+ * ```ts
1471
+ * import type { KitConfigInput } from '@h-ai/kit'
1472
+ *
1473
+ * const value: KitConfigInput = { transport: false }
1474
+ * void value
1475
+ * ```
1476
+ */
1477
+ interface KitConfigInput {
1478
+ readonly server?: KitServerConfigInput;
1479
+ readonly transport?: false | KitTransportConfigInput;
1480
+ readonly trustedProxies?: TrustedProxies;
1481
+ readonly access?: RequestAccessConfigInput;
1482
+ }
1483
+ /**
1484
+ * 浏览器可接收的 Kit 公共配置,仅包含传输协议路径和开关。
1485
+ * @example
1486
+ * ```ts
1487
+ * import type { KitPublicConfig } from '@h-ai/kit'
1488
+ * const config: KitPublicConfig = { transport: false }
1489
+ * ```
1490
+ */
1491
+ type KitPublicConfig = Pick<KitConfig, 'transport'>;
1492
+ /**
1493
+ * kit.auth 认证操作(由 createHandle auth.operations 注入)
1494
+ *
1495
+ * 注入后,kit.auth.login / kit.auth.logout 等函数自动委托到 iam.auth 对应方法。
1496
+ * 传入 `iam.auth` 即可,kit 会自动提取所需方法。
1497
+ * @example
1498
+ * ```ts
1499
+ * import type { AuthOperations } from '@h-ai/kit'
1500
+ * import { iam } from '@h-ai/iam'
1501
+ *
1502
+ * // 在 IAM 初始化后注入其当前操作对象。
1503
+ * const operations: AuthOperations = iam.auth
1504
+ * void operations
1505
+ * ```
1506
+ */
1507
+ type AuthOperations = Pick<AuthnOperations, 'login' | 'loginWithOtp' | 'loginWithLdap' | 'loginWithApiKey' | 'registerAndLogin' | 'logout'>;
1508
+ /**
1509
+ * 认证操作提供器:支持直接传对象或按需返回最新对象的工厂函数
1510
+ * @example
1511
+ * ```ts
1512
+ * import type { AuthOperationsProvider } from '@h-ai/kit'
1513
+ * import { iam } from '@h-ai/iam'
1514
+ *
1515
+ * const operations: AuthOperationsProvider = () => iam.auth
1516
+ * void operations
1517
+ * ```
1518
+ */
1519
+ type AuthOperationsProvider = AuthOperations | (() => AuthOperations);
1520
+ /**
1521
+ * 会话数据最小接口
1522
+ *
1523
+ * 守卫和权限检查函数所需的最小会话形状。
1524
+ * 应用层扩展的 session(如添加 displayName / avatarUrl 等字段)
1525
+ * 只要包含此接口的字段即可直接传入守卫函数,无需类型断言。
1526
+ * @example
1527
+ * ```ts
1528
+ * import type { SessionLike } from '@h-ai/kit'
1529
+ *
1530
+ * const value: SessionLike = { userId: 'user_1', roles: ['editor'], permissions: ['article:read'] }
1531
+ * void value
1532
+ * ```
1533
+ */
1534
+ interface SessionLike {
1535
+ /** 用户 ID */
1536
+ userId: string;
1537
+ /** 角色列表 */
1538
+ roles: string[];
1539
+ /** 权限列表 */
1540
+ permissions: string[];
1541
+ /** 允许任意扩展字段 */
1542
+ [key: string]: unknown;
1543
+ }
1544
+ /**
1545
+ * 用户会话数据
1546
+ *
1547
+ * 在 Handle Hook 中通过 `validateSession` 解析后注入 `event.locals.session`。
1548
+ * 守卫和中间件通过此结构判断用户身份、角色与权限。
1549
+ *
1550
+ * 应用层可通过 `& { displayName: string }` 等方式扩展,
1551
+ * 扩展后的类型自动兼容所有守卫和权限检查函数(它们接受 `SessionLike`)。
1552
+ * @example
1553
+ * ```ts
1554
+ * import type { SessionData } from '@h-ai/kit'
1555
+ *
1556
+ * const value: SessionData = { userId: 'user_1', username: 'alice', roles: ['editor'], permissions: ['article:read'] }
1557
+ * void value
1558
+ * ```
1559
+ */
1560
+ interface SessionData {
1561
+ /** 用户 ID */
1562
+ userId: string;
1563
+ /** 用户名 */
1564
+ username?: string;
1565
+ /** 角色列表 */
1566
+ roles: string[];
1567
+ /** 权限列表 */
1568
+ permissions: string[];
1569
+ /** 自定义数据 */
1570
+ data?: Record<string, unknown>;
1571
+ /** 允许任意扩展字段 */
1572
+ [key: string]: unknown;
1573
+ }
1574
+ /**
1575
+ * 扩展的请求事件
1576
+ *
1577
+ * 在 SvelteKit 原生 `RequestEvent` 基础上注入会话和请求 ID。
1578
+ * @example
1579
+ * ```ts
1580
+ * import type { HaiRequestEvent } from '@h-ai/kit'
1581
+ *
1582
+ * function requestLabel(event: HaiRequestEvent) {
1583
+ * return { requestId: event.requestId, userId: event.session?.userId }
1584
+ * }
1585
+ * ```
1586
+ */
1587
+ interface HaiRequestEvent extends RequestEvent {
1588
+ /** 会话数据 */
1589
+ session?: SessionData;
1590
+ /** 请求 ID */
1591
+ requestId: string;
1592
+ }
1593
+ /**
1594
+ * 中间件上下文
1595
+ *
1596
+ * 由 `createHandle` 构建,传递给所有中间件函数。
1597
+ * 包含当前请求事件、已解析的会话以及请求唯一 ID。
1598
+ * @example
1599
+ * ```ts
1600
+ * import type { MiddlewareContext } from '@h-ai/kit'
1601
+ *
1602
+ * function requestLabel(context: MiddlewareContext) {
1603
+ * return context.event.url.pathname + ':' + context.requestId
1604
+ * }
1605
+ * ```
1606
+ */
1607
+ interface MiddlewareContext {
1608
+ /** 请求事件 */
1609
+ event: RequestEvent;
1610
+ /** 会话数据 */
1611
+ session?: SessionData;
1612
+ /** 请求 ID */
1613
+ requestId: string;
1614
+ }
1615
+ /**
1616
+ * 中间件函数
1617
+ *
1618
+ * 遵循洋葱模型:调用 `next()` 前执行前置逻辑,调用后执行后置逻辑。
1619
+ * @example
1620
+ * ```ts
1621
+ * import type { Middleware } from '@h-ai/kit'
1622
+ *
1623
+ * const value: Middleware = async (_context, next) => { const response = await next(); response.headers.set('X-Example', 'enabled'); return response }
1624
+ * void value
1625
+ * ```
1626
+ */
1627
+ type Middleware = (context: MiddlewareContext, next: () => Promise<Response>) => Promise<Response>;
1628
+ /**
1629
+ * 路由守卫结果
1630
+ *
1631
+ * 守卫函数必须返回此结构。`allowed: true` 表示放行,否则根据
1632
+ * `redirect` / `message` / `status` 决定拦截行为。
1633
+ * @example
1634
+ * ```ts
1635
+ * import type { GuardResult } from '@h-ai/kit'
1636
+ *
1637
+ * const value: GuardResult = { allowed: false, status: 403 }
1638
+ * void value
1639
+ * ```
1640
+ */
1641
+ interface GuardResult {
1642
+ /** 是否允许访问 */
1643
+ allowed: boolean;
1644
+ /** 重定向 URL(拒绝时) */
1645
+ redirect?: string;
1646
+ /** 错误消息(拒绝时) */
1647
+ message?: string;
1648
+ /** HTTP 状态码 */
1649
+ status?: number;
1650
+ }
1651
+ /**
1652
+ * 路由守卫函数
1653
+ *
1654
+ * 接收请求事件与可选会话,返回 `GuardResult`(同步或异步均可)。
1655
+ * @example
1656
+ * ```ts
1657
+ * import type { RouteGuard } from '@h-ai/kit'
1658
+ *
1659
+ * const value: RouteGuard = (_event, session) => ({ allowed: session?.permissions.includes('article:read') ?? false, status: 403 })
1660
+ * void value
1661
+ * ```
1662
+ */
1663
+ type RouteGuard = (event: RequestEvent, session?: SessionData) => Promise<GuardResult> | GuardResult;
1664
+ /**
1665
+ * 守卫配置
1666
+ *
1667
+ * 在 `createHandle({ guards })` 中使用。
1668
+ * `paths` 支持 `/*` 和 `/**` 通配符,`exclude` 优先于 `paths`。
1669
+ * @example
1670
+ * ```ts
1671
+ * import type { GuardConfig } from '@h-ai/kit'
1672
+ *
1673
+ * const value: GuardConfig = { paths: ['/admin/**'], guard: (_event, session) => ({ allowed: Boolean(session) }) }
1674
+ * void value
1675
+ * ```
1676
+ */
1677
+ interface GuardConfig {
1678
+ /** 守卫函数 */
1679
+ guard: RouteGuard;
1680
+ /** 适用路径(glob 模式) */
1681
+ paths?: string[];
1682
+ /** 排除路径 */
1683
+ exclude?: string[];
1684
+ }
1685
+ /**
1686
+ * 认证配置
1687
+ *
1688
+ * 在 `HandleConfig.auth` 中使用,自动完成:
1689
+ * 1. 从 Bearer header / Cookie 提取 Token
1690
+ * 2. 调用 verifyToken 恢复会话
1691
+ * 3. 根据 protectedPaths / publicPaths 自动生成路由守卫
1692
+ *
1693
+ * API 路径(以 `/api/` 开头)未认证时返回 401 JSON;
1694
+ * 非 API 路径未认证时重定向到 `loginUrl`(若配置)或返回 401。
1695
+ * @example
1696
+ * ```ts
1697
+ * import type { HandleAuthConfig } from '@h-ai/kit'
1698
+ *
1699
+ * const value: HandleAuthConfig = { verifyToken: async () => null, protectedPaths: ['/admin/**'], loginUrl: '/auth/login' }
1700
+ * void value
1701
+ * ```
1702
+ */
1703
+ interface HandleAuthConfig {
1704
+ /** 令牌验证函数,返回 SessionData 或 null */
1705
+ verifyToken: (token: string) => Promise<SessionData | null>;
1706
+ /**
1707
+ * 认证操作。
1708
+ *
1709
+ * - 直接对象:`operations: iam.auth`
1710
+ * - 工厂函数:`operations: () => iam.auth`(推荐,避免模块加载阶段捕获旧引用)
1711
+ */
1712
+ operations?: AuthOperationsProvider;
1713
+ /** 未认证时 UI 路由重定向地址(如 `'/auth/login'`) */
1714
+ loginUrl?: string;
1715
+ /** Token Cookie 名(默认 `'hai_access_token'`) */
1716
+ cookieName?: string;
1717
+ /** 需要认证的路径(支持 `/*` `/**` 通配符) */
1718
+ protectedPaths?: string[];
1719
+ /** 免认证的路径(优先于 protectedPaths) */
1720
+ publicPaths?: string[];
1721
+ }
1722
+ /**
1723
+ * Handle Hook 配置
1724
+ *
1725
+ * 传给 `kit.createHandle()` 的配置。
1726
+ *
1727
+ * 自动完成:
1728
+ * 1. 生成 requestId 并注入 `event.locals`
1729
+ * 2. 根据 `auth` 配置解析会话
1730
+ * 3. 执行路由守卫
1731
+ * 4. 执行中间件链(logging / rateLimit / 自定义)
1732
+ * 5. 调用 resolve + 附加 `X-Request-Id` 响应头
1733
+ * @example
1734
+ * ```ts
1735
+ * import type { HandleConfig } from '@h-ai/kit'
1736
+ *
1737
+ * const value: HandleConfig = { logging: true, auth: { verifyToken: async () => null, protectedPaths: ['/admin/**'] } }
1738
+ * void value
1739
+ * ```
1740
+ */
1741
+ interface HandleConfig {
1742
+ /** 可信入口地址;auto 只信任受管私有容器网段,空数组忽略转发头。 */
1743
+ trustedProxies?: TrustedProxies;
1744
+ /** 每次请求的 IP/时间/路径策略;独立文件在创建 Handle 时读取并验证一次。 */
1745
+ access?: RequestAccessConfigInput;
1746
+ /**
1747
+ * 认证配置
1748
+ *
1749
+ * 提供后自动完成 Token 解析、会话恢复、路由守卫等。
1750
+ * 不提供则不做认证处理。
1751
+ */
1752
+ auth?: HandleAuthConfig;
1753
+ /**
1754
+ * 速率限制配置
1755
+ *
1756
+ * 提供对象启用速率限制;设为 `false` 显式禁用。
1757
+ * 不提供则不开启速率限制。
1758
+ */
1759
+ rateLimit?: Omit<RateLimitConfig, 'windowMs' | 'maxRequests'> & {
1760
+ windowMs?: number;
1761
+ maxRequests?: number;
1762
+ } | false;
1763
+ /**
1764
+ * 请求日志配置
1765
+ *
1766
+ * - `true`(默认):启用日志中间件
1767
+ * - `{ logBody: true }`:启用并记录请求体
1768
+ * - `false`:禁用日志
1769
+ */
1770
+ logging?: boolean | {
1771
+ logBody?: boolean;
1772
+ };
1773
+ /**
1774
+ * 加密配置(传输加密 + Cookie 加密)
1775
+ *
1776
+ * 启用后 kit 自动在 Handle 中完成:
1777
+ * - 传输加密:请求体解密 / 响应体加密 / 密钥交换端点
1778
+ * - Cookie 加密:对指定 Cookie 的 get/set 使用 SM4-CBC 加解密并验证 HMAC-SHA256 认证
1779
+ */
1780
+ crypto?: HookCryptoConfig;
1781
+ /** 自定义错误处理(不提供则使用内置的 500 JSON 响应) */
1782
+ onError?: (error: unknown, event: RequestEvent) => Response | Promise<Response>;
1783
+ /** 自定义守卫(在 auth 自动守卫之后执行) */
1784
+ guards?: GuardConfig[];
1785
+ /** 自定义中间件(在内置 logging / rateLimit 之后执行) */
1786
+ middleware?: Middleware[];
1787
+ /**
1788
+ * A2A 协议集成
1789
+ *
1790
+ * 传入 `ai.a2a` 操作对象后,自动挂载 Agent Card 发现端点和 JSON-RPC 处理端点。
1791
+ *
1792
+ * - 简单模式:`a2a: ai.a2a`(使用默认路径)
1793
+ * - 配置模式:`a2a: { operations: ai.a2a, rpcPath: '/api/a2a' }`
1794
+ */
1795
+ a2a?: HandleA2AOperations | HandleA2AConfig;
1796
+ }
1797
+ /**
1798
+ * A2A 操作接口(用于 Handle 集成)
1799
+ *
1800
+ * 与 `ai.a2a` 结构兼容,可直接传入 `ai.a2a` 对象。
1801
+ * @example
1802
+ * ```ts
1803
+ * import type { HandleA2AOperations } from '@h-ai/kit'
1804
+ * import { ai } from '@h-ai/ai'
1805
+ *
1806
+ * function operationsAfterInit(): HandleA2AOperations { return ai.a2a }
1807
+ * ```
1808
+ */
1809
+ interface HandleA2AOperations {
1810
+ /** 获取 Agent Card(返回 HaiResult 对象) */
1811
+ getAgentCard: () => {
1812
+ success: boolean;
1813
+ data?: unknown;
1814
+ error?: unknown;
1815
+ };
1816
+ /** 处理 JSON-RPC 请求 */
1817
+ handleRequest: (body: unknown, context?: Record<string, unknown>) => Promise<{
1818
+ streaming: boolean;
1819
+ body?: unknown;
1820
+ stream?: AsyncGenerator<unknown, void, undefined>;
1821
+ }>;
1822
+ }
1823
+ /**
1824
+ * A2A Handle 配置(高级模式)
1825
+ * @example
1826
+ * ```ts
1827
+ * import type { HandleA2AConfig } from '@h-ai/kit'
1828
+ * import { ai } from '@h-ai/ai'
1829
+ *
1830
+ * function configAfterInit(): HandleA2AConfig { return { operations: ai.a2a, authenticate: async () => null } }
1831
+ * ```
1832
+ */
1833
+ interface HandleA2AConfig {
1834
+ /** A2A 操作接口(通常传入 `ai.a2a`) */
1835
+ operations: HandleA2AOperations;
1836
+ /** Agent Card 端点路径(默认 `/.well-known/agent-card.json`) */
1837
+ cardPath?: string;
1838
+ /** JSON-RPC 端点路径(默认 `/a2a`) */
1839
+ rpcPath?: string;
1840
+ /**
1841
+ * A2A 认证
1842
+ *
1843
+ * - `'apiKey'`:使用 IAM API Key 认证(读取 Agent Card.securitySchemes.apiKey)
1844
+ * - 函数:自定义认证回调;返回 null/undefined 拒绝请求(401)
1845
+ * 未配置此项才允许匿名请求。
1846
+ */
1847
+ authenticate?: 'apiKey' | ((event: RequestEvent) => Promise<Record<string, unknown> | null | undefined>);
1848
+ }
1849
+ /**
1850
+ * 传输加密详细配置
1851
+ * @example
1852
+ * ```ts
1853
+ * import type { TransportEncryptionOptions } from '@h-ai/kit'
1854
+ * import type { TransportServerKeyRing, TransportKeyStore } from '@h-ai/crypto'
1855
+ *
1856
+ * function transport(serverKeyRing: TransportServerKeyRing, keyStore: TransportKeyStore): TransportEncryptionOptions {
1857
+ * return { serverKeyRing, keyStore, excludePaths: ['/api/health'] }
1858
+ * }
1859
+ * ```
1860
+ */
1861
+ interface TransportEncryptionOptions {
1862
+ /** 宿主构建挂载目录,默认空字符串;SvelteKit 传入 paths.relative=false 时的 resolve('/').replace(/\/$/, '')。 */
1863
+ basePath?: string;
1864
+ /** 双向业务明文 UTF-8 字节上限;默认 1 MiB,整数范围 1 KiB~64 MiB。 */
1865
+ maxPlaintextBytes?: number;
1866
+ /** 请求时间允许领先服务器的秒数,默认 30,整数范围 0~300。 */
1867
+ maxFutureSkewSeconds?: number;
1868
+ /** 请求从签发起的有效秒数,默认 300,整数范围 1~600。 */
1869
+ maxRequestAgeSeconds?: number;
1870
+ /** 路由明文容量;* 匹配一个完整路径段。 */
1871
+ routePlaintextBytes?: Readonly<Record<string, number>>;
1872
+ /** 受管服务端版本化密钥环,不进入公开 YAML/客户端配置。 */
1873
+ serverKeyRing: TransportServerKeyRing;
1874
+ /** 密钥交换端点路径(默认 `'/api/_hai/key-exchange'`) */
1875
+ keyExchangePath?: string;
1876
+ /** 排除路径(不加密),支持精确匹配和前缀匹配 */
1877
+ excludePaths?: readonly string[];
1878
+ /** 共享客户端公钥存储;适用于多节点部署。 */
1879
+ keyStore: TransportKeyStore;
1880
+ }
1881
+ /**
1882
+ * Handle Hook 加密配置
1883
+ *
1884
+ * 在 `kit.createHandle({ crypto: { ... } })` 中使用。
1885
+ * @example
1886
+ * ```ts
1887
+ * import type { HookCryptoConfig, TransportEncryptionOptions } from '@h-ai/kit'
1888
+ * import { crypto } from '@h-ai/crypto'
1889
+ *
1890
+ * function config(transport: TransportEncryptionOptions): HookCryptoConfig { return { crypto, transport } }
1891
+ * ```
1892
+ */
1893
+ interface HookCryptoConfig {
1894
+ /** 注入 @h-ai/crypto 实例 */
1895
+ crypto: CryptoFunctions;
1896
+ /**
1897
+ * 启用传输加密。
1898
+ * - `false` 或省略:关闭
1899
+ * - 对象:必填受管 serverKeyRing / keyStore,可附加公开路径配置
1900
+ */
1901
+ transport?: false | TransportEncryptionOptions;
1902
+ /**
1903
+ * 需要加密的 Cookie 名称列表
1904
+ *
1905
+ * 列出的 Cookie 在 set 时自动 SM4-CBC 加密,get 时自动解密。
1906
+ */
1907
+ encryptedCookies?: string[];
1908
+ /**
1909
+ * Cookie 加密密钥(32 字符十六进制 = 16 字节 SM4 密钥)
1910
+ *
1911
+ * 如不提供,则从环境变量 `HAI_KIT_COOKIE_KEY` 读取。
1912
+ * 配置了 `encryptedCookies` 但两者都未设置时,`kit.createHandle()` 会立即抛出配置错误,
1913
+ * 避免受保护 Cookie 静默降级为明文。
1914
+ */
1915
+ cookieEncryptionKey?: string;
1916
+ }
1917
+ /**
1918
+ * API 响应包装
1919
+ *
1920
+ * `kit.response.*` 系列函数统一返回此结构的 JSON 响应。
1921
+ * 成功时 `success: true` 且 `data` 有值;失败时 `success: false` 且 `error` 有值。
1922
+ * @example
1923
+ * ```ts
1924
+ * import type { ApiResponse } from '@h-ai/kit'
1925
+ *
1926
+ * const value: ApiResponse<{ id: string }> = { success: true, data: { id: 'article_1' } }
1927
+ * void value
1928
+ * ```
1929
+ */
1930
+ interface ApiResponse<T = unknown> {
1931
+ /** 是否成功 */
1932
+ success: boolean;
1933
+ /** 数据 */
1934
+ data?: T;
1935
+ /** 错误信息 */
1936
+ error?: {
1937
+ code: string;
1938
+ message: string;
1939
+ traceId?: string;
1940
+ /** 对应 HTTP 状态 */
1941
+ httpStatus?: number;
1942
+ /** 仅含已本地化 field/message 的字段校验信息 */
1943
+ cause?: HaiError['cause'];
1944
+ /** 经公开边界脱敏的扩展信息 */
1945
+ ext?: HaiError['ext'];
1946
+ details?: unknown;
1947
+ };
1948
+ /** 请求 ID */
1949
+ requestId?: string;
1950
+ }
1951
+ /**
1952
+ * 表单验证错误
1953
+ *
1954
+ * 由 `kit.validate.*` 在校验失败时返回。
1955
+ * `field` 使用点号路径(如 `'address.city'`),`_` 表示全局错误。
1956
+ * @example
1957
+ * ```ts
1958
+ * import type { FormError } from '@h-ai/kit'
1959
+ *
1960
+ * const value: FormError = { field: 'title', message: 'Title is required' }
1961
+ * void value
1962
+ * ```
1963
+ */
1964
+ interface FormError {
1965
+ /** 字段名 */
1966
+ field: string;
1967
+ /** 错误消息 */
1968
+ message: string;
1969
+ }
1970
+ /**
1971
+ * 表单验证结果
1972
+ *
1973
+ * @template T - Zod schema 推导出的数据类型
1974
+ * @example
1975
+ * ```ts
1976
+ * import type { FormValidationResult } from '@h-ai/kit'
1977
+ *
1978
+ * const value: FormValidationResult<{ title: string }> = { valid: true, data: { title: 'Example' }, errors: [] }
1979
+ * void value
1980
+ * ```
1981
+ */
1982
+ interface FormValidationResult<T> {
1983
+ /** 是否有效 */
1984
+ valid: boolean;
1985
+ /** 解析后的数据 */
1986
+ data?: T;
1987
+ /** 错误列表 */
1988
+ errors: FormError[];
1989
+ }
1990
+ /**
1991
+ * 速率限制配置
1992
+ *
1993
+ * 基于可插拔原子存储的固定窗口限流。超限后返回 429 状态码与 `Retry-After` 响应头。
1994
+ * 必须显式传入 store;生产使用共享计数器,故障返回503。
1995
+ * @example
1996
+ * ```ts
1997
+ * import type { RateLimitConfig } from '@h-ai/kit'
1998
+ * import { kit } from '@h-ai/kit'
1999
+ * import { cache } from '@h-ai/cache'
2000
+ *
2001
+ * const config: RateLimitConfig = { windowMs: 60_000, maxRequests: 100, store: kit.middleware.createCacheRateLimitStore(cache, { namespace: 'api' }) }
2002
+ * void config
2003
+ * ```
2004
+ */
2005
+ interface RateLimitConfig {
2006
+ /** 时间窗口 (ms) */
2007
+ windowMs: number;
2008
+ /** 最大请求数 */
2009
+ maxRequests: number;
2010
+ /** 自定义 key 生成 */
2011
+ keyGenerator?: (event: RequestEvent) => string;
2012
+ /** 超限处理 */
2013
+ onLimitReached?: (event: RequestEvent) => Response;
2014
+ /**
2015
+ * 自定义存储实现
2016
+ *
2017
+ * 必须提供原子 increment;不支持 get+set 回退。共享缓存由调用方初始化和关闭。
2018
+ */
2019
+ store: RateLimitStore;
2020
+ }
2021
+ /**
2022
+ * CORS 中间件配置
2023
+ *
2024
+ * 配置跨域资源共享策略。预检请求(OPTIONS)自动返回 204。
2025
+ * @example
2026
+ * ```ts
2027
+ * import type { CorsConfig } from '@h-ai/kit'
2028
+ *
2029
+ * const value: CorsConfig = { origin: ['https://app.example.com'], credentials: true }
2030
+ * void value
2031
+ * ```
2032
+ */
2033
+ interface CorsConfig {
2034
+ /** 允许的源(支持通配符,如 `*.example.com`) */
2035
+ origin?: string | string[] | ((origin: string) => boolean);
2036
+ /** 允许的方法 */
2037
+ methods?: string[];
2038
+ /** 允许的头 */
2039
+ allowedHeaders?: string[];
2040
+ /** 暴露的头 */
2041
+ exposedHeaders?: string[];
2042
+ /** 是否允许凭证 */
2043
+ credentials?: boolean;
2044
+ /** 预检缓存时间 (秒) */
2045
+ maxAge?: number;
2046
+ /** 是否自动允许 Capacitor WebView origin(默认 true) */
2047
+ capacitor?: boolean;
2048
+ }
2049
+
2050
+ export { MemoryRateLimitStore as $, IdParamSchema as _, PaginationQuerySchema as a0, defineCrud as a5, matchPermission as a6, resolveOptions as a7, resolveText as a8, createKitAuthActions as v, createKitClient as w, installBrowserTransport as x, installBrowserTransportFetch as y };
2051
+ export type { ApiResponse as A, BrowserKitFunctions as B, ClientTransportConfig as C, AuthCookieWriter as D, CrudApiDef as E, FormError as F, GuardConfig as G, HaiRequestEvent as H, CrudFieldDef as I, CrudFieldOption as J, KitClient as K, CrudFieldOptions as L, Middleware as M, CrudFieldType as N, CrudFieldValidation as O, CrudFilterParams as P, CrudOperations as Q, RateLimitConfig as R, SessionData as S, TransportEncryptionOptions as T, CrudPaginatedResult as U, CrudPaginationParams as V, CrudResourceDef as W, CrudTableColumn as X, CrudText as Y, FeedbackHandlerOptions as Z, AuthOperations as a, PermissionGuardConfig as a1, RateLimitCache as a2, RateLimitEntry as a3, RateLimitStore as a4, AuthOperationsProvider as b, CorsConfig as c, FormValidationResult as d, GuardResult as e, HandleA2AConfig as f, HandleA2AOperations as g, HandleAuthConfig as h, HandleConfig as i, HookCryptoConfig as j, KitClientConfig as k, KitConfig as l, KitConfigInput as m, KitPublicConfig as n, KitServerConfig as o, KitServerConfigInput as p, KitTransportConfig as q, KitTransportConfigInput as r, MiddlewareContext as s, RouteGuard as t, SessionLike as u, KitFunctions as z };