@velajs/vela 0.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +84 -0
  4. package/dist/application.d.ts +44 -0
  5. package/dist/application.js +112 -0
  6. package/dist/constants.d.ts +35 -0
  7. package/dist/constants.js +43 -0
  8. package/dist/container/container.d.ts +25 -0
  9. package/dist/container/container.js +195 -0
  10. package/dist/container/decorators.d.ts +8 -0
  11. package/dist/container/decorators.js +36 -0
  12. package/dist/container/index.d.ts +4 -0
  13. package/dist/container/index.js +3 -0
  14. package/dist/container/types.d.ts +37 -0
  15. package/dist/container/types.js +11 -0
  16. package/dist/errors/http-exception.d.ts +61 -0
  17. package/dist/errors/http-exception.js +128 -0
  18. package/dist/errors/index.d.ts +1 -0
  19. package/dist/errors/index.js +1 -0
  20. package/dist/factory.d.ts +5 -0
  21. package/dist/factory.js +39 -0
  22. package/dist/http/decorators.d.ts +122 -0
  23. package/dist/http/decorators.js +276 -0
  24. package/dist/http/index.d.ts +3 -0
  25. package/dist/http/index.js +2 -0
  26. package/dist/http/route.manager.d.ts +34 -0
  27. package/dist/http/route.manager.js +373 -0
  28. package/dist/http/types.d.ts +29 -0
  29. package/dist/http/types.js +1 -0
  30. package/dist/index.d.ts +20 -0
  31. package/dist/index.js +26 -0
  32. package/dist/lifecycle/index.d.ts +20 -0
  33. package/dist/lifecycle/index.js +15 -0
  34. package/dist/metadata.d.ts +10 -0
  35. package/dist/metadata.js +29 -0
  36. package/dist/module/decorators.d.ts +5 -0
  37. package/dist/module/decorators.js +32 -0
  38. package/dist/module/index.d.ts +3 -0
  39. package/dist/module/index.js +2 -0
  40. package/dist/module/module-loader.d.ts +20 -0
  41. package/dist/module/module-loader.js +159 -0
  42. package/dist/module/types.d.ts +19 -0
  43. package/dist/module/types.js +1 -0
  44. package/dist/pipeline/component.manager.d.ts +18 -0
  45. package/dist/pipeline/component.manager.js +105 -0
  46. package/dist/pipeline/decorators.d.ts +10 -0
  47. package/dist/pipeline/decorators.js +50 -0
  48. package/dist/pipeline/index.d.ts +7 -0
  49. package/dist/pipeline/index.js +5 -0
  50. package/dist/pipeline/pipes.d.ts +25 -0
  51. package/dist/pipeline/pipes.js +52 -0
  52. package/dist/pipeline/reflector.d.ts +102 -0
  53. package/dist/pipeline/reflector.js +166 -0
  54. package/dist/pipeline/tokens.d.ts +33 -0
  55. package/dist/pipeline/tokens.js +27 -0
  56. package/dist/pipeline/types.d.ts +31 -0
  57. package/dist/pipeline/types.js +1 -0
  58. package/dist/registry/index.d.ts +2 -0
  59. package/dist/registry/index.js +1 -0
  60. package/dist/registry/metadata.registry.d.ts +61 -0
  61. package/dist/registry/metadata.registry.js +276 -0
  62. package/dist/registry/types.d.ts +55 -0
  63. package/dist/registry/types.js +2 -0
  64. package/package.json +72 -0
