@velajs/vela 1.0.0 → 1.1.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/CHANGELOG.md +80 -0
- package/README.md +36 -2
- package/dist/cache/cache.decorators.d.ts +2 -2
- package/dist/cache/cache.module.d.ts +1 -1
- package/dist/cache/cache.module.js +1 -1
- package/dist/constants.d.ts +8 -8
- package/dist/constants.js +8 -8
- package/dist/container/container.js +2 -2
- package/dist/container/decorators.js +8 -11
- package/dist/container/types.d.ts +1 -0
- package/dist/errors/http-exception.d.ts +21 -20
- package/dist/errors/http-exception.js +6 -6
- package/dist/event-emitter/event-emitter.decorators.js +2 -3
- package/dist/event-emitter/event-emitter.subscriber.js +2 -1
- package/dist/factory.d.ts +0 -1
- package/dist/factory.js +2 -32
- package/dist/fetch/fetch.module.d.ts +2 -2
- package/dist/fetch/fetch.module.js +2 -2
- package/dist/health/health.service.js +6 -2
- package/dist/http/decorators.d.ts +6 -5
- package/dist/http/decorators.js +28 -76
- package/dist/http/execution-context.d.ts +4 -0
- package/dist/http/execution-context.js +15 -0
- package/dist/http/index.d.ts +2 -2
- package/dist/http/index.js +1 -1
- package/dist/http/route.manager.d.ts +1 -2
- package/dist/http/route.manager.js +19 -25
- package/dist/http/types.d.ts +0 -1
- package/dist/index.d.ts +2 -8
- package/dist/index.js +6 -11
- package/dist/internal.d.ts +11 -0
- package/dist/internal.js +13 -0
- package/dist/metadata.js +6 -15
- package/dist/module/decorators.d.ts +1 -3
- package/dist/module/decorators.js +8 -20
- package/dist/module/graph.d.ts +10 -0
- package/dist/module/graph.js +35 -0
- package/dist/module/index.d.ts +2 -0
- package/dist/module/index.js +1 -0
- package/dist/{http/middleware-consumer.d.ts → module/middleware.d.ts} +4 -14
- package/dist/{http/middleware-consumer.js → module/middleware.js} +0 -12
- package/dist/module/module-loader.d.ts +1 -1
- package/dist/module/module-loader.js +17 -13
- package/dist/module/types.d.ts +1 -29
- package/dist/openapi/decorators.js +15 -10
- package/dist/openapi/document.js +7 -42
- package/dist/pipeline/app-providers.d.ts +10 -0
- package/dist/pipeline/app-providers.js +43 -0
- package/dist/pipeline/decorators.d.ts +5 -5
- package/dist/pipeline/decorators.js +1 -9
- package/dist/pipeline/reflector.d.ts +8 -24
- package/dist/pipeline/reflector.js +10 -55
- package/dist/registry/index.d.ts +1 -1
- package/dist/registry/metadata.registry.d.ts +18 -13
- package/dist/registry/metadata.registry.js +133 -159
- package/dist/registry/paths.d.ts +3 -0
- package/dist/registry/paths.js +15 -0
- package/dist/registry/types.d.ts +24 -14
- package/dist/registry/types.js +0 -1
- package/dist/registry/util.d.ts +3 -0
- package/dist/registry/util.js +8 -0
- package/dist/schedule/schedule.decorators.js +3 -6
- package/dist/schedule/schedule.registry.js +3 -2
- package/dist/throttler/throttler.decorators.d.ts +2 -2
- package/package.json +5 -9
- package/dist/testing/index.d.ts +0 -2
- package/dist/testing/index.js +0 -2
- package/dist/testing/testing.builder.d.ts +0 -29
- package/dist/testing/testing.builder.js +0 -148
- package/dist/testing/testing.module.d.ts +0 -9
- package/dist/testing/testing.module.js +0 -15
package/dist/http/decorators.js
CHANGED
|
@@ -1,43 +1,30 @@
|
|
|
1
|
-
import { HttpMethod,
|
|
2
|
-
import { defineMetadata, getMetadata } from "../metadata.js";
|
|
1
|
+
import { HttpMethod, ParamType, Scope } from "../constants.js";
|
|
3
2
|
import { MetadataRegistry } from "../registry/metadata.registry.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
3
|
+
import { normalizePath } from "../registry/paths.js";
|
|
4
|
+
import { buildExecutionContext } from "./execution-context.js";
|
|
7
5
|
/**
|
|
8
6
|
* Marks a class as a controller.
|
|
9
|
-
* Accepts a
|
|
7
|
+
* Accepts a path string or an options object with `path` and `version`.
|
|
10
8
|
*
|
|
11
9
|
* @example
|
|
12
10
|
* ```ts
|
|
13
11
|
* @Controller('/users')
|
|
14
|
-
* @Controller({
|
|
15
|
-
* @Controller({
|
|
12
|
+
* @Controller({ path: '/users', version: 1 })
|
|
13
|
+
* @Controller({ path: '/users', version: [1, 2] })
|
|
16
14
|
* ```
|
|
17
|
-
*/ export function Controller(
|
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
15
|
+
*/ export function Controller(pathOrOptions) {
|
|
19
16
|
return (target)=>{
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
} else if (prefixOrOptions) {
|
|
25
|
-
prefix = prefixOrOptions.path ?? prefixOrOptions.prefix ?? '';
|
|
26
|
-
version = prefixOrOptions.version;
|
|
27
|
-
} else {
|
|
28
|
-
prefix = '';
|
|
29
|
-
}
|
|
30
|
-
MetadataRegistry.setControllerPath(target, normalizePath(prefix));
|
|
17
|
+
const ctor = target;
|
|
18
|
+
const path = typeof pathOrOptions === 'string' ? pathOrOptions : pathOrOptions?.path ?? '';
|
|
19
|
+
const version = typeof pathOrOptions === 'object' ? pathOrOptions?.version : undefined;
|
|
20
|
+
MetadataRegistry.setControllerPath(ctor, normalizePath(path));
|
|
31
21
|
if (version !== undefined) {
|
|
32
|
-
MetadataRegistry.setControllerOptions(
|
|
22
|
+
MetadataRegistry.setControllerOptions(ctor, {
|
|
33
23
|
version
|
|
34
24
|
});
|
|
35
25
|
}
|
|
36
|
-
MetadataRegistry.markInjectable(
|
|
37
|
-
MetadataRegistry.setScope(
|
|
38
|
-
// Keep WeakMap write for external package compat
|
|
39
|
-
defineMetadata(METADATA_KEYS.INJECTABLE, true, target);
|
|
40
|
-
defineMetadata(METADATA_KEYS.SCOPE, Scope.SINGLETON, target);
|
|
26
|
+
MetadataRegistry.markInjectable(ctor);
|
|
27
|
+
MetadataRegistry.setScope(ctor, Scope.SINGLETON);
|
|
41
28
|
};
|
|
42
29
|
}
|
|
43
30
|
/**
|
|
@@ -57,28 +44,25 @@ function normalizePath(path) {
|
|
|
57
44
|
* ```
|
|
58
45
|
*/ export function Version(version) {
|
|
59
46
|
return (target, propertyKey, _descriptor)=>{
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
// If route was already registered (decorator ran after @Get), patch it
|
|
65
|
-
const routes = MetadataRegistry.getRoutes(target.constructor);
|
|
66
|
-
const route = routes.find((r)=>r.handlerName === propertyKey);
|
|
47
|
+
const ctor = target.constructor;
|
|
48
|
+
MetadataRegistry.setRouteVersion(ctor, propertyKey, version);
|
|
49
|
+
// If route was already registered (decorator ran after @Get), patch it.
|
|
50
|
+
const route = MetadataRegistry.getRoutes(ctor).find((r)=>r.handlerName === propertyKey);
|
|
67
51
|
if (route) {
|
|
68
52
|
route.version = version;
|
|
69
53
|
}
|
|
70
54
|
};
|
|
71
55
|
}
|
|
72
56
|
export function getRouteVersion(target, propertyKey) {
|
|
73
|
-
return MetadataRegistry.getRouteVersion(target, propertyKey)
|
|
57
|
+
return MetadataRegistry.getRouteVersion(target, propertyKey);
|
|
74
58
|
}
|
|
75
59
|
function createMethodDecorator(method) {
|
|
76
60
|
return (path = '')=>{
|
|
77
61
|
return (target, propertyKey, _descriptor)=>{
|
|
62
|
+
const ctor = target.constructor;
|
|
78
63
|
const normalizedPath = normalizePath(path);
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
MetadataRegistry.addRoute(target.constructor, {
|
|
64
|
+
const version = MetadataRegistry.getRouteVersion(ctor, propertyKey);
|
|
65
|
+
MetadataRegistry.addRoute(ctor, {
|
|
82
66
|
method: method,
|
|
83
67
|
path: normalizedPath,
|
|
84
68
|
handlerName: propertyKey,
|
|
@@ -229,17 +213,7 @@ export const Cookie = createBuiltinParamDecorator(ParamType.COOKIE);
|
|
|
229
213
|
name: undefined,
|
|
230
214
|
factory: (_unused, ctx)=>{
|
|
231
215
|
const honoCtx = ctx;
|
|
232
|
-
const execCtx =
|
|
233
|
-
getType: ()=>'http',
|
|
234
|
-
getClass: ()=>target.constructor,
|
|
235
|
-
getHandler: ()=>propertyKey,
|
|
236
|
-
getContext: ()=>honoCtx,
|
|
237
|
-
getRequest: ()=>honoCtx.req.raw,
|
|
238
|
-
switchToHttp: ()=>({
|
|
239
|
-
getRequest: ()=>honoCtx.req.raw,
|
|
240
|
-
getResponse: ()=>honoCtx
|
|
241
|
-
})
|
|
242
|
-
};
|
|
216
|
+
const execCtx = buildExecutionContext(honoCtx, target.constructor, propertyKey);
|
|
243
217
|
return factory(data, execCtx);
|
|
244
218
|
},
|
|
245
219
|
...pipes.length > 0 ? {
|
|
@@ -317,37 +291,16 @@ export const Cookie = createBuiltinParamDecorator(ParamType.COOKIE);
|
|
|
317
291
|
}
|
|
318
292
|
// Metadata readers (used by RouteManager)
|
|
319
293
|
export function getHttpCode(target, method) {
|
|
320
|
-
|
|
321
|
-
if (meta?.httpCode !== undefined) return meta.httpCode;
|
|
322
|
-
return getMetadata(METADATA_KEYS.HTTP_CODE, target, method);
|
|
294
|
+
return MetadataRegistry.getHandlerHttpMeta(target, method)?.httpCode;
|
|
323
295
|
}
|
|
324
296
|
export function getResponseHeaders(target, method) {
|
|
325
|
-
|
|
326
|
-
if (meta?.responseHeaders) return meta.responseHeaders;
|
|
327
|
-
return getMetadata(METADATA_KEYS.RESPONSE_HEADERS, target, method) ?? [];
|
|
297
|
+
return MetadataRegistry.getHandlerHttpMeta(target, method)?.responseHeaders ?? [];
|
|
328
298
|
}
|
|
329
299
|
export function getRedirect(target, method) {
|
|
330
|
-
|
|
331
|
-
if (meta?.redirect) return meta.redirect;
|
|
332
|
-
return getMetadata(METADATA_KEYS.REDIRECT, target, method);
|
|
300
|
+
return MetadataRegistry.getHandlerHttpMeta(target, method)?.redirect;
|
|
333
301
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
* matching how stacked decorators behave when written separately.
|
|
337
|
-
*
|
|
338
|
-
* @example
|
|
339
|
-
* ```ts
|
|
340
|
-
* const Auth = (...roles: string[]) => applyDecorators(
|
|
341
|
-
* UseGuards(JwtGuard, RolesGuard),
|
|
342
|
-
* SetMetadata('roles', roles),
|
|
343
|
-
* );
|
|
344
|
-
*
|
|
345
|
-
* @Auth('admin')
|
|
346
|
-
* @Get('/admin')
|
|
347
|
-
* handle() { ... }
|
|
348
|
-
* ```
|
|
349
|
-
*/ export function applyDecorators(...decorators) {
|
|
350
|
-
const composed = (target, propertyKey, descriptor)=>{
|
|
302
|
+
export function applyDecorators(...decorators) {
|
|
303
|
+
return (target, propertyKey, descriptor)=>{
|
|
351
304
|
for (const decorator of decorators){
|
|
352
305
|
if (propertyKey === undefined && typeof descriptor !== 'number') {
|
|
353
306
|
decorator(target);
|
|
@@ -358,7 +311,6 @@ export function getRedirect(target, method) {
|
|
|
358
311
|
}
|
|
359
312
|
}
|
|
360
313
|
};
|
|
361
|
-
return composed;
|
|
362
314
|
}
|
|
363
315
|
// Helpers
|
|
364
316
|
export function isController(target) {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Context } from 'hono';
|
|
2
|
+
import type { Type } from '../container/types';
|
|
3
|
+
import type { ExecutionContext } from '../pipeline/types';
|
|
4
|
+
export declare function buildExecutionContext(c: Context, controller: Type, handlerName: string | symbol): ExecutionContext;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Single source of ExecutionContext shape — used by the route pipeline AND
|
|
2
|
+
// by createParamDecorator's deferred factory call.
|
|
3
|
+
export function buildExecutionContext(c, controller, handlerName) {
|
|
4
|
+
return {
|
|
5
|
+
getType: ()=>'http',
|
|
6
|
+
getClass: ()=>controller,
|
|
7
|
+
getHandler: ()=>handlerName,
|
|
8
|
+
getContext: ()=>c,
|
|
9
|
+
getRequest: ()=>c.req.raw,
|
|
10
|
+
switchToHttp: ()=>({
|
|
11
|
+
getRequest: ()=>c.req.raw,
|
|
12
|
+
getResponse: ()=>c
|
|
13
|
+
})
|
|
14
|
+
};
|
|
15
|
+
}
|
package/dist/http/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { RouteManager } from './route.manager';
|
|
2
2
|
export type { RouteManagerOptions } from './route.manager';
|
|
3
|
-
export { MiddlewareBuilder
|
|
4
|
-
export type { MiddlewareConsumer, MiddlewareConfigProxy, RouteInfo, NestModule, MiddlewareRouteDefinition } from '
|
|
3
|
+
export { MiddlewareBuilder } from '../module/middleware';
|
|
4
|
+
export type { MiddlewareConsumer, MiddlewareConfigProxy, RouteInfo, NestModule, MiddlewareRouteDefinition } from '../module/middleware';
|
|
5
5
|
export { Controller, Version, Get, Post, Put, Patch, Delete, Options, Head, All, Sse, Param, Query, Body, Headers, Req, Res, Ip, Cookie, Cookies, RawBody, HttpCode, Header, Redirect, createParamDecorator, applyDecorators, isController, } from './decorators';
|
|
6
6
|
export type { RouteMetadata, ControllerMetadata, ControllerOptions, ParamMetadata, ControllerRegistration, } from './types';
|
package/dist/http/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { RouteManager } from "./route.manager.js";
|
|
2
|
-
export { MiddlewareBuilder
|
|
2
|
+
export { MiddlewareBuilder } from "../module/middleware.js";
|
|
3
3
|
export { Controller, Version, Get, Post, Put, Patch, Delete, Options, Head, All, Sse, Param, Query, Body, Headers, Req, Res, Ip, Cookie, Cookies, RawBody, HttpCode, Header, Redirect, createParamDecorator, applyDecorators, isController } from "./decorators.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Context, type MiddlewareHandler, 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 '
|
|
4
|
+
import type { MiddlewareRouteDefinition } from '../module/middleware';
|
|
5
5
|
import type { CanActivate, ExceptionFilter, NestInterceptor, NestMiddleware, PipeTransform } from '../pipeline/types';
|
|
6
6
|
import type { FilterType, GuardType, InterceptorType, MiddlewareType, PipeType } from '../registry/types';
|
|
7
7
|
import type { ControllerRegistration } from './types';
|
|
@@ -49,7 +49,6 @@ export declare class RouteManager {
|
|
|
49
49
|
private createResponse;
|
|
50
50
|
private registerRoute;
|
|
51
51
|
private buildVersionedPaths;
|
|
52
|
-
private joinPaths;
|
|
53
52
|
private compilePathMatcher;
|
|
54
53
|
private compileRouteMatcher;
|
|
55
54
|
getControllers(): ControllerRegistration[];
|
|
@@ -2,7 +2,8 @@ import { Hono } from "hono";
|
|
|
2
2
|
import { getCookie } from "hono/cookie";
|
|
3
3
|
import { HttpMethod, ParamType } from "../constants.js";
|
|
4
4
|
import { getMetadata } from "../metadata.js";
|
|
5
|
-
import {
|
|
5
|
+
import { joinPaths } from "../registry/paths.js";
|
|
6
|
+
import { buildExecutionContext } from "./execution-context.js";
|
|
6
7
|
import { ForbiddenException, HttpException } from "../errors/http-exception.js";
|
|
7
8
|
import { ComponentManager } from "../pipeline/component.manager.js";
|
|
8
9
|
import { shouldFilterCatch } from "../pipeline/decorators.js";
|
|
@@ -301,31 +302,25 @@ export class RouteManager {
|
|
|
301
302
|
await buildCrudRoutes(app, controller, metadata.prefix, crudConfig, {
|
|
302
303
|
globalPrefix: this.globalPrefix,
|
|
303
304
|
globalGuards: this.instantiateMany(this.globalGuards, this.container),
|
|
304
|
-
joinPaths
|
|
305
|
+
joinPaths
|
|
306
|
+
});
|
|
307
|
+
} catch (err) {
|
|
308
|
+
throw new Error(`@Crud() requires '@velajs/crud'. Install it: pnpm add @velajs/crud`, {
|
|
309
|
+
cause: err
|
|
305
310
|
});
|
|
306
|
-
} catch {
|
|
307
|
-
throw new Error(`@Crud() requires '@velajs/crud'. Install it: bun add @velajs/crud`);
|
|
308
311
|
}
|
|
309
312
|
}
|
|
310
313
|
}
|
|
311
314
|
return app;
|
|
312
315
|
}
|
|
313
316
|
createExecutionContext(c, controller, route) {
|
|
314
|
-
return
|
|
315
|
-
getType: ()=>'http',
|
|
316
|
-
getClass: ()=>controller,
|
|
317
|
-
getHandler: ()=>route.handlerName,
|
|
318
|
-
getContext: ()=>c,
|
|
319
|
-
getRequest: ()=>c.req.raw,
|
|
320
|
-
switchToHttp: ()=>({
|
|
321
|
-
getRequest: ()=>c.req.raw,
|
|
322
|
-
getResponse: ()=>c
|
|
323
|
-
})
|
|
324
|
-
};
|
|
317
|
+
return buildExecutionContext(c, controller, route.handlerName);
|
|
325
318
|
}
|
|
326
319
|
createHandler(route, controller, allParamMetadata) {
|
|
327
320
|
const paramMetadata = (allParamMetadata.get(route.handlerName) || []).sort((a, b)=>a.index - b.index);
|
|
328
|
-
// Read param types once at build time for metatype population
|
|
321
|
+
// Read param types once at build time for metatype population.
|
|
322
|
+
// Routed via Reflect so the polyfill funnels both src-level and dist-level
|
|
323
|
+
// consumers to the same registry (matters in tests that import from dist).
|
|
329
324
|
const paramTypes = Reflect.getMetadata('design:paramtypes', controller.prototype, route.handlerName);
|
|
330
325
|
// Collect controller + method level components at build time
|
|
331
326
|
const methodGuards = ComponentManager.getComponents('guard', controller, route.handlerName);
|
|
@@ -470,12 +465,16 @@ export class RouteManager {
|
|
|
470
465
|
registerRoute(app, method, path, handler) {
|
|
471
466
|
const normalizedPath = path || '/';
|
|
472
467
|
const registrar = RouteManager.METHOD_REGISTRAR.get(method);
|
|
473
|
-
|
|
468
|
+
if (registrar) {
|
|
469
|
+
registrar(app, normalizedPath, handler);
|
|
470
|
+
} else {
|
|
471
|
+
app.on(method, normalizedPath, handler);
|
|
472
|
+
}
|
|
474
473
|
}
|
|
475
474
|
buildVersionedPaths(globalPrefix, controllerPrefix, routePath, version) {
|
|
476
475
|
if (version === undefined) {
|
|
477
476
|
return [
|
|
478
|
-
|
|
477
|
+
joinPaths(globalPrefix, joinPaths(controllerPrefix, routePath))
|
|
479
478
|
];
|
|
480
479
|
}
|
|
481
480
|
const versions = Array.isArray(version) ? version : [
|
|
@@ -483,14 +482,9 @@ export class RouteManager {
|
|
|
483
482
|
];
|
|
484
483
|
return versions.map((v)=>{
|
|
485
484
|
const versionSegment = `/v${v}`;
|
|
486
|
-
return
|
|
485
|
+
return joinPaths(globalPrefix, joinPaths(versionSegment, joinPaths(controllerPrefix, routePath)));
|
|
487
486
|
});
|
|
488
487
|
}
|
|
489
|
-
joinPaths(prefix, path) {
|
|
490
|
-
const cleanPrefix = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;
|
|
491
|
-
const cleanPath = path && !path.startsWith('/') ? `/${path}` : path;
|
|
492
|
-
return `${cleanPrefix}${cleanPath}` || '/';
|
|
493
|
-
}
|
|
494
488
|
compilePathMatcher(routePath) {
|
|
495
489
|
if (routePath === '*') return ()=>true;
|
|
496
490
|
const norm = routePath.startsWith('/') ? routePath : `/${routePath}`;
|
|
@@ -505,7 +499,7 @@ export class RouteManager {
|
|
|
505
499
|
const matchPath = this.compilePathMatcher(route.path);
|
|
506
500
|
return (path, method)=>{
|
|
507
501
|
if (!matchPath(path)) return false;
|
|
508
|
-
if (route.method && route.method !==
|
|
502
|
+
if (route.method && route.method !== HttpMethod.ALL) return method === route.method;
|
|
509
503
|
return true;
|
|
510
504
|
};
|
|
511
505
|
});
|
package/dist/http/types.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import './metadata';
|
|
2
2
|
export { defineMetadata, getMetadata } from './metadata';
|
|
3
|
-
export { VelaFactory
|
|
3
|
+
export { VelaFactory } from './factory';
|
|
4
4
|
export { VelaApplication } from './application';
|
|
5
5
|
export { createOpenApiDocument, ApiDoc, ApiTags, ApiResponse, zodToJsonSchema, } from './openapi/index';
|
|
6
6
|
export type { OpenApiDocument, OpenApiInfo, OpenApiOperation, OpenApiParameter, OpenApiPathItem, OpenApiRequestBody, OpenApiResponse, ApiDocMetadata, ApiResponseEntry, ApiResponseOptions, CreateOpenApiDocumentOptions, HttpVerb, JsonSchema, } from './openapi/index';
|
|
@@ -28,7 +28,6 @@ export { ThrottlerModule, ThrottlerGuard, ThrottlerStorage, Throttle, SkipThrott
|
|
|
28
28
|
export type { ThrottlerModuleOptions, ThrottleConfig, ThrottlerStore, ThrottlerStorageRecord, RateLimitInfo, } from './throttler/index';
|
|
29
29
|
export { Global, Module, createModuleRef } from './module/index';
|
|
30
30
|
export type { ModuleOptions, DynamicModule, AsyncModuleOptions, ModuleImport } from './module/index';
|
|
31
|
-
export { RequestMethod } from './http/index';
|
|
32
31
|
export type { MiddlewareConsumer, NestModule, RouteInfo } from './http/index';
|
|
33
32
|
export { UseMiddleware, UseGuards, UsePipes, UseInterceptors, UseFilters, Catch, SetMetadata, Reflector, APP_GUARD, APP_PIPE, APP_INTERCEPTOR, APP_FILTER, APP_MIDDLEWARE, } from './pipeline/index';
|
|
34
33
|
export type { HttpArgumentsHost, ExecutionContext, CanActivate, CallHandler, NestInterceptor, NestMiddleware, PipeTransform, ExceptionFilter, ArgumentMetadata, ReflectableDecorator, CreateDecoratorOptions, } from './pipeline/index';
|
|
@@ -37,13 +36,8 @@ export { ParseIntPipe, ParseFloatPipe, ParseBoolPipe, ParseUUIDPipe, ParseEnumPi
|
|
|
37
36
|
export type { ParseUUIDPipeOptions, ParseArrayPipeOptions } from './pipeline/index';
|
|
38
37
|
export { HttpException, BadRequestException, UnauthorizedException, ForbiddenException, NotFoundException, MethodNotAllowedException, NotAcceptableException, RequestTimeoutException, ConflictException, GoneException, PayloadTooLargeException, UnsupportedMediaTypeException, UnprocessableEntityException, TooManyRequestsException, InternalServerErrorException, NotImplementedException, BadGatewayException, ServiceUnavailableException, GatewayTimeoutException, } from './errors/index';
|
|
39
38
|
export type { OnModuleInit, OnApplicationBootstrap, OnModuleDestroy, OnApplicationShutdown, BeforeApplicationShutdown, } from './lifecycle/index';
|
|
40
|
-
export { MetadataRegistry } from './registry/
|
|
41
|
-
export { RouteManager } from './http/index';
|
|
42
|
-
export type { RouteManagerOptions } from './http/index';
|
|
43
|
-
export { ModuleLoader } from './module/index';
|
|
44
|
-
export { ComponentManager } from './pipeline/index';
|
|
39
|
+
export { MetadataRegistry } from './registry/metadata.registry';
|
|
45
40
|
export { createZodDto, ValidationPipe } from './validation/index';
|
|
46
41
|
export type { CreateZodDtoOptions } from './validation/index';
|
|
47
42
|
export { Serialize, SerializerInterceptor, SERIALIZE_METADATA } from './serialization/index';
|
|
48
|
-
export { Test, TestingModule, TestingModuleBuilder } from './testing/index';
|
|
49
43
|
export { getRuntimeKey, env } from 'hono/adapter';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "./metadata.js";
|
|
2
2
|
export { defineMetadata, getMetadata } from "./metadata.js";
|
|
3
3
|
// Factory & Application
|
|
4
|
-
export { VelaFactory
|
|
4
|
+
export { VelaFactory } from "./factory.js";
|
|
5
5
|
export { VelaApplication } from "./application.js";
|
|
6
6
|
// OpenAPI
|
|
7
7
|
export { createOpenApiDocument, ApiDoc, ApiTags, ApiResponse, zodToJsonSchema } from "./openapi/index.js";
|
|
@@ -31,25 +31,20 @@ export { HealthModule, HealthCheckService, HealthIndicatorService, HttpHealthInd
|
|
|
31
31
|
export { ThrottlerModule, ThrottlerGuard, ThrottlerStorage, Throttle, SkipThrottle, THROTTLER_OPTIONS, THROTTLER_STORAGE, THROTTLE_METADATA, SKIP_THROTTLE_METADATA } from "./throttler/index.js";
|
|
32
32
|
// Module
|
|
33
33
|
export { Global, Module, createModuleRef } from "./module/index.js";
|
|
34
|
-
export { RequestMethod } from "./http/index.js";
|
|
35
34
|
// Pipeline Decorators
|
|
36
35
|
export { UseMiddleware, UseGuards, UsePipes, UseInterceptors, UseFilters, Catch, SetMetadata, Reflector, APP_GUARD, APP_PIPE, APP_INTERCEPTOR, APP_FILTER, APP_MIDDLEWARE } from "./pipeline/index.js";
|
|
37
36
|
// Built-in Pipes
|
|
38
37
|
export { ParseIntPipe, ParseFloatPipe, ParseBoolPipe, ParseUUIDPipe, ParseEnumPipe, ParseArrayPipe, DefaultValuePipe, RequiredPipe, ZodValidationPipe } from "./pipeline/index.js";
|
|
39
38
|
// Errors
|
|
40
39
|
export { HttpException, BadRequestException, UnauthorizedException, ForbiddenException, NotFoundException, MethodNotAllowedException, NotAcceptableException, RequestTimeoutException, ConflictException, GoneException, PayloadTooLargeException, UnsupportedMediaTypeException, UnprocessableEntityException, TooManyRequestsException, InternalServerErrorException, NotImplementedException, BadGatewayException, ServiceUnavailableException, GatewayTimeoutException } from "./errors/index.js";
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
//
|
|
44
|
-
export {
|
|
45
|
-
export { ModuleLoader } from "./module/index.js";
|
|
46
|
-
// Component Manager (for advanced usage)
|
|
47
|
-
export { ComponentManager } from "./pipeline/index.js";
|
|
40
|
+
// MetadataRegistry — the central decoration store. Test setup typically
|
|
41
|
+
// uses `MetadataRegistry.clear()` between cases. Internal primitives like
|
|
42
|
+
// RouteManager/ModuleLoader/ComponentManager live only at @velajs/vela/internal.
|
|
43
|
+
export { MetadataRegistry } from "./registry/metadata.registry.js";
|
|
48
44
|
// Validation
|
|
49
45
|
export { createZodDto, ValidationPipe } from "./validation/index.js";
|
|
50
46
|
// Serialization
|
|
51
47
|
export { Serialize, SerializerInterceptor, SERIALIZE_METADATA } from "./serialization/index.js";
|
|
52
|
-
// Testing
|
|
53
|
-
export { Test, TestingModule, TestingModuleBuilder } from "./testing/index.js";
|
|
48
|
+
// Testing utilities live in @velajs/testing — see https://github.com/velajs/testing
|
|
54
49
|
// Hono Adapter Utilities
|
|
55
50
|
export { getRuntimeKey, env } from "hono/adapter";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { Container } from './container/container';
|
|
2
|
+
export { ModuleRef } from './container/module-ref';
|
|
3
|
+
export { bindAppProviders } from './pipeline/app-providers';
|
|
4
|
+
export { RouteManager } from './http/route.manager';
|
|
5
|
+
export type { RouteManagerOptions } from './http/route.manager';
|
|
6
|
+
export { ModuleLoader } from './module/module-loader';
|
|
7
|
+
export { ComponentManager } from './pipeline/component.manager';
|
|
8
|
+
export { VelaApplication } from './application';
|
|
9
|
+
export { MetadataRegistry } from './registry/metadata.registry';
|
|
10
|
+
export { APP_GUARD, APP_PIPE, APP_INTERCEPTOR, APP_FILTER, APP_MIDDLEWARE, } from './pipeline/tokens';
|
|
11
|
+
export { getModuleMetadata, isModule } from './module/decorators';
|
package/dist/internal.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Internal framework primitives — exposed for first-party consumers like
|
|
2
|
+
// @velajs/testing and advanced integration. Not covered by semver guarantees
|
|
3
|
+
// to the same degree as the public surface (./index).
|
|
4
|
+
export { Container } from "./container/container.js";
|
|
5
|
+
export { ModuleRef } from "./container/module-ref.js";
|
|
6
|
+
export { bindAppProviders } from "./pipeline/app-providers.js";
|
|
7
|
+
export { RouteManager } from "./http/route.manager.js";
|
|
8
|
+
export { ModuleLoader } from "./module/module-loader.js";
|
|
9
|
+
export { ComponentManager } from "./pipeline/component.manager.js";
|
|
10
|
+
export { VelaApplication } from "./application.js";
|
|
11
|
+
export { MetadataRegistry } from "./registry/metadata.registry.js";
|
|
12
|
+
export { APP_GUARD, APP_PIPE, APP_INTERCEPTOR, APP_FILTER, APP_MIDDLEWARE } from "./pipeline/tokens.js";
|
|
13
|
+
export { getModuleMetadata, isModule } from "./module/decorators.js";
|
package/dist/metadata.js
CHANGED
|
@@ -1,22 +1,13 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
function compositeKey(key, prop) {
|
|
6
|
-
return prop !== undefined ? `${key}\0${String(prop)}` : key;
|
|
7
|
-
}
|
|
1
|
+
// Single funnel: every Reflect.* metadata write/read routes into MetadataRegistry.
|
|
2
|
+
// SWC emits Reflect.metadata('design:paramtypes', ...) calls in compiled code;
|
|
3
|
+
// the polyfill catches those and parks them in the registry alongside vela's typed slots.
|
|
4
|
+
import { MetadataRegistry } from "./registry/metadata.registry.js";
|
|
8
5
|
export function defineMetadata(key, value, target, propertyKey) {
|
|
9
|
-
|
|
10
|
-
if (!map) {
|
|
11
|
-
map = new Map();
|
|
12
|
-
store.set(target, map);
|
|
13
|
-
}
|
|
14
|
-
map.set(compositeKey(key, propertyKey), value);
|
|
6
|
+
MetadataRegistry.setReflectMetadata(target, key, value, propertyKey);
|
|
15
7
|
}
|
|
16
8
|
export function getMetadata(key, target, propertyKey) {
|
|
17
|
-
return
|
|
9
|
+
return MetadataRegistry.getReflectMetadata(target, key, propertyKey);
|
|
18
10
|
}
|
|
19
|
-
// Minimal Reflect polyfill so the compiler's `Reflect.metadata(...)` calls work.
|
|
20
11
|
if (typeof Reflect.defineMetadata !== 'function') {
|
|
21
12
|
Reflect.defineMetadata = defineMetadata;
|
|
22
13
|
Reflect.getMetadata = getMetadata;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import type { Constructor } from '../registry/types';
|
|
2
|
-
import type { Type } from '../container/types';
|
|
3
|
-
import type { ModuleMetadata, ModuleOptions } from './types';
|
|
1
|
+
import type { Constructor, ModuleMetadata, ModuleOptions, Type } from '../registry/types';
|
|
4
2
|
export declare function Global(): ClassDecorator;
|
|
5
3
|
export declare function Module(options?: ModuleOptions): ClassDecorator;
|
|
6
4
|
export declare function isModule(target: Constructor): boolean;
|
|
@@ -1,34 +1,27 @@
|
|
|
1
|
-
import { METADATA_KEYS } from "../constants.js";
|
|
2
|
-
import { defineMetadata, getMetadata } from "../metadata.js";
|
|
3
1
|
import { MetadataRegistry } from "../registry/metadata.registry.js";
|
|
4
2
|
export function Global() {
|
|
5
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
6
3
|
return (target)=>{
|
|
7
|
-
const
|
|
8
|
-
MetadataRegistry.
|
|
4
|
+
const ctor = target;
|
|
5
|
+
const existing = MetadataRegistry.getModuleOptions(ctor);
|
|
6
|
+
MetadataRegistry.setModuleOptions(ctor, {
|
|
9
7
|
...existing,
|
|
10
8
|
isGlobal: true
|
|
11
9
|
});
|
|
12
10
|
};
|
|
13
11
|
}
|
|
14
12
|
export function Module(options = {}) {
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
16
13
|
return (target)=>{
|
|
17
|
-
|
|
14
|
+
MetadataRegistry.setModuleOptions(target, {
|
|
18
15
|
imports: options.imports,
|
|
19
16
|
providers: options.providers,
|
|
20
17
|
controllers: options.controllers,
|
|
21
18
|
exports: options.exports,
|
|
22
19
|
isGlobal: options.isGlobal
|
|
23
|
-
};
|
|
24
|
-
// WeakMap store survives MetadataRegistry.clear() — needed for framework modules
|
|
25
|
-
// decorated at import time (e.g. HttpModule, CorsModule).
|
|
26
|
-
defineMetadata(METADATA_KEYS.MODULE_OPTIONS, normalized, target);
|
|
27
|
-
MetadataRegistry.setModuleOptions(target, normalized);
|
|
20
|
+
});
|
|
28
21
|
};
|
|
29
22
|
}
|
|
30
23
|
export function isModule(target) {
|
|
31
|
-
return MetadataRegistry.getModuleOptions(target) !== undefined
|
|
24
|
+
return MetadataRegistry.getModuleOptions(target) !== undefined;
|
|
32
25
|
}
|
|
33
26
|
export function createModuleRef(name) {
|
|
34
27
|
const moduleClass = class {
|
|
@@ -39,13 +32,8 @@ export function createModuleRef(name) {
|
|
|
39
32
|
return moduleClass;
|
|
40
33
|
}
|
|
41
34
|
export function getModuleMetadata(target) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
const options = MetadataRegistry.getModuleOptions(target) ?? getMetadata(METADATA_KEYS.MODULE_OPTIONS, target);
|
|
46
|
-
if (!options || typeof options !== 'object') {
|
|
47
|
-
return undefined;
|
|
48
|
-
}
|
|
35
|
+
const options = MetadataRegistry.getModuleOptions(target);
|
|
36
|
+
if (!options) return undefined;
|
|
49
37
|
return {
|
|
50
38
|
providers: options.providers ?? [],
|
|
51
39
|
controllers: options.controllers ?? [],
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Type } from '../container/types';
|
|
2
|
+
/**
|
|
3
|
+
* Walks the module dependency graph from a root, unwrapping ForwardRef and
|
|
4
|
+
* dynamic-module imports along the way, and returns every controller
|
|
5
|
+
* reachable from it. Pure metadata read — no Container, no side effects.
|
|
6
|
+
*
|
|
7
|
+
* Used by createOpenApiDocument and any other consumer that needs a
|
|
8
|
+
* controller list without bootstrapping the application.
|
|
9
|
+
*/
|
|
10
|
+
export declare function collectControllers(rootModule: Type): Type[];
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ForwardRef } from "../container/types.js";
|
|
2
|
+
import { getModuleMetadata } from "./decorators.js";
|
|
3
|
+
function isDynamicModuleLike(value) {
|
|
4
|
+
return !!value && typeof value === 'object' && 'module' in value && typeof value.module === 'function';
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Walks the module dependency graph from a root, unwrapping ForwardRef and
|
|
8
|
+
* dynamic-module imports along the way, and returns every controller
|
|
9
|
+
* reachable from it. Pure metadata read — no Container, no side effects.
|
|
10
|
+
*
|
|
11
|
+
* Used by createOpenApiDocument and any other consumer that needs a
|
|
12
|
+
* controller list without bootstrapping the application.
|
|
13
|
+
*/ export function collectControllers(rootModule) {
|
|
14
|
+
const visited = new Set();
|
|
15
|
+
const controllers = new Set();
|
|
16
|
+
const visit = (entry)=>{
|
|
17
|
+
const unwrapped = entry instanceof ForwardRef ? entry.factory() : entry;
|
|
18
|
+
const moduleClass = isDynamicModuleLike(unwrapped) ? unwrapped.module : unwrapped;
|
|
19
|
+
const extraControllers = isDynamicModuleLike(unwrapped) ? unwrapped.controllers ?? [] : [];
|
|
20
|
+
const extraImports = isDynamicModuleLike(unwrapped) ? unwrapped.imports ?? [] : [];
|
|
21
|
+
if (typeof moduleClass !== 'function' || visited.has(moduleClass)) return;
|
|
22
|
+
visited.add(moduleClass);
|
|
23
|
+
const metadata = getModuleMetadata(moduleClass);
|
|
24
|
+
if (metadata) {
|
|
25
|
+
for (const controller of metadata.controllers)controllers.add(controller);
|
|
26
|
+
for (const imp of metadata.imports)visit(imp);
|
|
27
|
+
}
|
|
28
|
+
for (const controller of extraControllers)controllers.add(controller);
|
|
29
|
+
for (const imp of extraImports)visit(imp);
|
|
30
|
+
};
|
|
31
|
+
visit(rootModule);
|
|
32
|
+
return [
|
|
33
|
+
...controllers
|
|
34
|
+
];
|
|
35
|
+
}
|
package/dist/module/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { Global, Module, isModule, getModuleMetadata, createModuleRef } from './decorators';
|
|
2
2
|
export { ModuleLoader } from './module-loader';
|
|
3
|
+
export { MiddlewareBuilder } from './middleware';
|
|
4
|
+
export type { MiddlewareConsumer, MiddlewareConfigProxy, MiddlewareRouteDefinition, NestModule, RouteInfo, } from './middleware';
|
|
3
5
|
export type { ModuleOptions, ModuleMetadata, DynamicModule, AsyncModuleOptions, ModuleImport } from './types';
|
package/dist/module/index.js
CHANGED
|
@@ -1,19 +1,9 @@
|
|
|
1
|
+
import { HttpMethod } from '../constants';
|
|
1
2
|
import type { NestMiddleware } from '../pipeline/types';
|
|
2
|
-
import type { Type } from '../registry/types';
|
|
3
|
-
export declare const RequestMethod: {
|
|
4
|
-
readonly GET: "GET";
|
|
5
|
-
readonly POST: "POST";
|
|
6
|
-
readonly PUT: "PUT";
|
|
7
|
-
readonly DELETE: "DELETE";
|
|
8
|
-
readonly PATCH: "PATCH";
|
|
9
|
-
readonly OPTIONS: "OPTIONS";
|
|
10
|
-
readonly HEAD: "HEAD";
|
|
11
|
-
readonly ALL: "ALL";
|
|
12
|
-
};
|
|
13
|
-
export type RequestMethod = (typeof RequestMethod)[keyof typeof RequestMethod];
|
|
3
|
+
import type { Constructor, Type } from '../registry/types';
|
|
14
4
|
export interface RouteInfo {
|
|
15
5
|
path: string;
|
|
16
|
-
method?:
|
|
6
|
+
method?: HttpMethod;
|
|
17
7
|
}
|
|
18
8
|
export interface MiddlewareRouteDefinition {
|
|
19
9
|
middleware: Array<Type<NestMiddleware> | NestMiddleware>;
|
|
@@ -25,7 +15,7 @@ export interface MiddlewareRouteDefinition {
|
|
|
25
15
|
export interface MiddlewareConfigProxy {
|
|
26
16
|
exclude(...routes: Array<string | RouteInfo>): MiddlewareConfigProxy;
|
|
27
17
|
withPriority(priority: number): MiddlewareConfigProxy;
|
|
28
|
-
forRoutes(...routes: Array<string |
|
|
18
|
+
forRoutes(...routes: Array<string | Constructor | RouteInfo>): MiddlewareConsumer;
|
|
29
19
|
}
|
|
30
20
|
export interface MiddlewareConsumer {
|
|
31
21
|
apply(...middleware: Array<Type<NestMiddleware> | NestMiddleware>): MiddlewareConfigProxy;
|