@carno.js/core 0.2.11 → 1.0.2
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/LICENSE +673 -673
- package/README.md +188 -0
- package/dist/Carno.js +272 -333
- package/dist/Carno.mjs +268 -0
- package/dist/DefaultRoutes.js +51 -0
- package/dist/DefaultRoutes.mjs +34 -0
- package/dist/bun/index.js +183 -0
- package/dist/bun/index.js.map +86 -0
- package/dist/cache/CacheDriver.js +13 -0
- package/dist/cache/CacheDriver.mjs +0 -0
- package/dist/cache/CacheService.js +113 -0
- package/dist/cache/CacheService.mjs +93 -0
- package/dist/cache/MemoryDriver.js +66 -0
- package/dist/cache/MemoryDriver.mjs +46 -0
- package/dist/cache/RedisDriver.js +81 -0
- package/dist/cache/RedisDriver.mjs +61 -0
- package/dist/compiler/JITCompiler.js +111 -0
- package/dist/compiler/JITCompiler.mjs +89 -0
- package/dist/container/Container.js +99 -0
- package/dist/container/Container.mjs +78 -0
- package/dist/context/Context.js +97 -0
- package/dist/context/Context.mjs +77 -0
- package/dist/cors/CorsHandler.js +90 -0
- package/dist/cors/CorsHandler.mjs +68 -0
- package/dist/decorators/Controller.js +42 -0
- package/dist/decorators/Controller.mjs +22 -0
- package/dist/decorators/Inject.js +30 -0
- package/dist/decorators/Inject.mjs +10 -0
- package/dist/decorators/Middleware.js +35 -0
- package/dist/decorators/Middleware.mjs +15 -0
- package/dist/decorators/Service.js +31 -0
- package/dist/decorators/Service.mjs +12 -0
- package/dist/decorators/methods.js +60 -0
- package/dist/decorators/methods.mjs +34 -0
- package/dist/decorators/params.js +63 -0
- package/dist/decorators/params.mjs +37 -0
- package/dist/events/Lifecycle.js +69 -0
- package/dist/events/Lifecycle.mjs +41 -0
- package/dist/exceptions/HttpException.js +112 -26
- package/dist/exceptions/HttpException.mjs +82 -0
- package/dist/index.js +129 -31
- package/dist/index.mjs +94 -0
- package/dist/metadata.js +34 -0
- package/dist/metadata.mjs +9 -0
- package/dist/middleware/CarnoMiddleware.js +13 -0
- package/dist/middleware/CarnoMiddleware.mjs +0 -0
- package/dist/router/RadixRouter.js +121 -0
- package/dist/router/RadixRouter.mjs +101 -0
- package/dist/testing/TestHarness.js +81 -0
- package/dist/testing/TestHarness.mjs +60 -0
- package/dist/utils/Metadata.js +53 -0
- package/dist/utils/Metadata.mjs +31 -0
- package/dist/validation/ValibotAdapter.js +67 -0
- package/dist/validation/ValibotAdapter.mjs +48 -0
- package/dist/validation/ValidatorAdapter.js +35 -19
- package/dist/validation/ValidatorAdapter.mjs +14 -0
- package/dist/validation/ZodAdapter.js +80 -0
- package/dist/validation/ZodAdapter.mjs +59 -0
- package/package.json +21 -63
- package/src/Carno.ts +605 -0
- package/src/DefaultRoutes.ts +34 -0
- package/src/cache/CacheDriver.ts +50 -0
- package/src/cache/CacheService.ts +139 -0
- package/src/cache/MemoryDriver.ts +104 -0
- package/src/cache/RedisDriver.ts +116 -0
- package/src/compiler/JITCompiler.ts +167 -0
- package/src/container/Container.ts +168 -0
- package/src/context/Context.ts +128 -0
- package/src/cors/CorsHandler.ts +145 -0
- package/src/decorators/Controller.ts +63 -0
- package/src/decorators/Inject.ts +16 -0
- package/src/decorators/Middleware.ts +22 -0
- package/src/decorators/Service.ts +18 -0
- package/src/decorators/methods.ts +58 -0
- package/src/decorators/params.ts +47 -0
- package/src/events/Lifecycle.ts +97 -0
- package/src/exceptions/HttpException.ts +99 -0
- package/src/index.ts +92 -0
- package/src/metadata.ts +46 -0
- package/src/middleware/CarnoMiddleware.ts +14 -0
- package/src/router/RadixRouter.ts +225 -0
- package/src/testing/TestHarness.ts +177 -0
- package/src/utils/Metadata.ts +43 -0
- package/src/validation/ValibotAdapter.ts +95 -0
- package/src/validation/ValidatorAdapter.ts +69 -0
- package/src/validation/ZodAdapter.ts +102 -0
- package/dist/Carno.d.ts +0 -75
- package/dist/cache/bento-cache.driver.d.ts +0 -13
- package/dist/cache/bento-cache.driver.js +0 -55
- package/dist/cache/cache.service.d.ts +0 -8
- package/dist/cache/cache.service.js +0 -6
- package/dist/commons/decorators/Injectable.decorator.d.ts +0 -20
- package/dist/commons/decorators/Injectable.decorator.js +0 -33
- package/dist/commons/decorators/controller.decorator.d.ts +0 -8
- package/dist/commons/decorators/controller.decorator.js +0 -22
- package/dist/commons/decorators/http.decorators.d.ts +0 -13
- package/dist/commons/decorators/http.decorators.js +0 -63
- package/dist/commons/decorators/index.d.ts +0 -6
- package/dist/commons/decorators/index.js +0 -22
- package/dist/commons/decorators/inject.decorator.d.ts +0 -1
- package/dist/commons/decorators/inject.decorator.js +0 -5
- package/dist/commons/decorators/middleware.decorator.d.ts +0 -2
- package/dist/commons/decorators/middleware.decorator.js +0 -30
- package/dist/commons/decorators/service.decorator.d.ts +0 -2
- package/dist/commons/decorators/service.decorator.js +0 -7
- package/dist/commons/decorators/validation.decorator.d.ts +0 -32
- package/dist/commons/decorators/validation.decorator.js +0 -40
- package/dist/commons/http-code.enum.d.ts +0 -50
- package/dist/commons/http-code.enum.js +0 -54
- package/dist/commons/index.d.ts +0 -3
- package/dist/commons/index.js +0 -19
- package/dist/commons/registries/ProviderControl.d.ts +0 -77
- package/dist/commons/registries/ProviderControl.js +0 -112
- package/dist/commons/registries/ProviderRegistry.d.ts +0 -7
- package/dist/commons/registries/ProviderRegistry.js +0 -20
- package/dist/constants.d.ts +0 -8
- package/dist/constants.js +0 -11
- package/dist/container/ContainerConfiguration.d.ts +0 -45
- package/dist/container/ContainerConfiguration.js +0 -121
- package/dist/container/DependencyResolver.d.ts +0 -20
- package/dist/container/DependencyResolver.js +0 -85
- package/dist/container/InjectorService.d.ts +0 -58
- package/dist/container/InjectorService.js +0 -286
- package/dist/container/MethodInvoker.d.ts +0 -21
- package/dist/container/MethodInvoker.js +0 -83
- package/dist/container/RouteResolver.d.ts +0 -27
- package/dist/container/RouteResolver.js +0 -173
- package/dist/container/container.d.ts +0 -41
- package/dist/container/container.js +0 -71
- package/dist/container/createContainer.d.ts +0 -3
- package/dist/container/createContainer.js +0 -12
- package/dist/container/createInjector.d.ts +0 -2
- package/dist/container/createInjector.js +0 -7
- package/dist/container/index.d.ts +0 -6
- package/dist/container/index.js +0 -22
- package/dist/container/middleware.resolver.d.ts +0 -9
- package/dist/container/middleware.resolver.js +0 -35
- package/dist/default-routes-carno.d.ts +0 -3
- package/dist/default-routes-carno.js +0 -29
- package/dist/domain/BaseContext.d.ts +0 -15
- package/dist/domain/BaseContext.js +0 -2
- package/dist/domain/CarnoClosure.d.ts +0 -1
- package/dist/domain/CarnoClosure.js +0 -2
- package/dist/domain/CarnoMiddleware.d.ts +0 -5
- package/dist/domain/CarnoMiddleware.js +0 -2
- package/dist/domain/Context.d.ts +0 -58
- package/dist/domain/Context.js +0 -188
- package/dist/domain/FastContext.d.ts +0 -34
- package/dist/domain/FastContext.js +0 -59
- package/dist/domain/LocalsContainer.d.ts +0 -4
- package/dist/domain/LocalsContainer.js +0 -10
- package/dist/domain/Metadata.d.ts +0 -449
- package/dist/domain/Metadata.js +0 -511
- package/dist/domain/cors-config.d.ts +0 -12
- package/dist/domain/cors-config.js +0 -18
- package/dist/domain/cors-headers-cache.d.ts +0 -17
- package/dist/domain/cors-headers-cache.js +0 -101
- package/dist/domain/http-method.d.ts +0 -7
- package/dist/domain/http-method.js +0 -11
- package/dist/domain/index.d.ts +0 -10
- package/dist/domain/index.js +0 -26
- package/dist/domain/provider-scope.d.ts +0 -5
- package/dist/domain/provider-scope.js +0 -9
- package/dist/domain/provider-type.d.ts +0 -6
- package/dist/domain/provider-type.js +0 -10
- package/dist/domain/provider.d.ts +0 -37
- package/dist/domain/provider.js +0 -70
- package/dist/events/hooks.decorator.d.ts +0 -3
- package/dist/events/hooks.decorator.js +0 -29
- package/dist/events/index.d.ts +0 -2
- package/dist/events/index.js +0 -18
- package/dist/events/on-event.d.ts +0 -13
- package/dist/events/on-event.js +0 -11
- package/dist/exceptions/HttpException.d.ts +0 -9
- package/dist/exceptions/index.d.ts +0 -1
- package/dist/exceptions/index.js +0 -17
- package/dist/index.d.ts +0 -16
- package/dist/route/CompiledRoute.d.ts +0 -23
- package/dist/route/CompiledRoute.js +0 -9
- package/dist/route/FastPathExecutor.d.ts +0 -12
- package/dist/route/FastPathExecutor.js +0 -50
- package/dist/route/JITCompiler.d.ts +0 -28
- package/dist/route/JITCompiler.js +0 -245
- package/dist/route/Matcher.d.ts +0 -11
- package/dist/route/Matcher.js +0 -48
- package/dist/route/ParamResolverFactory.d.ts +0 -14
- package/dist/route/ParamResolverFactory.js +0 -49
- package/dist/route/RouteCompiler.d.ts +0 -28
- package/dist/route/RouteCompiler.js +0 -157
- package/dist/route/RouteExecutor.d.ts +0 -12
- package/dist/route/RouteExecutor.js +0 -84
- package/dist/route/memoirist.d.ts +0 -31
- package/dist/route/memoirist.js +0 -373
- package/dist/services/logger.service.d.ts +0 -23
- package/dist/services/logger.service.js +0 -47
- package/dist/testing/core-testing.d.ts +0 -24
- package/dist/testing/core-testing.js +0 -102
- package/dist/testing/index.d.ts +0 -1
- package/dist/testing/index.js +0 -17
- package/dist/utils/ValidationCache.d.ts +0 -5
- package/dist/utils/ValidationCache.js +0 -35
- package/dist/utils/ancestorOf.d.ts +0 -2
- package/dist/utils/ancestorOf.js +0 -10
- package/dist/utils/ancestorsOf.d.ts +0 -6
- package/dist/utils/ancestorsOf.js +0 -20
- package/dist/utils/classOf.d.ts +0 -13
- package/dist/utils/classOf.js +0 -21
- package/dist/utils/cleanObject.d.ts +0 -6
- package/dist/utils/cleanObject.js +0 -22
- package/dist/utils/constructorOf.d.ts +0 -11
- package/dist/utils/constructorOf.js +0 -18
- package/dist/utils/createInstance.d.ts +0 -1
- package/dist/utils/createInstance.js +0 -7
- package/dist/utils/decoratorTypeOf.d.ts +0 -11
- package/dist/utils/decoratorTypeOf.js +0 -32
- package/dist/utils/deepClone.d.ts +0 -6
- package/dist/utils/deepClone.js +0 -63
- package/dist/utils/deepMerge.d.ts +0 -9
- package/dist/utils/deepMerge.js +0 -62
- package/dist/utils/descriptorOf.d.ts +0 -8
- package/dist/utils/descriptorOf.js +0 -16
- package/dist/utils/formatValidationErrors.d.ts +0 -5
- package/dist/utils/formatValidationErrors.js +0 -80
- package/dist/utils/getClassOrSymbol.d.ts +0 -1
- package/dist/utils/getClassOrSymbol.js +0 -8
- package/dist/utils/getConstructorArgNames.d.ts +0 -1
- package/dist/utils/getConstructorArgNames.js +0 -12
- package/dist/utils/getMethodArgTypes.d.ts +0 -1
- package/dist/utils/getMethodArgTypes.js +0 -9
- package/dist/utils/getValue.d.ts +0 -32
- package/dist/utils/getValue.js +0 -47
- package/dist/utils/hasJsonMethod.d.ts +0 -1
- package/dist/utils/hasJsonMethod.js +0 -6
- package/dist/utils/index.d.ts +0 -15
- package/dist/utils/index.js +0 -31
- package/dist/utils/isArray.d.ts +0 -13
- package/dist/utils/isArray.js +0 -21
- package/dist/utils/isArrowFn.d.ts +0 -1
- package/dist/utils/isArrowFn.js +0 -7
- package/dist/utils/isBoolean.d.ts +0 -7
- package/dist/utils/isBoolean.js +0 -15
- package/dist/utils/isBuffer.d.ts +0 -7
- package/dist/utils/isBuffer.js +0 -19
- package/dist/utils/isClass.d.ts +0 -1
- package/dist/utils/isClass.js +0 -26
- package/dist/utils/isCollection.d.ts +0 -6
- package/dist/utils/isCollection.js +0 -20
- package/dist/utils/isDate.d.ts +0 -6
- package/dist/utils/isDate.js +0 -11
- package/dist/utils/isEmpty.d.ts +0 -6
- package/dist/utils/isEmpty.js +0 -12
- package/dist/utils/isFunction.d.ts +0 -1
- package/dist/utils/isFunction.js +0 -6
- package/dist/utils/isInheritedFrom.d.ts +0 -1
- package/dist/utils/isInheritedFrom.js +0 -24
- package/dist/utils/isMomentObject.d.ts +0 -1
- package/dist/utils/isMomentObject.js +0 -6
- package/dist/utils/isMongooseObject.d.ts +0 -2
- package/dist/utils/isMongooseObject.js +0 -11
- package/dist/utils/isNil.d.ts +0 -1
- package/dist/utils/isNil.js +0 -6
- package/dist/utils/isNumber.d.ts +0 -7
- package/dist/utils/isNumber.js +0 -15
- package/dist/utils/isObject.d.ts +0 -1
- package/dist/utils/isObject.js +0 -6
- package/dist/utils/isObservable.d.ts +0 -1
- package/dist/utils/isObservable.js +0 -6
- package/dist/utils/isPlainObject.d.ts +0 -7
- package/dist/utils/isPlainObject.js +0 -16
- package/dist/utils/isPrimitive.d.ts +0 -14
- package/dist/utils/isPrimitive.js +0 -28
- package/dist/utils/isPrimitiveType.d.ts +0 -1
- package/dist/utils/isPrimitiveType.js +0 -11
- package/dist/utils/isPromise.d.ts +0 -7
- package/dist/utils/isPromise.js +0 -14
- package/dist/utils/isProtectedKey.d.ts +0 -5
- package/dist/utils/isProtectedKey.js +0 -10
- package/dist/utils/isRegExp.d.ts +0 -1
- package/dist/utils/isRegExp.js +0 -6
- package/dist/utils/isRequestScope.d.ts +0 -11
- package/dist/utils/isRequestScope.js +0 -23
- package/dist/utils/isSerializable.d.ts +0 -1
- package/dist/utils/isSerializable.js +0 -11
- package/dist/utils/isStream.d.ts +0 -1
- package/dist/utils/isStream.js +0 -6
- package/dist/utils/isString.d.ts +0 -6
- package/dist/utils/isString.js +0 -14
- package/dist/utils/isSymbol.d.ts +0 -6
- package/dist/utils/isSymbol.js +0 -14
- package/dist/utils/methodsOf.d.ts +0 -9
- package/dist/utils/methodsOf.js +0 -24
- package/dist/utils/nameOf.d.ts +0 -14
- package/dist/utils/nameOf.js +0 -31
- package/dist/utils/objectKeys.d.ts +0 -1
- package/dist/utils/objectKeys.js +0 -7
- package/dist/utils/primitiveOf.d.ts +0 -1
- package/dist/utils/primitiveOf.js +0 -18
- package/dist/utils/prototypeOf.d.ts +0 -6
- package/dist/utils/prototypeOf.js +0 -12
- package/dist/utils/setValue.d.ts +0 -1
- package/dist/utils/setValue.js +0 -32
- package/dist/utils/toMap.d.ts +0 -3
- package/dist/utils/toMap.js +0 -34
- package/dist/utils/toStringConstructor.d.ts +0 -1
- package/dist/utils/toStringConstructor.js +0 -10
- package/dist/validation/ValidatorAdapter.d.ts +0 -66
- package/dist/validation/adapters/ClassValidatorAdapter.d.ts +0 -23
- package/dist/validation/adapters/ClassValidatorAdapter.js +0 -47
- package/dist/validation/adapters/ZodAdapter.d.ts +0 -14
- package/dist/validation/adapters/ZodAdapter.js +0 -56
- package/dist/validation/adapters/index.d.ts +0 -4
- package/dist/validation/adapters/index.js +0 -7
- package/dist/validation/index.d.ts +0 -3
- package/dist/validation/index.js +0 -20
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request Context for Turbo.
|
|
3
|
+
*
|
|
4
|
+
* Lazy initialization for maximum performance:
|
|
5
|
+
* - Query parsed only when accessed
|
|
6
|
+
* - Body parsed only when needed
|
|
7
|
+
* - Minimal allocations in hot path
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const EMPTY_PARAMS: Record<string, string> = Object.freeze({}) as Record<string, string>;
|
|
11
|
+
|
|
12
|
+
export class Context {
|
|
13
|
+
readonly req: Request;
|
|
14
|
+
params: Record<string, string>;
|
|
15
|
+
locals: Record<string, any> = {};
|
|
16
|
+
|
|
17
|
+
// Lazy fields - only allocated when accessed
|
|
18
|
+
private _query: Record<string, string> | null = null;
|
|
19
|
+
private _body: any;
|
|
20
|
+
private _bodyParsed = false;
|
|
21
|
+
private _url: URL | null = null;
|
|
22
|
+
private _status = 0;
|
|
23
|
+
|
|
24
|
+
constructor(req: Request, params: Record<string, string> = EMPTY_PARAMS) {
|
|
25
|
+
this.req = req;
|
|
26
|
+
this.params = params;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get status(): number {
|
|
30
|
+
return this._status || 200;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
set status(value: number) {
|
|
34
|
+
this._status = value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get url(): URL {
|
|
38
|
+
if (!this._url) {
|
|
39
|
+
this._url = new URL(this.req.url);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return this._url;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get query(): Record<string, string> {
|
|
46
|
+
if (!this._query) {
|
|
47
|
+
this._query = Object.fromEntries(this.url.searchParams);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return this._query;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get body(): any {
|
|
54
|
+
return this._body;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async parseBody(): Promise<any> {
|
|
58
|
+
if (this._bodyParsed) {
|
|
59
|
+
return this._body;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
this._bodyParsed = true;
|
|
63
|
+
const contentType = this.req.headers.get('content-type') || '';
|
|
64
|
+
|
|
65
|
+
if (contentType.includes('application/json')) {
|
|
66
|
+
this._body = await this.req.json();
|
|
67
|
+
} else if (contentType.includes('form')) {
|
|
68
|
+
const formData = await this.req.formData();
|
|
69
|
+
this._body = Object.fromEntries(formData);
|
|
70
|
+
} else if (contentType.includes('text')) {
|
|
71
|
+
this._body = await this.req.text();
|
|
72
|
+
} else {
|
|
73
|
+
this._body = await this.req.arrayBuffer();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return this._body;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
get method(): string {
|
|
80
|
+
return this.req.method;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get headers(): Headers {
|
|
84
|
+
return this.req.headers;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get path(): string {
|
|
88
|
+
return this.url.pathname;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
json(data: any, status?: number): Response {
|
|
92
|
+
if (status) this.status = status;
|
|
93
|
+
|
|
94
|
+
return Response.json(data, { status: this.status });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
text(data: string, status?: number): Response {
|
|
98
|
+
if (status) this.status = status;
|
|
99
|
+
|
|
100
|
+
return new Response(data, {
|
|
101
|
+
status: this.status,
|
|
102
|
+
headers: { 'Content-Type': 'text/plain' }
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
html(data: string, status?: number): Response {
|
|
107
|
+
if (status) this.status = status;
|
|
108
|
+
|
|
109
|
+
return new Response(data, {
|
|
110
|
+
status: this.status,
|
|
111
|
+
headers: { 'Content-Type': 'text/html' }
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
redirect(url: string, status: number = 302): Response {
|
|
116
|
+
return Response.redirect(url, status);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Creates a Context from a job (for queue processing).
|
|
121
|
+
*/
|
|
122
|
+
static createFromJob(job: any): Context {
|
|
123
|
+
const fakeRequest = new Request('http://localhost/job');
|
|
124
|
+
const ctx = new Context(fakeRequest);
|
|
125
|
+
ctx.locals.job = job;
|
|
126
|
+
return ctx;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CORS Configuration types.
|
|
3
|
+
*/
|
|
4
|
+
export type CorsOrigin =
|
|
5
|
+
| string
|
|
6
|
+
| string[]
|
|
7
|
+
| RegExp
|
|
8
|
+
| ((origin: string) => boolean);
|
|
9
|
+
|
|
10
|
+
export interface CorsConfig {
|
|
11
|
+
origins: CorsOrigin;
|
|
12
|
+
methods?: string[];
|
|
13
|
+
allowedHeaders?: string[];
|
|
14
|
+
exposedHeaders?: string[];
|
|
15
|
+
credentials?: boolean;
|
|
16
|
+
maxAge?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const DEFAULT_CORS_METHODS = ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'];
|
|
20
|
+
export const DEFAULT_CORS_HEADERS = ['Content-Type', 'Authorization', 'X-Requested-With', 'Accept', 'Origin'];
|
|
21
|
+
|
|
22
|
+
type OriginMatcher = (origin: string) => boolean;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* CORS Handler - Pre-computes headers at startup for maximum performance.
|
|
26
|
+
*/
|
|
27
|
+
export class CorsHandler {
|
|
28
|
+
private readonly cache = new Map<string, Record<string, string>>();
|
|
29
|
+
private readonly methodsStr: string;
|
|
30
|
+
private readonly headersStr: string;
|
|
31
|
+
private readonly exposedStr: string | null;
|
|
32
|
+
private readonly maxAgeStr: string | null;
|
|
33
|
+
private readonly hasCredentials: boolean;
|
|
34
|
+
private readonly isWildcard: boolean;
|
|
35
|
+
private readonly matcher: OriginMatcher;
|
|
36
|
+
|
|
37
|
+
// Pre-created preflight response for wildcard CORS
|
|
38
|
+
private readonly preflightResponse: Response | null = null;
|
|
39
|
+
|
|
40
|
+
constructor(config: CorsConfig) {
|
|
41
|
+
this.methodsStr = (config.methods || DEFAULT_CORS_METHODS).join(', ');
|
|
42
|
+
this.headersStr = (config.allowedHeaders || DEFAULT_CORS_HEADERS).join(', ');
|
|
43
|
+
this.exposedStr = config.exposedHeaders?.join(', ') || null;
|
|
44
|
+
this.maxAgeStr = config.maxAge?.toString() || null;
|
|
45
|
+
this.hasCredentials = !!config.credentials;
|
|
46
|
+
this.isWildcard = config.origins === '*';
|
|
47
|
+
this.matcher = this.buildMatcher(config.origins);
|
|
48
|
+
|
|
49
|
+
// Pre-create preflight response for wildcard
|
|
50
|
+
if (this.isWildcard) {
|
|
51
|
+
this.preflightResponse = new Response(null, {
|
|
52
|
+
status: 204,
|
|
53
|
+
headers: this.buildHeaders('*')
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Handle preflight (OPTIONS) request.
|
|
60
|
+
*/
|
|
61
|
+
preflight(origin: string): Response {
|
|
62
|
+
if (this.isWildcard && this.preflightResponse) {
|
|
63
|
+
return this.preflightResponse.clone();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!this.isAllowed(origin)) {
|
|
67
|
+
return new Response(null, { status: 403 });
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return new Response(null, {
|
|
71
|
+
status: 204,
|
|
72
|
+
headers: this.getHeaders(origin)
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Apply CORS headers to a response.
|
|
78
|
+
*/
|
|
79
|
+
apply(response: Response, origin: string): Response {
|
|
80
|
+
if (!this.isAllowed(origin)) {
|
|
81
|
+
return response;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const headers = this.getHeaders(origin);
|
|
85
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
86
|
+
response.headers.set(key, value);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return response;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Check if origin is allowed.
|
|
94
|
+
*/
|
|
95
|
+
isAllowed(origin: string): boolean {
|
|
96
|
+
return this.matcher(origin);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get cached CORS headers for origin.
|
|
101
|
+
*/
|
|
102
|
+
private getHeaders(origin: string): Record<string, string> {
|
|
103
|
+
const key = this.isWildcard ? '*' : origin;
|
|
104
|
+
let headers = this.cache.get(key);
|
|
105
|
+
|
|
106
|
+
if (!headers) {
|
|
107
|
+
headers = this.buildHeaders(origin);
|
|
108
|
+
this.cache.set(key, headers);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return headers;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private buildHeaders(origin: string): Record<string, string> {
|
|
115
|
+
const headers: Record<string, string> = {
|
|
116
|
+
'Access-Control-Allow-Origin': this.isWildcard ? '*' : origin,
|
|
117
|
+
'Access-Control-Allow-Methods': this.methodsStr,
|
|
118
|
+
'Access-Control-Allow-Headers': this.headersStr
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
if (this.hasCredentials) {
|
|
122
|
+
headers['Access-Control-Allow-Credentials'] = 'true';
|
|
123
|
+
}
|
|
124
|
+
if (this.exposedStr) {
|
|
125
|
+
headers['Access-Control-Expose-Headers'] = this.exposedStr;
|
|
126
|
+
}
|
|
127
|
+
if (this.maxAgeStr) {
|
|
128
|
+
headers['Access-Control-Max-Age'] = this.maxAgeStr;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return headers;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private buildMatcher(origins: CorsOrigin): OriginMatcher {
|
|
135
|
+
if (origins === '*') return () => true;
|
|
136
|
+
if (typeof origins === 'string') return (o) => o === origins;
|
|
137
|
+
if (Array.isArray(origins)) {
|
|
138
|
+
const set = new Set(origins);
|
|
139
|
+
return (o) => set.has(o);
|
|
140
|
+
}
|
|
141
|
+
if (origins instanceof RegExp) return (o) => origins.test(o);
|
|
142
|
+
if (typeof origins === 'function') return origins;
|
|
143
|
+
return () => false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { CONTROLLER_META, ROUTES_META } from '../metadata';
|
|
2
|
+
import type { ControllerOptions, ControllerMeta } from '../metadata';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Normalizes path or options to ControllerOptions.
|
|
6
|
+
*/
|
|
7
|
+
function normalizeOptions(pathOrOptions?: string | ControllerOptions): ControllerOptions {
|
|
8
|
+
if (!pathOrOptions) {
|
|
9
|
+
return {};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (typeof pathOrOptions === 'string') {
|
|
13
|
+
return { path: pathOrOptions };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return pathOrOptions;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Normalizes a path to start with / and not end with /.
|
|
21
|
+
*/
|
|
22
|
+
function normalizePath(path: string): string {
|
|
23
|
+
if (!path) return '';
|
|
24
|
+
|
|
25
|
+
let normalized = path.startsWith('/') ? path : '/' + path;
|
|
26
|
+
|
|
27
|
+
if (normalized !== '/' && normalized.endsWith('/')) {
|
|
28
|
+
normalized = normalized.slice(0, -1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return normalized;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Marks a class as a controller with a base path.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // Simple path
|
|
39
|
+
* @Controller('/users')
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // With options
|
|
43
|
+
* @Controller({ path: '/users', children: [ProfileController] })
|
|
44
|
+
*/
|
|
45
|
+
export function Controller(pathOrOptions?: string | ControllerOptions): ClassDecorator {
|
|
46
|
+
return (target) => {
|
|
47
|
+
const options = normalizeOptions(pathOrOptions);
|
|
48
|
+
const path = normalizePath(options.path || '');
|
|
49
|
+
|
|
50
|
+
const meta: ControllerMeta = {
|
|
51
|
+
path,
|
|
52
|
+
scope: options.scope,
|
|
53
|
+
children: options.children
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
Reflect.defineMetadata(CONTROLLER_META, meta, target);
|
|
57
|
+
|
|
58
|
+
// Ensure routes array exists
|
|
59
|
+
if (!Reflect.hasMetadata(ROUTES_META, target)) {
|
|
60
|
+
Reflect.defineMetadata(ROUTES_META, [], target);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { INJECT_META } from '../metadata';
|
|
2
|
+
import type { Token } from '../container/Container';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Explicitly specifies which token to inject.
|
|
6
|
+
* Useful for interfaces or when automatic detection fails.
|
|
7
|
+
*/
|
|
8
|
+
export function Inject(token: Token): ParameterDecorator {
|
|
9
|
+
return (target, propertyKey, parameterIndex) => {
|
|
10
|
+
const existing: Map<number, Token> = Reflect.getMetadata(INJECT_META, target) || new Map();
|
|
11
|
+
|
|
12
|
+
existing.set(parameterIndex, token);
|
|
13
|
+
|
|
14
|
+
Reflect.defineMetadata(INJECT_META, existing, target);
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MIDDLEWARE_META, type MiddlewareInfo } from '../metadata';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Middleware decorator.
|
|
5
|
+
* Can be applied to controllers or individual methods.
|
|
6
|
+
*/
|
|
7
|
+
export function Use(...middlewares: Function[]): ClassDecorator & MethodDecorator {
|
|
8
|
+
return function (target: any, propertyKey?: string) {
|
|
9
|
+
const isMethod = propertyKey !== undefined;
|
|
10
|
+
const metaTarget = isMethod ? target.constructor : target;
|
|
11
|
+
const existing: MiddlewareInfo[] = Reflect.getMetadata(MIDDLEWARE_META, metaTarget) || [];
|
|
12
|
+
|
|
13
|
+
for (const handler of middlewares) {
|
|
14
|
+
existing.push({
|
|
15
|
+
handler,
|
|
16
|
+
target: isMethod ? propertyKey : undefined
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
Reflect.defineMetadata(MIDDLEWARE_META, existing, metaTarget);
|
|
21
|
+
} as ClassDecorator & MethodDecorator;
|
|
22
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SERVICE_META } from '../metadata';
|
|
2
|
+
import { Scope } from '../container/Container';
|
|
3
|
+
|
|
4
|
+
export interface ServiceOptions {
|
|
5
|
+
scope?: Scope;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Marks a class as an injectable service.
|
|
10
|
+
* Services are singleton by default.
|
|
11
|
+
*/
|
|
12
|
+
export function Service(options: ServiceOptions = {}): ClassDecorator {
|
|
13
|
+
return (target) => {
|
|
14
|
+
Reflect.defineMetadata(SERVICE_META, {
|
|
15
|
+
scope: options.scope ?? Scope.SINGLETON
|
|
16
|
+
}, target);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ROUTES_META, type RouteInfo } from '../metadata';
|
|
2
|
+
|
|
3
|
+
type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head' | 'options';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a method decorator for HTTP methods.
|
|
7
|
+
* Supports both legacy decorators (experimentalDecorators) and TS5 stage 3 decorators.
|
|
8
|
+
*/
|
|
9
|
+
function createMethodDecorator(method: HttpMethod) {
|
|
10
|
+
return function (path: string = ''): any {
|
|
11
|
+
return function (
|
|
12
|
+
targetOrMethod: any,
|
|
13
|
+
contextOrPropertyKey?: string | symbol | ClassMethodDecoratorContext,
|
|
14
|
+
descriptor?: PropertyDescriptor
|
|
15
|
+
): any {
|
|
16
|
+
// TS5 Stage 3 decorators: context is ClassMethodDecoratorContext
|
|
17
|
+
if (contextOrPropertyKey && typeof contextOrPropertyKey === 'object' && 'kind' in contextOrPropertyKey) {
|
|
18
|
+
const context = contextOrPropertyKey as ClassMethodDecoratorContext;
|
|
19
|
+
|
|
20
|
+
context.addInitializer(function (this: any) {
|
|
21
|
+
const constructor = this.constructor;
|
|
22
|
+
const routes: RouteInfo[] = Reflect.getMetadata(ROUTES_META, constructor) || [];
|
|
23
|
+
|
|
24
|
+
routes.push({
|
|
25
|
+
method,
|
|
26
|
+
path: path.startsWith('/') ? path : '/' + path,
|
|
27
|
+
handlerName: String(context.name)
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
Reflect.defineMetadata(ROUTES_META, routes, constructor);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return targetOrMethod;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Legacy decorators (experimentalDecorators: true)
|
|
37
|
+
const constructor = targetOrMethod.constructor;
|
|
38
|
+
const propertyKey = contextOrPropertyKey as string | symbol;
|
|
39
|
+
const routes: RouteInfo[] = Reflect.getMetadata(ROUTES_META, constructor) || [];
|
|
40
|
+
|
|
41
|
+
routes.push({
|
|
42
|
+
method,
|
|
43
|
+
path: path.startsWith('/') ? path : '/' + path,
|
|
44
|
+
handlerName: String(propertyKey)
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
Reflect.defineMetadata(ROUTES_META, routes, constructor);
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const Get = createMethodDecorator('get');
|
|
53
|
+
export const Post = createMethodDecorator('post');
|
|
54
|
+
export const Put = createMethodDecorator('put');
|
|
55
|
+
export const Delete = createMethodDecorator('delete');
|
|
56
|
+
export const Patch = createMethodDecorator('patch');
|
|
57
|
+
export const Head = createMethodDecorator('head');
|
|
58
|
+
export const Options = createMethodDecorator('options');
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { PARAMS_META } from '../metadata';
|
|
2
|
+
|
|
3
|
+
export type ParamType = 'param' | 'query' | 'body' | 'header' | 'req' | 'ctx' | 'locals';
|
|
4
|
+
|
|
5
|
+
export interface ParamMetadata {
|
|
6
|
+
type: ParamType;
|
|
7
|
+
key?: string;
|
|
8
|
+
index: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function createParamDecorator(type: ParamType, key?: string) {
|
|
12
|
+
return function (target: any, propertyKey: string, index: number) {
|
|
13
|
+
const params: ParamMetadata[] = Reflect.getMetadata(PARAMS_META, target.constructor, propertyKey) || [];
|
|
14
|
+
|
|
15
|
+
params.push({ type, key, index });
|
|
16
|
+
|
|
17
|
+
Reflect.defineMetadata(PARAMS_META, params, target.constructor, propertyKey);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function Param(key?: string): ParameterDecorator {
|
|
22
|
+
return createParamDecorator('param', key) as ParameterDecorator;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function Query(key?: string): ParameterDecorator {
|
|
26
|
+
return createParamDecorator('query', key) as ParameterDecorator;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function Body(key?: string): ParameterDecorator {
|
|
30
|
+
return createParamDecorator('body', key) as ParameterDecorator;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function Header(key?: string): ParameterDecorator {
|
|
34
|
+
return createParamDecorator('header', key) as ParameterDecorator;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function Req(): ParameterDecorator {
|
|
38
|
+
return createParamDecorator('req') as ParameterDecorator;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function Ctx(): ParameterDecorator {
|
|
42
|
+
return createParamDecorator('ctx') as ParameterDecorator;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function Locals(key?: string): ParameterDecorator {
|
|
46
|
+
return createParamDecorator('locals', key) as ParameterDecorator;
|
|
47
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle Event Types.
|
|
3
|
+
*/
|
|
4
|
+
export enum EventType {
|
|
5
|
+
/** Called when DI container initializes, before server starts */
|
|
6
|
+
INIT = 'onInit',
|
|
7
|
+
/** Called right after application is fully bootstrapped */
|
|
8
|
+
BOOT = 'onBoot',
|
|
9
|
+
/** Called when application receives SIGTERM/SIGINT */
|
|
10
|
+
SHUTDOWN = 'onShutdown'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Stored event handler info.
|
|
15
|
+
*/
|
|
16
|
+
export interface EventHandler {
|
|
17
|
+
target: any;
|
|
18
|
+
methodName: string;
|
|
19
|
+
priority: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Metadata key for storing events.
|
|
24
|
+
*/
|
|
25
|
+
export const EVENTS_META = Symbol('turbo:events');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Event registry - stores all decorated event handlers.
|
|
29
|
+
* Populated at decoration time, read at bootstrap.
|
|
30
|
+
*/
|
|
31
|
+
const eventRegistry = new Map<EventType, EventHandler[]>();
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Register an event handler (called by decorators).
|
|
35
|
+
*/
|
|
36
|
+
export function registerEvent(type: EventType, target: any, methodName: string, priority: number = 0): void {
|
|
37
|
+
let handlers = eventRegistry.get(type);
|
|
38
|
+
if (!handlers) {
|
|
39
|
+
handlers = [];
|
|
40
|
+
eventRegistry.set(type, handlers);
|
|
41
|
+
}
|
|
42
|
+
handlers.push({ target, methodName, priority });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get all handlers for an event type, sorted by priority (descending).
|
|
47
|
+
*/
|
|
48
|
+
export function getEventHandlers(type: EventType): EventHandler[] {
|
|
49
|
+
const handlers = eventRegistry.get(type) || [];
|
|
50
|
+
return handlers.sort((a, b) => b.priority - a.priority);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Check if any handlers exist for an event type.
|
|
55
|
+
*/
|
|
56
|
+
export function hasEventHandlers(type: EventType): boolean {
|
|
57
|
+
return (eventRegistry.get(type)?.length ?? 0) > 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Clear all event handlers (for testing).
|
|
62
|
+
*/
|
|
63
|
+
export function clearEventRegistry(): void {
|
|
64
|
+
eventRegistry.clear();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ============ Decorators ============
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Called when DI container initializes, before the server starts.
|
|
71
|
+
* Use for database connections, cache warming, etc.
|
|
72
|
+
*/
|
|
73
|
+
export function OnApplicationInit(priority: number = 0) {
|
|
74
|
+
return function (target: any, propertyKey: string) {
|
|
75
|
+
registerEvent(EventType.INIT, target.constructor, propertyKey, priority);
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Called right after the application is fully bootstrapped and server is ready.
|
|
81
|
+
* Use for logging, health checks, etc.
|
|
82
|
+
*/
|
|
83
|
+
export function OnApplicationBoot(priority: number = 0) {
|
|
84
|
+
return function (target: any, propertyKey: string) {
|
|
85
|
+
registerEvent(EventType.BOOT, target.constructor, propertyKey, priority);
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Called when application receives SIGTERM or SIGINT.
|
|
91
|
+
* Use for graceful cleanup, closing connections, etc.
|
|
92
|
+
*/
|
|
93
|
+
export function OnApplicationShutdown(priority: number = 0) {
|
|
94
|
+
return function (target: any, propertyKey: string) {
|
|
95
|
+
registerEvent(EventType.SHUTDOWN, target.constructor, propertyKey, priority);
|
|
96
|
+
};
|
|
97
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base HTTP Exception class.
|
|
3
|
+
* Throw this from handlers to return custom HTTP error responses.
|
|
4
|
+
*/
|
|
5
|
+
export class HttpException extends Error {
|
|
6
|
+
constructor(
|
|
7
|
+
public readonly statusCode: number,
|
|
8
|
+
message: string,
|
|
9
|
+
public readonly errors?: any[]
|
|
10
|
+
) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = 'HttpException';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Convert exception to Response.
|
|
17
|
+
*/
|
|
18
|
+
toResponse(): Response {
|
|
19
|
+
const body = {
|
|
20
|
+
statusCode: this.statusCode,
|
|
21
|
+
message: this.message,
|
|
22
|
+
...(this.errors && { errors: this.errors })
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return Response.json(body, { status: this.statusCode });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Common HTTP Exceptions
|
|
30
|
+
|
|
31
|
+
export class BadRequestException extends HttpException {
|
|
32
|
+
constructor(message: string = 'Bad Request', errors?: any[]) {
|
|
33
|
+
super(400, message, errors);
|
|
34
|
+
this.name = 'BadRequestException';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class UnauthorizedException extends HttpException {
|
|
39
|
+
constructor(message: string = 'Unauthorized') {
|
|
40
|
+
super(401, message);
|
|
41
|
+
this.name = 'UnauthorizedException';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class ForbiddenException extends HttpException {
|
|
46
|
+
constructor(message: string = 'Forbidden') {
|
|
47
|
+
super(403, message);
|
|
48
|
+
this.name = 'ForbiddenException';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export class NotFoundException extends HttpException {
|
|
53
|
+
constructor(message: string = 'Not Found') {
|
|
54
|
+
super(404, message);
|
|
55
|
+
this.name = 'NotFoundException';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class MethodNotAllowedException extends HttpException {
|
|
60
|
+
constructor(message: string = 'Method Not Allowed') {
|
|
61
|
+
super(405, message);
|
|
62
|
+
this.name = 'MethodNotAllowedException';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export class ConflictException extends HttpException {
|
|
67
|
+
constructor(message: string = 'Conflict') {
|
|
68
|
+
super(409, message);
|
|
69
|
+
this.name = 'ConflictException';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export class UnprocessableEntityException extends HttpException {
|
|
74
|
+
constructor(message: string = 'Unprocessable Entity', errors?: any[]) {
|
|
75
|
+
super(422, message, errors);
|
|
76
|
+
this.name = 'UnprocessableEntityException';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export class TooManyRequestsException extends HttpException {
|
|
81
|
+
constructor(message: string = 'Too Many Requests') {
|
|
82
|
+
super(429, message);
|
|
83
|
+
this.name = 'TooManyRequestsException';
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export class InternalServerErrorException extends HttpException {
|
|
88
|
+
constructor(message: string = 'Internal Server Error') {
|
|
89
|
+
super(500, message);
|
|
90
|
+
this.name = 'InternalServerErrorException';
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export class ServiceUnavailableException extends HttpException {
|
|
95
|
+
constructor(message: string = 'Service Unavailable') {
|
|
96
|
+
super(503, message);
|
|
97
|
+
this.name = 'ServiceUnavailableException';
|
|
98
|
+
}
|
|
99
|
+
}
|