@keq-request/nestjs 5.0.0-beta.13 → 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.
@@ -1,10 +1,10 @@
1
1
 
2
- > @keq-request/nestjs@5.0.0-beta.13 build /home/runner/work/keq/keq/packages/nestjs
2
+ > @keq-request/nestjs@5.0.0-beta.14 build /home/runner/work/keq/keq/packages/nestjs
3
3
  > tsdown
4
4
 
5
5
  ℹ tsdown v0.21.10 powered by rolldown v1.0.0-rc.17
6
6
  ℹ config file: /home/runner/work/keq/keq/packages/nestjs/tsdown.config.ts
7
- (node:2744) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///home/runner/work/keq/keq/packages/nestjs/tsdown.config.ts?no-cache=63d674a9-ded8-4584-ad0b-ff9b06a87e93 is not specified and it doesn't parse as CommonJS.
7
+ (node:2770) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///home/runner/work/keq/keq/packages/nestjs/tsdown.config.ts?no-cache=cf17737d-cddf-4e16-88ae-5730b15e8f59 is not specified and it doesn't parse as CommonJS.
8
8
  Reparsing as ES module because module syntax was detected. This incurs a performance overhead.
9
9
  To eliminate this warning, add "type": "module" to /home/runner/work/keq/keq/packages/nestjs/package.json.
10
10
  (Use `node --trace-warnings ...` to show where the warning was created)
@@ -12,25 +12,25 @@ To eliminate this warning, add "type": "module" to /home/runner/work/keq/keq/pac
12
12
  ℹ target: node20
13
13
  ℹ tsconfig: tsconfig.lib.json
14
14
  ℹ Build start
15
- ℹ [CJS] dist/index.js 10.52 kB │ gzip: 3.95 kB
16
- ℹ [CJS] dist/index.js.map 15.05 kB │ gzip: 5.17 kB
17
- ℹ [CJS] 2 files, total: 25.57 kB
15
+ ℹ [CJS] dist/index.js  8.01 kB │ gzip: 2.93 kB
16
+ ℹ [CJS] dist/index.js.map 11.70 kB │ gzip: 3.78 kB
17
+ ℹ [CJS] 2 files, total: 19.72 kB
18
18
  [PLUGIN_TIMINGS] Warning: Your build spent significant time in plugin `tsdown:deps`. See https://rolldown.rs/options/checks#plugintimings for more details.
19
19
 
20
- ℹ [ESM] dist/index.mjs  9.19 kB │ gzip: 3.46 kB
21
- ℹ [ESM] dist/index.mjs.map 14.98 kB │ gzip: 5.14 kB
22
- ℹ [ESM] dist/index.d.mts.map  1.08 kB │ gzip: 0.47 kB
23
- ℹ [ESM] dist/index.d.mts  2.96 kB │ gzip: 1.38 kB
24
- ℹ [ESM] 4 files, total: 28.22 kB
25
- [PLUGIN_TIMINGS] Warning: Your build spent significant time in plugin `rolldown-plugin-dts:generate`. See https://rolldown.rs/options/checks#plugintimings for more details.
26
-
27
- ✔ Build complete in 5612ms
28
- ℹ [CJS] dist/index.d.ts.map 1.08 kB │ gzip: 0.47 kB
29
- ℹ [CJS] dist/index.d.ts 2.96 kB │ gzip: 1.37 kB
30
- ℹ [CJS] 2 files, total: 4.04 kB
20
+ ℹ [CJS] dist/index.d.ts.map 1.39 kB │ gzip: 0.55 kB
21
+ ℹ [CJS] dist/index.d.ts 3.81 kB │ gzip: 1.45 kB
22
+ ℹ [CJS] 2 files, total: 5.20 kB
31
23
  [PLUGIN_TIMINGS] Warning: Your build spent significant time in plugins. Here is a breakdown:
32
- - rolldown-plugin-dts:generate (48%)
33
- - tsdown:deps (43%)
24
+ - rolldown-plugin-dts:generate (58%)
25
+ - tsdown:deps (28%)
34
26
  See https://rolldown.rs/options/checks#plugintimings for more details.
35
27
 
