@longzai-intelligence-auth/elysia 0.0.5 → 0.0.6

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.
package/dist/index.d.ts CHANGED
@@ -1,32 +1,122 @@
1
1
  import { DomainError } from "@longzai-intelligence/error";
2
- import { JwtConfig, LoggerService, RateLimiterPort, ResourceAction, TenantValidateFn, TokenVerifierPort, UnifiedAuthContext, UnifiedAuthContext as UnifiedAuthContext$1 } from "@longzai-intelligence-auth/core";
2
+ import { JwtConfig, LoggerService, RateLimiterPort, ResourceAction, TokenVerifierPort, UnifiedAuthContext, UnifiedAuthContext as UnifiedAuthContext$1 } from "@longzai-intelligence-auth/core";
3
3
  import { Elysia } from "elysia";
4
4
  import { z } from "zod";
5
5
 
6
6
  //#region src/core/error-mapper.d.ts
7
- /** 根据 DomainError 类型映射 HTTP 状态码 */
7
+ /**
8
+ * 根据 DomainError 类型映射 HTTP 状态码
9
+ *
10
+ * @param error - 领域错误实例
11
+ * @returns 对应的 HTTP 状态码
12
+ */
8
13
  declare function mapDomainErrorToStatus(error: DomainError): number;
9
14
  //#endregion
15
+ //#region src/verifiers/static-token-verifier.d.ts
16
+ /**
17
+ * 静态令牌验证器配置
18
+ */
19
+ type StaticTokenVerifierOptions = {
20
+ /**
21
+ * 静态令牌(与 getToken 至少提供一个)
22
+ */
23
+ token?: string;
24
+ /**
25
+ * 动态获取令牌的回调,优先级高于 token
26
+ * 用于运行时从 secret manager / env 缓存等来源解析令牌
27
+ */
28
+ getToken?: () => string | null;
29
+ /**
30
+ * 验证通过后填充到 AccessTokenPayload.sub 中的主体标识
31
+ * 默认 "static"
32
+ */
33
+ subject?: string;
34
+ /**
35
+ * 验证通过后填充到 AccessTokenPayload.tenantId 中的租户标识
36
+ * 默认不设置
37
+ */
38
+ tenantId?: string;
39
+ };
40
+ /**
41
+ * 创建静态令牌验证器
42
+ *
43
+ * @param options - 静态令牌验证器配置
44
+ * @returns 实现 TokenVerifierPort 的静态令牌验证器
45
+ */
46
+ declare function createStaticTokenVerifier(options: StaticTokenVerifierOptions): TokenVerifierPort;
47
+ //#endregion
10
48
  //#region src/plugins/jwt-verify.plugin.d.ts
11
49
  /** JWT 验证插件解析后的认证上下文 */
12
50
  type VerifiedAuthContext = {
13
- /** 用户 ID(来自 payload.sub) */userId: string; /** 租户 ID(来自 payload.tenantId,默认使用 defaultTenantId) */
14
- tenantId: string; /** 角色列表 */
15
- roles: string[]; /** 权限列表 */
16
- permissions: string[]; /** JWT ID(用于 token 黑名单检查) */
51
+ /**
52
+ * 用户 ID(来自 payload.sub)
53
+ */
54
+ userId: string;
55
+ /**
56
+ * 租户 ID(来自 payload.tenantId,默认使用 defaultTenantId)
57
+ */
58
+ tenantId: string;
59
+ /**
60
+ * 角色列表
61
+ */
62
+ roles: string[];
63
+ /**
64
+ * 权限列表
65
+ */
66
+ permissions: string[];
67
+ /**
68
+ * JWT ID(用于 token 黑名单检查)
69
+ */
17
70
  jti?: string;
18
71
  };
72
+ /**
73
+ * JWT 验证插件配置选项
74
+ *
75
+ * @typeParam T - 扩展 schema 类型,用于从 payload 中解析自定义业务字段
76
+ */
19
77
  type JwtVerifyPluginOptions<T extends z.ZodTypeAny = z.ZodUndefined> = {
20
- /** 令牌验证器端口(用户注入,与 jwt 二选一) */verifier?: TokenVerifierPort; /** JWT 配置(与 verifier 二选一,未提供时使用默认配置) */
21
- jwt?: JwtConfig; /** 默认租户 ID */
22
- defaultTenantId?: string; /** 跳过认证的路径列表(精确匹配或前缀匹配,如 "/api/public/*") */
23
- publicPaths?: string[]; /** 扩展 schema,用于从 payload 中解析自定义业务字段 */
78
+ /**
79
+ * 令牌验证器端口(用户注入,与 jwt 二选一)
80
+ */
81
+ verifier?: TokenVerifierPort;
82
+ /**
83
+ * JWT 配置(与 verifier 二选一,未提供时使用默认配置)
84
+ */
85
+ jwt?: JwtConfig;
86
+ /**
87
+ * 默认租户 ID
88
+ */
89
+ defaultTenantId?: string;
90
+ /**
91
+ * 跳过认证的路径列表(精确匹配或前缀匹配,如 "/api/public/*")
92
+ */
93
+ publicPaths?: string[];
94
+ /**
95
+ * 扩展 schema,用于从 payload 中解析自定义业务字段
96
+ */
24
97
  extendSchema?: T;
25
98
  };
26
- /** 从 extendSchema 提取额外字段类型 */
99
+ /**
100
+ * 从 extendSchema 提取额外字段类型
101
+ *
102
+ * @typeParam T - 扩展 schema 类型,用于推断额外的业务字段类型
103
+ */
27
104
  type ExtractExtra<T extends z.ZodTypeAny> = T extends z.ZodUndefined ? Record<string, never> : z.infer<T>;
28
- /** 完整的认证上下文类型(基础字段 + 扩展字段) */
105
+ /**
106
+ * 完整的认证上下文类型(基础字段 + 扩展字段)
107
+ *
108
+ * @typeParam T - 扩展 schema 类型,用于推断额外的业务字段类型
109
+ */
29
110
  type AuthContextWithExtra<T extends z.ZodTypeAny = z.ZodUndefined> = VerifiedAuthContext & ExtractExtra<T>;
