@keq-request/nestjs 5.0.0-beta.9 → 5.0.1
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/.turbo/turbo-build.log +17 -17
- package/CHANGELOG.md +136 -0
- package/__tests__/keq-module.spec.ts +203 -0
- package/dist/index.d.mts +99 -50
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +99 -50
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +206 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +176 -39
- package/dist/index.mjs.map +1 -1
- package/jest.config.cts +12 -2
- package/package.json +11 -3
- package/src/constants.ts +3 -0
- package/src/decorators/inject-keq-consumer.decorator.ts +26 -0
- package/src/index.ts +5 -1
- package/src/interfaces/index.ts +9 -0
- package/src/interfaces/keq-middleware-consumer.interface.ts +30 -0
- package/src/{types/keq-module-options.ts → interfaces/keq-module-options.interface.ts} +2 -1
- package/src/interfaces/keq-nest-middleware.interface.ts +6 -0
- package/src/keq-consumer.ts +34 -0
- package/src/keq-middleware-collector.ts +150 -0
- package/src/keq-middleware-consumer.ts +33 -0
- package/src/keq.module.ts +10 -83
- package/src/keq.module-definition.ts +0 -11
- package/src/types/index.ts +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,62 +1,111 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { KeqMiddleware } from "keq";
|
|
1
|
+
import { KeqExecutionContext, KeqMiddleware, KeqNext, KeqRequest } from "keq";
|
|
2
|
+
import { Type } from "@nestjs/common";
|
|
4
3
|
|
|
5
|
-
//#region src/
|
|
4
|
+
//#region src/keq.module.d.ts
|
|
5
|
+
declare class KeqModule {}
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region src/constants.d.ts
|
|
8
|
+
declare const KEQ_ROUTES: {
|
|
9
|
+
readonly ALL: symbol;
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/interfaces/keq-nest-middleware.interface.d.ts
|
|
13
|
+
interface KeqNestMiddleware {
|
|
14
|
+
use(ctx: KeqExecutionContext, next: KeqNext): void | PromiseLike<void>;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/keq-consumer.d.ts
|
|
18
|
+
/**
|
|
19
|
+
* 为指定 Keq 模块按路由注册中间件。
|
|
20
|
+
*
|
|
21
|
+
* Keq 模块由 `@keq-request/cli` 生成,通过
|
|
22
|
+
* {@link InjectKeqConsumer} 装饰器注入本实例。
|
|
23
|
+
*
|
|
24
|
+
* @typeParam T - 目标模块类
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* constructor(
|
|
29
|
+
* \@InjectKeqConsumer(GeneratedModule) consumer: KeqConsumer<GeneratedModule>,
|
|
30
|
+
* ) {
|
|
31
|
+
* consumer.apply(authMw).forRoutes('*')
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
declare class KeqConsumer<T = KeqModuleClass> {
|
|
36
|
+
private readonly keqRequest;
|
|
37
|
+
constructor(keqRequest: KeqRequest);
|
|
38
|
+
apply(...middlewares: Array<KeqNestMiddleware | KeqMiddleware>): KeqScopedConfigProxy<T>;
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/interfaces/keq-middleware-consumer.interface.d.ts
|
|
42
|
+
interface KeqRouteInfo {
|
|
43
|
+
host?: string;
|
|
44
|
+
method?: string;
|
|
45
|
+
pathname?: string;
|
|
46
|
+
}
|
|
47
|
+
interface KeqModuleClass extends Type<any> {
|
|
48
|
+
readonly KEQ_REQUEST: symbol;
|
|
49
|
+
readonly KEQ_CONSUMER: symbol;
|
|
50
|
+
}
|
|
51
|
+
/** forRoutes() 接受的路由目标(不再包含 KeqModuleClass,模块绑定通过 @InjectKeqConsumer 实现) */
|
|
52
|
+
type KeqRouteTarget = typeof KEQ_ROUTES.ALL | KeqRouteInfo;
|
|
53
|
+
interface KeqMiddlewareConfigProxy {
|
|
54
|
+
exclude(...routes: KeqRouteInfo[]): KeqMiddlewareConfigProxy;
|
|
55
|
+
forRoutes(...routes: KeqRouteTarget[]): KeqMiddlewareConsumer;
|
|
56
|
+
}
|
|
57
|
+
/** 模块绑定 Consumer 的配置代理,forRoutes() 返回 KeqConsumer<T> */
|
|
58
|
+
interface KeqScopedConfigProxy<T = KeqModuleClass> {
|
|
59
|
+
exclude(...routes: KeqRouteInfo[]): KeqScopedConfigProxy<T>;
|
|
60
|
+
forRoutes(...routes: KeqRouteTarget[]): KeqConsumer<T>;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/keq-middleware-consumer.d.ts
|
|
64
|
+
/**
|
|
65
|
+
* 全局中间件消费者,提供 `.apply().forRoutes()` API。
|
|
66
|
+
*
|
|
67
|
+
* `forRoutes()` 返回 `KeqMiddlewareConsumer` 自身,支持链式注册:
|
|
68
|
+
*
|
|
69
|
+
* ```ts
|
|
70
|
+
* consumer
|
|
71
|
+
* .apply(mw1).forRoutes(KEQ_ROUTES.ALL)
|
|
72
|
+
* .apply(mw2).forRoutes({ pathname: '/api/*' })
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* 模块级别的中间件请使用 `@InjectKeqConsumer(GeneratedModule)` 注入
|
|
76
|
+
* `KeqConsumer<GeneratedModule>`,其 `forRoutes()` 直接作用于目标模块。
|
|
77
|
+
*/
|
|
78
|
+
declare class KeqMiddlewareConsumer {
|
|
79
|
+
private readonly keqRequest;
|
|
80
|
+
constructor(keqRequest: KeqRequest);
|
|
81
|
+
apply(...middlewares: Array<KeqNestMiddleware | KeqMiddleware>): KeqMiddlewareConfigProxy;
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/interfaces/keq-module-options.interface.d.ts
|
|
6
85
|
interface KeqModuleOptions {
|
|
7
86
|
middlewares?: KeqMiddleware[];
|
|
87
|
+
isolate?: boolean;
|
|
8
88
|
}
|
|
9
89
|
//#endregion
|
|
10
|
-
//#region src/keq
|
|
11
|
-
declare const ConfigurableModuleClass: _$_nestjs_common0.ConfigurableModuleCls<KeqModuleOptions, "register", "create", {}>, MODULE_OPTIONS_TOKEN: string | symbol, OPTIONS_TYPE: KeqModuleOptions & Partial<{}>, ASYNC_OPTIONS_TYPE: _$_nestjs_common0.ConfigurableModuleAsyncOptions<KeqModuleOptions, "create"> & Partial<{}>;
|
|
12
|
-
//#endregion
|
|
13
|
-
//#region src/keq.module.d.ts
|
|
90
|
+
//#region src/decorators/inject-keq-consumer.decorator.d.ts
|
|
14
91
|
/**
|
|
15
|
-
*
|
|
92
|
+
* 注入绑定到指定 Keq Module 的 `KeqConsumer<T>`。
|
|
16
93
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
94
|
+
* 被注入的 Module Class 必须同时包含 `KEQ_REQUEST` 和 `KEQ_CONSUMER` 静态属性,
|
|
95
|
+
* 两者均由 keq CLI 生成。
|
|
19
96
|
*
|
|
20
|
-
*
|
|
21
|
-
* ```
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* // Asynchronous registration
|
|
28
|
-
* KeqModule.registerAsync({
|
|
29
|
-
* imports: [ConfigModule],
|
|
30
|
-
* useFactory: (config: ConfigService) => ({
|
|
31
|
-
* middlewares: [...]
|
|
32
|
-
* }),
|
|
33
|
-
* inject: [ConfigService]
|
|
34
|
-
* })
|
|
35
|
-
*
|
|
36
|
-
* // Inject in service
|
|
37
|
-
* class UserService {
|
|
38
|
-
* constructor(private readonly keqRequest: KeqRequest) {}
|
|
39
|
-
* async getUser(id: string) {
|
|
40
|
-
* return await this.keqRequest.get(`/users/${id}`).resolveWith('json')
|
|
41
|
-
* }
|
|
97
|
+
* 使用方式:
|
|
98
|
+
* ```ts
|
|
99
|
+
* constructor(
|
|
100
|
+
* \@InjectKeqConsumer(GeneratedModule) consumer: KeqConsumer<GeneratedModule>,
|
|
101
|
+
* ) {
|
|
102
|
+
* consumer.apply(mw).forRoutes('*')
|
|
42
103
|
* }
|
|
43
104
|
* ```
|
|
105
|
+
*
|
|
106
|
+
* @param moduleClass - 目标 KeqModule 类(需具有 `KEQ_REQUEST` 和 `KEQ_CONSUMER` symbol)
|
|
44
107
|
*/
|
|
45
|
-
declare
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
* @param options - Configuration options including middlewares
|
|
49
|
-
* @returns DynamicModule with KeqRequest provider
|
|
50
|
-
*/
|
|
51
|
-
static register(options: typeof OPTIONS_TYPE): DynamicModule;
|
|
52
|
-
/**
|
|
53
|
-
* Register the module with asynchronous options
|
|
54
|
-
* Useful when you need to inject dependencies like ConfigService
|
|
55
|
-
* @param options - Async configuration options
|
|
56
|
-
* @returns DynamicModule with KeqRequest provider
|
|
57
|
-
*/
|
|
58
|
-
static registerAsync(options: typeof ASYNC_OPTIONS_TYPE): DynamicModule;
|
|
59
|
-
}
|
|
60
|
-
//#endregion
|
|
61
|
-
export { KeqModule, KeqModuleOptions };
|
|
108
|
+
declare function InjectKeqConsumer<T extends KeqModuleClass>(moduleClass: T): ParameterDecorator;
|
|
109
|
+
//#endregion
|
|
110
|
+
export { InjectKeqConsumer, KEQ_ROUTES, KeqConsumer, type KeqMiddlewareConfigProxy, KeqMiddlewareConsumer, KeqModule, type KeqModuleClass, type KeqModuleOptions, type KeqNestMiddleware, type KeqRouteInfo, type KeqRouteTarget, type KeqScopedConfigProxy };
|
|
62
111
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/keq.module.ts","../src/constants.ts","../src/interfaces/keq-nest-middleware.interface.ts","../src/keq-consumer.ts","../src/interfaces/keq-middleware-consumer.interface.ts","../src/keq-middleware-consumer.ts","../src/interfaces/keq-module-options.interface.ts","../src/decorators/inject-keq-consumer.decorator.ts"],"mappings":";;;;cAaa,SAAA;;;cCbA,UAAA;EAAA,SAEH,GAAA;AAAA;;;UCCO,iBAAA;EACf,GAAA,CAAI,GAAA,EAAK,mBAAA,EAAqB,IAAA,EAAM,OAAA,UAAiB,WAAA;AAAA;;;AFCvD;;;;;;;;ACLA;;;;;;;;ACGA;AFEA,cGmBa,WAAA,KAAgB,cAAA;EAAA,iBACE,UAAA;cAAA,UAAA,EAAY,UAAA;EAEzC,KAAA,CAAA,GACK,WAAA,EAAa,KAAA,CAAM,iBAAA,GAAoB,aAAA,IACzC,oBAAA,CAAqB,CAAA;AAAA;;;UCvBT,YAAA;EACf,IAAA;EACA,MAAA;EACA,QAAA;AAAA;AAAA,UAGe,cAAA,SAAuB,IAAA;EAAA,SAC7B,WAAA;EAAA,SACA,YAAA;AAAA;;KAIC,cAAA,UAAwB,UAAA,CAAW,GAAA,GAAM,YAAA;AAAA,UAEpC,wBAAA;EACf,OAAA,IAAW,MAAA,EAAQ,YAAA,KAAiB,wBAAA;EACpC,SAAA,IAAa,MAAA,EAAQ,cAAA,KAAmB,qBAAA;AAAA;;UAIzB,oBAAA,KAAyB,cAAA;EACxC,OAAA,IAAW,MAAA,EAAQ,YAAA,KAAiB,oBAAA,CAAqB,CAAA;EACzD,SAAA,IAAa,MAAA,EAAQ,cAAA,KAAmB,WAAA,CAAY,CAAA;AAAA;;;AJvBtD;;;;;;;;ACLA;;;;;;ADKA,cKkBa,qBAAA;EAAA,iBACkB,UAAA;cAAA,UAAA,EAAY,UAAA;EAEzC,KAAA,CAAA,GACK,WAAA,EAAa,KAAA,CAAM,iBAAA,GAAoB,aAAA,IACzC,wBAAA;AAAA;;;UCzBY,gBAAA;EACf,WAAA,GAAc,aAAA;EACd,OAAA;AAAA;;;;;;ANAF;;;;;;;;ACLA;;;;;;iBMqBgB,iBAAA,WAA4B,cAAA,CAAA,CAC1C,WAAA,EAAa,CAAA,GACZ,kBAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,138 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
value: mod,
|
|
21
|
+
enumerable: true
|
|
22
|
+
}) : target, mod));
|
|
23
|
+
//#endregion
|
|
3
24
|
let _nestjs_common = require("@nestjs/common");
|
|
4
|
-
|
|
5
|
-
|
|
25
|
+
let keq = require("keq");
|
|
26
|
+
let picomatch = require("picomatch");
|
|
27
|
+
picomatch = __toESM(picomatch);
|
|
28
|
+
//#region src/constants.ts
|
|
29
|
+
const KEQ_ROUTES = { ALL: Symbol("KEQ_ROUTES.ALL") };
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/keq-middleware-collector.ts
|
|
32
|
+
/**
|
|
33
|
+
* 中间件收集器,收集中间件配置条目并应用到指定的 {@link KeqRequest} 实例。
|
|
34
|
+
*
|
|
35
|
+
* 通过 `apply()` → `forRoutes()` 链式 API 收集多组中间件条目,
|
|
36
|
+
* 在 `forRoutes()` 被调用时立即将中间件绑定到目标请求。
|
|
37
|
+
*
|
|
38
|
+
* 注意:该类并非 `@Injectable()`,由 Consumer 内部手动创建。
|
|
39
|
+
*
|
|
40
|
+
* @typeParam TConsumer - Consumer 类型(`KeqMiddlewareConsumer` 或 `KeqConsumer<T>`)
|
|
41
|
+
*/
|
|
42
|
+
var KeqMiddlewareCollector = class {
|
|
43
|
+
entries = [];
|
|
44
|
+
constructor(keqRequest, consumer) {
|
|
45
|
+
this.keqRequest = keqRequest;
|
|
46
|
+
this.consumer = consumer;
|
|
47
|
+
}
|
|
48
|
+
apply(middlewares) {
|
|
49
|
+
const entry = {
|
|
50
|
+
middlewares,
|
|
51
|
+
routes: []
|
|
52
|
+
};
|
|
53
|
+
const excludedRouteInfos = [];
|
|
54
|
+
this.entries.push(entry);
|
|
55
|
+
const { keqRequest, consumer } = this;
|
|
56
|
+
const proxy = {
|
|
57
|
+
exclude: (...routes) => {
|
|
58
|
+
excludedRouteInfos.push(...routes);
|
|
59
|
+
return proxy;
|
|
60
|
+
},
|
|
61
|
+
forRoutes: (...routes) => {
|
|
62
|
+
entry.routes = routes;
|
|
63
|
+
if (excludedRouteInfos.length > 0) entry.excludedRouteInfos = excludedRouteInfos;
|
|
64
|
+
this.applyTo(keqRequest);
|
|
65
|
+
return consumer;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
return proxy;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 将收集的所有中间件条目解析并应用到指定的 {@link KeqRequest} 实例。
|
|
72
|
+
*/
|
|
73
|
+
applyTo(keqRequest) {
|
|
74
|
+
for (const entry of this.entries) {
|
|
75
|
+
let resolved = entry.middlewares.map((m) => this.normalizeMiddleware(m));
|
|
76
|
+
if (entry.excludedRouteInfos && entry.excludedRouteInfos.length > 0) {
|
|
77
|
+
const excludedRoutes = entry.excludedRouteInfos.map((info) => this.buildRoute(info));
|
|
78
|
+
resolved = resolved.map((mw) => this.wrapWithExclusion(mw, excludedRoutes));
|
|
79
|
+
}
|
|
80
|
+
if (entry.routes.length === 0 || entry.routes.some((r) => r === KEQ_ROUTES.ALL)) for (const mw of resolved) keqRequest.use(mw);
|
|
81
|
+
else for (const routeTarget of entry.routes) {
|
|
82
|
+
if (routeTarget === KEQ_ROUTES.ALL) continue;
|
|
83
|
+
const route = this.buildRoute(routeTarget);
|
|
84
|
+
keqRequest.useRouter().route(route, resolved);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 标准化中间件:将不同形式的中间件统一为 {@link KeqMiddleware} 函数。
|
|
90
|
+
* - 若已是 {@link KeqMiddleware} 函数 → 直接返回
|
|
91
|
+
* - 若为 {@link KeqNestMiddleware} 实例对象 → 包装 `use` 方法为中间件函数
|
|
92
|
+
*/
|
|
93
|
+
normalizeMiddleware(m) {
|
|
94
|
+
if (this.isNestMiddlewareInstance(m)) return async (ctx, next) => {
|
|
95
|
+
await m.use(ctx, next);
|
|
96
|
+
};
|
|
97
|
+
return m;
|
|
98
|
+
}
|
|
99
|
+
isNestMiddlewareInstance(m) {
|
|
100
|
+
return typeof m === "object" && m !== null && "use" in m;
|
|
101
|
+
}
|
|
102
|
+
buildRoute(info) {
|
|
103
|
+
const routes = [];
|
|
104
|
+
if (info.host) {
|
|
105
|
+
const host = info.host;
|
|
106
|
+
routes.push((ctx) => ctx.request.url.host === host);
|
|
107
|
+
}
|
|
108
|
+
if (info.method) {
|
|
109
|
+
const method = info.method.toLowerCase();
|
|
110
|
+
routes.push((ctx) => ctx.request.method.toLowerCase() === method);
|
|
111
|
+
}
|
|
112
|
+
if (info.pathname) {
|
|
113
|
+
const isMatch = (0, picomatch.default)(info.pathname);
|
|
114
|
+
routes.push((ctx) => isMatch(ctx.request.url.pathname));
|
|
115
|
+
}
|
|
116
|
+
if (routes.length === 1) return routes[0];
|
|
117
|
+
return (0, keq.composeRoute)(routes);
|
|
118
|
+
}
|
|
119
|
+
wrapWithExclusion(middleware, excludedRoutes) {
|
|
120
|
+
const excluded = async (ctx, next) => {
|
|
121
|
+
if (await this.checkExcluded(ctx, excludedRoutes)) return next();
|
|
122
|
+
return middleware(ctx, next);
|
|
123
|
+
};
|
|
124
|
+
return excluded;
|
|
125
|
+
}
|
|
126
|
+
async checkExcluded(ctx, excludedRoutes) {
|
|
127
|
+
for (const route of excludedRoutes) if (await route(ctx)) return true;
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region \0@oxc-project+runtime@0.127.0/helpers/decorateMetadata.js
|
|
133
|
+
function __decorateMetadata(k, v) {
|
|
134
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
135
|
+
}
|
|
6
136
|
//#endregion
|
|
7
137
|
//#region \0@oxc-project+runtime@0.127.0/helpers/decorate.js
|
|
8
138
|
function __decorate(decorators, target, key, desc) {
|
|
@@ -12,47 +142,86 @@ function __decorate(decorators, target, key, desc) {
|
|
|
12
142
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
13
143
|
}
|
|
14
144
|
//#endregion
|
|
145
|
+
//#region src/keq-middleware-consumer.ts
|
|
146
|
+
var _ref;
|
|
147
|
+
let KeqMiddlewareConsumer = class KeqMiddlewareConsumer {
|
|
148
|
+
constructor(keqRequest) {
|
|
149
|
+
this.keqRequest = keqRequest;
|
|
150
|
+
}
|
|
151
|
+
apply(...middlewares) {
|
|
152
|
+
return new KeqMiddlewareCollector(this.keqRequest, this).apply(middlewares);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
KeqMiddlewareConsumer = __decorate([(0, _nestjs_common.Injectable)(), __decorateMetadata("design:paramtypes", [typeof (_ref = typeof keq.KeqRequest !== "undefined" && keq.KeqRequest) === "function" ? _ref : Object])], KeqMiddlewareConsumer);
|
|
156
|
+
//#endregion
|
|
15
157
|
//#region src/keq.module.ts
|
|
158
|
+
let KeqModule = class KeqModule {};
|
|
159
|
+
KeqModule = __decorate([(0, _nestjs_common.Global)(), (0, _nestjs_common.Module)({
|
|
160
|
+
providers: [{
|
|
161
|
+
provide: keq.KeqRequest,
|
|
162
|
+
useFactory: () => new keq.KeqRequest()
|
|
163
|
+
}, KeqMiddlewareConsumer],
|
|
164
|
+
exports: [keq.KeqRequest, KeqMiddlewareConsumer]
|
|
165
|
+
})], KeqModule);
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region src/keq-consumer.ts
|
|
16
168
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
169
|
+
* 为指定 Keq 模块按路由注册中间件。
|
|
170
|
+
*
|
|
171
|
+
* Keq 模块由 `@keq-request/cli` 生成,通过
|
|
172
|
+
* {@link InjectKeqConsumer} 装饰器注入本实例。
|
|
173
|
+
*
|
|
174
|
+
* @typeParam T - 目标模块类
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```ts
|
|
178
|
+
* constructor(
|
|
179
|
+
* \@InjectKeqConsumer(GeneratedModule) consumer: KeqConsumer<GeneratedModule>,
|
|
180
|
+
* ) {
|
|
181
|
+
* consumer.apply(authMw).forRoutes('*')
|
|
182
|
+
* }
|
|
183
|
+
* ```
|
|
19
184
|
*/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const request = new keq.KeqRequest();
|
|
24
|
-
if (config.middlewares) for (const middleware of config.middlewares) request.use(middleware);
|
|
25
|
-
return request;
|
|
26
|
-
},
|
|
27
|
-
inject: [MODULE_OPTIONS_TOKEN]
|
|
28
|
-
};
|
|
29
|
-
let KeqModule = class KeqModule extends ConfigurableModuleClass {
|
|
30
|
-
/**
|
|
31
|
-
* Register the module with synchronous options
|
|
32
|
-
* @param options - Configuration options including middlewares
|
|
33
|
-
* @returns DynamicModule with KeqRequest provider
|
|
34
|
-
*/
|
|
35
|
-
static register(options) {
|
|
36
|
-
const mo = super.register(options);
|
|
37
|
-
mo.providers.push(requestProvider);
|
|
38
|
-
mo.global = true;
|
|
39
|
-
return mo;
|
|
185
|
+
var KeqConsumer = class {
|
|
186
|
+
constructor(keqRequest) {
|
|
187
|
+
this.keqRequest = keqRequest;
|
|
40
188
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
* Useful when you need to inject dependencies like ConfigService
|
|
44
|
-
* @param options - Async configuration options
|
|
45
|
-
* @returns DynamicModule with KeqRequest provider
|
|
46
|
-
*/
|
|
47
|
-
static registerAsync(options) {
|
|
48
|
-
const mo = super.registerAsync(options);
|
|
49
|
-
mo.providers.push(requestProvider);
|
|
50
|
-
mo.global = true;
|
|
51
|
-
return mo;
|
|
189
|
+
apply(...middlewares) {
|
|
190
|
+
return new KeqMiddlewareCollector(this.keqRequest, this).apply(middlewares);
|
|
52
191
|
}
|
|
53
192
|
};
|
|
54
|
-
KeqModule = __decorate([(0, _nestjs_common.Global)()], KeqModule);
|
|
55
193
|
//#endregion
|
|
194
|
+
//#region src/decorators/inject-keq-consumer.decorator.ts
|
|
195
|
+
/**
|
|
196
|
+
* 注入绑定到指定 Keq Module 的 `KeqConsumer<T>`。
|
|
197
|
+
*
|
|
198
|
+
* 被注入的 Module Class 必须同时包含 `KEQ_REQUEST` 和 `KEQ_CONSUMER` 静态属性,
|
|
199
|
+
* 两者均由 keq CLI 生成。
|
|
200
|
+
*
|
|
201
|
+
* 使用方式:
|
|
202
|
+
* ```ts
|
|
203
|
+
* constructor(
|
|
204
|
+
* \@InjectKeqConsumer(GeneratedModule) consumer: KeqConsumer<GeneratedModule>,
|
|
205
|
+
* ) {
|
|
206
|
+
* consumer.apply(mw).forRoutes('*')
|
|
207
|
+
* }
|
|
208
|
+
* ```
|
|
209
|
+
*
|
|
210
|
+
* @param moduleClass - 目标 KeqModule 类(需具有 `KEQ_REQUEST` 和 `KEQ_CONSUMER` symbol)
|
|
211
|
+
*/
|
|
212
|
+
function InjectKeqConsumer(moduleClass) {
|
|
213
|
+
return (0, _nestjs_common.Inject)(moduleClass.KEQ_CONSUMER);
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
exports.InjectKeqConsumer = InjectKeqConsumer;
|
|
217
|
+
exports.KEQ_ROUTES = KEQ_ROUTES;
|
|
218
|
+
exports.KeqConsumer = KeqConsumer;
|
|
219
|
+
Object.defineProperty(exports, "KeqMiddlewareConsumer", {
|
|
220
|
+
enumerable: true,
|
|
221
|
+
get: function() {
|
|
222
|
+
return KeqMiddlewareConsumer;
|
|
223
|
+
}
|
|
224
|
+
});
|
|
56
225
|
Object.defineProperty(exports, "KeqModule", {
|
|
57
226
|
enumerable: true,
|
|
58
227
|
get: function() {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["ConfigurableModuleBuilder","KeqRequest"],"sources":["../src/keq.module-definition.ts","../src/keq.module.ts"],"sourcesContent":["\nimport { ConfigurableModuleBuilder } from '@nestjs/common'\nimport { KeqModuleOptions } from './types/keq-module-options'\n\n\nexport const {\n ConfigurableModuleClass,\n MODULE_OPTIONS_TOKEN,\n OPTIONS_TYPE,\n ASYNC_OPTIONS_TYPE,\n} = new ConfigurableModuleBuilder<KeqModuleOptions>().build()\n","\nimport { KeqRequest } from 'keq'\nimport { DynamicModule, Global, Provider } from '@nestjs/common'\nimport { ASYNC_OPTIONS_TYPE, ConfigurableModuleClass, MODULE_OPTIONS_TOKEN, OPTIONS_TYPE } from './keq.module-definition.js'\nimport { KeqModuleOptions } from './types/index.js'\n\n\n/**\n * Provider that creates and configures a KeqRequest instance\n * Applies any middlewares defined in the module options\n */\nconst requestProvider: Provider = {\n provide: KeqRequest,\n useFactory: (config: KeqModuleOptions) => {\n const request = new KeqRequest()\n\n if (config.middlewares) {\n for (const middleware of config.middlewares) {\n request.use(middleware)\n }\n }\n\n return request\n },\n inject: [MODULE_OPTIONS_TOKEN],\n}\n\n/**\n * KeqModule - Dynamic module for integrating Keq HTTP client with NestJS\n *\n * This module is global, so KeqRequest can be injected anywhere in your application\n * without needing to import the module in every feature module.\n *\n * @example\n * ```typescript\n * // Synchronous registration\n * KeqModule.register({\n * middlewares: [...]\n * })\n *\n * // Asynchronous registration\n * KeqModule.registerAsync({\n * imports: [ConfigModule],\n * useFactory: (config: ConfigService) => ({\n * middlewares: [...]\n * }),\n * inject: [ConfigService]\n * })\n *\n * // Inject in service\n * class UserService {\n * constructor(private readonly keqRequest: KeqRequest) {}\n * async getUser(id: string) {\n * return await this.keqRequest.get(`/users/${id}`).resolveWith('json')\n * }\n * }\n * ```\n */\n@Global()\nexport class KeqModule extends ConfigurableModuleClass {\n /**\n * Register the module with synchronous options\n * @param options - Configuration options including middlewares\n * @returns DynamicModule with KeqRequest provider\n */\n static register(options: typeof OPTIONS_TYPE): DynamicModule {\n const mo = super.register(options)\n mo.providers!.push(requestProvider)\n mo.global = true\n\n return mo\n }\n\n /**\n * Register the module with asynchronous options\n * Useful when you need to inject dependencies like ConfigService\n * @param options - Async configuration options\n * @returns DynamicModule with KeqRequest provider\n */\n static registerAsync(options: typeof ASYNC_OPTIONS_TYPE): DynamicModule {\n const mo = super.registerAsync(options)\n mo.providers!.push(requestProvider)\n mo.global = true\n\n return mo\n }\n}\n"],"mappings":";;;;AAKA,MAAa,EACX,yBACA,sBACA,cACA,uBACE,IAAIA,eAAAA,2BAA6C,CAAC,OAAO;;;;;;;;;;;;;;;ACC7D,MAAM,kBAA4B;CAChC,SAASC,IAAAA;CACT,aAAa,WAA6B;EACxC,MAAM,UAAU,IAAIA,IAAAA,YAAY;AAEhC,MAAI,OAAO,YACT,MAAK,MAAM,cAAc,OAAO,YAC9B,SAAQ,IAAI,WAAW;AAI3B,SAAO;;CAET,QAAQ,CAAC,qBAAqB;CAC/B;AAkCM,IAAA,YAAA,MAAM,kBAAkB,wBAAwB;;;;;;CAMrD,OAAO,SAAS,SAA6C;EAC3D,MAAM,KAAK,MAAM,SAAS,QAAQ;AAClC,KAAG,UAAW,KAAK,gBAAgB;AACnC,KAAG,SAAS;AAEZ,SAAO;;;;;;;;CAST,OAAO,cAAc,SAAmD;EACtE,MAAM,KAAK,MAAM,cAAc,QAAQ;AACvC,KAAG,UAAW,KAAK,gBAAgB;AACnC,KAAG,SAAS;AAEZ,SAAO;;;oDA1BF,CAAA,EAAA,UAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["KeqRequest"],"sources":["../src/constants.ts","../src/keq-middleware-collector.ts","../src/keq-middleware-consumer.ts","../src/keq.module.ts","../src/keq-consumer.ts","../src/decorators/inject-keq-consumer.decorator.ts"],"sourcesContent":["export const KEQ_ROUTES = {\n ALL: Symbol('KEQ_ROUTES.ALL'),\n} as const\n","import type { KeqExecutionContext, KeqMiddleware, KeqRoute } from 'keq'\nimport { composeRoute, KeqRequest } from 'keq'\nimport picomatch from 'picomatch'\nimport { KEQ_ROUTES } from './constants.js'\nimport type { KeqMiddlewareConfigProxy, KeqRouteTarget, KeqRouteInfo } from './interfaces/keq-middleware-consumer.interface.js'\nimport type { KeqNestMiddleware } from './interfaces/keq-nest-middleware.interface.js'\n\n\n/** 单条中间件注册条目 */\ninterface MiddlewareEntry {\n middlewares: Array<KeqNestMiddleware | KeqMiddleware>\n routes: KeqRouteTarget[]\n excludedRouteInfos?: KeqRouteInfo[]\n}\n\n/**\n * 中间件收集器,收集中间件配置条目并应用到指定的 {@link KeqRequest} 实例。\n *\n * 通过 `apply()` → `forRoutes()` 链式 API 收集多组中间件条目,\n * 在 `forRoutes()` 被调用时立即将中间件绑定到目标请求。\n *\n * 注意:该类并非 `@Injectable()`,由 Consumer 内部手动创建。\n *\n * @typeParam TConsumer - Consumer 类型(`KeqMiddlewareConsumer` 或 `KeqConsumer<T>`)\n */\nexport class KeqMiddlewareCollector<TConsumer extends object = object> {\n private entries: MiddlewareEntry[] = []\n\n constructor(\n private readonly keqRequest: KeqRequest,\n private readonly consumer: TConsumer,\n ) {}\n\n apply(\n middlewares: Array<KeqNestMiddleware | KeqMiddleware>,\n ): KeqMiddlewareConfigProxy {\n const entry: MiddlewareEntry = { middlewares, routes: [] }\n const excludedRouteInfos: KeqRouteInfo[] = []\n this.entries.push(entry)\n\n const { keqRequest, consumer } = this\n\n const proxy = {\n exclude: (...routes: KeqRouteInfo[]) => {\n excludedRouteInfos.push(...routes)\n return proxy\n },\n forRoutes: (...routes: KeqRouteTarget[]) => {\n entry.routes = routes\n if (excludedRouteInfos.length > 0) {\n entry.excludedRouteInfos = excludedRouteInfos\n }\n this.applyTo(keqRequest)\n return consumer\n },\n }\n return proxy as unknown as KeqMiddlewareConfigProxy\n }\n\n /**\n * 将收集的所有中间件条目解析并应用到指定的 {@link KeqRequest} 实例。\n */\n applyTo(keqRequest: KeqRequest): void {\n for (const entry of this.entries) {\n let resolved = entry.middlewares.map((m) => this.normalizeMiddleware(m))\n\n if (entry.excludedRouteInfos && entry.excludedRouteInfos.length > 0) {\n const excludedRoutes = entry.excludedRouteInfos.map((info) => this.buildRoute(info))\n resolved = resolved.map((mw) => this.wrapWithExclusion(mw, excludedRoutes))\n }\n\n const isGlobal\n = entry.routes.length === 0 || entry.routes.some((r) => r === KEQ_ROUTES.ALL)\n\n if (isGlobal) {\n for (const mw of resolved) keqRequest.use(mw)\n } else {\n for (const routeTarget of entry.routes) {\n if (routeTarget === KEQ_ROUTES.ALL) continue\n const route = this.buildRoute(routeTarget as KeqRouteInfo)\n keqRequest.useRouter().route(route, resolved)\n }\n }\n }\n }\n\n // ─── 中间件标准化 ────────────────────────────────────\n\n /**\n * 标准化中间件:将不同形式的中间件统一为 {@link KeqMiddleware} 函数。\n * - 若已是 {@link KeqMiddleware} 函数 → 直接返回\n * - 若为 {@link KeqNestMiddleware} 实例对象 → 包装 `use` 方法为中间件函数\n */\n private normalizeMiddleware(\n m: KeqNestMiddleware | KeqMiddleware,\n ): KeqMiddleware {\n if (this.isNestMiddlewareInstance(m)) {\n return async (ctx, next) => {\n await m.use(ctx, next)\n }\n }\n return m\n }\n\n private isNestMiddlewareInstance(\n m: KeqNestMiddleware | KeqMiddleware,\n ): m is KeqNestMiddleware {\n return typeof m === 'object' && m !== null && 'use' in m\n }\n\n // ─── 路由构建 ─────────────────────────────────────────\n\n private buildRoute(info: KeqRouteInfo): KeqRoute {\n const routes: KeqRoute[] = []\n if (info.host) {\n const host = info.host\n routes.push((ctx) => ctx.request.url.host === host)\n }\n if (info.method) {\n const method = info.method.toLowerCase()\n routes.push((ctx) => ctx.request.method.toLowerCase() === method)\n }\n if (info.pathname) {\n const isMatch: (test: string) => boolean = picomatch(info.pathname)\n routes.push((ctx) => isMatch(ctx.request.url.pathname))\n }\n if (routes.length === 1) return routes[0]\n return composeRoute(routes)\n }\n\n private wrapWithExclusion(middleware: KeqMiddleware, excludedRoutes: KeqRoute[]): KeqMiddleware {\n const excluded: KeqMiddleware = async (ctx, next) => {\n if (await this.checkExcluded(ctx, excludedRoutes)) {\n return next()\n }\n return middleware(ctx, next)\n }\n return excluded\n }\n\n private async checkExcluded(\n ctx: KeqExecutionContext,\n excludedRoutes: KeqRoute[],\n ): Promise<boolean> {\n for (const route of excludedRoutes) {\n if (await route(ctx)) return true\n }\n return false\n }\n}\n","import { Injectable } from '@nestjs/common'\nimport type { KeqMiddleware } from 'keq'\nimport { KeqRequest } from 'keq'\nimport type { KeqMiddlewareConfigProxy } from './interfaces/keq-middleware-consumer.interface.js'\nimport type { KeqNestMiddleware } from './interfaces/keq-nest-middleware.interface.js'\nimport { KeqMiddlewareCollector } from './keq-middleware-collector.js'\n\n\n/**\n * 全局中间件消费者,提供 `.apply().forRoutes()` API。\n *\n * `forRoutes()` 返回 `KeqMiddlewareConsumer` 自身,支持链式注册:\n *\n * ```ts\n * consumer\n * .apply(mw1).forRoutes(KEQ_ROUTES.ALL)\n * .apply(mw2).forRoutes({ pathname: '/api/*' })\n * ```\n *\n * 模块级别的中间件请使用 `@InjectKeqConsumer(GeneratedModule)` 注入\n * `KeqConsumer<GeneratedModule>`,其 `forRoutes()` 直接作用于目标模块。\n */\n@Injectable()\nexport class KeqMiddlewareConsumer {\n constructor(private readonly keqRequest: KeqRequest) {}\n\n apply(\n ...middlewares: Array<KeqNestMiddleware | KeqMiddleware>\n ): KeqMiddlewareConfigProxy {\n const collector = new KeqMiddlewareCollector(this.keqRequest, this)\n return collector.apply(middlewares)\n }\n}\n","import { Global, Module } from '@nestjs/common'\nimport { KeqRequest } from 'keq'\nimport { KeqMiddlewareConsumer } from './keq-middleware-consumer.js'\n\n\n@Global()\n@Module({\n providers: [\n { provide: KeqRequest, useFactory: () => new KeqRequest() },\n KeqMiddlewareConsumer,\n ],\n exports: [KeqRequest, KeqMiddlewareConsumer],\n})\nexport class KeqModule {}\n","import type { KeqMiddleware } from 'keq'\nimport { KeqRequest } from 'keq'\nimport type { KeqModuleClass, KeqScopedConfigProxy } from './interfaces/keq-middleware-consumer.interface.js'\nimport type { KeqNestMiddleware } from './interfaces/keq-nest-middleware.interface.js'\nimport { KeqMiddlewareCollector } from './keq-middleware-collector.js'\n\n\n/**\n * 为指定 Keq 模块按路由注册中间件。\n *\n * Keq 模块由 `@keq-request/cli` 生成,通过\n * {@link InjectKeqConsumer} 装饰器注入本实例。\n *\n * @typeParam T - 目标模块类\n *\n * @example\n * ```ts\n * constructor(\n * \\@InjectKeqConsumer(GeneratedModule) consumer: KeqConsumer<GeneratedModule>,\n * ) {\n * consumer.apply(authMw).forRoutes('*')\n * }\n * ```\n */\nexport class KeqConsumer<T = KeqModuleClass> {\n constructor(private readonly keqRequest: KeqRequest) {}\n\n apply(\n ...middlewares: Array<KeqNestMiddleware | KeqMiddleware>\n ): KeqScopedConfigProxy<T> {\n const collector = new KeqMiddlewareCollector(this.keqRequest, this)\n return collector.apply(middlewares) as unknown as KeqScopedConfigProxy<T>\n }\n}\n","import { Inject } from '@nestjs/common'\nimport type { KeqModuleClass } from '../interfaces/keq-middleware-consumer.interface.js'\n\n\n/**\n * 注入绑定到指定 Keq Module 的 `KeqConsumer<T>`。\n *\n * 被注入的 Module Class 必须同时包含 `KEQ_REQUEST` 和 `KEQ_CONSUMER` 静态属性,\n * 两者均由 keq CLI 生成。\n *\n * 使用方式:\n * ```ts\n * constructor(\n * \\@InjectKeqConsumer(GeneratedModule) consumer: KeqConsumer<GeneratedModule>,\n * ) {\n * consumer.apply(mw).forRoutes('*')\n * }\n * ```\n *\n * @param moduleClass - 目标 KeqModule 类(需具有 `KEQ_REQUEST` 和 `KEQ_CONSUMER` symbol)\n */\nexport function InjectKeqConsumer<T extends KeqModuleClass>(\n moduleClass: T,\n): ParameterDecorator {\n return Inject(moduleClass.KEQ_CONSUMER)\n}\n"],"mappings":"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"}
|