@@ -0,0 +1,159 @@
1
+ import { getModuleMetadata, isModule } from "./decorators.js";
2
+ function isDynamicModule(value) {
3
+ return typeof value === 'object' && value !== null && 'module' in value && typeof value.module === 'function';
4
+ }
5
+ export class ModuleLoader {
6
+ container;
7
+ router;
8
+ processedModules = new Set();
9
+ processingStack = new Set();
10
+ collectedControllers = [];
11
+ registeredProviders = [];
12
+ moduleExportsCache = new Map();
13
+ constructor(container, router){
14
+ this.container = container;
15
+ this.router = router;
16
+ }
17
+ load(rootModule) {
18
+ this.processModule(rootModule);
19
+ for (const controller of this.collectedControllers){
20
+ this.router.registerController(controller);
21
+ }
22
+ }
23
+ processModule(moduleClassOrDynamic) {
24
+ // Handle dynamic modules ({ module, controllers, providers })
25
+ let moduleClass;
26
+ let extraControllers = [];
27
+ let extraProviders = [];
28
+ if (isDynamicModule(moduleClassOrDynamic)) {
29
+ moduleClass = moduleClassOrDynamic.module;
30
+ extraControllers = moduleClassOrDynamic.controllers ?? [];
31
+ extraProviders = moduleClassOrDynamic.providers ?? [];
32
+ } else {
33
+ moduleClass = moduleClassOrDynamic;
34
+ }
35
+ if (this.processedModules.has(moduleClass)) {
36
+ // Even if already processed, still collect extra controllers from dynamic module
37
+ for (const controller of extraControllers){
38
+ if (!this.collectedControllers.includes(controller)) {
39
+ this.collectedControllers.push(controller);
40
+ }
41
+ }
42
+ return this.moduleExportsCache.get(moduleClass) ?? new Set();
43
+ }
44
+ if (this.processingStack.has(moduleClass)) {
45
+ const chain = [
46
+ ...this.processingStack,
47
+ moduleClass
48
+ ].map((m)=>m.name).join(' -> ');
49
+ throw new Error(`Circular module dependency detected: ${chain}`);
50
+ }
51
+ if (!isModule(moduleClass)) {
52
+ throw new Error(`${moduleClass.name} is not a module. Add @Module() decorator to the class.`);
53
+ }
54
+ const metadata = getModuleMetadata(moduleClass);
55
+ if (!metadata) {
56
+ throw new Error(`Failed to get module metadata for ${moduleClass.name}`);
57
+ }
58
+ this.processingStack.add(moduleClass);
59
+ try {
60
+ const importedProviders = new Set();
61
+ for (const importedModule of metadata.imports){
62
+ const exportedTokens = this.processModule(importedModule);
63
+ for (const token of exportedTokens){
64
+ importedProviders.add(token);
65
+ }
66
+ }
67
+ // Register metadata providers + dynamic module extra providers
68
+ const allProviders = [
69
+ ...metadata.providers,
70
+ ...extraProviders
71
+ ];
72
+ for (const provider of allProviders){
73
+ this.registerProvider(provider);
74
+ }
75
+ // Collect metadata controllers + dynamic module extra controllers
76
+ const allControllers = [
77
+ ...metadata.controllers,
78
+ ...extraControllers
79
+ ];
80
+ for (const controller of allControllers){
81
+ if (!this.collectedControllers.includes(controller)) {
82
+ this.collectedControllers.push(controller);
83
+ }
84
+ }
85
+ this.processedModules.add(moduleClass);
86
+ const exports = this.buildExportSet(metadata.exports, allProviders, importedProviders);
87
+ this.moduleExportsCache.set(moduleClass, exports);
88
+ return exports;
89
+ } finally{
90
+ this.processingStack.delete(moduleClass);
91
+ }
92
+ }
93
+ registerProvider(provider) {
94
+ if (typeof provider === 'function') {
95
+ if (!this.container.has(provider)) {
96
+ this.container.register(provider);
97
+ this.registeredProviders.push(provider);
98
+ }
99
+ } else {
100
+ const token = provider.token;
101
+ if (token && !this.container.has(token)) {
102
+ this.container.register(provider);
103
+ this.registeredProviders.push(token);
104
+ } else if (!token) {
105
+ this.container.register(provider);
106
+ }
107
+ }
108
+ }
109
+ buildExportSet(exports, providers, importedProviders) {
110
+ const exportSet = new Set();
111
+ for (const exported of exports){
112
+ const isLocalProvider = providers.some((p)=>{
113
+ if (typeof p === 'function') {
114
+ return p === exported;
115
+ }
116
+ return p.token === exported;
117
+ });
118
+ const isImportedProvider = importedProviders.has(exported);
119
+ if (!isLocalProvider && !isImportedProvider) {
120
+ const name = exported.name ?? String(exported);
121
+ console.warn(`Warning: Exporting '${name}' which is neither a local provider nor imported from another module.`);
122
+ }
123
+ exportSet.add(exported);
124
+ }
125
+ return exportSet;
126
+ }
127
+ getControllers() {
128
+ return [
129
+ ...this.collectedControllers
130
+ ];
131
+ }
132
+ getRegisteredProviders() {
133
+ return [
134
+ ...this.registeredProviders
135
+ ];
136
+ }
137
+ resolveAllInstances() {
138
+ const instances = [];
139
+ for (const token of this.registeredProviders){
140
+ try {
141
+ const instance = this.container.resolve(token);
142
+ instances.push(instance);
143
+ } catch {
144
+ // Skip unresolvable tokens
145
+ }
146
+ }
147
+ for (const controller of this.collectedControllers){
148
+ try {
149
+ const instance = this.container.resolve(controller);
150
+ if (!instances.includes(instance)) {
151
+ instances.push(instance);
152
+ }
153
+ } catch {
154
+ // Skip unresolvable controllers
155
+ }
156
+ }
157
+ return instances;
158
+ }
159
+ }
@@ -0,0 +1,19 @@
1
+ import type { InjectionToken, ProviderOptions, Type } from '../container/types';
2
+ export interface DynamicModule {
3
+ module: Type;
4
+ providers?: Array<Type | ProviderOptions>;
5
+ controllers?: Type[];
6
+ exports?: Array<Type | InjectionToken>;
7
+ }
8
+ export interface ModuleOptions {
9
+ providers?: Array<Type | ProviderOptions>;
10
+ controllers?: Type[];
11
+ imports?: Array<Type | DynamicModule>;
12
+ exports?: Array<Type | InjectionToken>;
13
+ }
14
+ export interface ModuleMetadata {
15
+ providers: Array<Type | ProviderOptions>;
16
+ controllers: Type[];
17
+ imports: Array<Type | DynamicModule>;
18
+ exports: Array<Type | InjectionToken>;
19
+ }
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,18 @@
1
+ import type { Container } from '../container/container';
2
+ import type { ComponentType, ComponentTypeMap, Constructor, FilterType, GuardType, InterceptorType, MiddlewareType, PipeType } from '../registry/types';
3
+ import type { ArgumentMetadata, CanActivate, ExceptionFilter, ExecutionContext, NestInterceptor, NestMiddleware, PipeTransform } from './types';
4
+ export declare class ComponentManager {
5
+ private static container;
6
+ static init(container: Container): void;
7
+ static registerGlobal<T extends ComponentType>(type: T, ...components: ComponentTypeMap[T][]): void;
8
+ static registerController<T extends ComponentType>(type: T, controller: Constructor, ...components: ComponentTypeMap[T][]): void;
9
+ static registerHandler<T extends ComponentType>(type: T, controller: Constructor, handlerName: string | symbol, ...components: ComponentTypeMap[T][]): void;
10
+ static getComponents<T extends ComponentType>(type: T, controller: Constructor, handlerName: string | symbol): ComponentTypeMap[T][];
11
+ static resolveMiddleware(items: MiddlewareType[]): NestMiddleware[];
12
+ static resolveGuards(items: GuardType[]): CanActivate[];
13
+ static resolvePipes(items: PipeType[]): PipeTransform[];
14
+ static resolveInterceptors(items: InterceptorType[]): NestInterceptor[];
15
+ static resolveFilters(items: FilterType[]): ExceptionFilter[];
16
+ static executePipes(value: unknown, metadata: ArgumentMetadata, pipes: PipeTransform[]): Promise<unknown>;
17
+ static runInterceptorChain(interceptors: NestInterceptor[], context: ExecutionContext, coreHandler: () => Promise<unknown>): Promise<unknown>;
18
+ }
@@ -0,0 +1,105 @@
1
+ import { MetadataRegistry } from "../registry/metadata.registry.js";
2
+ function isObject(value) {
3
+ return typeof value === 'object' && value !== null;
4
+ }
5
+ export class ComponentManager {
6
+ static container;
7
+ static init(container) {
8
+ this.container = container;
9
+ }
10
+ // 3-level registration
11
+ static registerGlobal(type, ...components) {
12
+ for (const component of components){
13
+ MetadataRegistry.registerGlobal(type, component);
14
+ }
15
+ }
16
+ static registerController(type, controller, ...components) {
17
+ for (const component of components){
18
+ MetadataRegistry.registerController(type, controller, component);
19
+ }
20
+ }
21
+ static registerHandler(type, controller, handlerName, ...components) {
22
+ const handlerKey = `${controller.name}:${String(handlerName)}`;
23
+ for (const component of components){
24
+ MetadataRegistry.registerHandler(type, handlerKey, component);
25
+ }
26
+ }
27
+ // 3-level resolution: global → controller → handler
28
+ static getComponents(type, controller, handlerName) {
29
+ const handlerKey = `${controller.name}:${String(handlerName)}`;
30
+ const globalComponents = Array.from(MetadataRegistry.getGlobal(type));
31
+ const controllerComponents = MetadataRegistry.getController(type, controller);
32
+ const handlerComponents = MetadataRegistry.getHandler(type, handlerKey);
33
+ return [
34
+ ...globalComponents,
35
+ ...controllerComponents,
36
+ ...handlerComponents
37
+ ];
38
+ }
39
+ // Type-specific resolvers
40
+ static resolveMiddleware(items) {
41
+ return items.map((item)=>{
42
+ if (isObject(item) && 'use' in item) {
43
+ return item;
44
+ }
45
+ return this.container.resolve(item);
46
+ });
47
+ }
48
+ static resolveGuards(items) {
49
+ return items.map((item)=>{
50
+ if (isObject(item) && 'canActivate' in item) {
51
+ return item;
52
+ }
53
+ return this.container.resolve(item);
54
+ });
55
+ }
56
+ static resolvePipes(items) {
57
+ return items.map((item)=>{
58
+ if (isObject(item) && 'transform' in item) {
59
+ return item;
60
+ }
61
+ return this.container.resolve(item);
62
+ });
63
+ }
64
+ static resolveInterceptors(items) {
65
+ return items.map((item)=>{
66
+ if (isObject(item) && 'intercept' in item) {
67
+ return item;
68
+ }
69
+ return this.container.resolve(item);
70
+ });
71
+ }
72
+ static resolveFilters(items) {
73
+ return items.map((item)=>{
74
+ if (isObject(item) && 'catch' in item) {
75
+ return item;
76
+ }
77
+ return this.container.resolve(item);
78
+ });
79
+ }
80
+ // Pipe execution
81
+ static async executePipes(value, metadata, pipes) {
82
+ let transformed = value;
83
+ for (const pipe of pipes){
84
+ transformed = await pipe.transform(transformed, metadata);
85
+ }
86
+ return transformed;
87
+ }
88
+ // Interceptor chain (onion pattern)
89
+ static async runInterceptorChain(interceptors, context, coreHandler) {
90
+ if (interceptors.length === 0) {
91
+ return coreHandler();
92
+ }
93
+ let next = {
94
+ handle: coreHandler
95
+ };
96
+ for(let i = interceptors.length - 1; i >= 0; i--){
97
+ const interceptor = interceptors[i];
98
+ const currentNext = next;
99
+ next = {
100
+ handle: ()=>interceptor.intercept(context, currentNext)
101
+ };
102
+ }
103
+ return next.handle();
104
+ }
105
+ }
@@ -0,0 +1,10 @@
1
+ import type { Type } from '../container/types';
2
+ import type { ComponentTypeMap } from '../registry/types';
3
+ export declare function UseMiddleware(...middleware: ComponentTypeMap['middleware'][]): (target: Function | object, propertyKey?: string | symbol) => void;
4
+ export declare function UseGuards(...guards: ComponentTypeMap['guard'][]): (target: Function | object, propertyKey?: string | symbol) => void;
5
+ export declare function UsePipes(...pipes: ComponentTypeMap['pipe'][]): (target: Function | object, propertyKey?: string | symbol) => void;
6
+ export declare function UseInterceptors(...interceptors: ComponentTypeMap['interceptor'][]): (target: Function | object, propertyKey?: string | symbol) => void;
7
+ export declare function UseFilters(...filters: ComponentTypeMap['filter'][]): (target: Function | object, propertyKey?: string | symbol) => void;
8
+ export declare function Catch(...exceptions: Type<Error>[]): ClassDecorator;
9
+ export declare function getCatchTypes(filter: unknown): Type<Error>[];
10
+ export declare function shouldFilterCatch(filter: unknown, exception: unknown): boolean;
@@ -0,0 +1,50 @@
1
+ import { METADATA_KEYS } from "../constants.js";
2
+ import { getMetadata } from "../metadata.js";
3
+ import { ComponentManager } from "./component.manager.js";
4
+ import { MetadataRegistry } from "../registry/metadata.registry.js";
5
+ function UseComponent(type, ...components) {
6
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
7
+ return (target, propertyKey)=>{
8
+ if (propertyKey !== undefined) {
9
+ // Method decorator — target is prototype, target.constructor is the class
10
+ ComponentManager.registerHandler(type, target.constructor, propertyKey, ...components);
11
+ } else {
12
+ // Class decorator — target is the class itself
13
+ ComponentManager.registerController(type, target, ...components);
14
+ }
15
+ };
16
+ }
17
+ export function UseMiddleware(...middleware) {
18
+ return UseComponent('middleware', ...middleware);
19
+ }
20
+ export function UseGuards(...guards) {
21
+ return UseComponent('guard', ...guards);
22
+ }
23
+ export function UsePipes(...pipes) {
24
+ return UseComponent('pipe', ...pipes);
25
+ }
26
+ export function UseInterceptors(...interceptors) {
27
+ return UseComponent('interceptor', ...interceptors);
28
+ }
29
+ export function UseFilters(...filters) {
30
+ return UseComponent('filter', ...filters);
31
+ }
32
+ export function Catch(...exceptions) {
33
+ return (target)=>{
34
+ MetadataRegistry.setCatchTypes(target, exceptions);
35
+ };
36
+ }
37
+ export function getCatchTypes(filter) {
38
+ const filterClass = typeof filter === 'function' ? filter : filter.constructor;
39
+ if (MetadataRegistry.hasCatchTypes(filterClass)) {
40
+ return MetadataRegistry.getCatchTypes(filterClass) ?? [];
41
+ }
42
+ return getMetadata(METADATA_KEYS.CATCH, filterClass) ?? [];
43
+ }
44
+ export function shouldFilterCatch(filter, exception) {
45
+ const catchTypes = getCatchTypes(filter);
46
+ if (catchTypes.length === 0) {
47
+ return true;
48
+ }
49
+ return catchTypes.some((type)=>exception instanceof type);
50
+ }
@@ -0,0 +1,7 @@
1
+ export { ComponentManager } from './component.manager';
2
+ export { UseMiddleware, UseGuards, UsePipes, UseInterceptors, UseFilters, Catch, getCatchTypes, shouldFilterCatch, } from './decorators';
3
+ export { SetMetadata, Reflector } from './reflector';
4
+ export type { ReflectableDecorator, CreateDecoratorOptions } from './reflector';
5
+ export { APP_GUARD, APP_PIPE, APP_INTERCEPTOR, APP_FILTER, APP_MIDDLEWARE } from './tokens';
6
+ export { ParseIntPipe, ParseFloatPipe, ParseBoolPipe, DefaultValuePipe, RequiredPipe, ZodValidationPipe, } from './pipes';
7
+ export type { ExecutionContext, CanActivate, CallHandler, NestInterceptor, NestMiddleware, PipeTransform, ExceptionFilter, ArgumentMetadata, } from './types';
@@ -0,0 +1,5 @@
1
+ export { ComponentManager } from "./component.manager.js";
2
+ export { UseMiddleware, UseGuards, UsePipes, UseInterceptors, UseFilters, Catch, getCatchTypes, shouldFilterCatch } from "./decorators.js";
3
+ export { SetMetadata, Reflector } from "./reflector.js";
4
+ export { APP_GUARD, APP_PIPE, APP_INTERCEPTOR, APP_FILTER, APP_MIDDLEWARE } from "./tokens.js";
5
+ export { ParseIntPipe, ParseFloatPipe, ParseBoolPipe, DefaultValuePipe, RequiredPipe, ZodValidationPipe } from "./pipes.js";
@@ -0,0 +1,25 @@
1
+ import type { ArgumentMetadata, PipeTransform } from './types';
2
+ export declare class ParseIntPipe implements PipeTransform<string, number> {
3
+ transform(value: string, metadata: ArgumentMetadata): number;
4
+ }
5
+ export declare class ParseFloatPipe implements PipeTransform<string, number> {
6
+ transform(value: string, metadata: ArgumentMetadata): number;
7
+ }
8
+ export declare class ParseBoolPipe implements PipeTransform<string, boolean> {
9
+ transform(value: string, metadata: ArgumentMetadata): boolean;
10
+ }
11
+ export declare class DefaultValuePipe<T = unknown> implements PipeTransform<T | undefined, T> {
12
+ private readonly defaultValue;
13
+ constructor(defaultValue: T);
14
+ transform(value: T | undefined, _metadata: ArgumentMetadata): T;
15
+ }
16
+ export declare class RequiredPipe implements PipeTransform {
17
+ transform(value: unknown, metadata: ArgumentMetadata): unknown;
18
+ }
19
+ export declare class ZodValidationPipe implements PipeTransform {
20
+ private readonly schema;
21
+ constructor(schema: {
22
+ parse(data: unknown): unknown;
23
+ });
24
+ transform(value: unknown, _metadata: ArgumentMetadata): unknown;
25
+ }
@@ -0,0 +1,52 @@
1
+ import { BadRequestException } from "../errors/http-exception.js";
2
+ export class ParseIntPipe {
3
+ transform(value, metadata) {
4
+ const parsed = parseInt(value, 10);
5
+ if (isNaN(parsed)) {
6
+ throw new BadRequestException(`Validation failed (numeric string expected)${metadata.data ? ` for parameter '${metadata.data}'` : ''}`);
7
+ }
8
+ return parsed;
9
+ }
10
+ }
11
+ export class ParseFloatPipe {
12
+ transform(value, metadata) {
13
+ const parsed = parseFloat(value);
14
+ if (isNaN(parsed)) {
15
+ throw new BadRequestException(`Validation failed (float string expected)${metadata.data ? ` for parameter '${metadata.data}'` : ''}`);
16
+ }
17
+ return parsed;
18
+ }
19
+ }
20
+ export class ParseBoolPipe {
21
+ transform(value, metadata) {
22
+ if (value === 'true') return true;
23
+ if (value === 'false') return false;
24
+ throw new BadRequestException(`Validation failed (boolean string expected)${metadata.data ? ` for parameter '${metadata.data}'` : ''}`);
25
+ }
26
+ }
27
+ export class DefaultValuePipe {
28
+ defaultValue;
29
+ constructor(defaultValue){
30
+ this.defaultValue = defaultValue;
31
+ }
32
+ transform(value, _metadata) {
33
+ return value !== undefined && value !== null ? value : this.defaultValue;
34
+ }
35
+ }
36
+ export class RequiredPipe {
37
+ transform(value, metadata) {
38
+ if (value === undefined || value === null || value === '') {
39
+ throw new BadRequestException(`Validation failed (value required)${metadata.data ? ` for parameter '${metadata.data}'` : ''}`);
40
+ }
41
+ return value;
42
+ }
43
+ }
44
+ export class ZodValidationPipe {
45
+ schema;
46
+ constructor(schema){
47
+ this.schema = schema;
48
+ }
49
+ transform(value, _metadata) {
50
+ return this.schema.parse(value);
51
+ }
52
+ }
@@ -0,0 +1,102 @@
1
+ export interface CreateDecoratorOptions {
2
+ key?: string;
3
+ }
4
+ export interface ReflectableDecorator<TParam> {
5
+ (value: TParam): ClassDecorator & MethodDecorator;
6
+ KEY: string;
7
+ }
8
+ /**
9
+ * Decorator that attaches custom metadata to a class or method.
10
+ * Read via Reflector in guards/interceptors.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const Roles = (...roles: string[]) => SetMetadata('roles', roles);
15
+ *
16
+ * @Controller('/admin')
17
+ * @Roles('admin')
18
+ * class AdminController { ... }
19
+ * ```
20
+ */
21
+ export declare function SetMetadata<V = unknown>(key: string, value: V): (target: Function | object, propertyKey?: string | symbol) => void;
22
+ /**
23
+ * Reads custom metadata set by @SetMetadata().
24
+ * Use in guards/interceptors via ExecutionContext.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * class RolesGuard implements CanActivate {
29
+ * private reflector = new Reflector();
30
+ *
31
+ * canActivate(context: ExecutionContext): boolean {
32
+ * const roles = this.reflector.get<string[]>('roles', context);
33
+ * if (!roles) return true;
34
+ * const user = ...; // extract from request
35
+ * return roles.some(r => user.roles.includes(r));
36
+ * }
37
+ * }
38
+ * ```
39
+ */
40
+ export declare class Reflector {
41
+ /**
42
+ * Create a type-safe decorator that sets metadata with a typed key.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * const Roles = Reflector.createDecorator<string[]>();
47
+ * // Roles(['admin']) — class or method decorator
48
+ * // reflector.get(Roles, context) — typed as string[] | undefined
49
+ * ```
50
+ */
51
+ static createDecorator<TParam = unknown>(options?: CreateDecoratorOptions): ReflectableDecorator<TParam>;
52
+ private resolveKey;
53
+ /**
54
+ * Get metadata value from handler first, then class.
55
+ * Handler-level metadata takes priority over class-level.
56
+ */
57
+ get<T = unknown>(key: string | ReflectableDecorator<T>, context: {
58
+ getClass(): Function;
59
+ getHandler(): string | symbol;
60
+ }): T | undefined;
61
+ /**
62
+ * Get metadata only from the handler (method) level.
63
+ */
64
+ getHandler<T = unknown>(key: string | ReflectableDecorator<T>, context: {
65
+ getClass(): Function;
66
+ getHandler(): string | symbol;
67
+ }): T | undefined;
68
+ /**
69
+ * Get metadata only from the class level.
70
+ */
71
+ getClass<T = unknown>(key: string | ReflectableDecorator<T>, context: {
72
+ getClass(): Function;
73
+ }): T | undefined;
74
+ /**
75
+ * Get all metadata values for a key from both handler and class.
76
+ * Returns [handlerValue, classValue] (either may be undefined).
77
+ */
78
+ getAll<T = unknown>(key: string | ReflectableDecorator<T>, context: {
79
+ getClass(): Function;
80
+ getHandler(): string | symbol;
81
+ }): [T | undefined, T | undefined];
82
+ /**
83
+ * Returns handler value if defined, else class value, else undefined.
84
+ * First defined value wins.
85
+ */
86
+ getAllAndOverride<T = unknown>(key: string | ReflectableDecorator<T>, context: {
87
+ getClass(): Function;
88
+ getHandler(): string | symbol;
89
+ }): T | undefined;
90
+ /**
91
+ * Collects handler + class values, filters undefineds.
92
+ * - 0 values → []
93
+ * - 1 value → return it
94
+ * - Arrays → concatenate
95
+ * - Objects → Object.assign({}, ...values)
96
+ * - Otherwise → wrap in array
97
+ */
98
+ getAllAndMerge<T = unknown>(key: string | ReflectableDecorator<T>, context: {
99
+ getClass(): Function;
100
+ getHandler(): string | symbol;
101
+ }): T | T[];
102
+ }