@keq-request/nestjs 5.0.0-beta.12 → 5.0.0-beta.14

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.js CHANGED
@@ -22,23 +22,37 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
  }) : target, mod));
23
23
  //#endregion
24
24
  let _nestjs_common = require("@nestjs/common");
25
- let _nestjs_core = require("@nestjs/core");
26
25
  let keq = require("keq");
27
26
  let picomatch = require("picomatch");
28
27
  picomatch = __toESM(picomatch);
29
28
  //#region src/constants.ts
30
29
  const KEQ_ROUTES = { ALL: Symbol("KEQ_ROUTES.ALL") };
31
30
  //#endregion
32
- //#region src/keq-middleware-consumer.ts
33
- var KeqMiddlewareConsumerImpl = class {
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 {
34
43
  entries = [];
35
- apply(...middlewares) {
44
+ constructor(keqRequest, consumer) {
45
+ this.keqRequest = keqRequest;
46
+ this.consumer = consumer;
47
+ }
48
+ apply(middlewares) {
36
49
  const entry = {
37
50
  middlewares,
38
51
  routes: []
39
52
  };
40
53
  const excludedRouteInfos = [];
41
54
  this.entries.push(entry);
55
+ const { keqRequest, consumer } = this;
42
56
  const proxy = {
43
57
  exclude: (...routes) => {
44
58
  excludedRouteInfos.push(...routes);
@@ -47,14 +61,18 @@ var KeqMiddlewareConsumerImpl = class {
47
61
  forRoutes: (...routes) => {
48
62
  entry.routes = routes;
49
63
  if (excludedRouteInfos.length > 0) entry.excludedRouteInfos = excludedRouteInfos;
50
- return this;
64
+ this.applyTo(keqRequest);
65
+ return consumer;
51
66
  }
52
67
  };
53
68
  return proxy;
54
69
  }
55
- applyTo(keqRequest, moduleRef) {
70
+ /**
71
+ * 将收集的所有中间件条目解析并应用到指定的 {@link KeqRequest} 实例。
72
+ */
73
+ applyTo(keqRequest) {
56
74
  for (const entry of this.entries) {
57
- let resolved = entry.middlewares.map((m) => this.resolveMiddleware(m, moduleRef));
75
+ let resolved = entry.middlewares.map((m) => this.normalizeMiddleware(m));
58
76
  if (entry.excludedRouteInfos && entry.excludedRouteInfos.length > 0) {
59
77
  const excludedRoutes = entry.excludedRouteInfos.map((info) => this.buildRoute(info));
60
78
  resolved = resolved.map((mw) => this.wrapWithExclusion(mw, excludedRoutes));
@@ -62,31 +80,25 @@ var KeqMiddlewareConsumerImpl = class {
62
80
  if (entry.routes.length === 0 || entry.routes.some((r) => r === KEQ_ROUTES.ALL)) for (const mw of resolved) keqRequest.use(mw);
63
81
  else for (const routeTarget of entry.routes) {
64
82
  if (routeTarget === KEQ_ROUTES.ALL) continue;
65
- if (this.isKeqModuleClass(routeTarget)) {
66
- const targetRequest = moduleRef.get(routeTarget.KEQ_REQUEST, { strict: false });
67
- if (targetRequest) for (const mw of resolved) targetRequest.use(mw);
68
- } else {
69
- const route = this.buildRoute(routeTarget);
70
- keqRequest.useRouter().route(route, resolved);
71
- }
83
+ const route = this.buildRoute(routeTarget);
84
+ keqRequest.useRouter().route(route, resolved);
72
85
  }
73
86
  }
74
87
  }
75
- isKeqModuleClass(route) {
76
- return typeof route === "function" && "KEQ_REQUEST" in route && typeof route.KEQ_REQUEST === "symbol";
77
- }
78
- isNestMiddlewareClass(m) {
79
- return typeof m === "function" && m.prototype !== void 0 && "use" in m.prototype;
80
- }
81
- resolveMiddleware(m, moduleRef) {
82
- if (this.isNestMiddlewareClass(m)) {
83
- const instance = moduleRef.get(m, { strict: false });
84
- return async (ctx, next) => {
85
- await instance.use(ctx, next);
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
+ };
88
97
  return m;
89
98
  }
99
+ isNestMiddlewareInstance(m) {
100
+ return typeof m === "object" && m !== null && "use" in m;
101
+ }
90
102
  buildRoute(info) {
91
103
  const routes = [];
92
104
  if (info.host) {
@@ -117,11 +129,6 @@ var KeqMiddlewareConsumerImpl = class {
117
129
  }
118
130
  };
119
131
  //#endregion
120
- //#region src/utils/has-configure-keq-middleware.ts
121
- function hasConfigureKeqMiddleware(instance) {
122
- return instance !== null && instance !== void 0 && typeof instance.configureKeqMiddleware === "function";
123
- }
124
- //#endregion
125
132
  //#region \0@oxc-project+runtime@0.127.0/helpers/decorateMetadata.js
126
133
  function __decorateMetadata(k, v) {
127
134
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
@@ -135,42 +142,86 @@ function __decorate(decorators, target, key, desc) {
135
142
  return c > 3 && r && Object.defineProperty(target, key, r), r;
136
143
  }
137
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
138
157
  //#region src/keq.module.ts
139
- var _ref, _ref2, _ref3;
140
- let KeqModule = class KeqModule {
141
- constructor(modulesContainer, moduleRef, keqRequest) {
142
- this.modulesContainer = modulesContainer;
143
- this.moduleRef = moduleRef;
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
168
+ /**
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
+ * ```
184
+ */
185
+ var KeqConsumer = class {
186
+ constructor(keqRequest) {
144
187
  this.keqRequest = keqRequest;
145
188
  }
146
- onModuleInit() {
147
- for (const [, moduleWrapper] of this.modulesContainer) {
148
- const instance = moduleWrapper.instance;
149
- if (hasConfigureKeqMiddleware(instance)) {
150
- const consumer = new KeqMiddlewareConsumerImpl();
151
- instance.configureKeqMiddleware(consumer);
152
- consumer.applyTo(this.keqRequest, this.moduleRef);
153
- }
154
- }
189
+ apply(...middlewares) {
190
+ return new KeqMiddlewareCollector(this.keqRequest, this).apply(middlewares);
155
191
  }
156
192
  };
157
- KeqModule = __decorate([
158
- (0, _nestjs_common.Global)(),
159
- (0, _nestjs_common.Module)({
160
- providers: [{
161
- provide: keq.KeqRequest,
162
- useFactory: () => new keq.KeqRequest()
163
- }],
164
- exports: [keq.KeqRequest]
165
- }),
166
- __decorateMetadata("design:paramtypes", [
167
- typeof (_ref = typeof _nestjs_core.ModulesContainer !== "undefined" && _nestjs_core.ModulesContainer) === "function" ? _ref : Object,
168
- typeof (_ref2 = typeof _nestjs_core.ModuleRef !== "undefined" && _nestjs_core.ModuleRef) === "function" ? _ref2 : Object,
169
- typeof (_ref3 = typeof keq.KeqRequest !== "undefined" && keq.KeqRequest) === "function" ? _ref3 : Object
170
- ])
171
- ], KeqModule);
172
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;
173
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
+ });
174
225
  Object.defineProperty(exports, "KeqModule", {
175
226
  enumerable: true,
176
227
  get: function() {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["KeqRequest"],"sources":["../src/constants.ts","../src/keq-middleware-consumer.ts","../src/utils/has-configure-keq-middleware.ts","../src/keq.module.ts"],"sourcesContent":["export const KEQ_ROUTES = {\n ALL: Symbol('KEQ_ROUTES.ALL'),\n} as const\n","import type { Type } from '@nestjs/common'\nimport type { ModuleRef } from '@nestjs/core'\nimport type { KeqExecutionContext, KeqMiddleware, KeqRoute } from 'keq'\nimport { composeRoute, KeqRequest } from 'keq'\nimport picomatch from 'picomatch'\nimport { KEQ_ROUTES } from './constants.js'\nimport type { KeqMiddlewareConfigProxy, KeqMiddlewareConsumer, KeqModuleClass, KeqRouteInfo } from './interfaces/keq-middleware-consumer.interface.js'\nimport type { KeqNestMiddleware } from './interfaces/keq-nest-middleware.interface.js'\n\n\ninterface MiddlewareEntry {\n middlewares: Array<Type<KeqNestMiddleware> | KeqMiddleware>\n routes: Array<typeof KEQ_ROUTES.ALL | KeqRouteInfo | KeqModuleClass>\n excludedRouteInfos?: KeqRouteInfo[]\n}\n\nexport class KeqMiddlewareConsumerImpl implements KeqMiddlewareConsumer {\n private entries: MiddlewareEntry[] = []\n\n apply(...middlewares: Array<Type<KeqNestMiddleware> | KeqMiddleware>): KeqMiddlewareConfigProxy {\n const entry: MiddlewareEntry = { middlewares, routes: [] }\n const excludedRouteInfos: KeqRouteInfo[] = []\n this.entries.push(entry)\n\n const proxy: KeqMiddlewareConfigProxy = {\n exclude: (...routes) => {\n excludedRouteInfos.push(...routes)\n return proxy\n },\n forRoutes: (...routes) => {\n entry.routes = routes\n if (excludedRouteInfos.length > 0) {\n entry.excludedRouteInfos = excludedRouteInfos\n }\n return this\n },\n }\n return proxy\n }\n\n applyTo(keqRequest: KeqRequest, moduleRef: ModuleRef): void {\n for (const entry of this.entries) {\n let resolved = entry.middlewares.map((m) => this.resolveMiddleware(m, moduleRef))\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 = entry.routes.length === 0\n || 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\n if (this.isKeqModuleClass(routeTarget)) {\n const targetRequest = moduleRef.get<KeqRequest>(routeTarget.KEQ_REQUEST, { strict: false })\n if (targetRequest) {\n for (const mw of resolved) targetRequest.use(mw)\n }\n } else {\n const route = this.buildRoute(routeTarget as KeqRouteInfo)\n keqRequest.useRouter().route(route, resolved)\n }\n }\n }\n }\n }\n\n private isKeqModuleClass(route: unknown): route is KeqModuleClass {\n return (\n typeof route === 'function'\n && 'KEQ_REQUEST' in route\n && typeof (route as Record<string, unknown>).KEQ_REQUEST === 'symbol'\n )\n }\n\n private isNestMiddlewareClass(m: Type<KeqNestMiddleware> | KeqMiddleware): m is Type<KeqNestMiddleware> {\n return typeof m === 'function' && m.prototype !== undefined && 'use' in m.prototype\n }\n\n private resolveMiddleware(m: Type<KeqNestMiddleware> | KeqMiddleware, moduleRef: ModuleRef): KeqMiddleware {\n if (this.isNestMiddlewareClass(m)) {\n const instance = moduleRef.get<KeqNestMiddleware>(m, { strict: false })\n return async (ctx, next) => {\n await instance.use(ctx, next)\n }\n }\n return m\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(ctx: KeqExecutionContext, excludedRoutes: KeqRoute[]): Promise<boolean> {\n for (const route of excludedRoutes) {\n if (await route(ctx)) return true\n }\n return false\n }\n}\n","import type { KeqMiddlewareModule } from '../interfaces/keq-middleware-module.interface.js'\n\n\nexport function hasConfigureKeqMiddleware(instance: unknown): instance is KeqMiddlewareModule {\n return (\n instance !== null\n && instance !== undefined\n && typeof (instance as Record<string, unknown>).configureKeqMiddleware === 'function'\n )\n}\n","import { Global, Module, OnModuleInit } from '@nestjs/common'\nimport { ModulesContainer, ModuleRef } from '@nestjs/core'\nimport { KeqRequest } from 'keq'\nimport { KeqMiddlewareConsumerImpl } from './keq-middleware-consumer.js'\nimport { hasConfigureKeqMiddleware } from './utils/has-configure-keq-middleware.js'\n\n\n@Global()\n@Module({\n providers: [{ provide: KeqRequest, useFactory: () => new KeqRequest() }],\n exports: [KeqRequest],\n})\nexport class KeqModule implements OnModuleInit {\n constructor(\n private readonly modulesContainer: ModulesContainer,\n private readonly moduleRef: ModuleRef,\n private readonly keqRequest: KeqRequest,\n ) {}\n\n onModuleInit(): void {\n for (const [, moduleWrapper] of this.modulesContainer) {\n const instance = moduleWrapper.instance\n if (hasConfigureKeqMiddleware(instance)) {\n const consumer = new KeqMiddlewareConsumerImpl()\n instance.configureKeqMiddleware(consumer)\n consumer.applyTo(this.keqRequest, this.moduleRef)\n }\n }\n }\n}\n"],"mappings":"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"}
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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"}
package/dist/index.mjs CHANGED
@@ -1,20 +1,34 @@
1
- import { Global, Module } from "@nestjs/common";
2
- import { ModuleRef, ModulesContainer } from "@nestjs/core";
1
+ import { Global, Inject, Injectable, Module } from "@nestjs/common";
3
2
  import { KeqRequest, composeRoute } from "keq";
4
3
  import picomatch from "picomatch";
5
4
  //#region src/constants.ts
6
5
  const KEQ_ROUTES = { ALL: Symbol("KEQ_ROUTES.ALL") };
7
6
  //#endregion
8
- //#region src/keq-middleware-consumer.ts
9
- var KeqMiddlewareConsumerImpl = class {
7
+ //#region src/keq-middleware-collector.ts
8
+ /**
9
+ * 中间件收集器,收集中间件配置条目并应用到指定的 {@link KeqRequest} 实例。
10
+ *
11
+ * 通过 `apply()` → `forRoutes()` 链式 API 收集多组中间件条目,
12
+ * 在 `forRoutes()` 被调用时立即将中间件绑定到目标请求。
13
+ *
14
+ * 注意:该类并非 `@Injectable()`,由 Consumer 内部手动创建。
15
+ *
16
+ * @typeParam TConsumer - Consumer 类型(`KeqMiddlewareConsumer` 或 `KeqConsumer<T>`)
17
+ */
18
+ var KeqMiddlewareCollector = class {
10
19
  entries = [];
11
- apply(...middlewares) {
20
+ constructor(keqRequest, consumer) {
21
+ this.keqRequest = keqRequest;
22
+ this.consumer = consumer;
23
+ }
24
+ apply(middlewares) {
12
25
  const entry = {
13
26
  middlewares,
14
27
  routes: []
15
28
  };
16
29
  const excludedRouteInfos = [];
17
30
  this.entries.push(entry);
31
+ const { keqRequest, consumer } = this;
18
32
  const proxy = {
19
33
  exclude: (...routes) => {
20
34
  excludedRouteInfos.push(...routes);
@@ -23,14 +37,18 @@ var KeqMiddlewareConsumerImpl = class {
23
37
  forRoutes: (...routes) => {
24
38
  entry.routes = routes;
25
39
  if (excludedRouteInfos.length > 0) entry.excludedRouteInfos = excludedRouteInfos;
26
- return this;
40
+ this.applyTo(keqRequest);
41
+ return consumer;
27
42
  }
28
43
  };
29
44
  return proxy;
30
45
  }
31
- applyTo(keqRequest, moduleRef) {
46
+ /**
47
+ * 将收集的所有中间件条目解析并应用到指定的 {@link KeqRequest} 实例。
48
+ */
49
+ applyTo(keqRequest) {
32
50
  for (const entry of this.entries) {
33
- let resolved = entry.middlewares.map((m) => this.resolveMiddleware(m, moduleRef));
51
+ let resolved = entry.middlewares.map((m) => this.normalizeMiddleware(m));
34
52
  if (entry.excludedRouteInfos && entry.excludedRouteInfos.length > 0) {
35
53
  const excludedRoutes = entry.excludedRouteInfos.map((info) => this.buildRoute(info));
36
54
  resolved = resolved.map((mw) => this.wrapWithExclusion(mw, excludedRoutes));
@@ -38,31 +56,25 @@ var KeqMiddlewareConsumerImpl = class {
38
56
  if (entry.routes.length === 0 || entry.routes.some((r) => r === KEQ_ROUTES.ALL)) for (const mw of resolved) keqRequest.use(mw);
39
57
  else for (const routeTarget of entry.routes) {
40
58
  if (routeTarget === KEQ_ROUTES.ALL) continue;
41
- if (this.isKeqModuleClass(routeTarget)) {
42
- const targetRequest = moduleRef.get(routeTarget.KEQ_REQUEST, { strict: false });
43
- if (targetRequest) for (const mw of resolved) targetRequest.use(mw);
44
- } else {
45
- const route = this.buildRoute(routeTarget);
46
- keqRequest.useRouter().route(route, resolved);
47
- }
59
+ const route = this.buildRoute(routeTarget);
60
+ keqRequest.useRouter().route(route, resolved);
48
61
  }
49
62
  }
50
63
  }
51
- isKeqModuleClass(route) {
52
- return typeof route === "function" && "KEQ_REQUEST" in route && typeof route.KEQ_REQUEST === "symbol";
53
- }
54
- isNestMiddlewareClass(m) {
55
- return typeof m === "function" && m.prototype !== void 0 && "use" in m.prototype;
56
- }
57
- resolveMiddleware(m, moduleRef) {
58
- if (this.isNestMiddlewareClass(m)) {
59
- const instance = moduleRef.get(m, { strict: false });
60
- return async (ctx, next) => {
61
- await instance.use(ctx, next);
62
- };
63
- }
64
+ /**
65
+ * 标准化中间件:将不同形式的中间件统一为 {@link KeqMiddleware} 函数。
66
+ * - 若已是 {@link KeqMiddleware} 函数 → 直接返回
67
+ * - 若为 {@link KeqNestMiddleware} 实例对象 → 包装 `use` 方法为中间件函数
68
+ */
69
+ normalizeMiddleware(m) {
70
+ if (this.isNestMiddlewareInstance(m)) return async (ctx, next) => {
71
+ await m.use(ctx, next);
72
+ };
64
73
  return m;
65
74
  }
75
+ isNestMiddlewareInstance(m) {
76
+ return typeof m === "object" && m !== null && "use" in m;
77
+ }
66
78
  buildRoute(info) {
67
79
  const routes = [];
68
80
  if (info.host) {
@@ -93,11 +105,6 @@ var KeqMiddlewareConsumerImpl = class {
93
105
  }
94
106
  };
95
107
  //#endregion
96
- //#region src/utils/has-configure-keq-middleware.ts
97
- function hasConfigureKeqMiddleware(instance) {
98
- return instance !== null && instance !== void 0 && typeof instance.configureKeqMiddleware === "function";
99
- }
100
- //#endregion
101
108
  //#region \0@oxc-project+runtime@0.127.0/helpers/decorateMetadata.js
102
109
  function __decorateMetadata(k, v) {
103
110
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
@@ -111,41 +118,77 @@ function __decorate(decorators, target, key, desc) {
111
118
  return c > 3 && r && Object.defineProperty(target, key, r), r;
112
119
  }
113
120
  //#endregion
121
+ //#region src/keq-middleware-consumer.ts
122
+ var _ref;
123
+ let KeqMiddlewareConsumer = class KeqMiddlewareConsumer {
124
+ constructor(keqRequest) {
125
+ this.keqRequest = keqRequest;
126
+ }
127
+ apply(...middlewares) {
128
+ return new KeqMiddlewareCollector(this.keqRequest, this).apply(middlewares);
129
+ }
130
+ };
131
+ KeqMiddlewareConsumer = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [typeof (_ref = typeof KeqRequest !== "undefined" && KeqRequest) === "function" ? _ref : Object])], KeqMiddlewareConsumer);
132
+ //#endregion
114
133
  //#region src/keq.module.ts
115
- var _ref, _ref2, _ref3;
116
- let KeqModule = class KeqModule {
117
- constructor(modulesContainer, moduleRef, keqRequest) {
118
- this.modulesContainer = modulesContainer;
119
- this.moduleRef = moduleRef;
134
+ let KeqModule = class KeqModule {};
135
+ KeqModule = __decorate([Global(), Module({
136
+ providers: [{
137
+ provide: KeqRequest,
138
+ useFactory: () => new KeqRequest()
139
+ }, KeqMiddlewareConsumer],
140
+ exports: [KeqRequest, KeqMiddlewareConsumer]
141
+ })], KeqModule);
142
+ //#endregion
143
+ //#region src/keq-consumer.ts
144
+ /**
145
+ * 为指定 Keq 模块按路由注册中间件。
146
+ *
147
+ * Keq 模块由 `@keq-request/cli` 生成,通过
148
+ * {@link InjectKeqConsumer} 装饰器注入本实例。
149
+ *
150
+ * @typeParam T - 目标模块类
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * constructor(
155
+ * \@InjectKeqConsumer(GeneratedModule) consumer: KeqConsumer<GeneratedModule>,
156
+ * ) {
157
+ * consumer.apply(authMw).forRoutes('*')
158
+ * }
159
+ * ```
160
+ */
161
+ var KeqConsumer = class {
162
+ constructor(keqRequest) {
120
163
  this.keqRequest = keqRequest;
121
164
  }
122
- onModuleInit() {
123
- for (const [, moduleWrapper] of this.modulesContainer) {
124
- const instance = moduleWrapper.instance;
125
- if (hasConfigureKeqMiddleware(instance)) {
126
- const consumer = new KeqMiddlewareConsumerImpl();
127
- instance.configureKeqMiddleware(consumer);
128
- consumer.applyTo(this.keqRequest, this.moduleRef);
129
- }
130
- }
165
+ apply(...middlewares) {
166
+ return new KeqMiddlewareCollector(this.keqRequest, this).apply(middlewares);
131
167
  }
132
168
  };
133
- KeqModule = __decorate([
134
- Global(),
135
- Module({
136
- providers: [{
137
- provide: KeqRequest,
138
- useFactory: () => new KeqRequest()
139
- }],
140
- exports: [KeqRequest]
141
- }),
142
- __decorateMetadata("design:paramtypes", [
143
- typeof (_ref = typeof ModulesContainer !== "undefined" && ModulesContainer) === "function" ? _ref : Object,
144
- typeof (_ref2 = typeof ModuleRef !== "undefined" && ModuleRef) === "function" ? _ref2 : Object,
145
- typeof (_ref3 = typeof KeqRequest !== "undefined" && KeqRequest) === "function" ? _ref3 : Object
146
- ])
147
- ], KeqModule);
148
169
  //#endregion
149
- export { KEQ_ROUTES, KeqModule };
170
+ //#region src/decorators/inject-keq-consumer.decorator.ts
171
+ /**
172
+ * 注入绑定到指定 Keq Module 的 `KeqConsumer<T>`。
173
+ *
174
+ * 被注入的 Module Class 必须同时包含 `KEQ_REQUEST` 和 `KEQ_CONSUMER` 静态属性,
175
+ * 两者均由 keq CLI 生成。
176
+ *
177
+ * 使用方式:
178
+ * ```ts
179
+ * constructor(
180
+ * \@InjectKeqConsumer(GeneratedModule) consumer: KeqConsumer<GeneratedModule>,
181
+ * ) {
182
+ * consumer.apply(mw).forRoutes('*')
183
+ * }
184
+ * ```
185
+ *
186
+ * @param moduleClass - 目标 KeqModule 类(需具有 `KEQ_REQUEST` 和 `KEQ_CONSUMER` symbol)
187
+ */
188
+ function InjectKeqConsumer(moduleClass) {
189
+ return Inject(moduleClass.KEQ_CONSUMER);
190
+ }
191
+ //#endregion
192
+ export { InjectKeqConsumer, KEQ_ROUTES, KeqConsumer, KeqMiddlewareConsumer, KeqModule };
150
193
 
151
194
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/constants.ts","../src/keq-middleware-consumer.ts","../src/utils/has-configure-keq-middleware.ts","../src/keq.module.ts"],"sourcesContent":["export const KEQ_ROUTES = {\n ALL: Symbol('KEQ_ROUTES.ALL'),\n} as const\n","import type { Type } from '@nestjs/common'\nimport type { ModuleRef } from '@nestjs/core'\nimport type { KeqExecutionContext, KeqMiddleware, KeqRoute } from 'keq'\nimport { composeRoute, KeqRequest } from 'keq'\nimport picomatch from 'picomatch'\nimport { KEQ_ROUTES } from './constants.js'\nimport type { KeqMiddlewareConfigProxy, KeqMiddlewareConsumer, KeqModuleClass, KeqRouteInfo } from './interfaces/keq-middleware-consumer.interface.js'\nimport type { KeqNestMiddleware } from './interfaces/keq-nest-middleware.interface.js'\n\n\ninterface MiddlewareEntry {\n middlewares: Array<Type<KeqNestMiddleware> | KeqMiddleware>\n routes: Array<typeof KEQ_ROUTES.ALL | KeqRouteInfo | KeqModuleClass>\n excludedRouteInfos?: KeqRouteInfo[]\n}\n\nexport class KeqMiddlewareConsumerImpl implements KeqMiddlewareConsumer {\n private entries: MiddlewareEntry[] = []\n\n apply(...middlewares: Array<Type<KeqNestMiddleware> | KeqMiddleware>): KeqMiddlewareConfigProxy {\n const entry: MiddlewareEntry = { middlewares, routes: [] }\n const excludedRouteInfos: KeqRouteInfo[] = []\n this.entries.push(entry)\n\n const proxy: KeqMiddlewareConfigProxy = {\n exclude: (...routes) => {\n excludedRouteInfos.push(...routes)\n return proxy\n },\n forRoutes: (...routes) => {\n entry.routes = routes\n if (excludedRouteInfos.length > 0) {\n entry.excludedRouteInfos = excludedRouteInfos\n }\n return this\n },\n }\n return proxy\n }\n\n applyTo(keqRequest: KeqRequest, moduleRef: ModuleRef): void {\n for (const entry of this.entries) {\n let resolved = entry.middlewares.map((m) => this.resolveMiddleware(m, moduleRef))\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 = entry.routes.length === 0\n || 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\n if (this.isKeqModuleClass(routeTarget)) {\n const targetRequest = moduleRef.get<KeqRequest>(routeTarget.KEQ_REQUEST, { strict: false })\n if (targetRequest) {\n for (const mw of resolved) targetRequest.use(mw)\n }\n } else {\n const route = this.buildRoute(routeTarget as KeqRouteInfo)\n keqRequest.useRouter().route(route, resolved)\n }\n }\n }\n }\n }\n\n private isKeqModuleClass(route: unknown): route is KeqModuleClass {\n return (\n typeof route === 'function'\n && 'KEQ_REQUEST' in route\n && typeof (route as Record<string, unknown>).KEQ_REQUEST === 'symbol'\n )\n }\n\n private isNestMiddlewareClass(m: Type<KeqNestMiddleware> | KeqMiddleware): m is Type<KeqNestMiddleware> {\n return typeof m === 'function' && m.prototype !== undefined && 'use' in m.prototype\n }\n\n private resolveMiddleware(m: Type<KeqNestMiddleware> | KeqMiddleware, moduleRef: ModuleRef): KeqMiddleware {\n if (this.isNestMiddlewareClass(m)) {\n const instance = moduleRef.get<KeqNestMiddleware>(m, { strict: false })\n return async (ctx, next) => {\n await instance.use(ctx, next)\n }\n }\n return m\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(ctx: KeqExecutionContext, excludedRoutes: KeqRoute[]): Promise<boolean> {\n for (const route of excludedRoutes) {\n if (await route(ctx)) return true\n }\n return false\n }\n}\n","import type { KeqMiddlewareModule } from '../interfaces/keq-middleware-module.interface.js'\n\n\nexport function hasConfigureKeqMiddleware(instance: unknown): instance is KeqMiddlewareModule {\n return (\n instance !== null\n && instance !== undefined\n && typeof (instance as Record<string, unknown>).configureKeqMiddleware === 'function'\n )\n}\n","import { Global, Module, OnModuleInit } from '@nestjs/common'\nimport { ModulesContainer, ModuleRef } from '@nestjs/core'\nimport { KeqRequest } from 'keq'\nimport { KeqMiddlewareConsumerImpl } from './keq-middleware-consumer.js'\nimport { hasConfigureKeqMiddleware } from './utils/has-configure-keq-middleware.js'\n\n\n@Global()\n@Module({\n providers: [{ provide: KeqRequest, useFactory: () => new KeqRequest() }],\n exports: [KeqRequest],\n})\nexport class KeqModule implements OnModuleInit {\n constructor(\n private readonly modulesContainer: ModulesContainer,\n private readonly moduleRef: ModuleRef,\n private readonly keqRequest: KeqRequest,\n ) {}\n\n onModuleInit(): void {\n for (const [, moduleWrapper] of this.modulesContainer) {\n const instance = moduleWrapper.instance\n if (hasConfigureKeqMiddleware(instance)) {\n const consumer = new KeqMiddlewareConsumerImpl()\n instance.configureKeqMiddleware(consumer)\n consumer.applyTo(this.keqRequest, this.moduleRef)\n }\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"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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"}
package/jest.config.cts CHANGED
@@ -5,6 +5,16 @@ import { compilerOptions } from './tsconfig.json'
5
5
 
6
6
  // eslint-disable-next-line @typescript-eslint/require-await
7
7
  export default async (): Promise<Config> => ({
8
- preset: 'ts-jest',
9
- moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/src', useESM: true }),
8
+ transform: {
9
+ '^.+\\.tsx?$': ['ts-jest', {
10
+ tsconfig: {
11
+ noEmitOnError: false,
12
+ },
13
+ }],
14
+ },
15
+ testMatch: [
16
+ '<rootDir>/__tests__/**/*.spec.ts',
17
+ '<rootDir>/src/**/*.spec.ts',
18
+ ],
19
+ moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>', useESM: true }),
10
20
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keq-request/nestjs",
3
- "version": "5.0.0-beta.12",
3
+ "version": "5.0.0-beta.14",
4
4
  "description": "Request API write by Typescript for flexibility, readability, and a low learning curve.",
5
5
  "keywords": [
6
6
  "request",
@@ -39,14 +39,16 @@
39
39
  "devDependencies": {
40
40
  "@nestjs/common": "^11.1.19",
41
41
  "@nestjs/core": "^11.1.19",
42
+ "@nestjs/testing": "^11.1.27",
42
43
  "@types/node": "^20.19.39",
43
44
  "@types/picomatch": "^4.0.0",
44
- "keq": "5.0.0-beta.12"
45
+ "reflect-metadata": "^0.2.2",
46
+ "keq": "5.0.0-beta.14"
45
47
  },
46
48
  "peerDependencies": {
47
49
  "@nestjs/common": "^11.0.0",
48
50
  "@nestjs/core": "^11.0.0",
49
- "keq": "^5.0.0-beta.12"
51
+ "keq": "^5.0.0-beta.14"
50
52
  },
51
53
  "engines": {
52
54
  "node": ">=20.0.0"
@@ -0,0 +1,26 @@
1
+ import { Inject } from '@nestjs/common'
2
+ import type { KeqModuleClass } from '../interfaces/keq-middleware-consumer.interface.js'
3
+
4
+
5
+ /**
6
+ * 注入绑定到指定 Keq Module 的 `KeqConsumer<T>`。
7
+ *
8
+ * 被注入的 Module Class 必须同时包含 `KEQ_REQUEST` 和 `KEQ_CONSUMER` 静态属性,
9
+ * 两者均由 keq CLI 生成。
10
+ *
11
+ * 使用方式:
12
+ * ```ts
13
+ * constructor(
14
+ * \@InjectKeqConsumer(GeneratedModule) consumer: KeqConsumer<GeneratedModule>,
15
+ * ) {
16
+ * consumer.apply(mw).forRoutes('*')
17
+ * }
18
+ * ```
19
+ *
20
+ * @param moduleClass - 目标 KeqModule 类(需具有 `KEQ_REQUEST` 和 `KEQ_CONSUMER` symbol)
21
+ */
22
+ export function InjectKeqConsumer<T extends KeqModuleClass>(
23
+ moduleClass: T,
24
+ ): ParameterDecorator {
25
+ return Inject(moduleClass.KEQ_CONSUMER)
26
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,6 @@
1
1
  export * from './keq.module.js'
2
+ export * from './keq-middleware-consumer.js'
3
+ export * from './keq-consumer.js'
2
4
  export * from './constants.js'
3
5
  export * from './interfaces/index.js'
6
+ export { InjectKeqConsumer } from './decorators/inject-keq-consumer.decorator.js'