@riktajs/core 0.6.0 → 0.7.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.
@@ -0,0 +1,8 @@
1
+ import 'reflect-metadata';
2
+ type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
3
+ type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
4
+ type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
5
+ type AnyDecorator = ClassDecorator | MethodDecorator | PropertyDecorator;
6
+ export declare function applyDecorators(...decorators: AnyDecorator[]): MethodDecorator & ClassDecorator & PropertyDecorator;
7
+ export declare function SetMetadata<T = unknown>(key: string | symbol, value: T): MethodDecorator & ClassDecorator;
8
+ export {};
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyDecorators = applyDecorators;
4
+ exports.SetMetadata = SetMetadata;
5
+ require("reflect-metadata");
6
+ function applyDecorators(...decorators) {
7
+ return ((target, propertyKey, descriptor) => {
8
+ for (const decorator of decorators.reverse()) {
9
+ if (descriptor) {
10
+ const result = decorator(target, propertyKey, descriptor);
11
+ if (result) {
12
+ descriptor = result;
13
+ }
14
+ }
15
+ else if (propertyKey !== undefined) {
16
+ decorator(target, propertyKey);
17
+ }
18
+ else {
19
+ const result = decorator(target);
20
+ if (result) {
21
+ return result;
22
+ }
23
+ }
24
+ }
25
+ if (descriptor) {
26
+ return descriptor;
27
+ }
28
+ });
29
+ }
30
+ function SetMetadata(key, value) {
31
+ const decoratorFactory = (target, propertyKey, descriptor) => {
32
+ if (descriptor) {
33
+ Reflect.defineMetadata(key, value, target.constructor, propertyKey);
34
+ }
35
+ else {
36
+ Reflect.defineMetadata(key, value, target);
37
+ }
38
+ };
39
+ return decoratorFactory;
40
+ }
@@ -0,0 +1,11 @@
1
+ import 'reflect-metadata';
2
+ import { ExecutionContext } from '../guards/execution-context';
3
+ export declare const CUSTOM_PARAM_METADATA: unique symbol;
4
+ export interface CustomParamMetadata<T = unknown> {
5
+ index: number;
6
+ factory: CustomParamFactory<T, unknown>;
7
+ data?: T;
8
+ }
9
+ export type CustomParamFactory<TData = unknown, TResult = unknown> = (data: TData, ctx: ExecutionContext) => TResult | Promise<TResult>;
10
+ export declare function createParamDecorator<TData = unknown, TResult = unknown>(factory: CustomParamFactory<TData, TResult>): (data?: TData) => ParameterDecorator;
11
+ export declare function getCustomParamMetadata<T = unknown>(target: Function, propertyKey: string | symbol): CustomParamMetadata<T>[];
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CUSTOM_PARAM_METADATA = void 0;
4
+ exports.createParamDecorator = createParamDecorator;
5
+ exports.getCustomParamMetadata = getCustomParamMetadata;
6
+ require("reflect-metadata");
7
+ exports.CUSTOM_PARAM_METADATA = Symbol.for('rikta:custom:param:metadata');
8
+ function createParamDecorator(factory) {
9
+ return (data) => {
10
+ return (target, propertyKey, parameterIndex) => {
11
+ if (propertyKey === undefined)
12
+ return;
13
+ const existingParams = Reflect.getMetadata(exports.CUSTOM_PARAM_METADATA, target.constructor, propertyKey) ?? [];
14
+ const metadata = {
15
+ index: parameterIndex,
16
+ factory: factory,
17
+ data,
18
+ };
19
+ existingParams.push(metadata);
20
+ Reflect.defineMetadata(exports.CUSTOM_PARAM_METADATA, existingParams, target.constructor, propertyKey);
21
+ };
22
+ };
23
+ }
24
+ function getCustomParamMetadata(target, propertyKey) {
25
+ return Reflect.getMetadata(exports.CUSTOM_PARAM_METADATA, target, propertyKey) ?? [];
26
+ }
@@ -5,3 +5,5 @@ export * from './param.decorator';
5
5
  export * from './autowired.decorator';
6
6
  export * from './provider.decorator';
7
7
  export * from './config-property.decorator';
8
+ export * from './create-param-decorator';
9
+ export * from './apply-decorators';
@@ -21,3 +21,5 @@ __exportStar(require("./param.decorator"), exports);
21
21
  __exportStar(require("./autowired.decorator"), exports);
22
22
  __exportStar(require("./provider.decorator"), exports);
23
23
  __exportStar(require("./config-property.decorator"), exports);