36
- ✔ Build complete in 5614ms
28
+ ℹ [ESM] dist/index.mjs  6.58 kB │ gzip: 2.45 kB
29
+ ℹ [ESM] dist/index.mjs.map 11.61 kB │ gzip: 3.75 kB
30
+ ℹ [ESM] dist/index.d.mts.map  1.39 kB │ gzip: 0.55 kB
31
+ ℹ [ESM] dist/index.d.mts  3.81 kB │ gzip: 1.46 kB
32
+ ℹ [ESM] 4 files, total: 23.38 kB
33
+ ✔ Build complete in 5188ms
34
+ [PLUGIN_TIMINGS] Warning: Your build spent significant time in plugin `rolldown-plugin-dts:generate`. See https://rolldown.rs/options/checks#plugintimings for more details.
35
+
36
+ ✔ Build complete in 5195ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @keq-request/nestjs
2
2
 
3
+ ## 5.0.0-beta.14
4
+
5
+ ### Major Changes
6
+
7
+ - 23c971f: **BREAKING CHANGE:** Refactor NestJS middleware configuration from lifecycle hook pattern to dependency injection pattern, introducing `KeqMiddlewareConsumer` as an injectable service and `@InjectKeqConsumer()` decorator with `KeqConsumer<T>` for module-scoped middleware.
8
+
9
+ - Remove `KeqMiddlewareModule` interface and `configureKeqMiddleware()` lifecycle method. Middleware is now registered by injecting `KeqMiddlewareConsumer` or `KeqConsumer<T>` directly into services.
10
+ - Remove `KeqMiddlewareConsumer` interface — it is now a concrete `@Injectable()` class provided by `KeqModule`.
11
+ - Remove `hasConfigureKeqMiddleware()` utility function.
12
+ - Remove `forRoutes()` support for `KeqModuleClass` route targets. Use `KeqConsumer<T>` (injected via `@InjectKeqConsumer(ModuleClass)`) for module-scoped middleware.
13
+ - `KeqModuleClass` now requires a static `KEQ_CONSUMER: symbol` property in addition to `KEQ_REQUEST`.
14
+ - `KeqModule` no longer has a `register()` static method — it is now a bare `@Global()` module. Import `KeqModule` directly.
15
+ - Add `@InjectKeqConsumer(ModuleClass)` decorator, `KeqConsumer<T>` class, `KeqRouteTarget` type, and `KeqScopedConfigProxy<T>` interface.
16
+ - CLI-generated NestJS modules now expose `KEQ_CONSUMER` symbol and provide a `KeqConsumer` provider for `@InjectKeqConsumer()` injection.
17
+
18
+ ### Patch Changes
19
+
20
+ - keq@5.0.0-beta.14
21
+
3
22
  ## 5.0.0-beta.13
4
23
 
5
24
  ### Patch Changes
@@ -1,155 +1,203 @@
1
1
  import 'reflect-metadata'
2
2
  import { expect, test } from '@jest/globals'
3
- import { Module } from '@nestjs/common'
4
- import type { ModulesContainer } from '@nestjs/core'
5
- import { KeqModule, validateConfigureKeqMiddlewareImports } from '../src/keq.module.js'
6
-
7
- /**
8
- * 模拟 NestJS Module wrapper 的运行时结构。
9
- * NestJS 在扫描阶段会将 DynamicModule 的 imports 解析为 Set<Module>,
10
- * 因此使用 imports Set 而非静态 Reflect.getMetadata 来校验。
11
- */
12
- function createMockModule(metatype: unknown, importsModules: Array<{ metatype: unknown }> = []) {
13
- return {
14
- metatype,
15
- imports: new Set(importsModules),
16
- }
17
- }
18
-
19
- function mockModulesContainer(
20
- modules: Array<ReturnType<typeof createMockModule>>,
21
- ): ModulesContainer {
22
- const map = new Map()
23
- for (const mod of modules) {
24
- map.set(Symbol('module'), mod)
25
- }
26
- return map as unknown as ModulesContainer
27
- }
3
+ import type { KeqMiddleware } from 'keq'
4
+ import { KeqRequest } from 'keq'
5
+ import { KeqMiddlewareConsumer } from '../src/keq-middleware-consumer.js'
6
+ import { KeqConsumer } from '../src/keq-consumer.js'
7
+ import { KEQ_ROUTES } from '../src/constants.js'
28
8
 
29
9
 
