@buenojs/bueno 0.8.3 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +136 -16
- package/dist/cli/{index.js → bin.js} +3036 -1421
- package/dist/container/index.js +250 -0
- package/dist/context/index.js +219 -0
- package/dist/database/index.js +493 -0
- package/dist/frontend/index.js +7697 -0
- package/dist/health/index.js +364 -0
- package/dist/i18n/index.js +345 -0
- package/dist/index.js +11043 -6482
- package/dist/jobs/index.js +819 -0
- package/dist/lock/index.js +367 -0
- package/dist/logger/index.js +281 -0
- package/dist/metrics/index.js +289 -0
- package/dist/middleware/index.js +77 -0
- package/dist/migrations/index.js +571 -0
- package/dist/modules/index.js +3346 -0
- package/dist/notification/index.js +484 -0
- package/dist/observability/index.js +331 -0
- package/dist/openapi/index.js +776 -0
- package/dist/orm/index.js +1356 -0
- package/dist/router/index.js +886 -0
- package/dist/rpc/index.js +691 -0
- package/dist/schema/index.js +400 -0
- package/dist/telemetry/index.js +595 -0
- package/dist/template/index.js +640 -0
- package/dist/templates/index.js +640 -0
- package/dist/testing/index.js +1111 -0
- package/dist/types/index.js +60 -0
- package/package.json +121 -27
- package/src/cache/index.ts +2 -1
- package/src/cli/bin.ts +2 -2
- package/src/cli/commands/build.ts +183 -165
- package/src/cli/commands/dev.ts +96 -89
- package/src/cli/commands/generate.ts +142 -111
- package/src/cli/commands/help.ts +20 -16
- package/src/cli/commands/index.ts +3 -6
- package/src/cli/commands/migration.ts +124 -105
- package/src/cli/commands/new.ts +392 -438
- package/src/cli/commands/start.ts +81 -79
- package/src/cli/core/args.ts +68 -50
- package/src/cli/core/console.ts +89 -95
- package/src/cli/core/index.ts +4 -4
- package/src/cli/core/prompt.ts +65 -62
- package/src/cli/core/spinner.ts +23 -20
- package/src/cli/index.ts +46 -38
- package/src/cli/templates/database/index.ts +61 -0
- package/src/cli/templates/database/mysql.ts +14 -0
- package/src/cli/templates/database/none.ts +16 -0
- package/src/cli/templates/database/postgresql.ts +14 -0
- package/src/cli/templates/database/sqlite.ts +14 -0
- package/src/cli/templates/deploy.ts +29 -26
- package/src/cli/templates/docker.ts +41 -30
- package/src/cli/templates/frontend/index.ts +63 -0
- package/src/cli/templates/frontend/none.ts +17 -0
- package/src/cli/templates/frontend/react.ts +140 -0
- package/src/cli/templates/frontend/solid.ts +134 -0
- package/src/cli/templates/frontend/svelte.ts +131 -0
- package/src/cli/templates/frontend/vue.ts +130 -0
- package/src/cli/templates/generators/index.ts +339 -0
- package/src/cli/templates/generators/types.ts +56 -0
- package/src/cli/templates/index.ts +35 -2
- package/src/cli/templates/project/api.ts +81 -0
- package/src/cli/templates/project/default.ts +140 -0
- package/src/cli/templates/project/fullstack.ts +111 -0
- package/src/cli/templates/project/index.ts +95 -0
- package/src/cli/templates/project/minimal.ts +45 -0
- package/src/cli/templates/project/types.ts +94 -0
- package/src/cli/templates/project/website.ts +263 -0
- package/src/cli/utils/fs.ts +55 -41
- package/src/cli/utils/index.ts +3 -2
- package/src/cli/utils/strings.ts +47 -33
- package/src/cli/utils/version.ts +47 -0
- package/src/config/env-validation.ts +100 -0
- package/src/config/env.ts +169 -41
- package/src/config/index.ts +28 -20
- package/src/config/loader.ts +25 -16
- package/src/config/merge.ts +21 -10
- package/src/config/types.ts +545 -25
- package/src/config/validation.ts +215 -7
- package/src/container/forward-ref.ts +22 -22
- package/src/container/index.ts +34 -12
- package/src/context/index.ts +11 -1
- package/src/database/index.ts +7 -190
- package/src/database/orm/builder.ts +457 -0
- package/src/database/orm/casts/index.ts +130 -0
- package/src/database/orm/casts/types.ts +25 -0
- package/src/database/orm/compiler.ts +304 -0
- package/src/database/orm/hooks/index.ts +114 -0
- package/src/database/orm/index.ts +61 -0
- package/src/database/orm/model-registry.ts +59 -0
- package/src/database/orm/model.ts +821 -0
- package/src/database/orm/relationships/base.ts +146 -0
- package/src/database/orm/relationships/belongs-to-many.ts +179 -0
- package/src/database/orm/relationships/belongs-to.ts +56 -0
- package/src/database/orm/relationships/has-many.ts +45 -0
- package/src/database/orm/relationships/has-one.ts +41 -0
- package/src/database/orm/relationships/index.ts +11 -0
- package/src/database/orm/scopes/index.ts +55 -0
- package/src/events/__tests__/event-system.test.ts +235 -0
- package/src/events/config.ts +238 -0
- package/src/events/example-usage.ts +185 -0
- package/src/events/index.ts +278 -0
- package/src/events/manager.ts +385 -0
- package/src/events/registry.ts +182 -0
- package/src/events/types.ts +124 -0
- package/src/frontend/api-routes.ts +65 -23
- package/src/frontend/bundler.ts +76 -34
- package/src/frontend/console-client.ts +2 -2
- package/src/frontend/console-stream.ts +94 -38
- package/src/frontend/dev-server.ts +94 -46
- package/src/frontend/file-router.ts +61 -19
- package/src/frontend/frameworks/index.ts +37 -10
- package/src/frontend/frameworks/react.ts +10 -8
- package/src/frontend/frameworks/solid.ts +11 -9
- package/src/frontend/frameworks/svelte.ts +15 -9
- package/src/frontend/frameworks/vue.ts +13 -11
- package/src/frontend/hmr-client.ts +12 -10
- package/src/frontend/hmr.ts +146 -103
- package/src/frontend/index.ts +14 -5
- package/src/frontend/islands.ts +41 -22
- package/src/frontend/isr.ts +59 -37
- package/src/frontend/layout.ts +36 -21
- package/src/frontend/ssr/react.ts +74 -27
- package/src/frontend/ssr/solid.ts +54 -20
- package/src/frontend/ssr/svelte.ts +48 -14
- package/src/frontend/ssr/vue.ts +50 -18
- package/src/frontend/ssr.ts +83 -39
- package/src/frontend/types.ts +91 -56
- package/src/health/index.ts +21 -9
- package/src/i18n/engine.ts +305 -0
- package/src/i18n/index.ts +38 -0
- package/src/i18n/loader.ts +218 -0
- package/src/i18n/middleware.ts +164 -0
- package/src/i18n/negotiator.ts +162 -0
- package/src/i18n/types.ts +158 -0
- package/src/index.ts +179 -27
- package/src/jobs/drivers/memory.ts +315 -0
- package/src/jobs/drivers/redis.ts +459 -0
- package/src/jobs/index.ts +30 -0
- package/src/jobs/queue.ts +281 -0
- package/src/jobs/types.ts +295 -0
- package/src/jobs/worker.ts +380 -0
- package/src/logger/index.ts +1 -3
- package/src/logger/transports/index.ts +62 -22
- package/src/metrics/index.ts +25 -16
- package/src/migrations/index.ts +9 -0
- package/src/modules/filters.ts +13 -17
- package/src/modules/guards.ts +49 -26
- package/src/modules/index.ts +409 -298
- package/src/modules/interceptors.ts +58 -20
- package/src/modules/lazy.ts +11 -19
- package/src/modules/lifecycle.ts +15 -7
- package/src/modules/metadata.ts +15 -5
- package/src/modules/pipes.ts +94 -72
- package/src/notification/channels/base.ts +68 -0
- package/src/notification/channels/email.ts +105 -0
- package/src/notification/channels/push.ts +104 -0
- package/src/notification/channels/sms.ts +105 -0
- package/src/notification/channels/whatsapp.ts +104 -0
- package/src/notification/index.ts +48 -0
- package/src/notification/service.ts +354 -0
- package/src/notification/types.ts +344 -0
- package/src/observability/__tests__/observability.test.ts +483 -0
- package/src/observability/breadcrumbs.ts +114 -0
- package/src/observability/index.ts +136 -0
- package/src/observability/interceptor.ts +85 -0
- package/src/observability/service.ts +303 -0
- package/src/observability/trace.ts +37 -0
- package/src/observability/types.ts +196 -0
- package/src/openapi/__tests__/decorators.test.ts +335 -0
- package/src/openapi/__tests__/document-builder.test.ts +285 -0
- package/src/openapi/__tests__/route-scanner.test.ts +334 -0
- package/src/openapi/__tests__/schema-generator.test.ts +275 -0
- package/src/openapi/decorators.ts +328 -0
- package/src/openapi/document-builder.ts +274 -0
- package/src/openapi/index.ts +112 -0
- package/src/openapi/metadata.ts +112 -0
- package/src/openapi/route-scanner.ts +289 -0
- package/src/openapi/schema-generator.ts +256 -0
- package/src/openapi/swagger-module.ts +166 -0
- package/src/openapi/types.ts +398 -0
- package/src/orm/index.ts +10 -0
- package/src/rpc/index.ts +3 -1
- package/src/schema/index.ts +9 -0
- package/src/security/index.ts +15 -6
- package/src/ssg/index.ts +9 -8
- package/src/telemetry/index.ts +76 -22
- package/src/template/index.ts +7 -0
- package/src/templates/engine.ts +224 -0
- package/src/templates/index.ts +9 -0
- package/src/templates/loader.ts +331 -0
- package/src/templates/renderers/markdown.ts +212 -0
- package/src/templates/renderers/simple.ts +269 -0
- package/src/templates/types.ts +154 -0
- package/src/testing/index.ts +100 -27
- package/src/types/optional-deps.d.ts +347 -187
- package/src/validation/index.ts +92 -2
- package/src/validation/schemas.ts +536 -0
- package/tests/integration/fullstack.test.ts +4 -4
- package/tests/unit/database.test.ts +2 -72
- package/tests/unit/env-validation.test.ts +166 -0
- package/tests/unit/events.test.ts +910 -0
- package/tests/unit/i18n.test.ts +455 -0
- package/tests/unit/jobs.test.ts +493 -0
- package/tests/unit/notification.test.ts +988 -0
- package/tests/unit/observability.test.ts +453 -0
- package/tests/unit/orm/builder.test.ts +323 -0
- package/tests/unit/orm/casts.test.ts +179 -0
- package/tests/unit/orm/compiler.test.ts +220 -0
- package/tests/unit/orm/eager-loading.test.ts +285 -0
- package/tests/unit/orm/hooks.test.ts +191 -0
- package/tests/unit/orm/model.test.ts +373 -0
- package/tests/unit/orm/relationships.test.ts +303 -0
- package/tests/unit/orm/scopes.test.ts +74 -0
- package/tests/unit/templates-simple.test.ts +53 -0
- package/tests/unit/templates.test.ts +454 -0
- package/tests/unit/validation.test.ts +18 -24
- package/tsconfig.json +11 -3
package/src/modules/index.ts
CHANGED
|
@@ -7,108 +7,108 @@
|
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
Container,
|
|
10
|
+
type ForwardRef,
|
|
10
11
|
type Provider,
|
|
11
12
|
type Token,
|
|
12
|
-
type ForwardRef,
|
|
13
13
|
forwardRef,
|
|
14
|
+
getContainerMetadata,
|
|
15
|
+
getInjectTokens,
|
|
14
16
|
isForwardRef,
|
|
15
17
|
resolveForwardRef,
|
|
16
|
-
getInjectTokens,
|
|
17
18
|
setContainerMetadata,
|
|
18
|
-
getContainerMetadata,
|
|
19
19
|
} from "../container";
|
|
20
|
+
import type { Context } from "../context";
|
|
21
|
+
import { Router } from "../router";
|
|
22
|
+
import type { RouteHandler } from "../types";
|
|
23
|
+
import {
|
|
24
|
+
AllExceptionsFilter,
|
|
25
|
+
Catch,
|
|
26
|
+
type ExceptionFilter,
|
|
27
|
+
type ExecuteFiltersOptions,
|
|
28
|
+
type Filter,
|
|
29
|
+
type FilterFn,
|
|
30
|
+
HttpExceptionFilter,
|
|
31
|
+
NotFoundFilter,
|
|
32
|
+
UseFilters,
|
|
33
|
+
ValidationFilter,
|
|
34
|
+
canHandleException,
|
|
35
|
+
createDefaultErrorResponse,
|
|
36
|
+
createInternalErrorResponse,
|
|
37
|
+
executeFilter,
|
|
38
|
+
findAndExecuteFilter,
|
|
39
|
+
getCatchType,
|
|
40
|
+
getClassFilters,
|
|
41
|
+
getMethodFilters,
|
|
42
|
+
isExceptionFilter,
|
|
43
|
+
isFilterFn,
|
|
44
|
+
} from "./filters";
|
|
45
|
+
import {
|
|
46
|
+
type CanActivate,
|
|
47
|
+
type Guard,
|
|
48
|
+
type GuardFn,
|
|
49
|
+
createForbiddenResponse,
|
|
50
|
+
executeGuards,
|
|
51
|
+
getClassGuards,
|
|
52
|
+
getMethodGuards,
|
|
53
|
+
} from "./guards";
|
|
54
|
+
import {
|
|
55
|
+
type CallHandler,
|
|
56
|
+
type Interceptor,
|
|
57
|
+
type InterceptorFn,
|
|
58
|
+
type NestInterceptor,
|
|
59
|
+
executeInterceptors,
|
|
60
|
+
getClassInterceptors,
|
|
61
|
+
getMethodInterceptors,
|
|
62
|
+
isInterceptorFn,
|
|
63
|
+
isNestInterceptor,
|
|
64
|
+
} from "./interceptors";
|
|
20
65
|
import {
|
|
21
|
-
type LazyModuleLoader,
|
|
22
66
|
type Constructor as LazyConstructor,
|
|
23
|
-
type ModuleLoaderFn,
|
|
24
|
-
type LazyModuleMetadata,
|
|
25
|
-
LazyModuleLoaderImpl,
|
|
26
67
|
LazyModule,
|
|
27
|
-
|
|
68
|
+
type LazyModuleLoader,
|
|
69
|
+
LazyModuleLoaderImpl,
|
|
70
|
+
type LazyModuleMetadata,
|
|
71
|
+
LazyModuleRegistry,
|
|
28
72
|
MODULE_LOADER_TOKEN,
|
|
73
|
+
ModuleLoader,
|
|
74
|
+
type ModuleLoaderFn,
|
|
29
75
|
getLazyMetadata,
|
|
30
76
|
isLazyModule,
|
|
31
|
-
LazyModuleRegistry,
|
|
32
77
|
} from "./lazy";
|
|
33
|
-
import type { Context } from "../context";
|
|
34
|
-
import { Router } from "../router";
|
|
35
|
-
import type { RouteHandler } from "../types";
|
|
36
78
|
import {
|
|
79
|
+
type ApplicationLifecycle,
|
|
80
|
+
type BeforeApplicationShutdown,
|
|
81
|
+
type FullLifecycle,
|
|
37
82
|
LifecycleHookManager,
|
|
38
|
-
|
|
39
|
-
type OnModuleInit,
|
|
83
|
+
type OnAfterRequest,
|
|
40
84
|
type OnApplicationBootstrap,
|
|
41
|
-
type OnModuleDestroy,
|
|
42
|
-
type BeforeApplicationShutdown,
|
|
43
85
|
type OnApplicationShutdown,
|
|
44
86
|
type OnBeforeRequest,
|
|
45
|
-
type
|
|
87
|
+
type OnModuleDestroy,
|
|
88
|
+
type OnModuleInit,
|
|
46
89
|
type OnRequestError,
|
|
47
|
-
type ApplicationLifecycle,
|
|
48
90
|
type RequestLifecycle,
|
|
49
|
-
|
|
50
|
-
isOnModuleInit,
|
|
51
|
-
isOnApplicationBootstrap,
|
|
52
|
-
isOnModuleDestroy,
|
|
91
|
+
ShutdownSignalHandler,
|
|
53
92
|
isBeforeApplicationShutdown,
|
|
93
|
+
isOnAfterRequest,
|
|
94
|
+
isOnApplicationBootstrap,
|
|
54
95
|
isOnApplicationShutdown,
|
|
55
96
|
isOnBeforeRequest,
|
|
56
|
-
|
|
97
|
+
isOnModuleDestroy,
|
|
98
|
+
isOnModuleInit,
|
|
57
99
|
isOnRequestError,
|
|
58
100
|
} from "./lifecycle";
|
|
59
101
|
import {
|
|
60
|
-
type
|
|
61
|
-
type CanActivate,
|
|
62
|
-
type GuardFn,
|
|
63
|
-
getClassGuards,
|
|
64
|
-
getMethodGuards,
|
|
65
|
-
executeGuards,
|
|
66
|
-
createForbiddenResponse,
|
|
67
|
-
} from "./guards";
|
|
68
|
-
import {
|
|
69
|
-
type Interceptor,
|
|
70
|
-
type NestInterceptor,
|
|
71
|
-
type InterceptorFn,
|
|
72
|
-
type CallHandler,
|
|
73
|
-
getClassInterceptors,
|
|
74
|
-
getMethodInterceptors,
|
|
75
|
-
executeInterceptors,
|
|
76
|
-
isNestInterceptor,
|
|
77
|
-
isInterceptorFn,
|
|
78
|
-
} from "./interceptors";
|
|
79
|
-
import {
|
|
102
|
+
type ParameterPipeMetadata,
|
|
80
103
|
type Pipe,
|
|
81
|
-
type PipeTransform,
|
|
82
|
-
type PipeFn,
|
|
83
104
|
type PipeContext,
|
|
84
|
-
type
|
|
85
|
-
|
|
105
|
+
type PipeFn,
|
|
106
|
+
type PipeTransform,
|
|
107
|
+
createBadRequestResponse,
|
|
86
108
|
executePipes,
|
|
87
109
|
extractParameterValue,
|
|
88
|
-
|
|
110
|
+
getMethodPipes,
|
|
89
111
|
} from "./pipes";
|
|
90
|
-
import {
|
|
91
|
-
type Filter,
|
|
92
|
-
type ExceptionFilter,
|
|
93
|
-
type FilterFn,
|
|
94
|
-
type ExecuteFiltersOptions,
|
|
95
|
-
UseFilters,
|
|
96
|
-
Catch,
|
|
97
|
-
getClassFilters,
|
|
98
|
-
getMethodFilters,
|
|
99
|
-
getCatchType,
|
|
100
|
-
canHandleException,
|
|
101
|
-
isExceptionFilter,
|
|
102
|
-
isFilterFn,
|
|
103
|
-
executeFilter,
|
|
104
|
-
findAndExecuteFilter,
|
|
105
|
-
HttpExceptionFilter,
|
|
106
|
-
ValidationFilter,
|
|
107
|
-
NotFoundFilter,
|
|
108
|
-
AllExceptionsFilter,
|
|
109
|
-
createDefaultErrorResponse,
|
|
110
|
-
createInternalErrorResponse,
|
|
111
|
-
} from "./filters";
|
|
112
112
|
|
|
113
113
|
// ============= Types =============
|
|
114
114
|
|
|
@@ -129,14 +129,14 @@ export interface LifecycleHooks {
|
|
|
129
129
|
// ============= Metadata Storage =============
|
|
130
130
|
// Import metadata storage and decorators from isolated module to avoid circular dependencies
|
|
131
131
|
import {
|
|
132
|
-
setMetadata,
|
|
133
|
-
getMetadata,
|
|
134
|
-
setPrototypeMetadata,
|
|
135
|
-
getPrototypeMetadata,
|
|
136
|
-
Injectable,
|
|
137
132
|
Controller,
|
|
133
|
+
Injectable,
|
|
138
134
|
Module,
|
|
139
135
|
type ModuleMetadata,
|
|
136
|
+
getMetadata,
|
|
137
|
+
getPrototypeMetadata,
|
|
138
|
+
setMetadata,
|
|
139
|
+
setPrototypeMetadata,
|
|
140
140
|
} from "./metadata";
|
|
141
141
|
|
|
142
142
|
// Re-export decorators and types for external use
|
|
@@ -166,7 +166,10 @@ export function Inject(token: Token | ForwardRef<Token>): ParameterDecorator {
|
|
|
166
166
|
) => {
|
|
167
167
|
const targetObj = target as object;
|
|
168
168
|
const existingTokens: Array<Token | ForwardRef<Token>> =
|
|
169
|
-
getContainerMetadata<Array<Token | ForwardRef<Token>>>(
|
|
169
|
+
getContainerMetadata<Array<Token | ForwardRef<Token>>>(
|
|
170
|
+
targetObj,
|
|
171
|
+
"inject:tokens",
|
|
172
|
+
) ?? [];
|
|
170
173
|
existingTokens[parameterIndex] = token;
|
|
171
174
|
setContainerMetadata(targetObj, "inject:tokens", existingTokens);
|
|
172
175
|
};
|
|
@@ -250,9 +253,9 @@ export class AppModule {
|
|
|
250
253
|
|
|
251
254
|
// Add providers (normalize class references to provider objects)
|
|
252
255
|
if (metadata.providers) {
|
|
253
|
-
const normalizedProviders = metadata.providers.map(p => {
|
|
256
|
+
const normalizedProviders = metadata.providers.map((p) => {
|
|
254
257
|
// If it's a class constructor (function) without token, normalize it
|
|
255
|
-
if (typeof p ===
|
|
258
|
+
if (typeof p === "function" && !p.token) {
|
|
256
259
|
return { token: p, useClass: p };
|
|
257
260
|
}
|
|
258
261
|
return p;
|
|
@@ -349,7 +352,8 @@ export class Application {
|
|
|
349
352
|
private routeGuardMetadata: Map<string, RouteGuardMetadata> = new Map();
|
|
350
353
|
private routePipeMetadata: Map<string, RoutePipeMetadata> = new Map();
|
|
351
354
|
private routeFilterMetadata: Map<string, RouteFilterMetadata> = new Map();
|
|
352
|
-
private routeInterceptorMetadata: Map<string, RouteInterceptorMetadata> =
|
|
355
|
+
private routeInterceptorMetadata: Map<string, RouteInterceptorMetadata> =
|
|
356
|
+
new Map();
|
|
353
357
|
private moduleLoader: ModuleLoader;
|
|
354
358
|
private loadedLazyModules = new Set<Constructor>();
|
|
355
359
|
|
|
@@ -454,8 +458,13 @@ export class Application {
|
|
|
454
458
|
|
|
455
459
|
for (const provider of providers) {
|
|
456
460
|
const token = provider.token;
|
|
457
|
-
const instance = this.container.resolve(
|
|
458
|
-
|
|
461
|
+
const instance = this.container.resolve(
|
|
462
|
+
token as import("../container").Token,
|
|
463
|
+
);
|
|
464
|
+
this.providerInstances.set(
|
|
465
|
+
token as import("../container").Token,
|
|
466
|
+
instance,
|
|
467
|
+
);
|
|
459
468
|
this.lifecycleManager.registerInstance(instance);
|
|
460
469
|
}
|
|
461
470
|
}
|
|
@@ -486,21 +495,35 @@ export class Application {
|
|
|
486
495
|
// Create controller instance
|
|
487
496
|
// First, check for explicit injection tokens from @Inject decorator
|
|
488
497
|
let injectTokens =
|
|
489
|
-
getInjectTokens<Array<Token | ForwardRef<Token>>>(
|
|
490
|
-
|
|
498
|
+
getInjectTokens<Array<Token | ForwardRef<Token>>>(
|
|
499
|
+
controllerClass,
|
|
500
|
+
"inject:tokens",
|
|
501
|
+
) ?? [];
|
|
502
|
+
|
|
491
503
|
// If no explicit tokens, try to use TypeScript's design:paramtypes metadata
|
|
492
504
|
// This requires the reflect-metadata polyfill to be imported by the user
|
|
493
|
-
if (
|
|
494
|
-
|
|
505
|
+
if (
|
|
506
|
+
injectTokens.length === 0 &&
|
|
507
|
+
typeof Reflect !== "undefined" &&
|
|
508
|
+
typeof Reflect.getMetadata === "function"
|
|
509
|
+
) {
|
|
510
|
+
const paramTypes = Reflect.getMetadata(
|
|
511
|
+
"design:paramtypes",
|
|
512
|
+
controllerClass,
|
|
513
|
+
) as Array<new (...args: unknown[]) => unknown> | undefined;
|
|
495
514
|
if (paramTypes) {
|
|
496
515
|
// Use the constructor parameter types as injection tokens
|
|
497
|
-
injectTokens = paramTypes.map(
|
|
516
|
+
injectTokens = paramTypes.map(
|
|
517
|
+
(paramType) => paramType as unknown as Token,
|
|
518
|
+
);
|
|
498
519
|
}
|
|
499
520
|
}
|
|
500
|
-
|
|
521
|
+
|
|
501
522
|
const deps = injectTokens.map((tokenOrRef) => {
|
|
502
523
|
// Resolve forward reference if needed
|
|
503
|
-
const token = isForwardRef(tokenOrRef)
|
|
524
|
+
const token = isForwardRef(tokenOrRef)
|
|
525
|
+
? resolveForwardRef(tokenOrRef)
|
|
526
|
+
: tokenOrRef;
|
|
504
527
|
return this.container.resolve(token);
|
|
505
528
|
});
|
|
506
529
|
const instance = new controllerClass(...deps);
|
|
@@ -530,19 +553,23 @@ export class Application {
|
|
|
530
553
|
| "options";
|
|
531
554
|
|
|
532
555
|
// Get method-level guards
|
|
533
|
-
const methodGuards =
|
|
556
|
+
const methodGuards =
|
|
557
|
+
getMethodGuards(controllerClass.prototype, route.handler) ?? [];
|
|
534
558
|
|
|
535
559
|
// Get method-level pipes
|
|
536
|
-
const parameterPipes =
|
|
560
|
+
const parameterPipes =
|
|
561
|
+
getMethodPipes(controllerClass.prototype, route.handler) ?? [];
|
|
537
562
|
|
|
538
563
|
// Get class-level filters
|
|
539
564
|
const classFilters = getClassFilters(controllerClass) ?? [];
|
|
540
565
|
|
|
541
566
|
// Get method-level filters
|
|
542
|
-
const methodFilters =
|
|
567
|
+
const methodFilters =
|
|
568
|
+
getMethodFilters(controllerClass.prototype, route.handler) ?? [];
|
|
543
569
|
|
|
544
570
|
// Get method-level interceptors
|
|
545
|
-
const methodInterceptors =
|
|
571
|
+
const methodInterceptors =
|
|
572
|
+
getMethodInterceptors(controllerClass.prototype, route.handler) ?? [];
|
|
546
573
|
|
|
547
574
|
// Store guard metadata for this route
|
|
548
575
|
const routeKey = `${method.toUpperCase()}:${fullPath}`;
|
|
@@ -663,8 +690,13 @@ export class Application {
|
|
|
663
690
|
if (metadata.providers) {
|
|
664
691
|
for (const provider of metadata.providers) {
|
|
665
692
|
this.container.register(provider);
|
|
666
|
-
const instance = this.container.resolve(
|
|
667
|
-
|
|
693
|
+
const instance = this.container.resolve(
|
|
694
|
+
provider.token as import("../container").Token,
|
|
695
|
+
);
|
|
696
|
+
this.providerInstances.set(
|
|
697
|
+
provider.token as import("../container").Token,
|
|
698
|
+
instance,
|
|
699
|
+
);
|
|
668
700
|
this.lifecycleManager.registerInstance(instance);
|
|
669
701
|
}
|
|
670
702
|
|
|
@@ -706,7 +738,7 @@ export class Application {
|
|
|
706
738
|
|
|
707
739
|
/**
|
|
708
740
|
* Perform graceful shutdown
|
|
709
|
-
*
|
|
741
|
+
*
|
|
710
742
|
* Execution order:
|
|
711
743
|
* 1. Stop accepting new requests
|
|
712
744
|
* 2. beforeApplicationShutdown(signal)
|
|
@@ -787,7 +819,7 @@ export class Application {
|
|
|
787
819
|
// Execute guards (before interceptors and pipes)
|
|
788
820
|
const routeKey = `${request.method}:${url.pathname}`;
|
|
789
821
|
const guardMetadata = this.routeGuardMetadata.get(routeKey);
|
|
790
|
-
|
|
822
|
+
|
|
791
823
|
if (guardMetadata || this.globalGuards.length > 0) {
|
|
792
824
|
const guardsPassed = await executeGuards(context, {
|
|
793
825
|
globalGuards: this.globalGuards,
|
|
@@ -795,7 +827,11 @@ export class Application {
|
|
|
795
827
|
methodGuards: guardMetadata?.methodGuards ?? [],
|
|
796
828
|
resolveGuard: (guard: Guard) => {
|
|
797
829
|
// Try to resolve from container if it's a token
|
|
798
|
-
if (
|
|
830
|
+
if (
|
|
831
|
+
typeof guard === "object" &&
|
|
832
|
+
guard !== null &&
|
|
833
|
+
!("canActivate" in guard)
|
|
834
|
+
) {
|
|
799
835
|
try {
|
|
800
836
|
return this.container.resolve(guard as Token) as CanActivate;
|
|
801
837
|
} catch {
|
|
@@ -810,120 +846,155 @@ export class Application {
|
|
|
810
846
|
return createForbiddenResponse();
|
|
811
847
|
}
|
|
812
848
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
849
|
+
|
|
850
|
+
// Get interceptor metadata
|
|
851
|
+
const interceptorMetadata = this.routeInterceptorMetadata.get(routeKey);
|
|
852
|
+
|
|
853
|
+
// Create the handler function that executes pipes and middleware
|
|
854
|
+
const executeHandler = async (): Promise<Response> => {
|
|
855
|
+
// Execute pipes (after guards, before handler)
|
|
856
|
+
const pipeMetadata = this.routePipeMetadata.get(routeKey);
|
|
857
|
+
if (pipeMetadata || this.globalPipes.length > 0) {
|
|
858
|
+
try {
|
|
859
|
+
// Process each parameter with pipes
|
|
860
|
+
const params = pipeMetadata?.parameterPipes ?? [];
|
|
861
|
+
for (const paramMeta of params) {
|
|
862
|
+
// Extract the initial value for this parameter
|
|
863
|
+
const initialValue = await extractParameterValue(
|
|
864
|
+
context,
|
|
865
|
+
paramMeta,
|
|
866
|
+
);
|
|
867
|
+
|
|
868
|
+
// Create pipe context
|
|
869
|
+
const pipeContext: PipeContext = {
|
|
870
|
+
context,
|
|
871
|
+
metadata: {
|
|
872
|
+
index: paramMeta.index,
|
|
873
|
+
name: paramMeta.key,
|
|
874
|
+
decorator: paramMeta.decorator,
|
|
875
|
+
},
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
// Execute pipes for this parameter
|
|
879
|
+
const transformedValue = await executePipes(
|
|
880
|
+
initialValue,
|
|
881
|
+
pipeContext,
|
|
882
|
+
{
|
|
841
883
|
globalPipes: this.globalPipes,
|
|
842
884
|
parameterPipes: paramMeta.pipes,
|
|
843
885
|
resolvePipe: (pipe: Pipe) => {
|
|
844
886
|
// Try to resolve from container if it's a token
|
|
845
|
-
if (
|
|
887
|
+
if (
|
|
888
|
+
typeof pipe === "object" &&
|
|
889
|
+
pipe !== null &&
|
|
890
|
+
!("transform" in pipe)
|
|
891
|
+
) {
|
|
846
892
|
try {
|
|
847
|
-
return this.container.resolve(
|
|
893
|
+
return this.container.resolve(
|
|
894
|
+
pipe as Token,
|
|
895
|
+
) as PipeTransform;
|
|
848
896
|
} catch {
|
|
849
897
|
return null;
|
|
850
898
|
}
|
|
851
899
|
}
|
|
852
900
|
return null;
|
|
853
901
|
},
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
}
|
|
859
|
-
} catch (error) {
|
|
860
|
-
// Pipe transformation failed - return 400 Bad Request
|
|
861
|
-
if (error instanceof Error) {
|
|
862
|
-
return createBadRequestResponse(error);
|
|
863
|
-
}
|
|
864
|
-
return createBadRequestResponse(new Error("Pipe transformation failed"));
|
|
902
|
+
},
|
|
903
|
+
);
|
|
904
|
+
|
|
905
|
+
// Store the transformed value in context for handler access
|
|
906
|
+
context.set(`pipe:param:${paramMeta.index}`, transformedValue);
|
|
865
907
|
}
|
|
908
|
+
} catch (error) {
|
|
909
|
+
// Pipe transformation failed - return 400 Bad Request
|
|
910
|
+
if (error instanceof Error) {
|
|
911
|
+
return createBadRequestResponse(error);
|
|
912
|
+
}
|
|
913
|
+
return createBadRequestResponse(
|
|
914
|
+
new Error("Pipe transformation failed"),
|
|
915
|
+
);
|
|
866
916
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
// Execute middleware and handler
|
|
920
|
+
const pipeline = compose(
|
|
921
|
+
(match.middleware ?? []) as import("../middleware").Middleware[],
|
|
922
|
+
);
|
|
923
|
+
return pipeline(
|
|
924
|
+
context,
|
|
925
|
+
match.handler as import("../middleware").Handler,
|
|
926
|
+
);
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
// Execute interceptors wrapping around the handler
|
|
930
|
+
// Interceptors run after guards, before pipes
|
|
931
|
+
try {
|
|
932
|
+
const response = await executeInterceptors(context, executeHandler, {
|
|
933
|
+
globalInterceptors: this.globalInterceptors,
|
|
934
|
+
classInterceptors: interceptorMetadata?.classInterceptors ?? [],
|
|
935
|
+
methodInterceptors: interceptorMetadata?.methodInterceptors ?? [],
|
|
936
|
+
resolveInterceptor: (
|
|
937
|
+
interceptor: Interceptor,
|
|
938
|
+
): NestInterceptor | InterceptorFn | null => {
|
|
939
|
+
// Try to resolve from container if it's a token
|
|
940
|
+
if (
|
|
941
|
+
typeof interceptor === "object" &&
|
|
942
|
+
interceptor !== null &&
|
|
943
|
+
!isNestInterceptor(interceptor) &&
|
|
944
|
+
!isInterceptorFn(interceptor)
|
|
945
|
+
) {
|
|
946
|
+
try {
|
|
947
|
+
return this.container.resolve(
|
|
948
|
+
interceptor as Token,
|
|
949
|
+
) as NestInterceptor;
|
|
950
|
+
} catch {
|
|
951
|
+
return null;
|
|
888
952
|
}
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
953
|
+
}
|
|
954
|
+
// Try to instantiate if it's a class constructor
|
|
955
|
+
if (
|
|
956
|
+
typeof interceptor === "function" &&
|
|
957
|
+
!isInterceptorFn(interceptor)
|
|
958
|
+
) {
|
|
959
|
+
try {
|
|
960
|
+
const Constructor = interceptor as new () => NestInterceptor;
|
|
961
|
+
const instance = new Constructor();
|
|
962
|
+
if (isNestInterceptor(instance)) {
|
|
963
|
+
return instance;
|
|
899
964
|
}
|
|
965
|
+
} catch {
|
|
966
|
+
// Cannot instantiate
|
|
900
967
|
}
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
return response as Response;
|
|
968
|
+
}
|
|
969
|
+
return null;
|
|
970
|
+
},
|
|
971
|
+
});
|
|
972
|
+
|
|
973
|
+
// Execute onAfterRequest hooks
|
|
974
|
+
try {
|
|
975
|
+
await this.lifecycleManager.executeOnAfterRequest(
|
|
976
|
+
context,
|
|
977
|
+
response as Response,
|
|
978
|
+
);
|
|
913
979
|
} catch (error) {
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
980
|
+
console.error("Error in onAfterRequest hook:", error);
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
return response as Response;
|
|
984
|
+
} catch (error) {
|
|
985
|
+
// Execute onRequestError hooks
|
|
986
|
+
try {
|
|
987
|
+
await this.lifecycleManager.executeOnRequestError(
|
|
988
|
+
context,
|
|
989
|
+
error as Error,
|
|
990
|
+
);
|
|
991
|
+
} catch (hookError) {
|
|
992
|
+
console.error("Error in onRequestError hook:", hookError);
|
|
926
993
|
}
|
|
994
|
+
|
|
995
|
+
// Handle exception with filters
|
|
996
|
+
return this.handleException(error as Error, context, routeKey);
|
|
997
|
+
}
|
|
927
998
|
},
|
|
928
999
|
});
|
|
929
1000
|
|
|
@@ -949,7 +1020,7 @@ export class Application {
|
|
|
949
1020
|
// Execute guards (before interceptors and pipes)
|
|
950
1021
|
const routeKey = `${request.method}:${url.pathname}`;
|
|
951
1022
|
const guardMetadata = this.routeGuardMetadata.get(routeKey);
|
|
952
|
-
|
|
1023
|
+
|
|
953
1024
|
if (guardMetadata || this.globalGuards.length > 0) {
|
|
954
1025
|
const guardsPassed = await executeGuards(context, {
|
|
955
1026
|
globalGuards: this.globalGuards,
|
|
@@ -957,7 +1028,11 @@ export class Application {
|
|
|
957
1028
|
methodGuards: guardMetadata?.methodGuards ?? [],
|
|
958
1029
|
resolveGuard: (guard: Guard) => {
|
|
959
1030
|
// Try to resolve from container if it's a token
|
|
960
|
-
if (
|
|
1031
|
+
if (
|
|
1032
|
+
typeof guard === "object" &&
|
|
1033
|
+
guard !== null &&
|
|
1034
|
+
!("canActivate" in guard)
|
|
1035
|
+
) {
|
|
961
1036
|
try {
|
|
962
1037
|
return this.container.resolve(guard as Token) as CanActivate;
|
|
963
1038
|
} catch {
|
|
@@ -972,123 +1047,155 @@ export class Application {
|
|
|
972
1047
|
return createForbiddenResponse();
|
|
973
1048
|
}
|
|
974
1049
|
}
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1050
|
+
|
|
1051
|
+
// Get interceptor metadata
|
|
1052
|
+
const interceptorMetadata = this.routeInterceptorMetadata.get(routeKey);
|
|
1053
|
+
|
|
1054
|
+
// Create the handler function that executes pipes and middleware
|
|
1055
|
+
const executeHandler = async (): Promise<Response> => {
|
|
1056
|
+
// Execute pipes (after guards, before handler)
|
|
1057
|
+
const pipeMetadata = this.routePipeMetadata.get(routeKey);
|
|
1058
|
+
if (pipeMetadata || this.globalPipes.length > 0) {
|
|
1059
|
+
try {
|
|
1060
|
+
// Process each parameter with pipes
|
|
1061
|
+
const params = pipeMetadata?.parameterPipes ?? [];
|
|
1062
|
+
for (const paramMeta of params) {
|
|
1063
|
+
// Extract the initial value for this parameter
|
|
1064
|
+
const initialValue = await extractParameterValue(
|
|
1065
|
+
context,
|
|
1066
|
+
paramMeta,
|
|
1067
|
+
);
|
|
1068
|
+
|
|
1069
|
+
// Create pipe context
|
|
1070
|
+
const pipeContext: PipeContext = {
|
|
1071
|
+
context,
|
|
1072
|
+
metadata: {
|
|
1073
|
+
index: paramMeta.index,
|
|
1074
|
+
name: paramMeta.key,
|
|
1075
|
+
decorator: paramMeta.decorator,
|
|
1076
|
+
},
|
|
1077
|
+
};
|
|
1078
|
+
|
|
1079
|
+
// Execute pipes for this parameter
|
|
1080
|
+
const transformedValue = await executePipes(
|
|
1081
|
+
initialValue,
|
|
1082
|
+
pipeContext,
|
|
1083
|
+
{
|
|
1003
1084
|
globalPipes: this.globalPipes,
|
|
1004
1085
|
parameterPipes: paramMeta.pipes,
|
|
1005
1086
|
resolvePipe: (pipe: Pipe) => {
|
|
1006
1087
|
// Try to resolve from container if it's a token
|
|
1007
|
-
if (
|
|
1088
|
+
if (
|
|
1089
|
+
typeof pipe === "object" &&
|
|
1090
|
+
pipe !== null &&
|
|
1091
|
+
!("transform" in pipe)
|
|
1092
|
+
) {
|
|
1008
1093
|
try {
|
|
1009
|
-
return this.container.resolve(
|
|
1094
|
+
return this.container.resolve(
|
|
1095
|
+
pipe as Token,
|
|
1096
|
+
) as PipeTransform;
|
|
1010
1097
|
} catch {
|
|
1011
1098
|
return null;
|
|
1012
1099
|
}
|
|
1013
1100
|
}
|
|
1014
1101
|
return null;
|
|
1015
1102
|
},
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
}
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
return createBadRequestResponse(new Error("Pipe transformation failed"));
|
|
1103
|
+
},
|
|
1104
|
+
);
|
|
1105
|
+
|
|
1106
|
+
// Store the transformed value in context for handler access
|
|
1107
|
+
context.set(`pipe:param:${paramMeta.index}`, transformedValue);
|
|
1108
|
+
}
|
|
1109
|
+
} catch (error) {
|
|
1110
|
+
// Pipe transformation failed - return 400 Bad Request
|
|
1111
|
+
if (error instanceof Error) {
|
|
1112
|
+
return createBadRequestResponse(error);
|
|
1027
1113
|
}
|
|
1114
|
+
return createBadRequestResponse(
|
|
1115
|
+
new Error("Pipe transformation failed"),
|
|
1116
|
+
);
|
|
1028
1117
|
}
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
// Execute middleware and handler
|
|
1121
|
+
const pipeline = compose(
|
|
1122
|
+
(match.middleware ?? []) as import("../middleware").Middleware[],
|
|
1123
|
+
);
|
|
1124
|
+
return pipeline(
|
|
1125
|
+
context,
|
|
1126
|
+
match.handler as import("../middleware").Handler,
|
|
1127
|
+
);
|
|
1128
|
+
};
|
|
1129
|
+
|
|
1130
|
+
// Execute interceptors wrapping around the handler
|
|
1131
|
+
// Interceptors run after guards, before pipes
|
|
1132
|
+
try {
|
|
1133
|
+
const response = await executeInterceptors(context, executeHandler, {
|
|
1134
|
+
globalInterceptors: this.globalInterceptors,
|
|
1135
|
+
classInterceptors: interceptorMetadata?.classInterceptors ?? [],
|
|
1136
|
+
methodInterceptors: interceptorMetadata?.methodInterceptors ?? [],
|
|
1137
|
+
resolveInterceptor: (
|
|
1138
|
+
interceptor: Interceptor,
|
|
1139
|
+
): NestInterceptor | InterceptorFn | null => {
|
|
1140
|
+
// Try to resolve from container if it's a token
|
|
1141
|
+
if (
|
|
1142
|
+
typeof interceptor === "object" &&
|
|
1143
|
+
interceptor !== null &&
|
|
1144
|
+
!isNestInterceptor(interceptor) &&
|
|
1145
|
+
!isInterceptorFn(interceptor)
|
|
1146
|
+
) {
|
|
1147
|
+
try {
|
|
1148
|
+
return this.container.resolve(
|
|
1149
|
+
interceptor as Token,
|
|
1150
|
+
) as NestInterceptor;
|
|
1151
|
+
} catch {
|
|
1152
|
+
return null;
|
|
1050
1153
|
}
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1154
|
+
}
|
|
1155
|
+
// Try to instantiate if it's a class constructor
|
|
1156
|
+
if (
|
|
1157
|
+
typeof interceptor === "function" &&
|
|
1158
|
+
!isInterceptorFn(interceptor)
|
|
1159
|
+
) {
|
|
1160
|
+
try {
|
|
1161
|
+
const Constructor = interceptor as new () => NestInterceptor;
|
|
1162
|
+
const instance = new Constructor();
|
|
1163
|
+
if (isNestInterceptor(instance)) {
|
|
1164
|
+
return instance;
|
|
1061
1165
|
}
|
|
1166
|
+
} catch {
|
|
1167
|
+
// Cannot instantiate
|
|
1062
1168
|
}
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1169
|
+
}
|
|
1170
|
+
return null;
|
|
1171
|
+
},
|
|
1172
|
+
});
|
|
1173
|
+
|
|
1174
|
+
return response as Response;
|
|
1175
|
+
} catch (error) {
|
|
1176
|
+
// Handle exception with filters
|
|
1177
|
+
return this.handleException(error as Error, context, routeKey);
|
|
1072
1178
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
/**
|
|
1182
|
+
* Get the lifecycle manager for this application
|
|
1183
|
+
*/
|
|
1077
1184
|
getLifecycleManager(): LifecycleHookManager {
|
|
1078
1185
|
return this.lifecycleManager;
|
|
1079
1186
|
}
|
|
1080
1187
|
|
|
1081
1188
|
/**
|
|
1082
|
-
|
|
1083
|
-
|
|
1189
|
+
* Check if the application is shutting down
|
|
1190
|
+
*/
|
|
1084
1191
|
isShuttingDownNow(): boolean {
|
|
1085
1192
|
return this.isShuttingDown;
|
|
1086
1193
|
}
|
|
1087
1194
|
|
|
1088
1195
|
/**
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1196
|
+
* Handle an exception using the filters system
|
|
1197
|
+
* Filters are checked in order: method → class → global
|
|
1198
|
+
*/
|
|
1092
1199
|
private async handleException(
|
|
1093
1200
|
exception: Error,
|
|
1094
1201
|
context: Context,
|
|
@@ -1102,7 +1209,11 @@ export class Application {
|
|
|
1102
1209
|
methodFilters: filterMetadata?.methodFilters ?? [],
|
|
1103
1210
|
resolveFilter: (filter: Filter): ExceptionFilter | null => {
|
|
1104
1211
|
// Try to resolve from container if it's a token
|
|
1105
|
-
if (
|
|
1212
|
+
if (
|
|
1213
|
+
typeof filter === "object" &&
|
|
1214
|
+
filter !== null &&
|
|
1215
|
+
!isExceptionFilter(filter)
|
|
1216
|
+
) {
|
|
1106
1217
|
try {
|
|
1107
1218
|
return this.container.resolve(filter as Token) as ExceptionFilter;
|
|
1108
1219
|
} catch {
|
|
@@ -1138,17 +1249,17 @@ export function createApp(moduleClass: Constructor): Application {
|
|
|
1138
1249
|
export {
|
|
1139
1250
|
LifecycleHookManager,
|
|
1140
1251
|
ShutdownSignalHandler,
|
|
1141
|
-
OnModuleInit,
|
|
1142
|
-
OnApplicationBootstrap,
|
|
1143
|
-
OnModuleDestroy,
|
|
1144
|
-
BeforeApplicationShutdown,
|
|
1145
|
-
OnApplicationShutdown,
|
|
1146
|
-
OnBeforeRequest,
|
|
1147
|
-
OnAfterRequest,
|
|
1148
|
-
OnRequestError,
|
|
1149
|
-
ApplicationLifecycle,
|
|
1150
|
-
RequestLifecycle,
|
|
1151
|
-
FullLifecycle,
|
|
1252
|
+
type OnModuleInit,
|
|
1253
|
+
type OnApplicationBootstrap,
|
|
1254
|
+
type OnModuleDestroy,
|
|
1255
|
+
type BeforeApplicationShutdown,
|
|
1256
|
+
type OnApplicationShutdown,
|
|
1257
|
+
type OnBeforeRequest,
|
|
1258
|
+
type OnAfterRequest,
|
|
1259
|
+
type OnRequestError,
|
|
1260
|
+
type ApplicationLifecycle,
|
|
1261
|
+
type RequestLifecycle,
|
|
1262
|
+
type FullLifecycle,
|
|
1152
1263
|
isOnModuleInit,
|
|
1153
1264
|
isOnApplicationBootstrap,
|
|
1154
1265
|
isOnModuleDestroy,
|
|
@@ -1274,4 +1385,4 @@ export {
|
|
|
1274
1385
|
forwardRef,
|
|
1275
1386
|
isForwardRef,
|
|
1276
1387
|
resolveForwardRef,
|
|
1277
|
-
} from "../container";
|
|
1388
|
+
} from "../container";
|