24
+ __exportStar(require("./create-param-decorator"), exports);
25
+ __exportStar(require("./apply-decorators"), exports);
@@ -13,7 +13,7 @@ export declare class Router {
13
13
  private registerRoute;
14
14
  private compileParamResolvers;
15
15
  private createParamExtractor;
16
- private resolveParamsOptimized;
16
+ private resolveAllParams;
17
17
  private resolveGuardInstances;
18
18
  private executeGuardsOptimized;
19
19
  private resolveMiddlewareInstances;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Router = void 0;
4
4
  require("reflect-metadata");
5
5
  const constants_1 = require("../constants");
6
+ const create_param_decorator_1 = require("../decorators/create-param-decorator");
6
7
  const validation_exception_1 = require("../exceptions/validation.exception");
7
8
  const exceptions_1 = require("../exceptions/exceptions");
8
9
  const execution_context_1 = require("../guards/execution-context");
@@ -38,28 +39,41 @@ class Router {
38
39
  throw new Error(`Handler ${String(route.handlerName)} not found on ${controllerClass.name}`);
39
40
  }
40
41
  const paramsMeta = Reflect.getMetadata(constants_1.PARAM_METADATA, controllerClass, route.handlerName) ?? [];
42
+ const customParamsMeta = (0, create_param_decorator_1.getCustomParamMetadata)(controllerClass, route.handlerName);
41
43
  const statusCode = Reflect.getMetadata(constants_1.HTTP_CODE_METADATA, controllerClass, route.handlerName);
42
44
  const guards = (0, use_guards_decorator_1.getGuardsMetadata)(controllerClass, route.handlerName);
43
45
  const middleware = (0, use_middleware_decorator_1.getMiddlewareMetadata)(controllerClass, route.handlerName);
44
46
  const compiledResolvers = this.compileParamResolvers(paramsMeta);
45
- const hasParams = compiledResolvers.length > 0;
46
- const maxParamIndex = hasParams ? Math.max(...compiledResolvers.map(r => r.index)) : -1;
47
+ const hasBuiltinParams = compiledResolvers.length > 0;
48
+ const hasCustomParams = customParamsMeta.length > 0;
49
+ const hasParams = hasBuiltinParams || hasCustomParams;
50
+ const allParamIndexes = [
51
+ ...compiledResolvers.map(r => r.index),
52
+ ...customParamsMeta.map(r => r.index)
53
+ ];
54
+ const maxParamIndex = hasParams ? Math.max(...allParamIndexes) : -1;
47
55
  const guardInstances = this.resolveGuardInstances(guards);
48
56
  const hasGuards = guardInstances.length > 0;
49
57
  const middlewareInstances = this.resolveMiddlewareInstances(middleware);
50
58
  const hasMiddleware = middlewareInstances.length > 0;
51
- const createContext = hasGuards
59
+ const needsContext = hasGuards || hasCustomParams;
60
+ const createContext = needsContext
52
61
  ? (req, rep) => new execution_context_1.ExecutionContextImpl(req, rep, controllerClass, route.handlerName)
53
62
  : null;
54
63
  const routeHandler = async (request, reply) => {
55
- if (createContext) {
56
- await this.executeGuardsOptimized(guardInstances, createContext(request, reply));
64
+ const executionContext = createContext ? createContext(request, reply) : null;
65
+ if (hasGuards && executionContext) {
66
+ await this.executeGuardsOptimized(guardInstances, executionContext);
57
67
  }
58
68
  if (hasMiddleware) {
59
69
  await this.executeMiddlewareChain(middlewareInstances, request, reply);
60
70
  }
61
- const result = hasParams
62
- ? await handler.apply(controllerInstance, this.resolveParamsOptimized(compiledResolvers, maxParamIndex, request, reply))
71
+ let args;
72
+ if (hasParams) {
73
+ args = await this.resolveAllParams(compiledResolvers, customParamsMeta, maxParamIndex, request, reply, executionContext);
74
+ }
75
+ const result = args
76
+ ? await handler.apply(controllerInstance, args)
63
77
  : await handler.call(controllerInstance);
64
78
  if (statusCode)
65
79
  reply.status(statusCode);
@@ -113,8 +127,8 @@ class Router {
113
127
  return () => undefined;
114
128
  }
115
129
  }
116
- resolveParamsOptimized(resolvers, maxIndex, request, reply) {
117
- const context = {
130
+ async resolveAllParams(compiledResolvers, customParams, maxIndex, request, reply, executionContext) {
131
+ const routeContext = {
118
132
  request,
119
133
  reply,
120
134
  params: request.params,
@@ -122,9 +136,9 @@ class Router {
122
136
  body: request.body,
123
137
  };
124
138
  const args = new Array(maxIndex + 1);
125
- for (let i = 0; i < resolvers.length; i++) {
126
- const resolver = resolvers[i];
127
- let value = resolver.extract(context);
139
+ for (let i = 0; i < compiledResolvers.length; i++) {
140
+ const resolver = compiledResolvers[i];
141
+ let value = resolver.extract(routeContext);
128
142
  if (resolver.zodSchema) {
129
143
  const result = resolver.zodSchema.safeParse(value);
130
144
  if (!result.success) {
@@ -134,6 +148,13 @@ class Router {
134
148
  }
135
149
  args[resolver.index] = value;
136
150
  }
151
+ if (customParams.length > 0) {
152
+ const ctx = executionContext ?? new execution_context_1.ExecutionContextImpl(request, reply, {}, '');
153
+ for (const customParam of customParams) {
154
+ const value = await customParam.factory(customParam.data, ctx);
155
+ args[customParam.index] = value;
156
+ }
157
+ }
137
158
  return args;
138
159
  }
139
160
  resolveGuardInstances(guards) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riktajs/core",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "A fast and modern TypeScript backend framework with zero-config autowiring, powered by Fastify",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",