30
- test('throws when configureKeqMiddleware is declared without KeqModule in imports', () => {
31
- @Module({ imports: [] })
32
- class BadModule {
33
- configureKeqMiddleware(): void {}
34
- }
10
+ test('applies global middleware via forRoutes(KEQ_ROUTES.ALL)', () => {
11
+ const keqRequest = new KeqRequest()
12
+ const consumer = new KeqMiddlewareConsumer(keqRequest)
35
13
 
36
- const container = mockModulesContainer([
37
- createMockModule(KeqModule),
38
- createMockModule(BadModule),
39
- ])
14
+ const middleware: KeqMiddleware = async (_ctx, next) => { await next() }
15
+ consumer.apply(middleware).forRoutes(KEQ_ROUTES.ALL)
40
16
 
41
- expect(() => validateConfigureKeqMiddlewareImports(container)).toThrow(
42
- /\[KeqModule\] 'BadModule' implements configureKeqMiddleware\(\)/,
43
- )
17
+ expect(keqRequest.middlewares.length).toBe(1)
44
18
  })
45
19
 
46
- test('passes when configureKeqMiddleware is declared with KeqModule in imports', () => {
47
- @Module({ imports: [KeqModule] })
48
- class GoodModule {
49
- configureKeqMiddleware(): void {}
50
- }
20
+ test('applies global middleware when forRoutes receives no arguments', () => {
21
+ const keqRequest = new KeqRequest()
22
+ const consumer = new KeqMiddlewareConsumer(keqRequest)
23
+
24
+ const middleware: KeqMiddleware = async (_ctx, next) => { await next() }
25
+ consumer.apply(middleware).forRoutes()
51
26
 
52
- const keqModuleWrapper = createMockModule(KeqModule)
27
+ expect(keqRequest.middlewares.length).toBe(1)
28
+ })
29
+
30
+ test('applies route-specific middleware via forRoutes with KeqRouteInfo', () => {
31
+ const keqRequest = new KeqRequest()
32
+ const consumer = new KeqMiddlewareConsumer(keqRequest)
53
33
 
54
- const container = mockModulesContainer([
55
- keqModuleWrapper,
56
- createMockModule(GoodModule, [keqModuleWrapper]),
57
- ])
34
+ const middleware: KeqMiddleware = async (_ctx, next) => { await next() }
35
+ consumer.apply(middleware).forRoutes({ pathname: '/api/*' })
58
36
 
59
- expect(() => validateConfigureKeqMiddlewareImports(container)).not.toThrow()
37
+ expect(keqRequest.middlewares.length).toBe(1)
60
38
  })
61
39
 
62
- test('passes when module does not implement configureKeqMiddleware', () => {
63
- @Module({ imports: [] })
64
- class PlainModule {}
40
+ test('supports multiple middleware in single apply()', () => {
41
+ const keqRequest = new KeqRequest()
42
+ const consumer = new KeqMiddlewareConsumer(keqRequest)
65
43
 
66
- const container = mockModulesContainer([
67
- createMockModule(PlainModule),
68
- ])
44
+ const mw1: KeqMiddleware = async (_ctx, next) => { await next() }
45
+ const mw2: KeqMiddleware = async (_ctx, next) => { await next() }
46
+ consumer.apply(mw1, mw2).forRoutes(KEQ_ROUTES.ALL)
69
47
 
70
- expect(() => validateConfigureKeqMiddlewareImports(container)).not.toThrow()
48
+ expect(keqRequest.middlewares.length).toBe(2)
71
49
  })
72
50
 
73
- test('passes when KeqModule is imported as DynamicModule', () => {
74
- @Module({ imports: [{ module: KeqModule }] })
75
- class DynamicImportModule {
76
- configureKeqMiddleware(): void {}
77
- }
51
+ test('supports multiple apply() calls', () => {
52
+ const keqRequest = new KeqRequest()
53
+ const consumer = new KeqMiddlewareConsumer(keqRequest)
78
54
 
79
- // NestJS 在扫描阶段解析 DynamicModule,将 KeqModule wrapper 加入 imports Set
80
- const keqModuleWrapper = createMockModule(KeqModule)
55
+ const mw1: KeqMiddleware = async (_ctx, next) => { await next() }
56
+ const mw2: KeqMiddleware = async (_ctx, next) => { await next() }
81
57
 
82
- const container = mockModulesContainer([
83
- keqModuleWrapper,
84
- createMockModule(DynamicImportModule, [keqModuleWrapper]),
85
- ])
58
+ consumer.apply(mw1).forRoutes(KEQ_ROUTES.ALL)
59
+ consumer.apply(mw2).forRoutes({ pathname: '/api/*' })
86
60
 
87
- expect(() => validateConfigureKeqMiddlewareImports(container)).not.toThrow()
61
+ expect(keqRequest.middlewares.length).toBe(2)
88
62
  })
89
63
 
90
- test('passes when KeqModule is imported via forwardRef', () => {
91
- const { forwardRef } = require('@nestjs/common')
92
- @Module({ imports: [forwardRef(() => KeqModule)] })
93
- class ForwardRefModule {
94
- configureKeqMiddleware(): void {}
95
- }
64
+ test('supports exclude().forRoutes() chaining', () => {
65
+ const keqRequest = new KeqRequest()
66
+ const consumer = new KeqMiddlewareConsumer(keqRequest)
67
+
68
+ const middleware: KeqMiddleware = async (_ctx, next) => { await next() }
69
+ consumer.apply(middleware).exclude({ pathname: '/health' }).forRoutes(KEQ_ROUTES.ALL)
70
+
71
+ expect(keqRequest.middlewares.length).toBe(1)
72
+ })
73
+
74
+ test('middleware is applied synchronously at forRoutes() call time', () => {
75
+ const keqRequest = new KeqRequest()
76
+ const consumer = new KeqMiddlewareConsumer(keqRequest)
77
+
78
+ const middleware: KeqMiddleware = async (_ctx, next) => { await next() }
79
+
80
+ expect(keqRequest.middlewares.length).toBe(0)
81
+ consumer.apply(middleware).forRoutes(KEQ_ROUTES.ALL)
82
+ expect(keqRequest.middlewares.length).toBe(1)
83
+ })
84
+
85
+ test('supports chaining multiple apply() calls via forRoutes returning consumer', () => {
86
+ const keqRequest = new KeqRequest()
87
+ const consumer = new KeqMiddlewareConsumer(keqRequest)
88
+
89
+ const mw1: KeqMiddleware = async (_ctx, next) => { await next() }
90
+ const mw2: KeqMiddleware = async (_ctx, next) => { await next() }
91
+ const mw3: KeqMiddleware = async (_ctx, next) => { await next() }
92
+
93
+ consumer
94
+ .apply(mw1).forRoutes(KEQ_ROUTES.ALL)
95
+ .apply(mw2).forRoutes({ pathname: '/api/*' })
96
+ .apply(mw3).exclude({ pathname: '/health' }).forRoutes(KEQ_ROUTES.ALL)
97
+
98
+ expect(keqRequest.middlewares.length).toBe(3)
99
+ })
100
+
101
+ // ─── KeqConsumer(模块绑定)测试 ──────────────────────────
96
102
 
97
- // NestJS 在扫描阶段解析 forwardRef,将 KeqModule wrapper 加入 imports Set
98
- const keqModuleWrapper = createMockModule(KeqModule)
103
+ test('KeqConsumer applies middleware to its own KeqRequest', () => {
104
+ const scopedKeqRequest = new KeqRequest()
105
+ const consumer = new KeqConsumer(scopedKeqRequest)
99
106
 
100
- const container = mockModulesContainer([
101
- keqModuleWrapper,
102
- createMockModule(ForwardRefModule, [keqModuleWrapper]),
103
- ])
107
+ const middleware: KeqMiddleware = async (_ctx, next) => { await next() }
108
+ consumer.apply(middleware).forRoutes(KEQ_ROUTES.ALL)
104
109
 
105
- expect(() => validateConfigureKeqMiddlewareImports(container)).not.toThrow()
110
+ expect(scopedKeqRequest.middlewares.length).toBe(1)
106
111
  })
107
112
 
108
- test('passes when metatype is null', () => {
109
- const container = mockModulesContainer([
110
- createMockModule(null as unknown as undefined),
111
- ])
113
+ test('KeqConsumer does not affect other KeqRequest instances', () => {
114
+ const globalKeqRequest = new KeqRequest()
115
+ const scopedKeqRequest = new KeqRequest()
116
+
117
+ const globalConsumer = new KeqMiddlewareConsumer(globalKeqRequest)
118
+ const scopedConsumer = new KeqConsumer(scopedKeqRequest)
112
119
 
113
- expect(() => validateConfigureKeqMiddlewareImports(container)).not.toThrow()
120
+ const middleware: KeqMiddleware = async (_ctx, next) => { await next() }
121
+ scopedConsumer.apply(middleware).forRoutes(KEQ_ROUTES.ALL)
122
+
123
+ expect(scopedKeqRequest.middlewares.length).toBe(1)
124
+ expect(globalKeqRequest.middlewares.length).toBe(0)
114
125
  })
115
126
 
116
- test('throws when module has configureKeqMiddleware but KeqModule is not in container', () => {
117
- // KeqModule 未在 ModulesContainer 中注册时,任何实现了 configureKeqMiddleware
118
- // 的模块都无法通过校验,因为缺少 KeqModule 来注册中间件
119
- @Module({ imports: [] })
120
- class SomeModule {
121
- configureKeqMiddleware(): void {}
127
+ // ─── KeqNestMiddleware 实例对象测试 ──────────────────────
128
+
129
+ test('applies KeqNestMiddleware instance via apply()', () => {
130
+ const keqRequest = new KeqRequest()
131
+ const consumer = new KeqMiddlewareConsumer(keqRequest)
132
+
133
+ const middleware = {
134
+ use: async (_ctx: unknown, next: () => Promise<void>) => { await next() },
122
135
  }
136
+ consumer.apply(middleware).forRoutes(KEQ_ROUTES.ALL)
137
+
138
+ expect(keqRequest.middlewares.length).toBe(1)
139
+ })
123
140
 
124
- const container = mockModulesContainer([
125
- createMockModule(SomeModule),
126
- ])
141
+ test('applies KeqNestMiddleware instance to specific route', () => {
142
+ const keqRequest = new KeqRequest()
143
+ const consumer = new KeqMiddlewareConsumer(keqRequest)
144
+
145
+ const middleware = {
146
+ use: async (_ctx: unknown, next: () => Promise<void>) => { await next() },
147
+ }
148
+ consumer.apply(middleware).forRoutes({ pathname: '/api/*' })
127
149
 
128
- expect(() => validateConfigureKeqMiddlewareImports(container)).toThrow(
129
- /\[KeqModule\] 'SomeModule'/,
130
- )
150
+ expect(keqRequest.middlewares.length).toBe(1)
131
151
  })
132
152
 
133
- test('throws for one module while another is valid', () => {
134
- @Module({ imports: [] })
135
- class BadModule {
136
- configureKeqMiddleware(): void {}
153
+ test('mixes KeqMiddleware function and KeqNestMiddleware instance', () => {
154
+ const keqRequest = new KeqRequest()
155
+ const consumer = new KeqMiddlewareConsumer(keqRequest)
156
+
157
+ const fnMw: KeqMiddleware = async (_ctx, next) => { await next() }
158
+ const instanceMw = {
159
+ use: async (_ctx: unknown, next: () => Promise<void>) => { await next() },
137
160
  }
161
+ consumer.apply(fnMw, instanceMw).forRoutes(KEQ_ROUTES.ALL)
162
+
163
+ expect(keqRequest.middlewares.length).toBe(2)
164
+ })
165
+
166
+ test('KeqNestMiddleware instance receives ctx and next in use()', async () => {
167
+ const keqRequest = new KeqRequest()
168
+ const consumer = new KeqMiddlewareConsumer(keqRequest)
169
+
170
+ let capturedCtx: unknown = null
171
+ let capturedNext: unknown = null
138
172
 
139
- @Module({ imports: [KeqModule] })
140
- class GoodModule {
141
- configureKeqMiddleware(): void {}
173
+ const middleware = {
174
+ use: async (ctx: unknown, next: () => Promise<void>) => {
175
+ capturedCtx = ctx
176
+ capturedNext = next
177
+ await next()
178
+ },
142
179
  }
180
+ consumer.apply(middleware).forRoutes(KEQ_ROUTES.ALL)
143
181
 
144
- const keqModuleWrapper = createMockModule(KeqModule)
182
+ const middlewareFn = keqRequest.middlewares[0]
183
+ const mockCtx = { request: { url: { host: 'example.com', pathname: '/' }, method: 'GET' } }
184
+ const mockNext = async () => {}
145
185
 
146
- const container = mockModulesContainer([
147
- keqModuleWrapper,
148
- createMockModule(GoodModule, [keqModuleWrapper]),
149
- createMockModule(BadModule),
150
- ])
186
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
187
+ await (middlewareFn as any)(mockCtx, mockNext)
188
+
189
+ expect(capturedCtx).toBe(mockCtx)
190
+ expect(typeof capturedNext).toBe('function')
191
+ })
192
+
193
+ test('KeqConsumer accepts KeqNestMiddleware instance', () => {
194
+ const scopedKeqRequest = new KeqRequest()
195
+ const consumer = new KeqConsumer(scopedKeqRequest)
196
+
197
+ const middleware = {
198
+ use: async (_ctx: unknown, next: () => Promise<void>) => { await next() },
199
+ }
200
+ consumer.apply(middleware).forRoutes(KEQ_ROUTES.ALL)
151
201
 
152
- expect(() => validateConfigureKeqMiddlewareImports(container)).toThrow(
153
- /'BadModule'/,
154
- )
202
+ expect(scopedKeqRequest.middlewares.length).toBe(1)
155
203
  })
package/dist/index.d.mts CHANGED
@@ -1,31 +1,8 @@
1
- import { OnModuleInit, Type } from "@nestjs/common";
2
- import { ModulesContainer } from "@nestjs/core";
1
+ import { Type } from "@nestjs/common";
3
2
  import { KeqExecutionContext, KeqMiddleware, KeqNext, KeqRequest } from "keq";
4
3
 
5
4
  //#region src/keq.module.d.ts
6
- /**
7
- * 在 NestJS 模块初始化早期阶段校验 `configureKeqMiddleware` 的实现模块
8
- * 是否显式导入了 `KeqModule`。
9
- *
10
- * NestJS 初始化分为两个严格串行的阶段:
11
- * 1. 全量扫描 — 所有模块 wrapper 加入 ModulesContainer,metatype 已设置,
12
- * DynamicModule 的 imports 已被解析并写入 moduleWrapper.imports Set
13
- * 2. 实例创建 — 按依赖顺序调用构造函数 → onModuleInit
14
- *
15
- * 此校验在阶段 2 开头(构造函数中)执行,早于所有 onModuleInit,
16
- * 确保中间件缺失问题在启动期就被捕获,而非在业务模块 onModuleInit 发请求时静默失效。
17
- *
18
- * 使用运行时 imports Set 而非 Reflect.getMetadata('imports', metatype) 的原因:
19
- * - DynamicModule 通过 register() 返回的 imports 不在静态装饰器元数据中
20
- * - 从 ModulesContainer 获取 KeqModule metatype 可避免 pnpm 重复包实例导致的 === 比对失败
21
- */
22
- declare function validateConfigureKeqMiddlewareImports(modulesContainer: ModulesContainer): void;
23
- declare class KeqModule implements OnModuleInit {
24
- private readonly modulesContainer;
25
- private readonly keqRequest;
26
- constructor(modulesContainer: ModulesContainer, keqRequest: KeqRequest);
27
- onModuleInit(): void;
28
- }
5
+ declare class KeqModule {}
29
6
  //#endregion
30
7
  //#region src/constants.d.ts
31
8
  declare const KEQ_ROUTES: {
@@ -37,6 +14,30 @@ interface KeqNestMiddleware {
37
14
  use(ctx: KeqExecutionContext, next: KeqNext): void | PromiseLike<void>;
38
15
  }
39
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
40
41
  //#region src/interfaces/keq-middleware-consumer.interface.d.ts
41
42
  interface KeqRouteInfo {
42
43
  host?: string;
@@ -45,18 +46,39 @@ interface KeqRouteInfo {
45
46
  }
46
47
  interface KeqModuleClass extends Type<any> {
47
48
  readonly KEQ_REQUEST: symbol;
49
+ readonly KEQ_CONSUMER: symbol;
48
50
  }
51
+ /** forRoutes() 接受的路由目标(不再包含 KeqModuleClass,模块绑定通过 @InjectKeqConsumer 实现) */
52
+ type KeqRouteTarget = typeof KEQ_ROUTES.ALL | KeqRouteInfo;
49
53
  interface KeqMiddlewareConfigProxy {
50
54
  exclude(...routes: KeqRouteInfo[]): KeqMiddlewareConfigProxy;
51
- forRoutes(...routes: Array<typeof KEQ_ROUTES.ALL | KeqRouteInfo | KeqModuleClass>): KeqMiddlewareConsumer;
55
+ forRoutes(...routes: KeqRouteTarget[]): KeqMiddlewareConsumer;
52
56
  }
53
- interface KeqMiddlewareConsumer {
54
- apply(...middlewares: Array<Type<KeqNestMiddleware> | KeqMiddleware>): KeqMiddlewareConfigProxy;
57
+ /** 模块绑定 Consumer 的配置代理,forRoutes() 返回 KeqConsumer<T> */
58
+ interface KeqScopedConfigProxy<T = KeqModuleClass> {
59
+ exclude(...routes: KeqRouteInfo[]): KeqScopedConfigProxy<T>;
60
+ forRoutes(...routes: KeqRouteTarget[]): KeqConsumer<T>;
55
61
  }
56
62
  //#endregion
57
- //#region src/interfaces/keq-middleware-module.interface.d.ts
58
- interface KeqMiddlewareModule {
59
- configureKeqMiddleware(consumer: KeqMiddlewareConsumer): void;
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;
60
82
  }
61
83
  //#endregion
62
84
  //#region src/interfaces/keq-module-options.interface.d.ts
@@ -65,5 +87,25 @@ interface KeqModuleOptions {
65
87
  isolate?: boolean;
66
88
  }
67
89
  //#endregion
68
- export { KEQ_ROUTES, type KeqMiddlewareConfigProxy, type KeqMiddlewareConsumer, type KeqMiddlewareModule, KeqModule, type KeqModuleClass, type KeqModuleOptions, type KeqNestMiddleware, type KeqRouteInfo, validateConfigureKeqMiddlewareImports };
90
+ //#region src/decorators/inject-keq-consumer.decorator.d.ts
91
+ /**
92
+ * 注入绑定到指定 Keq Module 的 `KeqConsumer<T>`。
93
+ *
94
+ * 被注入的 Module Class 必须同时包含 `KEQ_REQUEST` 和 `KEQ_CONSUMER` 静态属性,
95
+ * 两者均由 keq CLI 生成。
96
+ *
97
+ * 使用方式:
98
+ * ```ts
99
+ * constructor(
100
+ * \@InjectKeqConsumer(GeneratedModule) consumer: KeqConsumer<GeneratedModule>,
101
+ * ) {
102
+ * consumer.apply(mw).forRoutes('*')
103
+ * }
104
+ * ```
105
+ *
106
+ * @param moduleClass - 目标 KeqModule 类(需具有 `KEQ_REQUEST` 和 `KEQ_CONSUMER` symbol)
107
+ */
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 };
69
111
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/keq.module.ts","../src/constants.ts","../src/interfaces/keq-nest-middleware.interface.ts","../src/interfaces/keq-middleware-consumer.interface.ts","../src/interfaces/keq-middleware-module.interface.ts","../src/interfaces/keq-module-options.interface.ts"],"mappings":";;;;;;;AAoCA;;;;;AAkCA;;;;;;;;;iBAlCgB,qCAAA,CAAsC,gBAAA,EAAkB,gBAAA;AAAA,cAuC3D,SAAA,YAAqB,YAAA;EAAA,iBAEb,gBAAA;EAAA,iBACA,UAAA;cADA,gBAAA,EAAkB,gBAAA,EAClB,UAAA,EAAY,UAAA;EAK/B,YAAA,CAAA;AAAA;;;cCnFW,UAAA;EAAA,SAEH,GAAA;AAAA;;;UCCO,iBAAA;EACf,GAAA,CAAI,GAAA,EAAK,mBAAA,EAAqB,IAAA,EAAM,OAAA,UAAiB,WAAA;AAAA;;;UCEtC,YAAA;EACf,IAAA;EACA,MAAA;EACA,QAAA;AAAA;AAAA,UAGe,cAAA,SAAuB,IAAA;EAAA,SAC7B,WAAA;AAAA;AAAA,UAGM,wBAAA;EACf,OAAA,IAAW,MAAA,EAAQ,YAAA,KAAiB,wBAAA;EACpC,SAAA,IAAa,MAAA,EAAQ,KAAA,QAAa,UAAA,CAAW,GAAA,GAAM,YAAA,GAAe,cAAA,IAAkB,qBAAA;AAAA;AAAA,UAGrE,qBAAA;EACf,KAAA,IAAS,WAAA,EAAa,KAAA,CAAM,IAAA,CAAK,iBAAA,IAAqB,aAAA,IAAiB,wBAAA;AAAA;;;UCnBxD,mBAAA;EACf,sBAAA,CAAuB,QAAA,EAAU,qBAAA;AAAA;;;UCDlB,gBAAA;EACf,WAAA,GAAc,aAAA;EACd,OAAA;AAAA"}
1
+ {"version":3,"file":"index.d.mts","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"}