@dangao/bun-server 0.1.4 → 0.1.5
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/auth/decorators.d.ts.map +1 -1
- package/dist/config/config-module.d.ts +14 -0
- package/dist/config/config-module.d.ts.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/service.d.ts +32 -0
- package/dist/config/service.d.ts.map +1 -0
- package/dist/config/types.d.ts +22 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/core/application.d.ts.map +1 -1
- package/dist/health/controller.d.ts +27 -0
- package/dist/health/controller.d.ts.map +1 -0
- package/dist/health/health-module.d.ts +9 -0
- package/dist/health/health-module.d.ts.map +1 -0
- package/dist/health/index.d.ts +4 -0
- package/dist/health/index.d.ts.map +1 -0
- package/dist/health/types.d.ts +22 -0
- package/dist/health/types.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +283 -50
- package/dist/router/router.d.ts +6 -1
- package/dist/router/router.d.ts.map +1 -1
- package/dist/security/context.d.ts +7 -2
- package/dist/security/context.d.ts.map +1 -1
- package/dist/security/filter.d.ts.map +1 -1
- package/package.json +1 -1
- package/readme.md +14 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/auth/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAO1B;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,MAAM,GAAE,UAAe,GAAG,eAAe,CAU7D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,MAAM,GAC3B,UAAU,GAAG,SAAS,CAGxB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/auth/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAO1B;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,MAAM,GAAE,UAAe,GAAG,eAAe,CAU7D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,MAAM,GAC3B,UAAU,GAAG,SAAS,CAGxB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAOlF;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,MAAM,EAC5B,SAAS,GAAE,MAAM,EAAO,GACvB,OAAO,CAMT"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ConfigModuleOptions } from './types';
|
|
2
|
+
export declare class ConfigModule {
|
|
3
|
+
/**
|
|
4
|
+
* 创建配置模块
|
|
5
|
+
* @param options - 模块配置
|
|
6
|
+
*/
|
|
7
|
+
static forRoot(options?: ConfigModuleOptions): typeof ConfigModule;
|
|
8
|
+
/**
|
|
9
|
+
* 获取环境变量快照
|
|
10
|
+
* 方便测试和未来扩展(如 .env 文件解析)
|
|
11
|
+
*/
|
|
12
|
+
private static snapshotEnv;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=config-module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-module.d.ts","sourceRoot":"","sources":["../../src/config/config-module.ts"],"names":[],"mappings":"AAGA,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEzE,qBAGa,YAAY;IACvB;;;OAGG;WACW,OAAO,CACnB,OAAO,GAAE,mBAAwB,GAChC,OAAO,YAAY;IA+CtB;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;CAO3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,oBAAoB,EACpB,KAAK,mBAAmB,GACzB,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 配置服务
|
|
3
|
+
* 提供类型安全的配置访问能力
|
|
4
|
+
*/
|
|
5
|
+
export declare class ConfigService<TConfig extends Record<string, unknown> = Record<string, unknown>> {
|
|
6
|
+
private readonly config;
|
|
7
|
+
private readonly namespace?;
|
|
8
|
+
constructor(config: TConfig, namespace?: string);
|
|
9
|
+
/**
|
|
10
|
+
* 获取完整配置对象
|
|
11
|
+
*/
|
|
12
|
+
getAll(): TConfig;
|
|
13
|
+
/**
|
|
14
|
+
* 获取配置值(支持点号路径)
|
|
15
|
+
* @param key - 配置键(如 "db.host")
|
|
16
|
+
* @param defaultValue - 默认值(可选)
|
|
17
|
+
*/
|
|
18
|
+
get<T = unknown>(key: string, defaultValue?: T): T | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* 获取必需的配置值,如果不存在则抛出错误
|
|
21
|
+
* @param key - 配置键
|
|
22
|
+
*/
|
|
23
|
+
getRequired<T = unknown>(key: string): T;
|
|
24
|
+
/**
|
|
25
|
+
* 创建带命名空间的 ConfigService 视图
|
|
26
|
+
* @param namespace - 命名空间前缀
|
|
27
|
+
*/
|
|
28
|
+
withNamespace(namespace: string): ConfigService<TConfig>;
|
|
29
|
+
private applyNamespace;
|
|
30
|
+
private getValueByPath;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/config/service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,aAAa,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1F,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAS;gBAEjB,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM;IAKtD;;OAEG;IACI,MAAM,IAAI,OAAO;IAIxB;;;;OAIG;IACI,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS;IASrE;;;OAGG;IACI,WAAW,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC;IAQ/C;;;OAGG;IACI,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC;IAI/D,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,cAAc;CAuBvB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ConfigModuleOptions<TConfig extends Record<string, unknown> = Record<string, unknown>> {
|
|
2
|
+
/**
|
|
3
|
+
* 默认配置对象(最低优先级)
|
|
4
|
+
*/
|
|
5
|
+
defaultConfig?: Partial<TConfig>;
|
|
6
|
+
/**
|
|
7
|
+
* 从环境变量加载配置
|
|
8
|
+
* @param env - process.env 快照
|
|
9
|
+
*/
|
|
10
|
+
load?: (env: Record<string, string | undefined>) => Partial<TConfig>;
|
|
11
|
+
/**
|
|
12
|
+
* 配置验证函数(可抛出错误)
|
|
13
|
+
* 可用于集成 class-validator 风格的校验逻辑
|
|
14
|
+
*/
|
|
15
|
+
validate?: (config: TConfig) => void;
|
|
16
|
+
/**
|
|
17
|
+
* 命名空间前缀,用于逻辑分组(可选)
|
|
18
|
+
*/
|
|
19
|
+
namespace?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const CONFIG_SERVICE_TOKEN: unique symbol;
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACpG;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEjC;;;OAGG;IACH,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAErE;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAErC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,oBAAoB,eAA8C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/core/application.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAsB,MAAM,UAAU,CAAC;AAKzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGhE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,CAAY;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA2B;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA8B;gBAEtC,OAAO,GAAE,kBAAuB;IAcnD;;;OAGG;IACI,GAAG,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAIxC;;OAEG;IACI,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAgBrD;;OAEG;IACI,IAAI,IAAI,IAAI;IAInB;;;;OAIG;YACW,aAAa;
|
|
1
|
+
{"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/core/application.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAsB,MAAM,UAAU,CAAC;AAKzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGhE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,CAAY;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA2B;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA8B;gBAEtC,OAAO,GAAE,kBAAuB;IAcnD;;;OAGG;IACI,GAAG,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAIxC;;OAEG;IACI,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAgBrD;;OAEG;IACI,IAAI,IAAI,IAAI;IAInB;;;;OAIG;YACW,aAAa;IA2B3B;;;OAGG;IACI,kBAAkB,CAAC,eAAe,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI;IAKtE;;;OAGG;IACI,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAgBrD;;;OAGG;IACI,wBAAwB,CAAC,YAAY,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI;IAIzE;;;OAGG;IACI,iBAAiB,CAAC,SAAS,EAAE,oBAAoB,GAAG,IAAI;IAK/D;;;OAGG;IACI,SAAS,IAAI,SAAS,GAAG,SAAS;IAIzC;;;OAGG;IACI,YAAY;CAGpB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { HealthIndicator, HealthStatus } from './types';
|
|
2
|
+
import type { HealthModuleOptions } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* 健康检查控制器
|
|
5
|
+
*
|
|
6
|
+
* 提供 `/health` 和 `/ready` 两个端点:
|
|
7
|
+
* - /health:存活检查(liveness)
|
|
8
|
+
* - /ready:就绪检查(readiness)
|
|
9
|
+
*/
|
|
10
|
+
export declare class HealthController {
|
|
11
|
+
private readonly indicators;
|
|
12
|
+
private readonly options?;
|
|
13
|
+
constructor(indicators?: HealthIndicator[], options?: HealthModuleOptions | undefined);
|
|
14
|
+
/**
|
|
15
|
+
* 存活检查
|
|
16
|
+
*/
|
|
17
|
+
health(): Promise<HealthStatus>;
|
|
18
|
+
/**
|
|
19
|
+
* 就绪检查
|
|
20
|
+
*/
|
|
21
|
+
ready(): Promise<HealthStatus>;
|
|
22
|
+
/**
|
|
23
|
+
* 执行所有健康检查指示器
|
|
24
|
+
*/
|
|
25
|
+
private checkIndicators;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/health/controller.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EAEf,YAAY,EACb,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAGnD;;;;;;GAMG;AACH,qBACa,gBAAgB;IAGzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAE3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAFR,UAAU,GAAE,eAAe,EAAO,EAElC,OAAO,CAAC,EAAE,mBAAmB,YAAA;IAGhD;;OAEG;IAEU,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC;IAI5C;;OAEG;IAEU,KAAK,IAAI,OAAO,CAAC,YAAY,CAAC;IAI3C;;OAEG;YACW,eAAe;CA0B9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-module.d.ts","sourceRoot":"","sources":["../../src/health/health-module.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAmB,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAGpE,qBAIa,YAAY;IACvB;;;OAGG;WACW,OAAO,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,YAAY;CAiC9E"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { HealthModule } from './health-module';
|
|
2
|
+
export { HealthController } from './controller';
|
|
3
|
+
export { HEALTH_INDICATORS_TOKEN, HEALTH_OPTIONS_TOKEN, type HealthIndicator, type HealthIndicatorResult, type HealthStatus, type HealthModuleOptions, } from './types';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/health/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EACjB,KAAK,mBAAmB,GACzB,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const HEALTH_INDICATORS_TOKEN: unique symbol;
|
|
2
|
+
export declare const HEALTH_OPTIONS_TOKEN: unique symbol;
|
|
3
|
+
export type HealthStatusValue = 'up' | 'down';
|
|
4
|
+
export interface HealthIndicatorResult {
|
|
5
|
+
status: HealthStatusValue;
|
|
6
|
+
details?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export interface HealthIndicator {
|
|
9
|
+
name: string;
|
|
10
|
+
check(): Promise<HealthIndicatorResult> | HealthIndicatorResult;
|
|
11
|
+
}
|
|
12
|
+
export interface HealthStatus {
|
|
13
|
+
status: HealthStatusValue;
|
|
14
|
+
details: Record<string, HealthIndicatorResult>;
|
|
15
|
+
}
|
|
16
|
+
export interface HealthModuleOptions {
|
|
17
|
+
/**
|
|
18
|
+
* 健康检查指示器列表
|
|
19
|
+
*/
|
|
20
|
+
indicators?: HealthIndicator[];
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/health/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,eAAiD,CAAC;AACtF,eAAO,MAAM,oBAAoB,eAA8C,CAAC;AAEhF,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,MAAM,CAAC;AAE9C,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,IAAI,OAAO,CAAC,qBAAqB,CAAC,GAAG,qBAAqB,CAAC;CACjE;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;CAChC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export { WebSocketGateway, OnOpen, OnMessage, OnClose, WebSocketGatewayRegistry,
|
|
|
21
21
|
export { LoggerExtension, LoggerModule, LogLevel, LOGGER_TOKEN, type Logger, type LoggerOptions, type LoggerModuleOptions, type LogEntry, } from './extensions';
|
|
22
22
|
export { SwaggerExtension, SwaggerModule, SwaggerGenerator, createSwaggerUIMiddleware, ApiTags, ApiOperation, ApiParam, ApiBody, ApiResponse, type SwaggerOptions, type SwaggerModuleOptions, type SwaggerDocument, type ApiOperationMetadata, type ApiParamMetadata, type ApiBodyMetadata, type ApiResponseMetadata, } from './swagger';
|
|
23
23
|
export { SecurityModule, SecurityContextHolder, AuthenticationManager, RoleBasedAccessDecisionManager, JwtAuthenticationProvider, OAuth2AuthenticationProvider, createSecurityFilter, type SecurityModuleConfig, type SecurityConfig, type SecurityContext, type Authentication, type AuthenticationProvider, type AuthenticationRequest, type Principal, type Credentials, type AccessDecisionManager, } from './security';
|
|
24
|
+
export { ConfigModule, ConfigService, CONFIG_SERVICE_TOKEN, type ConfigModuleOptions, } from './config';
|
|
25
|
+
export { HealthModule, type HealthIndicator, type HealthIndicatorResult, type HealthStatus, type HealthModuleOptions, HEALTH_INDICATORS_TOKEN, HEALTH_OPTIONS_TOKEN, } from './health';
|
|
24
26
|
export { JWTUtil, OAuth2Service, OAuth2Controller, Auth, getAuthMetadata, requiresAuth, checkRoles, OAUTH2_SERVICE_TOKEN, JWT_UTIL_TOKEN, type JWTConfig, type JWTPayload, type OAuth2Client, type OAuth2AuthorizationRequest, type OAuth2TokenRequest, type OAuth2TokenResponse, type UserInfo, type AuthContext, type AuthConfig, } from './auth';
|
|
25
27
|
export { PerformanceHarness, StressTester, type BenchmarkResult, type StressResult, } from './testing/harness';
|
|
26
28
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACpE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvG,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,EACL,MAAM,EACN,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACjE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EACL,sBAAsB,EACtB,8BAA8B,EAC9B,6BAA6B,EAC7B,oBAAoB,EACpB,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,UAAU,EACV,SAAS,EACT,eAAe,EACf,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,4BAA4B,EAC5B,uBAAuB,EACvB,KAAK,eAAe,GACrB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,gBAAgB,EAChB,MAAM,EACN,SAAS,EACT,OAAO,EACP,wBAAwB,EACxB,KAAK,uBAAuB,GAC7B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,QAAQ,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,yBAAyB,EACzB,OAAO,EACP,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,WAAW,EACX,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,mBAAmB,GACzB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,8BAA8B,EAC9B,yBAAyB,EACzB,4BAA4B,EAC5B,oBAAoB,EACpB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,qBAAqB,GAC3B,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -396,7 +396,7 @@ class Router {
|
|
|
396
396
|
}
|
|
397
397
|
return;
|
|
398
398
|
}
|
|
399
|
-
async
|
|
399
|
+
async preHandle(context) {
|
|
400
400
|
const method = context.method;
|
|
401
401
|
const path = this.normalizePath(context.path);
|
|
402
402
|
const route = this.findRoute(method, path);
|
|
@@ -413,6 +413,15 @@ class Router {
|
|
|
413
413
|
method: route.methodName
|
|
414
414
|
};
|
|
415
415
|
}
|
|
416
|
+
}
|
|
417
|
+
async handle(context) {
|
|
418
|
+
await this.preHandle(context);
|
|
419
|
+
const method = context.method;
|
|
420
|
+
const path = this.normalizePath(context.path);
|
|
421
|
+
const route = this.findRoute(method, path);
|
|
422
|
+
if (!route) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
416
425
|
return await route.execute(context);
|
|
417
426
|
}
|
|
418
427
|
getRoutes() {
|
|
@@ -1920,6 +1929,7 @@ class Application {
|
|
|
1920
1929
|
}
|
|
1921
1930
|
const registry = RouteRegistry.getInstance();
|
|
1922
1931
|
const router = registry.getRouter();
|
|
1932
|
+
await router.preHandle(context);
|
|
1923
1933
|
return await this.middlewarePipeline.run(context, async () => {
|
|
1924
1934
|
const response = await router.handle(context);
|
|
1925
1935
|
if (response) {
|
|
@@ -2445,6 +2455,8 @@ SwaggerModule = __legacyDecorateClassTS([
|
|
|
2445
2455
|
})
|
|
2446
2456
|
], SwaggerModule);
|
|
2447
2457
|
// src/security/context.ts
|
|
2458
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
2459
|
+
|
|
2448
2460
|
class SecurityContextImpl {
|
|
2449
2461
|
_authentication = null;
|
|
2450
2462
|
get authentication() {
|
|
@@ -2468,17 +2480,24 @@ class SecurityContextImpl {
|
|
|
2468
2480
|
}
|
|
2469
2481
|
|
|
2470
2482
|
class SecurityContextHolder {
|
|
2471
|
-
static
|
|
2483
|
+
static storage = new AsyncLocalStorage;
|
|
2472
2484
|
static getContext() {
|
|
2473
|
-
|
|
2474
|
-
if (!
|
|
2475
|
-
|
|
2485
|
+
let context = this.storage.getStore();
|
|
2486
|
+
if (!context) {
|
|
2487
|
+
context = new SecurityContextImpl;
|
|
2488
|
+
this.storage.enterWith(context);
|
|
2476
2489
|
}
|
|
2477
|
-
return
|
|
2490
|
+
return context;
|
|
2491
|
+
}
|
|
2492
|
+
static runWithContext(callback) {
|
|
2493
|
+
const existing = this.storage.getStore() ?? new SecurityContextImpl;
|
|
2494
|
+
return this.storage.run(existing, callback);
|
|
2478
2495
|
}
|
|
2479
2496
|
static clearContext() {
|
|
2480
|
-
const
|
|
2481
|
-
|
|
2497
|
+
const context = this.storage.getStore();
|
|
2498
|
+
if (context) {
|
|
2499
|
+
context.clear();
|
|
2500
|
+
}
|
|
2482
2501
|
}
|
|
2483
2502
|
}
|
|
2484
2503
|
// src/security/authentication-manager.ts
|
|
@@ -2532,7 +2551,10 @@ function getAuthMetadata(target, propertyKey) {
|
|
|
2532
2551
|
}
|
|
2533
2552
|
function requiresAuth(target, propertyKey) {
|
|
2534
2553
|
const config = getAuthMetadata(target, propertyKey);
|
|
2535
|
-
|
|
2554
|
+
if (!config) {
|
|
2555
|
+
return false;
|
|
2556
|
+
}
|
|
2557
|
+
return config.required !== false;
|
|
2536
2558
|
}
|
|
2537
2559
|
function checkRoles(target, propertyKey, userRoles = []) {
|
|
2538
2560
|
const config = getAuthMetadata(target, propertyKey);
|
|
@@ -2552,53 +2574,58 @@ function createSecurityFilter(config) {
|
|
|
2552
2574
|
extractToken
|
|
2553
2575
|
} = config;
|
|
2554
2576
|
return async (ctx, next) => {
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
const securityContext = SecurityContextHolder.getContext();
|
|
2560
|
-
try {
|
|
2561
|
-
const token = extractToken ? extractToken(ctx) : extractTokenFromHeader(ctx);
|
|
2562
|
-
if (token) {
|
|
2563
|
-
const request = {
|
|
2564
|
-
principal: "",
|
|
2565
|
-
credentials: token,
|
|
2566
|
-
type: "jwt"
|
|
2567
|
-
};
|
|
2568
|
-
const authentication = await authenticationManager.authenticate(request);
|
|
2569
|
-
if (authentication) {
|
|
2570
|
-
securityContext.setAuthentication(authentication);
|
|
2571
|
-
}
|
|
2577
|
+
return SecurityContextHolder.runWithContext(async () => {
|
|
2578
|
+
const path = ctx.path || ctx.request.url.split("?")[0].replace(/^https?:\/\/[^/]+/, "");
|
|
2579
|
+
if (excludePaths.some((exclude) => path.startsWith(exclude))) {
|
|
2580
|
+
return await next();
|
|
2572
2581
|
}
|
|
2573
|
-
const
|
|
2574
|
-
|
|
2575
|
-
const
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2582
|
+
const securityContext = SecurityContextHolder.getContext();
|
|
2583
|
+
try {
|
|
2584
|
+
const token = extractToken ? extractToken(ctx) : extractTokenFromHeader(ctx);
|
|
2585
|
+
if (token) {
|
|
2586
|
+
const request = {
|
|
2587
|
+
principal: "",
|
|
2588
|
+
credentials: token,
|
|
2589
|
+
type: "jwt"
|
|
2590
|
+
};
|
|
2591
|
+
const authentication = await authenticationManager.authenticate(request);
|
|
2592
|
+
if (authentication) {
|
|
2593
|
+
securityContext.setAuthentication(authentication);
|
|
2581
2594
|
}
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2595
|
+
}
|
|
2596
|
+
const handler = ctx.routeHandler;
|
|
2597
|
+
if (handler) {
|
|
2598
|
+
const controllerClass = handler.controller;
|
|
2599
|
+
const controllerTarget = controllerClass && controllerClass.prototype || controllerClass;
|
|
2600
|
+
const method = handler.method;
|
|
2601
|
+
if (requiresAuth(controllerTarget, method)) {
|
|
2602
|
+
const authentication = securityContext.authentication;
|
|
2603
|
+
if (!authentication || !authentication.authenticated) {
|
|
2604
|
+
throw new UnauthorizedException("Authentication required");
|
|
2605
|
+
}
|
|
2606
|
+
const requiredRoles = getRequiredRoles(controllerTarget, method);
|
|
2607
|
+
if (requiredRoles.length > 0) {
|
|
2608
|
+
const hasAccess = accessDecisionManager.decide(authentication, requiredRoles);
|
|
2609
|
+
if (!hasAccess) {
|
|
2610
|
+
const userRoles = authentication.authorities || [];
|
|
2611
|
+
throw new ForbiddenException(`Insufficient permissions. Required roles: ${requiredRoles.join(", ")}, User roles: ${userRoles.join(", ")}`);
|
|
2612
|
+
}
|
|
2588
2613
|
}
|
|
2589
2614
|
}
|
|
2615
|
+
} else if (defaultAuthRequired && !securityContext.isAuthenticated()) {
|
|
2616
|
+
throw new UnauthorizedException("Authentication required");
|
|
2590
2617
|
}
|
|
2591
|
-
|
|
2592
|
-
|
|
2618
|
+
ctx.security = securityContext;
|
|
2619
|
+
ctx.auth = {
|
|
2620
|
+
isAuthenticated: securityContext.isAuthenticated(),
|
|
2621
|
+
user: securityContext.getPrincipal(),
|
|
2622
|
+
payload: securityContext.authentication?.details
|
|
2623
|
+
};
|
|
2624
|
+
return await next();
|
|
2625
|
+
} finally {
|
|
2626
|
+
SecurityContextHolder.clearContext();
|
|
2593
2627
|
}
|
|
2594
|
-
|
|
2595
|
-
ctx.auth = {
|
|
2596
|
-
isAuthenticated: securityContext.isAuthenticated(),
|
|
2597
|
-
user: securityContext.getPrincipal(),
|
|
2598
|
-
payload: securityContext.authentication?.details
|
|
2599
|
-
};
|
|
2600
|
-
return await next();
|
|
2601
|
-
} finally {}
|
|
2628
|
+
});
|
|
2602
2629
|
};
|
|
2603
2630
|
}
|
|
2604
2631
|
function extractTokenFromHeader(ctx) {
|
|
@@ -3111,6 +3138,206 @@ SecurityModule = __legacyDecorateClassTS([
|
|
|
3111
3138
|
middlewares: []
|
|
3112
3139
|
})
|
|
3113
3140
|
], SecurityModule);
|
|
3141
|
+
// src/config/service.ts
|
|
3142
|
+
class ConfigService {
|
|
3143
|
+
config;
|
|
3144
|
+
namespace;
|
|
3145
|
+
constructor(config, namespace) {
|
|
3146
|
+
this.config = config;
|
|
3147
|
+
this.namespace = namespace;
|
|
3148
|
+
}
|
|
3149
|
+
getAll() {
|
|
3150
|
+
return this.config;
|
|
3151
|
+
}
|
|
3152
|
+
get(key, defaultValue) {
|
|
3153
|
+
const namespacedKey = this.applyNamespace(key);
|
|
3154
|
+
const value = this.getValueByPath(this.config, namespacedKey);
|
|
3155
|
+
if (value === undefined) {
|
|
3156
|
+
return defaultValue;
|
|
3157
|
+
}
|
|
3158
|
+
return value;
|
|
3159
|
+
}
|
|
3160
|
+
getRequired(key) {
|
|
3161
|
+
const value = this.get(key);
|
|
3162
|
+
if (value === undefined) {
|
|
3163
|
+
throw new Error(`Config value required for key: ${key}`);
|
|
3164
|
+
}
|
|
3165
|
+
return value;
|
|
3166
|
+
}
|
|
3167
|
+
withNamespace(namespace) {
|
|
3168
|
+
return new ConfigService(this.config, namespace);
|
|
3169
|
+
}
|
|
3170
|
+
applyNamespace(key) {
|
|
3171
|
+
if (!this.namespace) {
|
|
3172
|
+
return key;
|
|
3173
|
+
}
|
|
3174
|
+
if (!key) {
|
|
3175
|
+
return this.namespace;
|
|
3176
|
+
}
|
|
3177
|
+
if (key.startsWith(this.namespace + ".")) {
|
|
3178
|
+
return key;
|
|
3179
|
+
}
|
|
3180
|
+
return `${this.namespace}.${key}`;
|
|
3181
|
+
}
|
|
3182
|
+
getValueByPath(obj, path) {
|
|
3183
|
+
if (!path) {
|
|
3184
|
+
return obj;
|
|
3185
|
+
}
|
|
3186
|
+
const segments = path.split(".");
|
|
3187
|
+
let current = obj;
|
|
3188
|
+
for (const segment of segments) {
|
|
3189
|
+
if (current === undefined || current === null || typeof current !== "object") {
|
|
3190
|
+
return;
|
|
3191
|
+
}
|
|
3192
|
+
current = current[segment];
|
|
3193
|
+
}
|
|
3194
|
+
return current;
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3197
|
+
|
|
3198
|
+
// src/config/types.ts
|
|
3199
|
+
var CONFIG_SERVICE_TOKEN = Symbol("@dangao/bun-server:config:service");
|
|
3200
|
+
|
|
3201
|
+
// src/config/config-module.ts
|
|
3202
|
+
class ConfigModule {
|
|
3203
|
+
static forRoot(options = {}) {
|
|
3204
|
+
const providers2 = [];
|
|
3205
|
+
const env = ConfigModule.snapshotEnv();
|
|
3206
|
+
const defaultConfig = options.defaultConfig ?? {};
|
|
3207
|
+
const loadedConfig = options.load ? options.load(env) : {};
|
|
3208
|
+
const mergedConfig = {
|
|
3209
|
+
...defaultConfig,
|
|
3210
|
+
...loadedConfig
|
|
3211
|
+
};
|
|
3212
|
+
const service = new ConfigService(mergedConfig, options.namespace);
|
|
3213
|
+
if (options.validate) {
|
|
3214
|
+
options.validate(mergedConfig);
|
|
3215
|
+
}
|
|
3216
|
+
providers2.push({
|
|
3217
|
+
provide: CONFIG_SERVICE_TOKEN,
|
|
3218
|
+
useValue: service
|
|
3219
|
+
}, ConfigService);
|
|
3220
|
+
const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, ConfigModule) || {};
|
|
3221
|
+
const metadata = {
|
|
3222
|
+
...existingMetadata,
|
|
3223
|
+
providers: [...existingMetadata.providers || [], ...providers2],
|
|
3224
|
+
exports: [
|
|
3225
|
+
...existingMetadata.exports || [],
|
|
3226
|
+
CONFIG_SERVICE_TOKEN,
|
|
3227
|
+
ConfigService
|
|
3228
|
+
]
|
|
3229
|
+
};
|
|
3230
|
+
Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, ConfigModule);
|
|
3231
|
+
return ConfigModule;
|
|
3232
|
+
}
|
|
3233
|
+
static snapshotEnv() {
|
|
3234
|
+
const env = {};
|
|
3235
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
3236
|
+
env[key] = value;
|
|
3237
|
+
}
|
|
3238
|
+
return env;
|
|
3239
|
+
}
|
|
3240
|
+
}
|
|
3241
|
+
ConfigModule = __legacyDecorateClassTS([
|
|
3242
|
+
Module({
|
|
3243
|
+
providers: []
|
|
3244
|
+
})
|
|
3245
|
+
], ConfigModule);
|
|
3246
|
+
// src/health/types.ts
|
|
3247
|
+
var HEALTH_INDICATORS_TOKEN = Symbol("@dangao/bun-server:health:indicators");
|
|
3248
|
+
var HEALTH_OPTIONS_TOKEN = Symbol("@dangao/bun-server:health:options");
|
|
3249
|
+
|
|
3250
|
+
// src/health/controller.ts
|
|
3251
|
+
class HealthController {
|
|
3252
|
+
indicators;
|
|
3253
|
+
options;
|
|
3254
|
+
constructor(indicators = [], options) {
|
|
3255
|
+
this.indicators = indicators;
|
|
3256
|
+
this.options = options;
|
|
3257
|
+
}
|
|
3258
|
+
async health() {
|
|
3259
|
+
return await this.checkIndicators();
|
|
3260
|
+
}
|
|
3261
|
+
async ready() {
|
|
3262
|
+
return await this.checkIndicators();
|
|
3263
|
+
}
|
|
3264
|
+
async checkIndicators() {
|
|
3265
|
+
const details = {};
|
|
3266
|
+
for (const indicator of this.indicators || []) {
|
|
3267
|
+
try {
|
|
3268
|
+
const result = await indicator.check();
|
|
3269
|
+
details[indicator.name] = result;
|
|
3270
|
+
} catch (error) {
|
|
3271
|
+
details[indicator.name] = {
|
|
3272
|
+
status: "down",
|
|
3273
|
+
details: {
|
|
3274
|
+
error: error.message
|
|
3275
|
+
}
|
|
3276
|
+
};
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3279
|
+
const allUp = Object.keys(details).length === 0 || Object.values(details).every((result) => result.status === "up");
|
|
3280
|
+
return {
|
|
3281
|
+
status: allUp ? "up" : "down",
|
|
3282
|
+
details
|
|
3283
|
+
};
|
|
3284
|
+
}
|
|
3285
|
+
}
|
|
3286
|
+
__legacyDecorateClassTS([
|
|
3287
|
+
GET("/health"),
|
|
3288
|
+
__legacyMetadataTS("design:type", Function),
|
|
3289
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
3290
|
+
__legacyMetadataTS("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
3291
|
+
], HealthController.prototype, "health", null);
|
|
3292
|
+
__legacyDecorateClassTS([
|
|
3293
|
+
GET("/ready"),
|
|
3294
|
+
__legacyMetadataTS("design:type", Function),
|
|
3295
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
3296
|
+
__legacyMetadataTS("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
3297
|
+
], HealthController.prototype, "ready", null);
|
|
3298
|
+
HealthController = __legacyDecorateClassTS([
|
|
3299
|
+
Controller("/"),
|
|
3300
|
+
__legacyDecorateParamTS(0, Inject(HEALTH_INDICATORS_TOKEN)),
|
|
3301
|
+
__legacyDecorateParamTS(1, Inject(HEALTH_OPTIONS_TOKEN)),
|
|
3302
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
3303
|
+
Array,
|
|
3304
|
+
typeof HealthModuleOptions === "undefined" ? Object : HealthModuleOptions
|
|
3305
|
+
])
|
|
3306
|
+
], HealthController);
|
|
3307
|
+
|
|
3308
|
+
// src/health/health-module.ts
|
|
3309
|
+
class HealthModule {
|
|
3310
|
+
static forRoot(options = {}) {
|
|
3311
|
+
const providers2 = [];
|
|
3312
|
+
const indicators = options.indicators ?? [];
|
|
3313
|
+
providers2.push({
|
|
3314
|
+
provide: HEALTH_INDICATORS_TOKEN,
|
|
3315
|
+
useValue: indicators
|
|
3316
|
+
}, {
|
|
3317
|
+
provide: HEALTH_OPTIONS_TOKEN,
|
|
3318
|
+
useValue: options
|
|
3319
|
+
});
|
|
3320
|
+
const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, HealthModule) || {};
|
|
3321
|
+
const metadata = {
|
|
3322
|
+
...existingMetadata,
|
|
3323
|
+
controllers: [...existingMetadata.controllers || [], HealthController],
|
|
3324
|
+
providers: [...existingMetadata.providers || [], ...providers2],
|
|
3325
|
+
exports: [
|
|
3326
|
+
...existingMetadata.exports || [],
|
|
3327
|
+
HEALTH_INDICATORS_TOKEN,
|
|
3328
|
+
HEALTH_OPTIONS_TOKEN
|
|
3329
|
+
]
|
|
3330
|
+
};
|
|
3331
|
+
Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, HealthModule);
|
|
3332
|
+
return HealthModule;
|
|
3333
|
+
}
|
|
3334
|
+
}
|
|
3335
|
+
HealthModule = __legacyDecorateClassTS([
|
|
3336
|
+
Module({
|
|
3337
|
+
controllers: [HealthController],
|
|
3338
|
+
providers: []
|
|
3339
|
+
})
|
|
3340
|
+
], HealthModule);
|
|
3114
3341
|
// src/testing/harness.ts
|
|
3115
3342
|
import { performance as performance2 } from "perf_hooks";
|
|
3116
3343
|
|
|
@@ -3236,7 +3463,10 @@ export {
|
|
|
3236
3463
|
Injectable,
|
|
3237
3464
|
Inject,
|
|
3238
3465
|
HttpException,
|
|
3466
|
+
HealthModule,
|
|
3239
3467
|
Header,
|
|
3468
|
+
HEALTH_OPTIONS_TOKEN,
|
|
3469
|
+
HEALTH_INDICATORS_TOKEN,
|
|
3240
3470
|
GET,
|
|
3241
3471
|
ForbiddenException,
|
|
3242
3472
|
ExceptionFilterRegistry,
|
|
@@ -3245,6 +3475,9 @@ export {
|
|
|
3245
3475
|
Controller,
|
|
3246
3476
|
Context,
|
|
3247
3477
|
Container,
|
|
3478
|
+
ConfigService,
|
|
3479
|
+
ConfigModule,
|
|
3480
|
+
CONFIG_SERVICE_TOKEN,
|
|
3248
3481
|
BunServer,
|
|
3249
3482
|
BodyParser,
|
|
3250
3483
|
Body,
|
package/dist/router/router.d.ts
CHANGED
|
@@ -65,7 +65,12 @@ export declare class Router {
|
|
|
65
65
|
*/
|
|
66
66
|
findRoute(method: HttpMethod, path: string): Route | undefined;
|
|
67
67
|
/**
|
|
68
|
-
*
|
|
68
|
+
* 预处理请求:仅匹配路由并设置路径参数 / routeHandler,但不执行处理器
|
|
69
|
+
* 供安全过滤器等中间件在真正执行前基于路由元数据做鉴权
|
|
70
|
+
*/
|
|
71
|
+
preHandle(context: Context): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* 处理请求(包含路由匹配 + 执行)
|
|
69
74
|
* @param context - 请求上下文
|
|
70
75
|
* @returns 响应对象,如果没有匹配的路由则返回 undefined
|
|
71
76
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;GAGG;AACH,qBAAa,MAAM;IACjB;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA4B;IACzD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAE7C;;OAEG;IACH,OAAO,CAAC,aAAa;IAOrB;;;;;;;;OAQG;IACI,QAAQ,CACb,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,YAAY,EACrB,WAAW,GAAE,UAAU,EAAO,EAC9B,eAAe,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EACrD,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI;IAaP;;;;OAIG;IACI,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,GAAE,UAAU,EAAO,GAAG,IAAI;IAIrF;;;;OAIG;IACI,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,GAAE,UAAU,EAAO,GAAG,IAAI;IAItF;;;;OAIG;IACI,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,GAAE,UAAU,EAAO,GAAG,IAAI;IAIrF;;;;OAIG;IACI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,GAAE,UAAU,EAAO,GAAG,IAAI;IAIxF;;;;OAIG;IACI,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,GAAE,UAAU,EAAO,GAAG,IAAI;IAIvF;;;;;OAKG;IACI,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAerE;;;;OAIG;IACU,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;GAGG;AACH,qBAAa,MAAM;IACjB;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA4B;IACzD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAE7C;;OAEG;IACH,OAAO,CAAC,aAAa;IAOrB;;;;;;;;OAQG;IACI,QAAQ,CACb,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,YAAY,EACrB,WAAW,GAAE,UAAU,EAAO,EAC9B,eAAe,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EACrD,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI;IAaP;;;;OAIG;IACI,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,GAAE,UAAU,EAAO,GAAG,IAAI;IAIrF;;;;OAIG;IACI,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,GAAE,UAAU,EAAO,GAAG,IAAI;IAItF;;;;OAIG;IACI,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,GAAE,UAAU,EAAO,GAAG,IAAI;IAIrF;;;;OAIG;IACI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,GAAE,UAAU,EAAO,GAAG,IAAI;IAIxF;;;;OAIG;IACI,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,GAAE,UAAU,EAAO,GAAG,IAAI;IAIvF;;;;;OAKG;IACI,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAerE;;;OAGG;IACU,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBvD;;;;OAIG;IACU,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAepE;;;OAGG;IACI,SAAS,IAAI,SAAS,KAAK,EAAE;IAIpC;;OAEG;IACI,KAAK,IAAI,IAAI;CAKrB"}
|
|
@@ -33,13 +33,18 @@ export declare class SecurityContextImpl implements SecurityContext {
|
|
|
33
33
|
* 安全上下文持有者(ThreadLocal 模式)
|
|
34
34
|
*/
|
|
35
35
|
export declare class SecurityContextHolder {
|
|
36
|
-
private static readonly
|
|
36
|
+
private static readonly storage;
|
|
37
37
|
/**
|
|
38
38
|
* 获取当前上下文
|
|
39
39
|
*/
|
|
40
40
|
static getContext(): SecurityContextImpl;
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
42
|
+
* 在给定回调中运行,绑定独立的安全上下文(每个请求一个)
|
|
43
|
+
* @param callback - 要在安全上下文中执行的回调
|
|
44
|
+
*/
|
|
45
|
+
static runWithContext<T>(callback: () => T): T;
|
|
46
|
+
/**
|
|
47
|
+
* 清除当前上下文中的认证信息
|
|
43
48
|
*/
|
|
44
49
|
static clearContext(): void;
|
|
45
50
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/security/context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/security/context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1E;;GAEG;AACH,qBAAa,mBAAoB,YAAW,eAAe;IACzD,OAAO,CAAC,eAAe,CAA+B;IAEtD;;OAEG;IACH,IAAW,cAAc,IAAI,cAAc,GAAG,IAAI,CAEjD;IAED;;OAEG;IACI,iBAAiB,CAAC,cAAc,EAAE,cAAc,GAAG,IAAI,GAAG,IAAI;IAIrE;;OAEG;IACI,eAAe,IAAI,OAAO;IAIjC;;OAEG;IACI,YAAY,IAAI,SAAS,GAAG,IAAI;IAIvC;;OAEG;IACI,cAAc,IAAI,MAAM,EAAE;IAIjC;;OAEG;IACI,KAAK,IAAI,IAAI;CAGrB;AAED;;GAEG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAgD;IAE/E;;OAEG;WACW,UAAU,IAAI,mBAAmB;IAS/C;;;OAGG;WACW,cAAc,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC;IAKrD;;OAEG;WACW,YAAY,IAAI,IAAI;CAMnC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/security/filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAyB,MAAM,SAAS,CAAC;AAIrE;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC1D;;OAEG;IACH,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C;;OAEG;IACH,qBAAqB,CAAC,EAAE,8BAA8B,CAAC;IACvD;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,CAAC;CAChD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/security/filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAyB,MAAM,SAAS,CAAC;AAIrE;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC1D;;OAEG;IACH,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C;;OAEG;IACH,qBAAqB,CAAC,EAAE,8BAA8B,CAAC;IACvD;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,CAAC;CAChD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,UAAU,CA2F7E"}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
可扩展**:松耦合的模块系统、扩展系统与日志框架,既可以快速起步,也能按需裁剪。
|
|
32
32
|
- **Monorepo 友好**:原生支持 Bun workspaces,使用 `workspace:*`
|
|
33
33
|
协议管理内部依赖,配合 catalog 统一版本,完美适配多包协作场景。
|
|
34
|
-
-
|
|
34
|
+
- **完整测试矩阵**:内置单元/集成测试、压力与基准测试用例,Security 和 Swagger 模块测试覆盖完整,便于持续优化。
|
|
35
35
|
|
|
36
36
|
## 核心特性
|
|
37
37
|
|
|
@@ -43,6 +43,8 @@
|
|
|
43
43
|
**中间件管道**:支持全局/控制器/方法级中间件,内置日志、错误处理、CORS、文件上传、静态资源等。
|
|
44
44
|
- ✅ **输入校验**:声明式验证装饰器,直连 `ValidationError` 与异常过滤器。
|
|
45
45
|
- 📡 **WebSocket**:`@WebSocketGateway`、`@OnMessage` 等装饰器级开发体验。
|
|
46
|
+
- 📖 **Swagger/OpenAPI**:内置 Swagger 插件,支持 `@ApiTags`、`@ApiOperation`、`@ApiParam`、`@ApiBody`、`@ApiResponse` 等装饰器,自动生成 API 文档和 Swagger UI。
|
|
47
|
+
- 🔐 **安全认证**:内置 SecurityModule,支持 JWT 和 OAuth2 认证,提供 `@Auth()` 装饰器进行角色权限控制。
|
|
46
48
|
- 📚 **示例与文档**:多语言文档、基础/完整示例、基准脚本与最佳实践。
|
|
47
49
|
|
|
48
50
|
## 架构总览
|
|
@@ -126,11 +128,12 @@ bun --cwd=benchmark run bench:di # 仅运行 DI 基准
|
|
|
126
128
|
|
|
127
129
|
## 示例与扩展
|
|
128
130
|
|
|
129
|
-
- `examples/basic-app.ts`:最小可运行示例,覆盖 DI + Logger + Middleware。
|
|
130
|
-
- `examples/full-app.ts`:包含验证、文件上传、WebSocket
|
|
131
|
-
- `examples/multi-module-app.ts
|
|
132
|
-
- `
|
|
133
|
-
|
|
131
|
+
- `examples/basic-app.ts`:最小可运行示例,覆盖 DI + Logger + Middleware + Swagger + ConfigModule。
|
|
132
|
+
- `examples/full-app.ts`:包含验证、文件上传、WebSocket、复杂控制器,使用 ConfigModule 管理端口与中间件配置。
|
|
133
|
+
- `examples/multi-module-app.ts`:多模块示例,展示模块间的依赖关系和服务共享,使用 ConfigModule 统一管理应用配置。
|
|
134
|
+
- `examples/auth-app.ts`:完整的认证演示,包含 JWT + OAuth2 认证流程、前端演示页面,并通过 ConfigModule 管理应用标题和端口。
|
|
135
|
+
- `packages/bun-server/src/extensions/`:官方扩展(如
|
|
136
|
+
LoggerExtension、SwaggerExtension),可用于注册第三方能力。
|
|
134
137
|
|
|
135
138
|
## 性能与 Benchmark
|
|
136
139
|
|
|
@@ -153,10 +156,11 @@ bun benchmark/di.bench.ts
|
|
|
153
156
|
## 文档与多语言支持
|
|
154
157
|
|
|
155
158
|
- 中文默认文档位于 `docs/`
|
|
156
|
-
- `docs/api.md`
|
|
157
|
-
- `docs/guide.md`
|
|
158
|
-
- `docs/
|
|
159
|
-
- `docs/
|
|
159
|
+
- `docs/api.md` - API 参考文档
|
|
160
|
+
- `docs/guide.md` - 使用指南
|
|
161
|
+
- `docs/extensions.md` - 扩展系统说明(中间件、扩展、模块等)
|
|
162
|
+
- `docs/best-practices.md` - 最佳实践
|
|
163
|
+
- `docs/migration.md` - 迁移指南
|
|
160
164
|
- 英文草稿位于
|
|
161
165
|
`docs/en/`,与中文文件结构一致;如果缺失内容,请优先参考中文版本。
|
|
162
166
|
|