@velajs/vela 0.4.3 → 0.5.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/dist/cache/cache.module.d.ts +4 -1
- package/dist/cache/cache.module.js +51 -9
- package/dist/config/config.module.d.ts +4 -1
- package/dist/config/config.module.js +40 -3
- package/dist/config/config.types.d.ts +1 -0
- package/dist/constants.d.ts +6 -1
- package/dist/constants.js +5 -0
- package/dist/container/container.d.ts +2 -0
- package/dist/container/container.js +47 -15
- package/dist/container/decorators.d.ts +3 -1
- package/dist/container/decorators.js +27 -6
- package/dist/container/index.d.ts +4 -2
- package/dist/container/index.js +4 -2
- package/dist/container/mixin.d.ts +24 -0
- package/dist/container/mixin.js +26 -0
- package/dist/container/module-ref.d.ts +21 -0
- package/dist/container/module-ref.js +48 -0
- package/dist/container/types.d.ts +9 -3
- package/dist/container/types.js +9 -0
- package/dist/cors/cors.module.js +2 -2
- package/dist/factory.js +11 -2
- package/dist/fetch/fetch.module.d.ts +6 -0
- package/dist/fetch/fetch.module.js +77 -0
- package/dist/fetch/fetch.service.d.ts +24 -0
- package/dist/fetch/fetch.service.js +145 -0
- package/dist/fetch/fetch.types.d.ts +24 -0
- package/dist/fetch/fetch.types.js +1 -0
- package/dist/fetch/index.d.ts +3 -0
- package/dist/fetch/index.js +2 -0
- package/dist/http/decorators.d.ts +64 -0
- package/dist/http/decorators.js +89 -1
- package/dist/http/index.d.ts +3 -1
- package/dist/http/index.js +2 -1
- package/dist/http/middleware-consumer.d.ts +36 -0
- package/dist/http/middleware-consumer.js +71 -0
- package/dist/http/route.manager.d.ts +4 -0
- package/dist/http/route.manager.js +75 -1
- package/dist/index.d.ts +11 -6
- package/dist/index.js +7 -4
- package/dist/metadata.d.ts +1 -1
- package/dist/module/decorators.d.ts +1 -0
- package/dist/module/decorators.js +24 -8
- package/dist/module/index.d.ts +2 -2
- package/dist/module/index.js +1 -1
- package/dist/module/module-loader.d.ts +5 -1
- package/dist/module/module-loader.js +54 -10
- package/dist/module/types.d.ts +13 -3
- package/dist/pipeline/index.d.ts +3 -2
- package/dist/pipeline/index.js +1 -1
- package/dist/pipeline/pipes.d.ts +22 -0
- package/dist/pipeline/pipes.js +50 -0
- package/dist/pipeline/tokens.d.ts +1 -1
- package/dist/pipeline/tokens.js +1 -1
- package/dist/pipeline/types.d.ts +16 -0
- package/dist/registry/metadata.registry.d.ts +7 -6
- package/dist/registry/metadata.registry.js +13 -0
- package/dist/registry/types.d.ts +1 -0
- package/dist/schedule/schedule.module.d.ts +4 -1
- package/dist/schedule/schedule.module.js +39 -7
- package/dist/testing/testing.builder.js +5 -5
- package/dist/throttler/throttler.module.d.ts +2 -1
- package/dist/throttler/throttler.module.js +47 -9
- package/package.json +1 -1
package/dist/factory.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { VelaApplication } from "./application.js";
|
|
2
2
|
import { Container } from "./container/container.js";
|
|
3
|
+
import { ModuleRef } from "./container/module-ref.js";
|
|
3
4
|
import { RouteManager } from "./http/route.manager.js";
|
|
4
5
|
import { ModuleLoader } from "./module/module-loader.js";
|
|
5
6
|
import { ComponentManager } from "./pipeline/component.manager.js";
|
|
@@ -8,9 +9,16 @@ export const VelaFactory = {
|
|
|
8
9
|
async create (rootModule) {
|
|
9
10
|
const container = new Container();
|
|
10
11
|
container.register({
|
|
11
|
-
|
|
12
|
+
provide: Container,
|
|
12
13
|
useValue: container
|
|
13
14
|
});
|
|
15
|
+
container.register({
|
|
16
|
+
provide: ModuleRef,
|
|
17
|
+
useFactory: (c)=>new ModuleRef(c),
|
|
18
|
+
inject: [
|
|
19
|
+
Container
|
|
20
|
+
]
|
|
21
|
+
});
|
|
14
22
|
const routeManager = new RouteManager(container);
|
|
15
23
|
ComponentManager.init(container);
|
|
16
24
|
const loader = new ModuleLoader(container, routeManager);
|
|
@@ -45,8 +53,9 @@ export const VelaFactory = {
|
|
|
45
53
|
} else if (container.has(APP_MIDDLEWARE)) {
|
|
46
54
|
routeManager.useGlobalMiddlewareTokens(APP_MIDDLEWARE);
|
|
47
55
|
}
|
|
56
|
+
routeManager.registerConsumerMiddleware(loader.getConsumerMiddlewareDefinitions());
|
|
48
57
|
const app = new VelaApplication(container, routeManager);
|
|
49
|
-
const instances = loader.resolveAllInstances();
|
|
58
|
+
const instances = await loader.resolveAllInstances();
|
|
50
59
|
app.setInstances(instances);
|
|
51
60
|
await app.callOnModuleInit();
|
|
52
61
|
await app.callOnApplicationBootstrap();
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AsyncModuleOptions, DynamicModule } from '../module/types';
|
|
2
|
+
import type { HttpModuleOptions } from './fetch.types';
|
|
3
|
+
export declare class HttpModule {
|
|
4
|
+
static register(options?: HttpModuleOptions): DynamicModule;
|
|
5
|
+
static registerAsync(options: AsyncModuleOptions<HttpModuleOptions>): DynamicModule;
|
|
6
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
}
|
|
7
|
+
import { METADATA_KEYS } from "../constants.js";
|
|
8
|
+
import { defineMetadata } from "../metadata.js";
|
|
9
|
+
import { MetadataRegistry } from "../registry/metadata.registry.js";
|
|
10
|
+
import { Module } from "../module/decorators.js";
|
|
11
|
+
import { HttpService, HTTP_MODULE_OPTIONS } from "./fetch.service.js";
|
|
12
|
+
export class HttpModule {
|
|
13
|
+
static register(options = {}) {
|
|
14
|
+
const moduleClass = class HttpDynamicModule {
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(moduleClass, 'name', {
|
|
17
|
+
value: 'HttpModule'
|
|
18
|
+
});
|
|
19
|
+
defineMetadata(METADATA_KEYS.MODULE, true, moduleClass);
|
|
20
|
+
MetadataRegistry.setModuleOptions(moduleClass, {
|
|
21
|
+
exports: [
|
|
22
|
+
HttpService,
|
|
23
|
+
HTTP_MODULE_OPTIONS
|
|
24
|
+
]
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
module: moduleClass,
|
|
28
|
+
providers: [
|
|
29
|
+
{
|
|
30
|
+
provide: HTTP_MODULE_OPTIONS,
|
|
31
|
+
useValue: options
|
|
32
|
+
},
|
|
33
|
+
HttpService
|
|
34
|
+
]
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
static registerAsync(options) {
|
|
38
|
+
const moduleClass = class HttpAsyncDynamicModule {
|
|
39
|
+
};
|
|
40
|
+
Object.defineProperty(moduleClass, 'name', {
|
|
41
|
+
value: 'HttpModule'
|
|
42
|
+
});
|
|
43
|
+
defineMetadata(METADATA_KEYS.MODULE, true, moduleClass);
|
|
44
|
+
MetadataRegistry.setModuleOptions(moduleClass, {
|
|
45
|
+
imports: options.imports ?? [],
|
|
46
|
+
exports: [
|
|
47
|
+
HttpService,
|
|
48
|
+
HTTP_MODULE_OPTIONS
|
|
49
|
+
]
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
module: moduleClass,
|
|
53
|
+
providers: [
|
|
54
|
+
{
|
|
55
|
+
provide: HTTP_MODULE_OPTIONS,
|
|
56
|
+
useFactory: options.useFactory,
|
|
57
|
+
inject: options.inject ?? []
|
|
58
|
+
},
|
|
59
|
+
HttpService
|
|
60
|
+
]
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
HttpModule = _ts_decorate([
|
|
65
|
+
Module({
|
|
66
|
+
providers: [
|
|
67
|
+
{
|
|
68
|
+
provide: HTTP_MODULE_OPTIONS,
|
|
69
|
+
useValue: {}
|
|
70
|
+
},
|
|
71
|
+
HttpService
|
|
72
|
+
],
|
|
73
|
+
exports: [
|
|
74
|
+
HttpService
|
|
75
|
+
]
|
|
76
|
+
})
|
|
77
|
+
], HttpModule);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { InjectionToken } from '../container/index';
|
|
2
|
+
import type { HttpModuleOptions, HttpRequestConfig, HttpResponse, RequestConfig } from './fetch.types';
|
|
3
|
+
export declare const HTTP_MODULE_OPTIONS: InjectionToken<HttpModuleOptions>;
|
|
4
|
+
export declare class HttpRequestException extends Error {
|
|
5
|
+
readonly status: number;
|
|
6
|
+
readonly statusText: string;
|
|
7
|
+
readonly response: Response;
|
|
8
|
+
constructor(status: number, statusText: string, response: Response);
|
|
9
|
+
}
|
|
10
|
+
export declare class HttpService {
|
|
11
|
+
private readonly baseURL;
|
|
12
|
+
private readonly defaultHeaders;
|
|
13
|
+
private readonly defaultTimeout;
|
|
14
|
+
constructor(options: HttpModuleOptions);
|
|
15
|
+
get<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>;
|
|
16
|
+
post<T = unknown>(url: string, body?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>;
|
|
17
|
+
put<T = unknown>(url: string, body?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>;
|
|
18
|
+
patch<T = unknown>(url: string, body?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>;
|
|
19
|
+
delete<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>;
|
|
20
|
+
head(url: string, config?: RequestConfig): Promise<HttpResponse<void>>;
|
|
21
|
+
request<T = unknown>(config: HttpRequestConfig): Promise<HttpResponse<T>>;
|
|
22
|
+
private buildUrl;
|
|
23
|
+
private parseBody;
|
|
24
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
}
|
|
7
|
+
function _ts_metadata(k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
}
|
|
10
|
+
function _ts_param(paramIndex, decorator) {
|
|
11
|
+
return function(target, key) {
|
|
12
|
+
decorator(target, key, paramIndex);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
import { Inject, Injectable, InjectionToken, Optional } from "../container/index.js";
|
|
16
|
+
export const HTTP_MODULE_OPTIONS = new InjectionToken('HTTP_MODULE_OPTIONS');
|
|
17
|
+
export class HttpRequestException extends Error {
|
|
18
|
+
status;
|
|
19
|
+
statusText;
|
|
20
|
+
response;
|
|
21
|
+
constructor(status, statusText, response){
|
|
22
|
+
super(`HTTP ${status} ${statusText}`), this.status = status, this.statusText = statusText, this.response = response;
|
|
23
|
+
this.name = 'HttpRequestException';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export class HttpService {
|
|
27
|
+
baseURL;
|
|
28
|
+
defaultHeaders;
|
|
29
|
+
defaultTimeout;
|
|
30
|
+
constructor(options){
|
|
31
|
+
const opts = options ?? {};
|
|
32
|
+
this.baseURL = opts.baseURL ?? '';
|
|
33
|
+
this.defaultHeaders = opts.headers ?? {};
|
|
34
|
+
this.defaultTimeout = opts.timeout;
|
|
35
|
+
}
|
|
36
|
+
get(url, config) {
|
|
37
|
+
return this.request({
|
|
38
|
+
method: 'GET',
|
|
39
|
+
url,
|
|
40
|
+
...config
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
post(url, body, config) {
|
|
44
|
+
return this.request({
|
|
45
|
+
method: 'POST',
|
|
46
|
+
url,
|
|
47
|
+
body,
|
|
48
|
+
...config
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
put(url, body, config) {
|
|
52
|
+
return this.request({
|
|
53
|
+
method: 'PUT',
|
|
54
|
+
url,
|
|
55
|
+
body,
|
|
56
|
+
...config
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
patch(url, body, config) {
|
|
60
|
+
return this.request({
|
|
61
|
+
method: 'PATCH',
|
|
62
|
+
url,
|
|
63
|
+
body,
|
|
64
|
+
...config
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
delete(url, config) {
|
|
68
|
+
return this.request({
|
|
69
|
+
method: 'DELETE',
|
|
70
|
+
url,
|
|
71
|
+
...config
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
head(url, config) {
|
|
75
|
+
return this.request({
|
|
76
|
+
method: 'HEAD',
|
|
77
|
+
url,
|
|
78
|
+
...config
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
async request(config) {
|
|
82
|
+
const fullUrl = this.buildUrl(config.url, config.params);
|
|
83
|
+
const headers = {
|
|
84
|
+
...this.defaultHeaders,
|
|
85
|
+
...config.headers
|
|
86
|
+
};
|
|
87
|
+
const init = {
|
|
88
|
+
method: config.method,
|
|
89
|
+
headers
|
|
90
|
+
};
|
|
91
|
+
if (config.body !== undefined) {
|
|
92
|
+
if (typeof config.body === 'string' || config.body instanceof FormData) {
|
|
93
|
+
init.body = config.body;
|
|
94
|
+
} else {
|
|
95
|
+
init.body = JSON.stringify(config.body);
|
|
96
|
+
if (!headers['Content-Type'] && !headers['content-type']) {
|
|
97
|
+
headers['Content-Type'] = 'application/json';
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const timeout = config.timeout ?? this.defaultTimeout;
|
|
102
|
+
if (timeout !== undefined) {
|
|
103
|
+
init.signal = AbortSignal.timeout(timeout);
|
|
104
|
+
}
|
|
105
|
+
const response = await fetch(fullUrl, init);
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
throw new HttpRequestException(response.status, response.statusText, response);
|
|
108
|
+
}
|
|
109
|
+
const data = await this.parseBody(response);
|
|
110
|
+
return {
|
|
111
|
+
data,
|
|
112
|
+
status: response.status,
|
|
113
|
+
statusText: response.statusText,
|
|
114
|
+
headers: response.headers
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
buildUrl(url, params) {
|
|
118
|
+
const base = this.baseURL ? `${this.baseURL}${url}` : url;
|
|
119
|
+
if (!params || Object.keys(params).length === 0) return base;
|
|
120
|
+
const searchParams = new URLSearchParams(Object.entries(params).map(([k, v])=>[
|
|
121
|
+
k,
|
|
122
|
+
String(v)
|
|
123
|
+
]));
|
|
124
|
+
return `${base}?${searchParams.toString()}`;
|
|
125
|
+
}
|
|
126
|
+
async parseBody(response) {
|
|
127
|
+
if (response.status === 204 || response.headers.get('content-length') === '0') {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
131
|
+
if (contentType.includes('application/json')) {
|
|
132
|
+
return response.json();
|
|
133
|
+
}
|
|
134
|
+
return response.text();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
HttpService = _ts_decorate([
|
|
138
|
+
Injectable(),
|
|
139
|
+
_ts_param(0, Optional()),
|
|
140
|
+
_ts_param(0, Inject(HTTP_MODULE_OPTIONS)),
|
|
141
|
+
_ts_metadata("design:type", Function),
|
|
142
|
+
_ts_metadata("design:paramtypes", [
|
|
143
|
+
typeof HttpModuleOptions === "undefined" ? Object : HttpModuleOptions
|
|
144
|
+
])
|
|
145
|
+
], HttpService);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface HttpModuleOptions {
|
|
2
|
+
/** Base URL prepended to all requests. */
|
|
3
|
+
baseURL?: string;
|
|
4
|
+
/** Default headers sent with every request. */
|
|
5
|
+
headers?: Record<string, string>;
|
|
6
|
+
/** Default timeout in milliseconds (uses AbortSignal.timeout). */
|
|
7
|
+
timeout?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface RequestConfig {
|
|
10
|
+
headers?: Record<string, string>;
|
|
11
|
+
params?: Record<string, string | number | boolean>;
|
|
12
|
+
timeout?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface HttpRequestConfig extends RequestConfig {
|
|
15
|
+
method: string;
|
|
16
|
+
url: string;
|
|
17
|
+
body?: unknown;
|
|
18
|
+
}
|
|
19
|
+
export interface HttpResponse<T = unknown> {
|
|
20
|
+
data: T;
|
|
21
|
+
status: number;
|
|
22
|
+
statusText: string;
|
|
23
|
+
headers: Headers;
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -44,6 +44,53 @@ export declare const Query: (nameOrPipe?: string | PipeType, ...pipes: PipeType[
|
|
|
44
44
|
export declare const Body: (nameOrPipe?: string | PipeType, ...pipes: PipeType[]) => ParameterDecorator;
|
|
45
45
|
export declare const Headers: (nameOrPipe?: string | PipeType, ...pipes: PipeType[]) => ParameterDecorator;
|
|
46
46
|
export declare const Req: (nameOrPipe?: string | PipeType, ...pipes: PipeType[]) => ParameterDecorator;
|
|
47
|
+
/**
|
|
48
|
+
* Injects the Hono `Context` as the response handle.
|
|
49
|
+
* In Hono, request and response state are unified in the `Context` object,
|
|
50
|
+
* so `@Res()` and `@Req()` both return it.
|
|
51
|
+
*
|
|
52
|
+
* Use `c.header()`, `c.setCookie()`, `c.redirect()`, etc. for response control.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* @Get('/set-cookie')
|
|
57
|
+
* handle(@Res() c: Context) {
|
|
58
|
+
* c.setCookie('session', 'abc123', { httpOnly: true });
|
|
59
|
+
* return { ok: true };
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare const Res: (nameOrPipe?: string | PipeType, ...pipes: PipeType[]) => ParameterDecorator;
|
|
64
|
+
export declare const Ip: (nameOrPipe?: string | PipeType, ...pipes: PipeType[]) => ParameterDecorator;
|
|
65
|
+
export declare const Cookie: (nameOrPipe?: string | PipeType, ...pipes: PipeType[]) => ParameterDecorator;
|
|
66
|
+
/**
|
|
67
|
+
* Injects all cookies as a `Record<string, string>`, or a single cookie value by name.
|
|
68
|
+
*
|
|
69
|
+
* - `@Cookie()` — all cookies as an object
|
|
70
|
+
* - `@Cookie('token')` — the value of the `token` cookie
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* @Get('/me')
|
|
75
|
+
* handle(@Cookie('session') session: string) { ... }
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export declare const Cookies: (nameOrPipe?: string | PipeType, ...pipes: PipeType[]) => ParameterDecorator;
|
|
79
|
+
/**
|
|
80
|
+
* Injects the raw request body as a `Uint8Array`.
|
|
81
|
+
* Useful for webhook HMAC verification (Stripe, GitHub, etc.) where you
|
|
82
|
+
* need the raw bytes before any JSON parsing.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* @Post('/webhook')
|
|
87
|
+
* async handle(@RawBody() body: Uint8Array) {
|
|
88
|
+
* const sig = new TextDecoder().decode(body);
|
|
89
|
+
* // verify HMAC...
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export declare function RawBody(): ParameterDecorator;
|
|
47
94
|
/**
|
|
48
95
|
* Factory for creating custom parameter decorators.
|
|
49
96
|
*
|
|
@@ -120,4 +167,21 @@ export declare function getRedirect(target: Constructor, method: string | symbol
|
|
|
120
167
|
url: string;
|
|
121
168
|
statusCode: number;
|
|
122
169
|
} | undefined;
|
|
170
|
+
/**
|
|
171
|
+
* Composes multiple decorators into one. Applies them in order (top to bottom),
|
|
172
|
+
* matching how stacked decorators behave when written separately.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```ts
|
|
176
|
+
* const Auth = (...roles: string[]) => applyDecorators(
|
|
177
|
+
* UseGuards(JwtGuard, RolesGuard),
|
|
178
|
+
* SetMetadata('roles', roles),
|
|
179
|
+
* );
|
|
180
|
+
*
|
|
181
|
+
* @Auth('admin')
|
|
182
|
+
* @Get('/admin')
|
|
183
|
+
* handle() { ... }
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
export declare function applyDecorators(...decorators: Array<ClassDecorator | MethodDecorator | PropertyDecorator | ParameterDecorator>): ClassDecorator & MethodDecorator & PropertyDecorator;
|
|
123
187
|
export declare function isController(target: Constructor): boolean;
|
package/dist/http/decorators.js
CHANGED
|
@@ -136,6 +136,60 @@ export const Query = createBuiltinParamDecorator(ParamType.QUERY);
|
|
|
136
136
|
export const Body = createBuiltinParamDecorator(ParamType.BODY);
|
|
137
137
|
export const Headers = createBuiltinParamDecorator(ParamType.HEADERS);
|
|
138
138
|
export const Req = createBuiltinParamDecorator(ParamType.REQUEST);
|
|
139
|
+
/**
|
|
140
|
+
* Injects the Hono `Context` as the response handle.
|
|
141
|
+
* In Hono, request and response state are unified in the `Context` object,
|
|
142
|
+
* so `@Res()` and `@Req()` both return it.
|
|
143
|
+
*
|
|
144
|
+
* Use `c.header()`, `c.setCookie()`, `c.redirect()`, etc. for response control.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* @Get('/set-cookie')
|
|
149
|
+
* handle(@Res() c: Context) {
|
|
150
|
+
* c.setCookie('session', 'abc123', { httpOnly: true });
|
|
151
|
+
* return { ok: true };
|
|
152
|
+
* }
|
|
153
|
+
* ```
|
|
154
|
+
*/ export const Res = createBuiltinParamDecorator(ParamType.RESPONSE);
|
|
155
|
+
export const Ip = createBuiltinParamDecorator(ParamType.IP);
|
|
156
|
+
export const Cookie = createBuiltinParamDecorator(ParamType.COOKIE);
|
|
157
|
+
/**
|
|
158
|
+
* Injects all cookies as a `Record<string, string>`, or a single cookie value by name.
|
|
159
|
+
*
|
|
160
|
+
* - `@Cookie()` — all cookies as an object
|
|
161
|
+
* - `@Cookie('token')` — the value of the `token` cookie
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```ts
|
|
165
|
+
* @Get('/me')
|
|
166
|
+
* handle(@Cookie('session') session: string) { ... }
|
|
167
|
+
* ```
|
|
168
|
+
*/ export const Cookies = Cookie;
|
|
169
|
+
/**
|
|
170
|
+
* Injects the raw request body as a `Uint8Array`.
|
|
171
|
+
* Useful for webhook HMAC verification (Stripe, GitHub, etc.) where you
|
|
172
|
+
* need the raw bytes before any JSON parsing.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```ts
|
|
176
|
+
* @Post('/webhook')
|
|
177
|
+
* async handle(@RawBody() body: Uint8Array) {
|
|
178
|
+
* const sig = new TextDecoder().decode(body);
|
|
179
|
+
* // verify HMAC...
|
|
180
|
+
* }
|
|
181
|
+
* ```
|
|
182
|
+
*/ export function RawBody() {
|
|
183
|
+
return (target, propertyKey, parameterIndex)=>{
|
|
184
|
+
if (propertyKey === undefined) {
|
|
185
|
+
throw new Error('Parameter decorators can only be used on method parameters');
|
|
186
|
+
}
|
|
187
|
+
MetadataRegistry.addParameter(target.constructor, propertyKey, {
|
|
188
|
+
index: parameterIndex,
|
|
189
|
+
type: ParamType.RAW_BODY
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
}
|
|
139
193
|
/**
|
|
140
194
|
* Factory for creating custom parameter decorators.
|
|
141
195
|
*
|
|
@@ -175,10 +229,15 @@ export const Req = createBuiltinParamDecorator(ParamType.REQUEST);
|
|
|
175
229
|
factory: (_unused, ctx)=>{
|
|
176
230
|
const honoCtx = ctx;
|
|
177
231
|
const execCtx = {
|
|
232
|
+
getType: ()=>'http',
|
|
178
233
|
getClass: ()=>target.constructor,
|
|
179
234
|
getHandler: ()=>propertyKey,
|
|
180
235
|
getContext: ()=>honoCtx,
|
|
181
|
-
getRequest: ()=>honoCtx.req.raw
|
|
236
|
+
getRequest: ()=>honoCtx.req.raw,
|
|
237
|
+
switchToHttp: ()=>({
|
|
238
|
+
getRequest: ()=>honoCtx.req.raw,
|
|
239
|
+
getResponse: ()=>honoCtx
|
|
240
|
+
})
|
|
182
241
|
};
|
|
183
242
|
return factory(data, execCtx);
|
|
184
243
|
},
|
|
@@ -271,6 +330,35 @@ export function getRedirect(target, method) {
|
|
|
271
330
|
if (meta?.redirect) return meta.redirect;
|
|
272
331
|
return getMetadata(METADATA_KEYS.REDIRECT, target, method);
|
|
273
332
|
}
|
|
333
|
+
/**
|
|
334
|
+
* Composes multiple decorators into one. Applies them in order (top to bottom),
|
|
335
|
+
* matching how stacked decorators behave when written separately.
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* ```ts
|
|
339
|
+
* const Auth = (...roles: string[]) => applyDecorators(
|
|
340
|
+
* UseGuards(JwtGuard, RolesGuard),
|
|
341
|
+
* SetMetadata('roles', roles),
|
|
342
|
+
* );
|
|
343
|
+
*
|
|
344
|
+
* @Auth('admin')
|
|
345
|
+
* @Get('/admin')
|
|
346
|
+
* handle() { ... }
|
|
347
|
+
* ```
|
|
348
|
+
*/ export function applyDecorators(...decorators) {
|
|
349
|
+
const composed = (target, propertyKey, descriptor)=>{
|
|
350
|
+
for (const decorator of decorators){
|
|
351
|
+
if (propertyKey === undefined && typeof descriptor !== 'number') {
|
|
352
|
+
decorator(target);
|
|
353
|
+
} else if (typeof descriptor === 'number') {
|
|
354
|
+
decorator(target, propertyKey, descriptor);
|
|
355
|
+
} else {
|
|
356
|
+
decorator(target, propertyKey, descriptor);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
return composed;
|
|
361
|
+
}
|
|
274
362
|
// Helpers
|
|
275
363
|
export function isController(target) {
|
|
276
364
|
return MetadataRegistry.getControllerPath(target) !== '' || MetadataRegistry.getRoutes(target).length > 0;
|
package/dist/http/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { RouteManager } from './route.manager';
|
|
2
|
-
export {
|
|
2
|
+
export { MiddlewareBuilder, RequestMethod } from './middleware-consumer';
|
|
3
|
+
export type { MiddlewareConsumer, MiddlewareConfigProxy, RouteInfo, NestModule, MiddlewareRouteDefinition } from './middleware-consumer';
|
|
4
|
+
export { Controller, Version, Get, Post, Put, Patch, Delete, Options, Head, Sse, Param, Query, Body, Headers, Req, Res, Ip, Cookie, Cookies, RawBody, HttpCode, Header, Redirect, createParamDecorator, applyDecorators, isController, } from './decorators';
|
|
3
5
|
export type { RouteMetadata, ControllerMetadata, ControllerOptions, ParamMetadata, ControllerRegistration, } from './types';
|
package/dist/http/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { RouteManager } from "./route.manager.js";
|
|
2
|
-
export {
|
|
2
|
+
export { MiddlewareBuilder, RequestMethod } from "./middleware-consumer.js";
|
|
3
|
+
export { Controller, Version, Get, Post, Put, Patch, Delete, Options, Head, Sse, Param, Query, Body, Headers, Req, Res, Ip, Cookie, Cookies, RawBody, HttpCode, Header, Redirect, createParamDecorator, applyDecorators, isController } from "./decorators.js";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { NestMiddleware } from '../pipeline/types';
|
|
2
|
+
import type { Type } from '../registry/types';
|
|
3
|
+
export declare enum RequestMethod {
|
|
4
|
+
GET = "GET",
|
|
5
|
+
POST = "POST",
|
|
6
|
+
PUT = "PUT",
|
|
7
|
+
DELETE = "DELETE",
|
|
8
|
+
PATCH = "PATCH",
|
|
9
|
+
OPTIONS = "OPTIONS",
|
|
10
|
+
HEAD = "HEAD",
|
|
11
|
+
ALL = "ALL"
|
|
12
|
+
}
|
|
13
|
+
export interface RouteInfo {
|
|
14
|
+
path: string;
|
|
15
|
+
method?: RequestMethod;
|
|
16
|
+
}
|
|
17
|
+
export interface MiddlewareRouteDefinition {
|
|
18
|
+
middleware: Array<Type<NestMiddleware> | NestMiddleware>;
|
|
19
|
+
routes: RouteInfo[];
|
|
20
|
+
excludes: RouteInfo[];
|
|
21
|
+
}
|
|
22
|
+
export interface MiddlewareConfigProxy {
|
|
23
|
+
exclude(...routes: Array<string | RouteInfo>): MiddlewareConfigProxy;
|
|
24
|
+
forRoutes(...routes: Array<string | Function | RouteInfo>): MiddlewareConsumer;
|
|
25
|
+
}
|
|
26
|
+
export interface MiddlewareConsumer {
|
|
27
|
+
apply(...middleware: Array<Type<NestMiddleware> | NestMiddleware>): MiddlewareConfigProxy;
|
|
28
|
+
}
|
|
29
|
+
export interface NestModule {
|
|
30
|
+
configure(consumer: MiddlewareConsumer): void;
|
|
31
|
+
}
|
|
32
|
+
export declare class MiddlewareBuilder implements MiddlewareConsumer {
|
|
33
|
+
private definitions;
|
|
34
|
+
apply(...middleware: Array<Type<NestMiddleware> | NestMiddleware>): MiddlewareConfigProxy;
|
|
35
|
+
getDefinitions(): MiddlewareRouteDefinition[];
|
|
36
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { MetadataRegistry } from "../registry/metadata.registry.js";
|
|
2
|
+
export var RequestMethod = /*#__PURE__*/ function(RequestMethod) {
|
|
3
|
+
RequestMethod["GET"] = "GET";
|
|
4
|
+
RequestMethod["POST"] = "POST";
|
|
5
|
+
RequestMethod["PUT"] = "PUT";
|
|
6
|
+
RequestMethod["DELETE"] = "DELETE";
|
|
7
|
+
RequestMethod["PATCH"] = "PATCH";
|
|
8
|
+
RequestMethod["OPTIONS"] = "OPTIONS";
|
|
9
|
+
RequestMethod["HEAD"] = "HEAD";
|
|
10
|
+
RequestMethod["ALL"] = "ALL";
|
|
11
|
+
return RequestMethod;
|
|
12
|
+
}({});
|
|
13
|
+
export class MiddlewareBuilder {
|
|
14
|
+
definitions = [];
|
|
15
|
+
apply(...middleware) {
|
|
16
|
+
const currentMiddleware = [
|
|
17
|
+
...middleware
|
|
18
|
+
];
|
|
19
|
+
let currentExcludes = [];
|
|
20
|
+
const proxy = {
|
|
21
|
+
exclude: (...routes)=>{
|
|
22
|
+
currentExcludes = routes.map(normalizeRouteArg);
|
|
23
|
+
return proxy;
|
|
24
|
+
},
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
26
|
+
forRoutes: (...routes)=>{
|
|
27
|
+
this.definitions.push({
|
|
28
|
+
middleware: currentMiddleware,
|
|
29
|
+
routes: routes.flatMap(resolveRouteArg),
|
|
30
|
+
excludes: [
|
|
31
|
+
...currentExcludes
|
|
32
|
+
]
|
|
33
|
+
});
|
|
34
|
+
currentExcludes = [];
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
return proxy;
|
|
39
|
+
}
|
|
40
|
+
getDefinitions() {
|
|
41
|
+
return [
|
|
42
|
+
...this.definitions
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function normalizeRouteArg(route) {
|
|
47
|
+
return typeof route === 'string' ? {
|
|
48
|
+
path: route
|
|
49
|
+
} : route;
|
|
50
|
+
}
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
52
|
+
function resolveRouteArg(route) {
|
|
53
|
+
if (typeof route === 'string') {
|
|
54
|
+
return [
|
|
55
|
+
{
|
|
56
|
+
path: route
|
|
57
|
+
}
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
if (typeof route === 'function') {
|
|
61
|
+
const prefix = MetadataRegistry.getControllerPath(route);
|
|
62
|
+
return [
|
|
63
|
+
{
|
|
64
|
+
path: prefix || '/'
|
|
65
|
+
}
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
return [
|
|
69
|
+
route
|
|
70
|
+
];
|
|
71
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import type { Container } from '../container/container';
|
|
3
3
|
import type { Token, Type } from '../container/types';
|
|
4
|
+
import type { MiddlewareRouteDefinition } from './middleware-consumer';
|
|
4
5
|
import type { CanActivate, ExceptionFilter, NestInterceptor, NestMiddleware, PipeTransform } from '../pipeline/types';
|
|
5
6
|
import type { FilterType, GuardType, InterceptorType, MiddlewareType, PipeType } from '../registry/types';
|
|
6
7
|
import type { ControllerRegistration } from './types';
|
|
@@ -13,7 +14,9 @@ export declare class RouteManager {
|
|
|
13
14
|
private globalInterceptors;
|
|
14
15
|
private globalFilters;
|
|
15
16
|
private globalPrefix;
|
|
17
|
+
private consumerMiddlewareDefinitions;
|
|
16
18
|
constructor(container: Container);
|
|
19
|
+
registerConsumerMiddleware(definitions: MiddlewareRouteDefinition[]): this;
|
|
17
20
|
setGlobalPrefix(prefix: string): this;
|
|
18
21
|
useGlobalMiddleware(...middleware: MiddlewareType[]): this;
|
|
19
22
|
useGlobalMiddlewareTokens(...middlewareTokens: Array<Token<NestMiddleware>>): this;
|
|
@@ -38,5 +41,6 @@ export declare class RouteManager {
|
|
|
38
41
|
private registerRoute;
|
|
39
42
|
private buildVersionedPaths;
|
|
40
43
|
private joinPaths;
|
|
44
|
+
private matchesConsumerPath;
|
|
41
45
|
getControllers(): ControllerRegistration[];
|
|
42
46
|
}
|