111
+ /**
112
+ * 创建 JWT 验证插件
113
+ *
114
+ * 该插件从请求头中提取 Bearer token 并验证,验证失败时抛出异常。
115
+ *
116
+ * @typeParam T - 扩展 schema 类型,用于从 payload 中解析自定义业务字段
117
+ * @param options - 插件配置选项
118
+ * @returns Elysia 插件实例
119
+ */
30
120
  declare function createJwtVerifyPlugin<T extends z.ZodTypeAny = z.ZodUndefined>(options: JwtVerifyPluginOptions<T>): Elysia<"", {
31
121
  decorator: {};
32
122
  store: {};
@@ -61,16 +151,46 @@ declare function createJwtVerifyPlugin<T extends z.ZodTypeAny = z.ZodUndefined>(
61
151
  }>;
62
152
  //#endregion
63
153
  //#region src/plugins/optional-jwt.plugin.d.ts
154
+ /**
155
+ * 可选 JWT 认证插件配置选项
156
+ *
157
+ * @typeParam T - 扩展 schema 类型,用于从 payload 中解析自定义业务字段
158
+ */
64
159
  type OptionalJwtPluginOptions<T extends z.ZodTypeAny = z.ZodUndefined> = {
65
- /** 令牌验证器端口(用户注入,与 jwt 二选一) */verifier?: TokenVerifierPort; /** JWT 配置(与 verifier 二选一,未提供时使用默认配置) */
66
- jwt?: JwtConfig; /** 默认租户 ID */
67
- defaultTenantId?: string; /** 扩展 schema,用于从 payload 中解析自定义业务字段 */
160
+ /**
161
+ * 令牌验证器端口(用户注入,与 jwt 二选一)
162
+ */
163
+ verifier?: TokenVerifierPort;
164
+ /**
165
+ * JWT 配置(与 verifier 二选一,未提供时使用默认配置)
166
+ */
167
+ jwt?: JwtConfig;
168
+ /**
169
+ * 默认租户 ID
170
+ */
171
+ defaultTenantId?: string;
172
+ /**
173
+ * 扩展 schema,用于从 payload 中解析自定义业务字段
174
+ */
68
175
  extendSchema?: T;
69
176
  };
70
- /** 可选认证上下文,auth 为 null 表示未认证 */
177
+ /**
178
+ * 可选认证上下文,auth 为 null 表示未认证
179
+ *
180
+ * @typeParam T - 扩展 schema 类型,用于推断额外的业务字段类型
181
+ */
71
182
  type OptionalAuthContext<T extends z.ZodTypeAny = z.ZodUndefined> = {
72
183
  auth: (UnifiedAuthContext$1 & (T extends z.ZodUndefined ? Record<string, never> : z.infer<T>)) | null;
73
184
  };
185
+ /**
186
+ * 创建可选 JWT 认证插件
187
+ *
188
+ * 该插件从请求头中提取 Bearer token 并验证,如果验证失败或无 token 则返回 null 认证上下文。
189
+ *
190
+ * @typeParam T - 扩展 schema 类型,用于从 payload 中解析自定义业务字段
191
+ * @param options - 插件配置选项
192
+ * @returns Elysia 插件实例
193
+ */
74
194
  declare function createOptionalJwtPlugin<T extends z.ZodTypeAny = z.ZodUndefined>(options: OptionalJwtPluginOptions<T>): Elysia<"", {
75
195
  decorator: {};
76
196
  store: {};
@@ -107,11 +227,26 @@ declare function createOptionalJwtPlugin<T extends z.ZodTypeAny = z.ZodUndefined
107
227
  //#region src/plugins/rbac.plugin.d.ts
108
228
  /** 用户角色策略接口,用于数据库查询权限 */
109
229
  type UserRoleStrategy = {
110
- /** 查询用户在指定租户下的所有权限 */findPermissionsByUserId(userId: string, tenantId: string): Promise<ResourceAction[]>;
230
+ /**
231
+ * 查询用户在指定租户下的所有权限
232
+ */
233
+ findPermissionsByUserId(userId: string, tenantId: string): Promise<ResourceAction[]>;
111
234
  };
235
+ /**
236
+ * RBAC 插件配置选项
237
+ */
112
238
  type RbacPluginOptions = {
113
- /** 用户角色策略(用于数据库查询权限,优先于上下文权限) */userRole?: UserRoleStrategy;
239
+ /**
240
+ * 用户角色策略(用于数据库查询权限,优先于上下文权限)
241
+ */
242
+ userRole?: UserRoleStrategy;
114
243
  };
244
+ /**
245
+ * 创建 RBAC 插件
246
+ *
247
+ * @param options - 插件配置选项
248
+ * @returns Elysia 插件实例
249
+ */
115
250
  declare function createRbacPlugin(options?: RbacPluginOptions): Elysia<"", {
116
251
  decorator: {};
117
252
  store: {};
@@ -148,15 +283,42 @@ declare function createRbacPlugin(options?: RbacPluginOptions): Elysia<"", {
148
283
  //#region src/plugins/api-key.plugin.d.ts
149
284
  /** API Key 认证的主体信息 */
150
285
  type ApiKeyPrincipal = {
151
- /** 主体标识 */principalId: string; /** 租户 ID */
152
- tenantId?: string; /** 角色列表 */
153
- roles: string[]; /** 权限列表 */
286
+ /**
287
+ * 主体标识
288
+ */
289
+ principalId: string;
290
+ /**
291
+ * 租户 ID
292
+ */
293
+ tenantId?: string;
294
+ /**
295
+ * 角色列表
296
+ */
297
+ roles: string[];
298
+ /**
299
+ * 权限列表
300
+ */
154
301
  permissions: string[];
155
302
  };
303
+ /**
304
+ * API Key 认证插件配置选项
305
+ */
156
306
  type ApiKeyPluginOptions = {
157
- /** API Key 所在的请求头名称(默认 "x-api-key") */header?: string; /** API Key 验证器,返回 null 表示无效 */
307
+ /**
308
+ * API Key 所在的请求头名称(默认 "x-api-key")
309
+ */
310
+ header?: string;
311
+ /**
312
+ * API Key 验证器,返回 null 表示无效
313
+ */
158
314
  validator: (key: string) => Promise<ApiKeyPrincipal | null>;
159
315
  };
316
+ /**
317
+ * 创建 API Key 认证插件
318
+ *
319
+ * @param options - 插件配置选项
320
+ * @returns Elysia 插件实例
321
+ */
160
322
  declare function createApiKeyPlugin(options: ApiKeyPluginOptions): Elysia<"", {
161
323
  decorator: {};
162
324
  store: {};
@@ -193,9 +355,21 @@ declare function createApiKeyPlugin(options: ApiKeyPluginOptions): Elysia<"", {
193
355
  //#region src/plugins/in-memory-api-key-validator.d.ts
194
356
  /** 内存 API Key 映射条目 */
195
357
  type InMemoryApiKeyEntry = {
196
- /** 主体标识 */principalId: string; /** 租户ID(可选) */
197
- tenantId?: string; /** 角色列表 */
198
- roles: string[]; /** 权限列表 */
358
+ /**
359
+ * 主体标识
360
+ */
361
+ principalId: string;
362
+ /**
363
+ * 租户ID(可选)
364
+ */
365
+ tenantId?: string;
366
+ /**
367
+ * 角色列表
368
+ */
369
+ roles: string[];
370
+ /**
371
+ * 权限列表
372
+ */
199
373
  permissions: string[];
200
374
  };
201
375
  /** 内存 API Key 映射表 */
@@ -203,22 +377,55 @@ type InMemoryApiKeyMap = Record<string, InMemoryApiKeyEntry>;
203
377
  /**
204
378
  * 创建内存 API Key 验证器
205
379
  * 接受静态 API Key 映射,返回符合 createApiKeyPlugin 的 validator 函数
380
+ *
206
381
  * @param keyMap - API Key 到主体信息的映射
207
382
  * @returns validator 函数
208
383
  */
209
384
  declare function createInMemoryApiKeyValidator(keyMap: InMemoryApiKeyMap): (key: string) => Promise<ApiKeyPrincipal | null>;
210
385
  //#endregion
211
386
  //#region src/plugins/composite-auth.plugin.d.ts
387
+ /**
388
+ * 组合认证插件配置选项
389
+ *
390
+ * 支持多种认证方式(JWT 和 API Key),优先尝试 JWT 认证。
391
+ */
212
392
  type CompositeAuthPluginOptions = {
213
- /** 令牌验证器端口(用户注入,与 jwt 二选一) */verifier?: TokenVerifierPort; /** JWT 配置(与 verifier 二选一,未提供时使用默认配置) */
214
- jwt?: JwtConfig; /** 默认租户 ID */
215
- defaultTenantId?: string; /** API Key 验证器 */
216
- apiKeyValidator?: (key: string) => Promise<ApiKeyPrincipal | null>; /** API Key 所在的请求头名称(默认 "x-api-key") */
217
- apiKeyHeader?: string; /** 跳过认证的路径列表(精确匹配或前缀匹配,如 "/api/public/*") */
393
+ /**
394
+ * 令牌验证器端口(用户注入,与 jwt 二选一)
395
+ */
396
+ verifier?: TokenVerifierPort;
397
+ /**
398
+ * JWT 配置(与 verifier 二选一,未提供时使用默认配置)
399
+ */
400
+ jwt?: JwtConfig;
401
+ /**
402
+ * 默认租户 ID
403
+ */
404
+ defaultTenantId?: string;
405
+ /**
406
+ * API Key 验证器
407
+ */
408
+ apiKeyValidator?: (key: string) => Promise<ApiKeyPrincipal | null>;
409
+ /**
410
+ * API Key 所在的请求头名称(默认 "x-api-key")
411
+ */
412
+ apiKeyHeader?: string;
413
+ /**
414
+ * 跳过认证的路径列表(精确匹配或前缀匹配,如 "/api/public/*")
415
+ */
218
416
  publicPaths?: string[];
219
417
  };
220
418
  /** 组合认证上下文(向后兼容,内部使用 UnifiedAuthContext) */
221
419
  type CompositeAuthContext = UnifiedAuthContext$1;
420
+ /**
421
+ * 创建组合认证插件
422
+ *
423
+ * 该插件支持多种认证方式(JWT 和 API Key),优先尝试 JWT 认证,
424
+ * 如果 JWT 认证失败则尝试 API Key 认证,未认证时返回 null。
425
+ *
426
+ * @param options - 插件配置选项
427
+ * @returns Elysia 插件实例
428
+ */
222
429
  declare function createCompositeAuthPlugin(options: CompositeAuthPluginOptions): Elysia<"", {
223
430
  decorator: {};
224
431
  store: {};
@@ -251,7 +458,12 @@ declare function createCompositeAuthPlugin(options: CompositeAuthPluginOptions):
251
458
  standaloneSchema: {};
252
459
  response: {};
253
460
  }>;
254
- /** 创建要求认证的组合认证插件(未认证时抛出异常) */
461
+ /**
462
+ * 创建要求认证的组合认证插件(未认证时抛出异常)
463
+ *
464
+ * @param options - 插件配置选项
465
+ * @returns Elysia 插件实例
466
+ */
255
467
  declare function createRequiredCompositeAuthPlugin(options: CompositeAuthPluginOptions): Elysia<"", {
256
468
  decorator: {};
257
469
  store: {};
@@ -285,50 +497,30 @@ declare function createRequiredCompositeAuthPlugin(options: CompositeAuthPluginO
285
497
  response: {};
286
498
  }>;
287
499
  //#endregion
288
- //#region src/plugins/tenant.plugin.d.ts
289
- type TenantPluginOptions = {
290
- /** 默认租户 ID */defaultTenantId?: string; /** 租户验证函数 */
291
- validateFn?: TenantValidateFn;
292
- };
293
- declare function createTenantPlugin(options?: TenantPluginOptions): Elysia<"", {
294
- decorator: {};
295
- store: {};
296
- derive: {
297
- tenantId: string;
298
- };
299
- resolve: {};
300
- }, {
301
- typebox: {};
302
- error: {};
303
- }, {
304
- schema: {};
305
- standaloneSchema: {};
306
- macro: {};
307
- macroFn: {};
308
- parser: {};
309
- response: import("elysia").ExtractErrorFromHandle<{
310
- tenantId: string;
311
- }> & {};
312
- }, {}, {
313
- derive: {};
314
- resolve: {};
315
- schema: {};
316
- standaloneSchema: {};
317
- response: {};
318
- }, {
319
- derive: {};
320
- resolve: {};
321
- schema: {};
322
- standaloneSchema: {};
323
- response: {};
324
- }>;
325
- //#endregion
326
500
  //#region src/plugins/rate-limit.plugin.d.ts
501
+ /**
502
+ * 速率限制插件配置选项
503
+ */
327
504
  type RateLimitPluginOptions = {
328
- /** 速率限制器端口(用户注入) */limiter: RateLimiterPort; /** 日志服务 */
329
- logger?: LoggerService; /** 键生成器(用于从请求中提取限制键) */
505
+ /**
506
+ * 速率限制器端口(用户注入)
507
+ */
508
+ limiter: RateLimiterPort;
509
+ /**
510
+ * 日志服务
511
+ */
512
+ logger?: LoggerService;
513
+ /**
514
+ * 键生成器(用于从请求中提取限制键)
515
+ */
330
516
  keyGenerator?: (request: Request) => string;
331
517
  };
518
+ /**
519
+ * 创建速率限制插件
520
+ *
521
+ * @param options - 插件配置选项
522
+ * @returns Elysia 插件实例
523
+ */
332
524
  declare function createRateLimitPlugin(options: RateLimitPluginOptions): Elysia<"", {
333
525
  decorator: {};
334
526
  store: {};
@@ -444,13 +636,42 @@ declare function createLoggerPlugin(options: LoggerPluginOptions): Elysia<"", {
444
636
  }>;
445
637
  //#endregion
446
638
  //#region src/presets/basic-preset.d.ts
639
+ /**
640
+ * 基础预设配置选项
641
+ *
642
+ * @typeParam T - 扩展 schema 类型,用于从 payload 中解析自定义业务字段
643
+ */
447
644
  type BasicPresetOptions<T extends z.ZodTypeAny = z.ZodUndefined> = {
448
- /** 令牌验证器端口(用户注入) */tokenVerifier: TokenVerifierPort; /** 默认租户 ID */
449
- defaultTenantId?: string; /** 日志服务 */
450
- logger?: LoggerService; /** 跳过认证的路径列表(精确匹配或前缀匹配,如 "/api/public/*") */
451
- publicPaths?: string[]; /** 扩展 schema,用于从 payload 中解析自定义业务字段 */
645
+ /**
646
+ * 令牌验证器端口(用户注入)
647
+ */
648
+ tokenVerifier: TokenVerifierPort;
649
+ /**
650
+ * 默认租户 ID
651
+ */
652
+ defaultTenantId?: string;
653
+ /**
654
+ * 日志服务
655
+ */
656
+ logger?: LoggerService;
657
+ /**
658
+ * 跳过认证的路径列表(精确匹配或前缀匹配,如 "/api/public/*")
659
+ */
660
+ publicPaths?: string[];
661
+ /**
662
+ * 扩展 schema,用于从 payload 中解析自定义业务字段
663
+ */
452
664
  extendSchema?: T;
453
665
  };
666
+ /**
667
+ * 创建基础预设插件
668
+ *
669
+ * 该预设包含 JWT 验证插件和错误处理插件,提供完整的认证功能。
670
+ *
671
+ * @typeParam T - 扩展 schema 类型,用于从 payload 中解析自定义业务字段
672
+ * @param options - 预设配置选项
673
+ * @returns Elysia 插件实例
674
+ */
454
675
  declare function createBasicPreset<T extends z.ZodTypeAny = z.ZodUndefined>(options: BasicPresetOptions<T>): Elysia<"", {
455
676
  decorator: {};
456
677
  store: {};
@@ -517,24 +738,59 @@ declare function createBasicPreset<T extends z.ZodTypeAny = z.ZodUndefined>(opti
517
738
  }>;
518
739
  //#endregion
519
740
  //#region src/presets/standard-preset.d.ts
741
+ /**
742
+ * 标准预设配置选项
743
+ *
744
+ * @typeParam T - 扩展 schema 类型,用于从 payload 中解析自定义业务字段
745
+ */
520
746
  type StandardPresetOptions<T extends z.ZodTypeAny = z.ZodUndefined> = {
521
- /** 令牌验证器端口(用户注入) */tokenVerifier: TokenVerifierPort; /** 速率限制器端口(可选,用户注入) */
522
- rateLimiter?: RateLimiterPort; /** 默认租户 ID */
523
- defaultTenantId?: string; /** 租户验证函数 */
524
- validateFn?: TenantValidateFn; /** 用户角色策略 */
525
- userRole?: UserRoleStrategy; /** 日志服务 */
526
- logger?: LoggerService; /** 跳过认证的路径列表(精确匹配或前缀匹配,如 "/api/public/*") */
527
- publicPaths?: string[]; /** 扩展 schema,用于从 payload 中解析自定义业务字段(仅在未使用 apiKeyValidator 时生效) */
528
- extendSchema?: T; /** API Key 验证器(提供后使用组合认证插件替代 JWT 验证插件) */
747
+ /**
748
+ * 令牌验证器端口(用户注入)
749
+ */
750
+ tokenVerifier: TokenVerifierPort;
751
+ /**
752
+ * 速率限制器端口(可选,用户注入)
753
+ */
754
+ rateLimiter?: RateLimiterPort;
755
+ /**
756
+ * 默认租户 ID
757
+ */
758
+ defaultTenantId?: string;
759
+ /**
760
+ * 用户角色策略
761
+ */
762
+ userRole?: UserRoleStrategy;
763
+ /**
764
+ * 日志服务
765
+ */
766
+ logger?: LoggerService;
767
+ /**
768
+ * 跳过认证的路径列表(精确匹配或前缀匹配,如 "/api/public/*")
769
+ */
770
+ publicPaths?: string[];
771
+ /**
772
+ * 扩展 schema,用于从 payload 中解析自定义业务字段(仅在未使用 apiKeyValidator 时生效)
773
+ */
774
+ extendSchema?: T;
775
+ /**
776
+ * API Key 验证器(提供后使用组合认证插件替代 JWT 验证插件)
777
+ */
529
778
  apiKeyValidator?: (key: string) => Promise<ApiKeyPrincipal | null>;
530
779
  };
780
+ /**
781
+ * 创建标准预设插件
782
+ *
783
+ * 该预设包含认证插件、RBAC 插件、可选的限流插件和错误处理插件。
784
+ *
785
+ * @typeParam T - 扩展 schema 类型,用于从 payload 中解析自定义业务字段
786
+ * @param options - 预设配置选项
787
+ * @returns Elysia 插件实例
788
+ */
531
789
  declare function createStandardPreset<T extends z.ZodTypeAny = z.ZodUndefined>(options: StandardPresetOptions<T>): Elysia<"", {
532
790
  decorator: {};
533
791
  store: {};
534
792
  derive: {
535
793
  readonly requirePermission: (resource: string, action: string) => Promise<void>;
536
- } & {
537
- tenantId: string;
538
794
  };
539
795
  resolve: {};
540
796
  }, {
@@ -556,15 +812,6 @@ declare function createStandardPreset<T extends z.ZodTypeAny = z.ZodUndefined>(o
556
812
  response: import("elysia").ExtractErrorFromHandle<{
557
813
  readonly requirePermission: (resource: string, action: string) => Promise<void>;
558
814
  }>;
559
- } & {
560
- schema: {};
561
- standaloneSchema: {};
562
- macro: {};
563
- macroFn: {};
564
- parser: {};
565
- response: import("elysia").ExtractErrorFromHandle<{
566
- tenantId: string;
567
- }> & {};
568
815
  } & {
569
816
  schema: {};
570
817
  standaloneSchema: {};
@@ -591,13 +838,13 @@ declare function createStandardPreset<T extends z.ZodTypeAny = z.ZodUndefined>(o
591
838
  schema: {};
592
839
  standaloneSchema: {};
593
840
  response: {};
594
- }, ({
841
+ }, (({
595
842
  derive: {};
596
843
  resolve: {};
597
844
  schema: {};
598
845
  standaloneSchema: {};
599
846
  response: {};
600
- } & {
847
+ } & ({
601
848
  derive: {
602
849
  auth: import("@longzai-intelligence-auth/core").UnifiedAuthContext;
603
850
  };
@@ -607,19 +854,7 @@ declare function createStandardPreset<T extends z.ZodTypeAny = z.ZodUndefined>(o
607
854
  response: import("elysia").ExtractErrorFromHandle<{
608
855
  auth: import("@longzai-intelligence-auth/core").UnifiedAuthContext;
609
856
  }>;
610
- } & {
611
- derive: {};
612
- resolve: {};
613
- schema: {};
614
- standaloneSchema: {};
615
- response: {};
616
- }) | ({
617
- derive: {};
618
- resolve: {};
619
- schema: {};
620
- standaloneSchema: {};
621
- response: {};
622
- } & {
857
+ } | {
623
858
  derive: {
624
859
  readonly auth: any;
625
860
  };
@@ -629,20 +864,36 @@ declare function createStandardPreset<T extends z.ZodTypeAny = z.ZodUndefined>(o
629
864
  response: import("elysia").ExtractErrorFromHandle<{
630
865
  readonly auth: any;
631
866
  }>;
632
- } & {
867
+ })) & {
868
+ derive: {};
869
+ resolve: {};
870
+ schema: {};
871
+ standaloneSchema: {};
872
+ response: {};
873
+ }) & {
633
874
  derive: {};
634
875
  resolve: {};
635
876
  schema: {};
636
877
  standaloneSchema: {};
637
878
  response: {};
638
- })>;
879
+ }>;
639
880
  //#endregion
640
881
  //#region src/utils/extract-client-ip.d.ts
641
- /** 从请求中提取客户端 IP 地址 */
882
+ /**
883
+ * 从请求中提取客户端 IP 地址
884
+ *
885
+ * @param request - HTTP 请求对象
886
+ * @returns 客户端 IP 地址,如果无法提取则返回 undefined
887
+ */
642
888
  declare function extractClientIp(request: Request): string | undefined;
643
889
  //#endregion
644
890
  //#region src/utils/extract-user-agent.d.ts
645
- /** 从请求中提取用户代理 */
891
+ /**
892
+ * 从请求中提取用户代理
893
+ *
894
+ * @param request - HTTP 请求对象
895
+ * @returns 用户代理字符串,如果无法提取则返回 undefined
896
+ */
646
897
  declare function extractUserAgent(request: Request): string | undefined;
647
898
  //#endregion
648
- export { type ApiKeyPluginOptions, type ApiKeyPrincipal, type AuthContextWithExtra, type BasicPresetOptions, type CompositeAuthContext, type CompositeAuthPluginOptions, type ErrorHandlerPluginOptions, type ExtractExtra, type InMemoryApiKeyEntry, type InMemoryApiKeyMap, type JwtVerifyPluginOptions, type LoggerPluginOptions, type OptionalAuthContext, type OptionalJwtPluginOptions, type RateLimitPluginOptions, type RbacPluginOptions, type StandardPresetOptions, type TenantPluginOptions, type UnifiedAuthContext, type UserRoleStrategy, type VerifiedAuthContext, createApiKeyPlugin, createBasicPreset, createCompositeAuthPlugin, createErrorHandlerPlugin, createInMemoryApiKeyValidator, createJwtVerifyPlugin, createLoggerPlugin, createOptionalJwtPlugin, createRateLimitPlugin, createRbacPlugin, createRequiredCompositeAuthPlugin, createStandardPreset, createTenantPlugin, extractClientIp, extractUserAgent, mapDomainErrorToStatus };
899
+ export { type ApiKeyPluginOptions, type ApiKeyPrincipal, type AuthContextWithExtra, type BasicPresetOptions, type CompositeAuthContext, type CompositeAuthPluginOptions, type ErrorHandlerPluginOptions, type ExtractExtra, type InMemoryApiKeyEntry, type InMemoryApiKeyMap, type JwtVerifyPluginOptions, type LoggerPluginOptions, type OptionalAuthContext, type OptionalJwtPluginOptions, type RateLimitPluginOptions, type RbacPluginOptions, type StandardPresetOptions, type StaticTokenVerifierOptions, type UnifiedAuthContext, type UserRoleStrategy, type VerifiedAuthContext, createApiKeyPlugin, createBasicPreset, createCompositeAuthPlugin, createErrorHandlerPlugin, createInMemoryApiKeyValidator, createJwtVerifyPlugin, createLoggerPlugin, createOptionalJwtPlugin, createRateLimitPlugin, createRbacPlugin, createRequiredCompositeAuthPlugin, createStandardPreset, createStaticTokenVerifier, extractClientIp, extractUserAgent, mapDomainErrorToStatus };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{AuthenticationError as e,DomainError as t,DuplicateEntityError as n,isBusinessRuleError as r,isConcurrencyError as i,isEntityNotFoundError as a,isPermissionDeniedError as o,isValidationError as s}from"@longzai-intelligence/error";import{AccountDisabledError as c,InvalidCredentialsError as l,MfaRequiredError as u,RateLimitExceededError as d,TokenExpiredError as f,TokenInvalidError as p,TokenMissingError as m,UserAlreadyExistsError as h,accessTokenPayloadSchema as g,createDefaultJwtConfig as _}from"@longzai-intelligence-auth/core";import{Elysia as v}from"elysia";import{JwtTokenVerifier as y}from"@longzai-intelligence-auth/jwt";function b(t){return s(t)?400:t instanceof f||t instanceof p||t instanceof m||t instanceof u||t instanceof l||t instanceof c||t instanceof e?401:o(t)?403:a(t)?404:t instanceof n||t instanceof h?409:t instanceof d?429:i(t)?409:r(t)||t.code===`PASSWORD_POLICY_VIOLATION`?422:500}function x(e,t){return{userId:e.sub,tenantId:e.tenantId??t,roles:e.roles??[],permissions:e.permissions??[],authMethod:`jwt`}}function S(e){return{userId:``,tenantId:e,roles:[],permissions:[],authMethod:`jwt`}}function C(e,t){return t.some(t=>t.endsWith(`/*`)?e.startsWith(t.slice(0,-2)):e===t)}function w(e){return{algorithm:`HS256`,secret:e.secret,accessExpiresIn:e.accessExpiresIn,refreshExpiresIn:e.refreshExpiresIn}}function T(e,t){return e||new y(w(t??_()))}function E(e){let{verifier:t,jwt:n,defaultTenantId:r=`default`,publicPaths:i=[],extendSchema:a}=e,o=T(t,n);return new v({name:`@longzai-intelligence-auth/jwt-verify`}).derive(async({request:e})=>{if(C(new URL(e.url).pathname,i)){let e=a?a.parse({}):{};return{auth:{...S(r),...e}}}let t=e.headers.get(`Authorization`),n=t?.startsWith(`Bearer `)?t.slice(7):null;if(!n)throw new m;let s=await o.verifyAccessToken(n);if(!s.success||!s.payload)throw new p(s.error);g.parse(s.payload);let c=x(s.payload,r),l=a?a.parse(s.payload):{};return{auth:{...c,...l}}}).as(`scoped`)}function D(e){return{algorithm:`HS256`,secret:e.secret,accessExpiresIn:e.accessExpiresIn,refreshExpiresIn:e.refreshExpiresIn}}function O(e,t){return e||new y(D(t??_()))}function k(e){let{verifier:t,jwt:n,defaultTenantId:r=`default`,extendSchema:i}=e,a=O(t,n);return new v({name:`@longzai-intelligence-auth/optional-jwt`}).derive(async({request:e})=>{let t=e.headers.get(`Authorization`),n=t?.startsWith(`Bearer `)?t.slice(7):null;if(!n)return{auth:null};try{let e=await a.verifyAccessToken(n);if(!e.success||!e.payload)return{auth:null};g.parse(e.payload);let t=e.payload,o={userId:t.sub,tenantId:t.tenantId??r,roles:t.roles??[],permissions:t.permissions??[],authMethod:`jwt`},s=i?i.parse(t):{};return{auth:{...o,...s}}}catch{return{auth:null}}}).as(`scoped`)}function A(e,t,n){return e.some(e=>e.resource===`*`&&e.action===`*`||e.resource===t&&e.action===`*`||e.resource===`*`&&e.action===n||e.resource===t&&e.action===n)}function j(e,t,n){let r=`${t}:${n}`;return e.includes(r)||e.includes(`${t}:*`)||e.includes(`*:${n}`)||e.includes(`*:*`)}function M(e={}){let{userRole:t}=e;return new v({name:`@longzai-intelligence-auth/rbac`}).derive({as:`scoped`},async e=>{let n=e.auth;if(!n)throw new m;let r=n.userId,i=n.tenantId;return{requirePermission:async(e,a)=>{if(t){if(A(await t.findPermissionsByUserId(r,i),e,a))return;let{PermissionDeniedError:n}=await import(`@longzai-intelligence/error`);throw new n(e,a)}if(j(n.permissions??[],e,a))return;let{PermissionDeniedError:o}=await import(`@longzai-intelligence/error`);throw new o(e,a)}}}).as(`global`)}function N(e){let{header:t=`x-api-key`,validator:n}=e;return new v({name:`@longzai-intelligence-auth/api-key`}).derive(async({request:e})=>{let r=e.headers.get(t)??e.headers.get(t.toLowerCase());if(!r)throw new m(`缺少 API Key`);let i=await n(r);if(!i)throw new p(`无效的 API Key`);return{auth:{userId:i.principalId,tenantId:i.tenantId??`default`,roles:i.roles,permissions:i.permissions,authMethod:`api-key`}}}).as(`scoped`)}function P(e){return async t=>{let n=e[t];return n?{principalId:n.principalId,tenantId:n.tenantId,roles:n.roles,permissions:n.permissions}:null}}function F(e){return{authMethod:`jwt`,userId:e.userId,tenantId:e.tenantId,roles:e.roles,permissions:e.permissions}}function I(e,t){return{authMethod:`api-key`,userId:e.principalId,tenantId:e.tenantId??t,roles:e.roles,permissions:e.permissions}}function L(e){return{algorithm:`HS256`,secret:e.secret,accessExpiresIn:e.accessExpiresIn,refreshExpiresIn:e.refreshExpiresIn}}function R(e,t){return e||new y(L(t??_()))}function z(e,t){return t.some(t=>t.endsWith(`/*`)?e.startsWith(t.slice(0,-2)):e===t)}function B(e){let{verifier:t,jwt:n,defaultTenantId:r=`default`,apiKeyValidator:i,apiKeyHeader:a=`x-api-key`,publicPaths:o=[]}=e,s=R(t,n);return new v({name:`@longzai-intelligence-auth/composite-auth`}).derive(async({request:e})=>{if(z(new URL(e.url).pathname,o))return{auth:null};let t=e.headers.get(`Authorization`),n=t?.startsWith(`Bearer `)?t.slice(7):null;if(n)try{let e=await s.verifyAccessToken(n);if(e.success&&e.payload)return g.parse(e.payload),{auth:F({userId:e.payload.sub,tenantId:e.payload.tenantId??r,roles:e.payload.roles??[],permissions:e.payload.permissions??[]})}}catch{}if(i){let t=e.headers.get(a)??e.headers.get(a.toLowerCase());if(t){let e=await i(t);if(e)return{auth:I(e,r)}}}return{auth:null}}).as(`scoped`)}function V(e){let{verifier:t,jwt:n,defaultTenantId:r=`default`,apiKeyValidator:i,apiKeyHeader:a=`x-api-key`,publicPaths:o=[]}=e,s=R(t,n);return new v({name:`@longzai-intelligence-auth/required-composite-auth`}).derive(async({request:e})=>{if(z(new URL(e.url).pathname,o))return{auth:{authMethod:`jwt`,userId:``,tenantId:r,roles:[],permissions:[]}};let t=e.headers.get(`Authorization`),n=t?.startsWith(`Bearer `)?t.slice(7):null;if(n)try{let e=await s.verifyAccessToken(n);if(e.success&&e.payload)return g.parse(e.payload),{auth:F({userId:e.payload.sub,tenantId:e.payload.tenantId??r,roles:e.payload.roles??[],permissions:e.payload.permissions??[]})}}catch{}if(i){let t=e.headers.get(a)??e.headers.get(a.toLowerCase());if(t){let e=await i(t);if(e)return{auth:I(e,r)}}}throw Error(`认证失败:需要提供有效的 JWT Token 或 API Key`)}).as(`scoped`)}function H(e={}){let{defaultTenantId:t=`default`,validateFn:n}=e;return new v({name:`@longzai-intelligence-auth/tenant`}).derive(({request:e})=>({tenantId:e.headers.get(`x-tenant-id`)??t})).as(`scoped`).onBeforeHandle(async({tenantId:e})=>{if(n&&e!==t&&!(await n(e)).valid){let{PermissionDeniedError:e}=await import(`@longzai-intelligence/error`);throw new e(`tenant`,`access`)}}).as(`global`)}function U(e){return e.headers.get(`x-forwarded-for`)?.split(`,`)[0]?.trim()??e.headers.get(`x-real-ip`)??`unknown`}function W(e){let{limiter:t,logger:n}=e,r=e.keyGenerator??U;return new v({name:`@longzai-intelligence-auth/rate-limit`}).derive(({request:e})=>({clientIp:r(e)})).derive(async({clientIp:e,request:r})=>{let i=new URL(r.url).pathname,a=`${e}:${i}`,o=await t.checkLimit(a);if(!o.allowed)throw n?.warn(`限流触发`,{clientIp:e,path:i}),new d;return{rateLimitRemaining:o.remaining}}).as(`global`)}function G(e={}){let{logger:n}=e;return new v({name:`@longzai-intelligence-auth/error-handler`}).onError(({code:e,error:r,set:i})=>{if(r instanceof t)return i.status=b(r),{code:r.code,message:r.message,...r.context&&Object.keys(r.context).length>0?{details:r.context}:{}};switch(e){case`VALIDATION`:return i.status=400,{code:`VALIDATION_ERROR`,message:`请求参数验证失败`,details:r.all.map(e=>({path:e.path,message:e.summary}))};case`NOT_FOUND`:return i.status=404,{code:`NOT_FOUND`,message:`未找到请求的资源`};case`PARSE`:return i.status=400,{code:`PARSE_ERROR`,message:`请求数据解析失败`};default:return n?.error(`未预期的错误`,{error:r instanceof Error?r.message:String(r),stack:r instanceof Error?r.stack:void 0}),i.status=500,{code:`INTERNAL_ERROR`,message:`服务器内部错误`}}}).as(`global`)}function K(e){let{logger:t}=e;return new v({name:`@longzai-intelligence-auth/logger`}).onRequest(({request:e})=>{t.info(`${e.method} ${e.url}`)}).onAfterResponse(({request:e,set:n})=>{t.info(`${e.method} ${e.url} ${n.status}`)}).onError(({request:e,error:n})=>{t.error(`${e.method} ${e.url} 请求错误`,{error:n instanceof Error?n.message:String(n)})}).as(`global`)}function q(e){return new v({name:`@longzai-intelligence-auth/basic-preset`}).use(E({verifier:e.tokenVerifier,defaultTenantId:e.defaultTenantId,publicPaths:e.publicPaths,extendSchema:e.extendSchema})).use(G({logger:e.logger}))}function J(e){let t=e.apiKeyValidator?V({verifier:e.tokenVerifier,defaultTenantId:e.defaultTenantId,publicPaths:e.publicPaths,apiKeyValidator:e.apiKeyValidator}):E({verifier:e.tokenVerifier,defaultTenantId:e.defaultTenantId,publicPaths:e.publicPaths,extendSchema:e.extendSchema}),n=new v({name:`@longzai-intelligence-auth/standard-preset`}).use(t).use(M({userRole:e.userRole})).use(H({defaultTenantId:e.defaultTenantId,validateFn:e.validateFn}));return e.rateLimiter&&n.use(W({limiter:e.rateLimiter,logger:e.logger})),n.use(G({logger:e.logger}))}function Y(e){return e.headers.get(`x-forwarded-for`)?.split(`,`)[0]?.trim()??e.headers.get(`x-real-ip`)??void 0}function X(e){return e.headers.get(`user-agent`)??void 0}export{N as createApiKeyPlugin,q as createBasicPreset,B as createCompositeAuthPlugin,G as createErrorHandlerPlugin,P as createInMemoryApiKeyValidator,E as createJwtVerifyPlugin,K as createLoggerPlugin,k as createOptionalJwtPlugin,W as createRateLimitPlugin,M as createRbacPlugin,V as createRequiredCompositeAuthPlugin,J as createStandardPreset,H as createTenantPlugin,Y as extractClientIp,X as extractUserAgent,b as mapDomainErrorToStatus};
1
+ import{AuthenticationError as e,DomainError as t,DuplicateEntityError as n,isBusinessRuleError as r,isConcurrencyError as i,isEntityNotFoundError as a,isPermissionDeniedError as o,isValidationError as s}from"@longzai-intelligence/error";import{AccountDisabledError as c,InvalidCredentialsError as l,MfaRequiredError as u,RateLimitExceededError as d,TokenExpiredError as f,TokenInvalidError as p,TokenMissingError as m,UserAlreadyExistsError as h,accessTokenPayloadSchema as g,createDefaultJwtConfig as _}from"@longzai-intelligence-auth/core";import v from"node:crypto";import{Elysia as y}from"elysia";import{JwtTokenVerifier as b}from"@longzai-intelligence-auth/jwt";function x(t){return s(t)?400:t instanceof f||t instanceof p||t instanceof m||t instanceof u||t instanceof l||t instanceof c||t instanceof e?401:o(t)?403:a(t)?404:t instanceof n||t instanceof h?409:t instanceof d?429:i(t)?409:r(t)||t.code===`PASSWORD_POLICY_VIOLATION`?422:500}function S(e,t){let n=Buffer.from(e,`utf-8`),r=Buffer.from(t,`utf-8`);if(n.length!==r.length){let e=Buffer.alloc(n.length);return v.timingSafeEqual(n,e),!1}return v.timingSafeEqual(n,r)}function C(e){let{token:t,getToken:n,subject:r=`static`,tenantId:i}=e;if(!t&&!n)throw Error(`createStaticTokenVerifier 需要至少提供 token 或 getToken 之一`);let a=()=>{if(n){let e=n();if(e)return e}return t??null};return{async verifyAccessToken(e){let t=a();return t?S(e,t)?{success:!0,payload:{sub:r,type:`access`,...i!==void 0&&{tenantId:i}}}:{success:!1,error:`静态令牌不匹配`}:{success:!1,error:`静态令牌未配置`}},async verifyRefreshToken(){return{success:!1,error:`静态令牌模式不支持 refresh token`}}}}function w(e,t){return{userId:e.sub,tenantId:e.tenantId??t,roles:e.roles??[],permissions:e.permissions??[],authMethod:`jwt`}}function T(e){return{userId:``,tenantId:e,roles:[],permissions:[],authMethod:`jwt`}}function E(e,t){return t.some(t=>t.endsWith(`/*`)?e.startsWith(t.slice(0,-2)):e===t)}function D(e){return{algorithm:`HS256`,secret:e.secret,accessExpiresIn:e.accessExpiresIn,refreshExpiresIn:e.refreshExpiresIn}}function O(e,t){return e||new b(D(t??_()))}function k(e){let{verifier:t,jwt:n,defaultTenantId:r=`default`,publicPaths:i=[],extendSchema:a}=e,o=O(t,n);return new y({name:`@longzai-intelligence-auth/jwt-verify`}).derive(async({request:e})=>{if(E(new URL(e.url).pathname,i)){let e=a?a.parse({}):{};return{auth:{...T(r),...e}}}let t=e.headers.get(`Authorization`),n=t?.startsWith(`Bearer `)?t.slice(7):null;if(!n)throw new m;let s=await o.verifyAccessToken(n);if(!s.success||!s.payload)throw new p(s.error);g.parse(s.payload);let c=w(s.payload,r),l=a?a.parse(s.payload):{};return{auth:{...c,...l}}}).as(`scoped`)}function A(e){return{algorithm:`HS256`,secret:e.secret,accessExpiresIn:e.accessExpiresIn,refreshExpiresIn:e.refreshExpiresIn}}function j(e,t){return e||new b(A(t??_()))}function M(e){let{verifier:t,jwt:n,defaultTenantId:r=`default`,extendSchema:i}=e,a=j(t,n);return new y({name:`@longzai-intelligence-auth/optional-jwt`}).derive(async({request:e})=>{let t=e.headers.get(`Authorization`),n=t?.startsWith(`Bearer `)?t.slice(7):null;if(!n)return{auth:null};try{let e=await a.verifyAccessToken(n);if(!e.success||!e.payload)return{auth:null};g.parse(e.payload);let t=e.payload,o={userId:t.sub,tenantId:t.tenantId??r,roles:t.roles??[],permissions:t.permissions??[],authMethod:`jwt`},s=i?i.parse(t):{};return{auth:{...o,...s}}}catch{return{auth:null}}}).as(`scoped`)}function N(e,t,n){return e.some(e=>e.resource===`*`&&e.action===`*`||e.resource===t&&e.action===`*`||e.resource===`*`&&e.action===n||e.resource===t&&e.action===n)}function P(e,t,n){let r=`${t}:${n}`;return e.includes(r)||e.includes(`${t}:*`)||e.includes(`*:${n}`)||e.includes(`*:*`)}function F(e={}){let{userRole:t}=e;return new y({name:`@longzai-intelligence-auth/rbac`}).derive({as:`scoped`},async e=>{let n=e.auth;if(!n)throw new m;let r=n.userId,i=n.tenantId;return{requirePermission:async(e,a)=>{if(t){if(N(await t.findPermissionsByUserId(r,i),e,a))return;let{PermissionDeniedError:n}=await import(`@longzai-intelligence/error`);throw new n(e,a)}if(P(n.permissions??[],e,a))return;let{PermissionDeniedError:o}=await import(`@longzai-intelligence/error`);throw new o(e,a)}}}).as(`global`)}function I(e){let{header:t=`x-api-key`,validator:n}=e;return new y({name:`@longzai-intelligence-auth/api-key`}).derive(async({request:e})=>{let r=e.headers.get(t)??e.headers.get(t.toLowerCase());if(!r)throw new m(`缺少 API Key`);let i=await n(r);if(!i)throw new p(`无效的 API Key`);return{auth:{userId:i.principalId,tenantId:i.tenantId??`default`,roles:i.roles,permissions:i.permissions,authMethod:`api-key`}}}).as(`scoped`)}function L(e){return async t=>{let n=e[t];return n?{principalId:n.principalId,tenantId:n.tenantId,roles:n.roles,permissions:n.permissions}:null}}function R(e){return{authMethod:`jwt`,userId:e.userId,tenantId:e.tenantId,roles:e.roles,permissions:e.permissions}}function z(e,t){return{authMethod:`api-key`,userId:e.principalId,tenantId:e.tenantId??t,roles:e.roles,permissions:e.permissions}}function B(e){return{algorithm:`HS256`,secret:e.secret,accessExpiresIn:e.accessExpiresIn,refreshExpiresIn:e.refreshExpiresIn}}function V(e,t){return e||new b(B(t??_()))}function H(e,t){return t.some(t=>t.endsWith(`/*`)?e.startsWith(t.slice(0,-2)):e===t)}function U(e){let{verifier:t,jwt:n,defaultTenantId:r=`default`,apiKeyValidator:i,apiKeyHeader:a=`x-api-key`,publicPaths:o=[]}=e,s=V(t,n);return new y({name:`@longzai-intelligence-auth/composite-auth`}).derive(async({request:e})=>{if(H(new URL(e.url).pathname,o))return{auth:null};let t=e.headers.get(`Authorization`),n=t?.startsWith(`Bearer `)?t.slice(7):null;if(n)try{let e=await s.verifyAccessToken(n);if(e.success&&e.payload)return g.parse(e.payload),{auth:R({userId:e.payload.sub,tenantId:e.payload.tenantId??r,roles:e.payload.roles??[],permissions:e.payload.permissions??[]})}}catch{}if(i){let t=e.headers.get(a)??e.headers.get(a.toLowerCase());if(t){let e=await i(t);if(e)return{auth:z(e,r)}}}return{auth:null}}).as(`scoped`)}function W(e){let{verifier:t,jwt:n,defaultTenantId:r=`default`,apiKeyValidator:i,apiKeyHeader:a=`x-api-key`,publicPaths:o=[]}=e,s=V(t,n);return new y({name:`@longzai-intelligence-auth/required-composite-auth`}).derive(async({request:e})=>{if(H(new URL(e.url).pathname,o))return{auth:{authMethod:`jwt`,userId:``,tenantId:r,roles:[],permissions:[]}};let t=e.headers.get(`Authorization`),n=t?.startsWith(`Bearer `)?t.slice(7):null;if(n)try{let e=await s.verifyAccessToken(n);if(e.success&&e.payload)return g.parse(e.payload),{auth:R({userId:e.payload.sub,tenantId:e.payload.tenantId??r,roles:e.payload.roles??[],permissions:e.payload.permissions??[]})}}catch{}if(i){let t=e.headers.get(a)??e.headers.get(a.toLowerCase());if(t){let e=await i(t);if(e)return{auth:z(e,r)}}}throw Error(`认证失败:需要提供有效的 JWT Token 或 API Key`)}).as(`scoped`)}function G(e){return e.headers.get(`x-forwarded-for`)?.split(`,`)[0]?.trim()??e.headers.get(`x-real-ip`)??`unknown`}function K(e){let{limiter:t,logger:n}=e,r=e.keyGenerator??G;return new y({name:`@longzai-intelligence-auth/rate-limit`}).derive(({request:e})=>({clientIp:r(e)})).derive(async({clientIp:e,request:r})=>{let i=new URL(r.url).pathname,a=`${e}:${i}`,o=await t.checkLimit(a);if(!o.allowed)throw n?.warn(`限流触发`,{clientIp:e,path:i}),new d;return{rateLimitRemaining:o.remaining}}).as(`global`)}function q(e={}){let{logger:n}=e;return new y({name:`@longzai-intelligence-auth/error-handler`}).onError(({code:e,error:r,set:i})=>{if(r instanceof t)return i.status=x(r),{code:r.code,message:r.message,...r.context&&Object.keys(r.context).length>0?{details:r.context}:{}};switch(e){case`VALIDATION`:return i.status=400,{code:`VALIDATION_ERROR`,message:`请求参数验证失败`,details:r.all.map(e=>({path:e.path,message:e.summary}))};case`NOT_FOUND`:return i.status=404,{code:`NOT_FOUND`,message:`未找到请求的资源`};case`PARSE`:return i.status=400,{code:`PARSE_ERROR`,message:`请求数据解析失败`};default:return n?.error(`未预期的错误`,{error:r instanceof Error?r.message:String(r),stack:r instanceof Error?r.stack:void 0}),i.status=500,{code:`INTERNAL_ERROR`,message:`服务器内部错误`}}}).as(`global`)}function J(e){let{logger:t}=e;return new y({name:`@longzai-intelligence-auth/logger`}).onRequest(({request:e})=>{t.info(`${e.method} ${e.url}`)}).onAfterResponse(({request:e,set:n})=>{t.info(`${e.method} ${e.url} ${n.status}`)}).onError(({request:e,error:n})=>{t.error(`${e.method} ${e.url} 请求错误`,{error:n instanceof Error?n.message:String(n)})}).as(`global`)}function Y(e){return new y({name:`@longzai-intelligence-auth/basic-preset`}).use(k({verifier:e.tokenVerifier,defaultTenantId:e.defaultTenantId,publicPaths:e.publicPaths,extendSchema:e.extendSchema})).use(q({logger:e.logger}))}function X(e){let t=e.apiKeyValidator?W({verifier:e.tokenVerifier,defaultTenantId:e.defaultTenantId,publicPaths:e.publicPaths,apiKeyValidator:e.apiKeyValidator}):k({verifier:e.tokenVerifier,defaultTenantId:e.defaultTenantId,publicPaths:e.publicPaths,extendSchema:e.extendSchema}),n=new y({name:`@longzai-intelligence-auth/standard-preset`}).use(t).use(F({userRole:e.userRole}));return e.rateLimiter&&n.use(K({limiter:e.rateLimiter,logger:e.logger})),n.use(q({logger:e.logger}))}function Z(e){return e.headers.get(`x-forwarded-for`)?.split(`,`)[0]?.trim()??e.headers.get(`x-real-ip`)??void 0}function Q(e){return e.headers.get(`user-agent`)??void 0}export{I as createApiKeyPlugin,Y as createBasicPreset,U as createCompositeAuthPlugin,q as createErrorHandlerPlugin,L as createInMemoryApiKeyValidator,k as createJwtVerifyPlugin,J as createLoggerPlugin,M as createOptionalJwtPlugin,K as createRateLimitPlugin,F as createRbacPlugin,W as createRequiredCompositeAuthPlugin,X as createStandardPreset,C as createStaticTokenVerifier,Z as extractClientIp,Q as extractUserAgent,x as mapDomainErrorToStatus};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@longzai-intelligence-auth/elysia",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -33,11 +33,11 @@
33
33
  "test:coverage": "bun test --coverage",
34
34
  "test:unit": "bun test src/__tests__/unit/",
35
35
  "test:integration": "bun test src/__tests__/integration/",
36
- "clean": "rm -rf dist out .cache"
36
+ "clean": "rimraf dist out .cache"
37
37
  },
38
38
  "dependencies": {
39
- "@longzai-intelligence-auth/core": "0.0.5",
40
- "@longzai-intelligence-auth/jwt": "0.0.5",
39
+ "@longzai-intelligence-auth/core": "0.0.6",
40
+ "@longzai-intelligence-auth/jwt": "0.0.6",
41
41
  "@longzai-intelligence/error": "^0.0.5",
42
42
  "@elysiajs/bearer": "^1.3",
43
43
  "zod": "^3.24"