@keq-request/nestjs 5.0.0-beta.9 → 5.0.0
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 +19 -19
- package/CHANGELOG.md +134 -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/.turbo/turbo-build.log
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
> @keq-request/nestjs@5.0.0
|
|
2
|
+
> @keq-request/nestjs@5.0.0 build /home/runner/work/keq/keq/packages/nestjs
|
|
3
3
|
> tsdown
|
|
4
4
|
|
|
5
5
|
[34mℹ[39m [34mtsdown v0.21.10[39m powered by [38;2;255;126;23mrolldown v1.0.0-rc.17[39m
|
|
6
6
|
[34mℹ[39m config file: [4m/home/runner/work/keq/keq/packages/nestjs/tsdown.config.ts[24m
|
|
7
|
-
(node:
|
|
7
|
+
(node:2649) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///home/runner/work/keq/keq/packages/nestjs/tsdown.config.ts?no-cache=b4493cd8-de60-412b-b47f-2197ce30ef21 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
|
[34mℹ[39m target: [34mnode20[39m
|
|
13
13
|
[34mℹ[39m tsconfig: [34mtsconfig.lib.json[39m
|
|
14
14
|
[34mℹ[39m Build start
|
|
15
|
-
[34mℹ[39m [33m[CJS][39m [2mdist/[22m[1mindex.js[22m [
|
|
16
|
-
[34mℹ[39m [33m[CJS][39m [2mdist/[22mindex.js.map [
|
|
17
|
-
[34mℹ[39m [33m[CJS][39m 2 files, total:
|
|
15
|
+
[34mℹ[39m [33m[CJS][39m [2mdist/[22m[1mindex.js[22m [2m 8.01 kB[22m [2m│ gzip: 2.93 kB[22m
|
|
16
|
+
[34mℹ[39m [33m[CJS][39m [2mdist/[22mindex.js.map [2m11.70 kB[22m [2m│ gzip: 3.78 kB[22m
|
|
17
|
+
[34mℹ[39m [33m[CJS][39m 2 files, total: 19.72 kB
|
|
18
18
|
[33m[PLUGIN_TIMINGS] Warning:[0m Your build spent significant time in plugin `tsdown:deps`. See https://rolldown.rs/options/checks#plugintimings for more details.
|
|
19
19
|
|
|
20
|
-
[34mℹ[39m [
|
|
21
|
-
[34mℹ[39m [
|
|
22
|
-
[34mℹ[39m [
|
|
20
|
+
[34mℹ[39m [34m[ESM][39m [2mdist/[22m[1mindex.mjs[22m [2m 6.58 kB[22m [2m│ gzip: 2.45 kB[22m
|
|
21
|
+
[34mℹ[39m [34m[ESM][39m [2mdist/[22mindex.mjs.map [2m11.61 kB[22m [2m│ gzip: 3.75 kB[22m
|
|
22
|
+
[34mℹ[39m [34m[ESM][39m [2mdist/[22mindex.d.mts.map [2m 1.39 kB[22m [2m│ gzip: 0.55 kB[22m
|
|
23
|
+
[34mℹ[39m [34m[ESM][39m [2mdist/[22m[32m[1mindex.d.mts[22m[39m [2m 3.81 kB[22m [2m│ gzip: 1.46 kB[22m
|
|
24
|
+
[34mℹ[39m [34m[ESM][39m 4 files, total: 23.38 kB
|
|
25
|
+
[33m[PLUGIN_TIMINGS] Warning:[0m Your build spent significant time in plugin `rolldown-plugin-dts:generate`. See https://rolldown.rs/options/checks#plugintimings for more details.
|
|
26
|
+
|
|
27
|
+
[34mℹ[39m [33m[CJS][39m [2mdist/[22mindex.d.ts.map [2m1.39 kB[22m [2m│ gzip: 0.55 kB[22m
|
|
28
|
+
[34mℹ[39m [33m[CJS][39m [2mdist/[22m[32m[1mindex.d.ts[22m[39m [2m3.81 kB[22m [2m│ gzip: 1.45 kB[22m
|
|
29
|
+
[34mℹ[39m [33m[CJS][39m 2 files, total: 5.20 kB
|
|
23
30
|
[33m[PLUGIN_TIMINGS] Warning:[0m Your build spent significant time in plugins. Here is a breakdown:
|
|
24
|
-
- rolldown-plugin-dts:generate (
|
|
25
|
-
|
|
26
|
-
[34mℹ[39m [34m[ESM][39m [2mdist/[22mindex.mjs.map [2m3.49 kB[22m [2m│ gzip: 1.34 kB[22m
|
|
27
|
-
[34mℹ[39m [34m[ESM][39m [2mdist/[22mindex.d.mts.map [2m0.54 kB[22m [2m│ gzip: 0.30 kB[22m
|
|
28
|
-
[34mℹ[39m [34m[ESM][39m [2mdist/[22m[32m[1mindex.d.mts[22m[39m [2m2.17 kB[22m [2m│ gzip: 0.89 kB[22m
|
|
29
|
-
[34mℹ[39m [34m[ESM][39m 4 files, total: 8.37 kB
|
|
30
|
-
[32m✔[39m Build complete in [32m4631ms[39m
|
|
31
|
-
[32m✔[39m Build complete in [32m4632ms[39m
|
|
32
|
-
- tsdown:deps (46%)
|
|
31
|
+
- rolldown-plugin-dts:generate (47%)
|
|
32
|
+
- tsdown:deps (37%)
|
|
33
33
|
See https://rolldown.rs/options/checks#plugintimings for more details.
|
|
34
34
|
|
|
35
|
-
[
|
|
36
|
-
|
|
35
|
+
[32m✔[39m Build complete in [32m5166ms[39m
|
|
36
|
+
[32m✔[39m Build complete in [32m5168ms[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,139 @@
|
|
|
1
1
|
# @keq-request/nestjs
|
|
2
2
|
|
|
3
|
+
## 5.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 23c971f: **BREAKING CHANGE:** Add NestJS integration with dependency injection pattern.
|
|
8
|
+
|
|
9
|
+
- Introduce `KeqMiddlewareConsumer` as an injectable service and `@InjectKeqConsumer()` decorator with `KeqConsumer<T>` for module-scoped middleware.
|
|
10
|
+
- Remove `KeqMiddlewareModule` interface and `configureKeqMiddleware()` lifecycle method. Middleware is now registered by injecting `KeqMiddlewareConsumer` or `KeqConsumer<T>` directly into services.
|
|
11
|
+
- Remove `KeqMiddlewareConsumer` interface — it is now a concrete `@Injectable()` class provided by `KeqModule`.
|
|
12
|
+
- Remove `hasConfigureKeqMiddleware()` utility function.
|
|
13
|
+
- Remove `forRoutes()` support for `KeqModuleClass` route targets. Use `KeqConsumer<T>` (injected via `@InjectKeqConsumer(ModuleClass)`) for module-scoped middleware.
|
|
14
|
+
- `KeqModuleClass` now requires a static `KEQ_CONSUMER: symbol` property in addition to `KEQ_REQUEST`.
|
|
15
|
+
- `KeqModule` no longer has a `register()` static method — it is now a bare `@Global()` module. Import `KeqModule` directly.
|
|
16
|
+
- Add `@InjectKeqConsumer(ModuleClass)` decorator, `KeqConsumer<T>` class, `KeqRouteTarget` type, and `KeqScopedConfigProxy<T>` interface.
|
|
17
|
+
- Add `exclude()` method to `KeqMiddlewareConfigProxy`, allowing middleware to skip specific routes.
|
|
18
|
+
- CLI-generated NestJS modules auto-import `KeqModule` and expose `KEQ_CONSUMER` symbol with `KeqConsumer` provider for `@InjectKeqConsumer()` injection.
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [c2d4453]
|
|
23
|
+
- Updated dependencies [95908fd]
|
|
24
|
+
- Updated dependencies [153244f]
|
|
25
|
+
- Updated dependencies [0a2eb2f]
|
|
26
|
+
- Updated dependencies [153244f]
|
|
27
|
+
- Updated dependencies [a960073]
|
|
28
|
+
- Updated dependencies [214ae66]
|
|
29
|
+
- Updated dependencies [153244f]
|
|
30
|
+
- Updated dependencies [7ff2162]
|
|
31
|
+
- Updated dependencies [f84775d]
|
|
32
|
+
- Updated dependencies [153244f]
|
|
33
|
+
- Updated dependencies [a7a83da]
|
|
34
|
+
- Updated dependencies [153244f]
|
|
35
|
+
- Updated dependencies [153244f]
|
|
36
|
+
- Updated dependencies [f8abc63]
|
|
37
|
+
- Updated dependencies [153244f]
|
|
38
|
+
- Updated dependencies [ca6c879]
|
|
39
|
+
- Updated dependencies [b8d02ca]
|
|
40
|
+
- Updated dependencies [0a04864]
|
|
41
|
+
- Updated dependencies [153244f]
|
|
42
|
+
- Updated dependencies [eed26f9]
|
|
43
|
+
- keq@5.0.0
|
|
44
|
+
|
|
45
|
+
## 5.0.0-beta.19
|
|
46
|
+
|
|
47
|
+
### Patch Changes
|
|
48
|
+
|
|
49
|
+
- Updated dependencies [cc017de]
|
|
50
|
+
- keq@5.0.0-beta.19
|
|
51
|
+
|
|
52
|
+
## 5.0.0-beta.18
|
|
53
|
+
|
|
54
|
+
### Patch Changes
|
|
55
|
+
|
|
56
|
+
- keq@5.0.0-beta.18
|
|
57
|
+
|
|
58
|
+
## 5.0.0-beta.17
|
|
59
|
+
|
|
60
|
+
### Patch Changes
|
|
61
|
+
|
|
62
|
+
- keq@5.0.0-beta.17
|
|
63
|
+
|
|
64
|
+
## 5.0.0-beta.16
|
|
65
|
+
|
|
66
|
+
### Patch Changes
|
|
67
|
+
|
|
68
|
+
- Updated dependencies [c2d4453]
|
|
69
|
+
- Updated dependencies [a960073]
|
|
70
|
+
- Updated dependencies [f84775d]
|
|
71
|
+
- keq@5.0.0-beta.16
|
|
72
|
+
|
|
73
|
+
## 5.0.0-beta.15
|
|
74
|
+
|
|
75
|
+
### Patch Changes
|
|
76
|
+
|
|
77
|
+
- keq@5.0.0-beta.15
|
|
78
|
+
|
|
79
|
+
## 5.0.0-beta.14
|
|
80
|
+
|
|
81
|
+
### Major Changes
|
|
82
|
+
|
|
83
|
+
- 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.
|
|
84
|
+
|
|
85
|
+
- Remove `KeqMiddlewareModule` interface and `configureKeqMiddleware()` lifecycle method. Middleware is now registered by injecting `KeqMiddlewareConsumer` or `KeqConsumer<T>` directly into services.
|
|
86
|
+
- Remove `KeqMiddlewareConsumer` interface — it is now a concrete `@Injectable()` class provided by `KeqModule`.
|
|
87
|
+
- Remove `hasConfigureKeqMiddleware()` utility function.
|
|
88
|
+
- Remove `forRoutes()` support for `KeqModuleClass` route targets. Use `KeqConsumer<T>` (injected via `@InjectKeqConsumer(ModuleClass)`) for module-scoped middleware.
|
|
89
|
+
- `KeqModuleClass` now requires a static `KEQ_CONSUMER: symbol` property in addition to `KEQ_REQUEST`.
|
|
90
|
+
- `KeqModule` no longer has a `register()` static method — it is now a bare `@Global()` module. Import `KeqModule` directly.
|
|
91
|
+
- Add `@InjectKeqConsumer(ModuleClass)` decorator, `KeqConsumer<T>` class, `KeqRouteTarget` type, and `KeqScopedConfigProxy<T>` interface.
|
|
92
|
+
- CLI-generated NestJS modules now expose `KEQ_CONSUMER` symbol and provide a `KeqConsumer` provider for `@InjectKeqConsumer()` injection.
|
|
93
|
+
|
|
94
|
+
### Patch Changes
|
|
95
|
+
|
|
96
|
+
- keq@5.0.0-beta.14
|
|
97
|
+
|
|
98
|
+
## 5.0.0-beta.13
|
|
99
|
+
|
|
100
|
+
### Patch Changes
|
|
101
|
+
|
|
102
|
+
- 59f4773: **Fix:** ensure `configureKeqMiddleware()` works correctly in pnpm monorepos and validate module imports at startup.
|
|
103
|
+
|
|
104
|
+
- Fix middleware not being applied when pnpm creates multiple `@keq-request/nestjs` instances due to peerDependency version differences.
|
|
105
|
+
- Detect missing `KeqModule` imports in modules that implement `configureKeqMiddleware()` at startup, throwing a clear error instead of silently skipping middleware.
|
|
106
|
+
- Prevent middleware from being applied more than once when multiple `KeqModule` instances exist.
|
|
107
|
+
- Throw a descriptive error when a NestJS middleware class passed to `consumer.apply()` is not registered as a provider.
|
|
108
|
+
- keq@5.0.0-beta.13
|
|
109
|
+
|
|
110
|
+
## 5.0.0-beta.12
|
|
111
|
+
|
|
112
|
+
### Minor Changes
|
|
113
|
+
|
|
114
|
+
- fbc851f: **Feat:** Add `exclude()` method to `KeqMiddlewareConfigProxy`, allowing middleware to skip specific routes. Supports `KeqRouteInfo` with `host`, `method`, and `pathname` patterns, following the NestJS `MiddlewareConfigProxy.exclude()` convention.
|
|
115
|
+
|
|
116
|
+
### Patch Changes
|
|
117
|
+
|
|
118
|
+
- keq@5.0.0-beta.12
|
|
119
|
+
|
|
120
|
+
## 5.0.0-beta.11
|
|
121
|
+
|
|
122
|
+
### Patch Changes
|
|
123
|
+
|
|
124
|
+
- keq@5.0.0-beta.11
|
|
125
|
+
|
|
126
|
+
## 5.0.0-beta.10
|
|
127
|
+
|
|
128
|
+
### Minor Changes
|
|
129
|
+
|
|
130
|
+
- 2e13e75: **BREAKING CHANGE:** Remove `request` option from `KeqModuleOptions`, use fork-based instance isolation instead.
|
|
131
|
+
|
|
132
|
+
### Patch Changes
|
|
133
|
+
|
|
134
|
+
- Updated dependencies [95908fd]
|
|
135
|
+
- keq@5.0.0-beta.10
|
|
136
|
+
|
|
3
137
|
## 5.0.0-beta.9
|
|
4
138
|
|
|
5
139
|
### Patch Changes
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import 'reflect-metadata'
|
|
2
|
+
import { expect, test } from '@jest/globals'
|
|
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'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
test('applies global middleware via forRoutes(KEQ_ROUTES.ALL)', () => {
|
|
11
|
+
const keqRequest = new KeqRequest()
|
|
12
|
+
const consumer = new KeqMiddlewareConsumer(keqRequest)
|
|
13
|
+
|
|
14
|
+
const middleware: KeqMiddleware = async (_ctx, next) => { await next() }
|
|
15
|
+
consumer.apply(middleware).forRoutes(KEQ_ROUTES.ALL)
|
|
16
|
+
|
|
17
|
+
expect(keqRequest.middlewares.length).toBe(1)
|
|
18
|
+
})
|
|
19
|
+
|
|
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()
|
|
26
|
+
|
|
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)
|
|
33
|
+
|
|
34
|
+
const middleware: KeqMiddleware = async (_ctx, next) => { await next() }
|
|
35
|
+
consumer.apply(middleware).forRoutes({ pathname: '/api/*' })
|
|
36
|
+
|
|
37
|
+
expect(keqRequest.middlewares.length).toBe(1)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('supports multiple middleware in single apply()', () => {
|
|
41
|
+
const keqRequest = new KeqRequest()
|
|
42
|
+
const consumer = new KeqMiddlewareConsumer(keqRequest)
|
|
43
|
+
|
|
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)
|
|
47
|
+
|
|
48
|
+
expect(keqRequest.middlewares.length).toBe(2)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('supports multiple apply() calls', () => {
|
|
52
|
+
const keqRequest = new KeqRequest()
|
|
53
|
+
const consumer = new KeqMiddlewareConsumer(keqRequest)
|
|
54
|
+
|
|
55
|
+
const mw1: KeqMiddleware = async (_ctx, next) => { await next() }
|
|
56
|
+
const mw2: KeqMiddleware = async (_ctx, next) => { await next() }
|
|
57
|
+
|
|
58
|
+
consumer.apply(mw1).forRoutes(KEQ_ROUTES.ALL)
|
|
59
|
+
consumer.apply(mw2).forRoutes({ pathname: '/api/*' })
|
|
60
|
+
|
|
61
|
+
expect(keqRequest.middlewares.length).toBe(2)
|
|
62
|
+
})
|
|
63
|
+
|
|
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(模块绑定)测试 ──────────────────────────
|
|
102
|
+
|
|
103
|
+
test('KeqConsumer applies middleware to its own KeqRequest', () => {
|
|
104
|
+
const scopedKeqRequest = new KeqRequest()
|
|
105
|
+
const consumer = new KeqConsumer(scopedKeqRequest)
|
|
106
|
+
|
|
107
|
+
const middleware: KeqMiddleware = async (_ctx, next) => { await next() }
|
|
108
|
+
consumer.apply(middleware).forRoutes(KEQ_ROUTES.ALL)
|
|
109
|
+
|
|
110
|
+
expect(scopedKeqRequest.middlewares.length).toBe(1)
|
|
111
|
+
})
|
|
112
|
+
|
|
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)
|
|
119
|
+
|
|
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)
|
|
125
|
+
})
|
|
126
|
+
|
|
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() },
|
|
135
|
+
}
|
|
136
|
+
consumer.apply(middleware).forRoutes(KEQ_ROUTES.ALL)
|
|
137
|
+
|
|
138
|
+
expect(keqRequest.middlewares.length).toBe(1)
|
|
139
|
+
})
|
|
140
|
+
|
|
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/*' })
|
|
149
|
+
|
|
150
|
+
expect(keqRequest.middlewares.length).toBe(1)
|
|
151
|
+
})
|
|
152
|
+
|
|
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() },
|
|
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
|
|
172
|
+
|
|
173
|
+
const middleware = {
|
|
174
|
+
use: async (ctx: unknown, next: () => Promise<void>) => {
|
|
175
|
+
capturedCtx = ctx
|
|
176
|
+
capturedNext = next
|
|
177
|
+
await next()
|
|
178
|
+
},
|
|
179
|
+
}
|
|
180
|
+
consumer.apply(middleware).forRoutes(KEQ_ROUTES.ALL)
|
|
181
|
+
|
|
182
|
+
const middlewareFn = keqRequest.middlewares[0]
|
|
183
|
+
const mockCtx = { request: { url: { host: 'example.com', pathname: '/' }, method: 'GET' } }
|
|
184
|
+
const mockNext = async () => {}
|
|
185
|
+
|
|
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)
|
|
201
|
+
|
|
202
|
+
expect(scopedKeqRequest.middlewares.length).toBe(1)
|
|
203
|
+
})
|
package/dist/index.d.mts
CHANGED
|
@@ -1,62 +1,111 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { DynamicModule } from "@nestjs/common";
|
|
1
|
+
import { Type } from "@nestjs/common";
|
|
2
|
+
import { KeqExecutionContext, KeqMiddleware, KeqNext, KeqRequest } from "keq";
|
|
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.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/
|
|
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"}
|