@carno.js/core 0.2.7 → 0.2.9

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 (49) hide show
  1. package/dist/Carno.d.ts +9 -7
  2. package/dist/Carno.js +14 -1
  3. package/dist/commons/decorators/index.d.ts +1 -0
  4. package/dist/commons/decorators/index.js +1 -0
  5. package/dist/commons/decorators/validation.decorator.d.ts +32 -0
  6. package/dist/commons/decorators/validation.decorator.js +40 -0
  7. package/dist/constants.d.ts +1 -0
  8. package/dist/constants.js +2 -1
  9. package/dist/container/InjectorService.d.ts +3 -1
  10. package/dist/container/InjectorService.js +4 -3
  11. package/dist/container/MethodInvoker.d.ts +3 -2
  12. package/dist/container/MethodInvoker.js +4 -17
  13. package/dist/exceptions/HttpException.js +5 -5
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.js +1 -0
  16. package/dist/route/ParamResolverFactory.d.ts +0 -5
  17. package/dist/route/ParamResolverFactory.js +0 -40
  18. package/dist/route/RouteCompiler.d.ts +3 -3
  19. package/dist/route/RouteCompiler.js +2 -11
  20. package/dist/route/memoirist.js +4 -0
  21. package/dist/utils/ValidationCache.d.ts +2 -0
  22. package/dist/utils/ValidationCache.js +10 -2
  23. package/dist/utils/formatValidationErrors.d.ts +5 -0
  24. package/dist/utils/formatValidationErrors.js +80 -0
  25. package/dist/utils/index.d.ts +1 -1
  26. package/dist/utils/index.js +1 -1
  27. package/dist/validation/ValidatorAdapter.d.ts +66 -0
  28. package/dist/validation/ValidatorAdapter.js +20 -0
  29. package/dist/validation/adapters/ClassValidatorAdapter.d.ts +23 -0
  30. package/dist/validation/adapters/ClassValidatorAdapter.js +47 -0
  31. package/dist/validation/adapters/ZodAdapter.d.ts +14 -0
  32. package/dist/validation/adapters/ZodAdapter.js +56 -0
  33. package/dist/validation/adapters/index.d.ts +4 -0
  34. package/dist/validation/adapters/index.js +7 -0
  35. package/dist/validation/index.d.ts +3 -0
  36. package/dist/validation/index.js +20 -0
  37. package/package.json +17 -6
  38. package/dist/Cheetah.d.ts +0 -65
  39. package/dist/Cheetah.js +0 -307
  40. package/dist/default-routes-cheetah.d.ts +0 -3
  41. package/dist/default-routes-cheetah.js +0 -29
  42. package/dist/domain/CheetahClosure.d.ts +0 -1
  43. package/dist/domain/CheetahClosure.js +0 -2
  44. package/dist/domain/CheetahMiddleware.d.ts +0 -5
  45. package/dist/domain/CheetahMiddleware.js +0 -2
  46. package/dist/services/request-logger.service.d.ts +0 -15
  47. package/dist/services/request-logger.service.js +0 -50
  48. package/dist/utils/isClassValidator.d.ts +0 -6
  49. package/dist/utils/isClassValidator.js +0 -13
package/dist/Carno.d.ts CHANGED
@@ -1,27 +1,29 @@
1
1
  import { Server } from "bun";
2
- import { ValidatorOptions } from "class-validator";
3
2
  import * as pino from "pino";
3
+ import type { ValidationConfig, ValidatorAdapterConstructor } from "./validation/ValidatorAdapter";
4
4
  import { TokenRouteWithProvider } from "./container/ContainerConfiguration";
5
5
  import { CorsConfig } from "./domain/cors-config";
6
6
  import Memoirist from "./route/memoirist";
7
7
  import { type CompiledRoute } from "./route/CompiledRoute";
8
- export interface ApplicationConfig {
9
- validation?: ValidatorOptions;
8
+ export interface ApplicationConfig<TAdapter extends ValidatorAdapterConstructor = ValidatorAdapterConstructor> {
9
+ validation?: ValidationConfig<TAdapter>;
10
10
  logger?: pino.LoggerOptions;
11
11
  exports?: any[];
12
12
  providers?: any[];
13
13
  cors?: CorsConfig;
14
14
  globalMiddlewares?: any[];
15
15
  }
16
- export declare class Carno {
17
- config: ApplicationConfig;
16
+ export declare class Carno<TAdapter extends ValidatorAdapterConstructor = ValidatorAdapterConstructor> {
17
+ config: ApplicationConfig<TAdapter>;
18
18
  router: Memoirist<CompiledRoute | TokenRouteWithProvider>;
19
19
  private injector;
20
20
  private corsCache?;
21
21
  private readonly emptyLocals;
22
+ private validatorAdapter;
22
23
  private fetch;
23
24
  private server;
24
- constructor(config?: ApplicationConfig);
25
+ constructor(config?: ApplicationConfig<TAdapter>);
26
+ private resolveValidatorAdapter;
25
27
  /**
26
28
  * Use the Carno plugin.
27
29
  *
@@ -49,7 +51,7 @@ export declare class Carno {
49
51
  listen(port?: number): Promise<void>;
50
52
  private registerShutdownHandlers;
51
53
  getHttpServer(): Server<any>;
52
- getInjector(): import(".").InjectorService;
54
+ getInjector(): import("./container").InjectorService;
53
55
  private createHttpServer;
54
56
  private fetcher;
55
57
  private catcher;
package/dist/Carno.js CHANGED
@@ -5,6 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Carno = void 0;
7
7
  const node_process_1 = __importDefault(require("node:process"));
8
+ const ZodAdapter_1 = require("./validation/adapters/ZodAdapter");
9
+ const ValidationCache_1 = require("./utils/ValidationCache");
8
10
  const index_1 = require("./commons/index");
9
11
  const constants_1 = require("./constants");
10
12
  const createContainer_1 = require("./container/createContainer");
@@ -56,11 +58,21 @@ class Carno {
56
58
  console.error("Unhandled error:", error);
57
59
  return new Response("Internal Server Error", { status: 500 });
58
60
  };
61
+ this.validatorAdapter = this.resolveValidatorAdapter();
59
62
  if (config.cors) {
60
63
  this.corsCache = new cors_headers_cache_1.CorsHeadersCache(config.cors);
61
64
  }
62
65
  void this.bootstrapApplication();
63
66
  }
67
+ resolveValidatorAdapter() {
68
+ const config = this.config.validation;
69
+ if (!config?.adapter) {
70
+ return new ZodAdapter_1.ZodAdapter();
71
+ }
72
+ const AdapterClass = config.adapter;
73
+ const options = config.options || {};
74
+ return new AdapterClass(options);
75
+ }
64
76
  /**
65
77
  * Use the Carno plugin.
66
78
  *
@@ -148,8 +160,9 @@ class Carno {
148
160
  };
149
161
  }
150
162
  async init() {
163
+ (0, ValidationCache_1.setValidatorAdapter)(this.validatorAdapter);
151
164
  this.loadProvidersAndControllers();
152
- await this.injector.loadModule((0, createContainer_1.createContainer)(), this.config, this.router);
165
+ await this.injector.loadModule((0, createContainer_1.createContainer)(), this.config, this.router, this.validatorAdapter);
153
166
  }
154
167
  async listen(port = 3000) {
155
168
  this.registerShutdownHandlers();
@@ -3,3 +3,4 @@ export * from './http.decorators';
3
3
  export * from './service.decorator';
4
4
  export * from './middleware.decorator';
5
5
  export * from './Injectable.decorator';
6
+ export * from './validation.decorator';
@@ -19,3 +19,4 @@ __exportStar(require("./http.decorators"), exports);
19
19
  __exportStar(require("./service.decorator"), exports);
20
20
  __exportStar(require("./middleware.decorator"), exports);
21
21
  __exportStar(require("./Injectable.decorator"), exports);
22
+ __exportStar(require("./validation.decorator"), exports);
@@ -0,0 +1,32 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Decorator to attach a Zod schema to a DTO class
4
+ * The schema will be used for validation when the DTO is used in route handlers
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * const CreateUserSchema = z.object({
9
+ * name: z.string().min(3),
10
+ * email: z.string().email()
11
+ * });
12
+ *
13
+ * @ZodSchema(CreateUserSchema)
14
+ * class CreateUserDto {
15
+ * name: string;
16
+ * email: string;
17
+ * }
18
+ *
19
+ * @Controller('/users')
20
+ * class UserController {
21
+ * @Post()
22
+ * create(@Body() dto: CreateUserDto) {
23
+ * // dto is validated and typed
24
+ * return dto;
25
+ * }
26
+ * }
27
+ * ```
28
+ *
29
+ * @param schema - The Zod schema to use for validation
30
+ * @returns Class decorator
31
+ */
32
+ export declare function ZodSchema<T extends z.ZodType>(schema: T): ClassDecorator;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ZodSchema = ZodSchema;
4
+ const Metadata_1 = require("../../domain/Metadata");
5
+ const constants_1 = require("../../constants");
6
+ /**
7
+ * Decorator to attach a Zod schema to a DTO class
8
+ * The schema will be used for validation when the DTO is used in route handlers
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const CreateUserSchema = z.object({
13
+ * name: z.string().min(3),
14
+ * email: z.string().email()
15
+ * });
16
+ *
17
+ * @ZodSchema(CreateUserSchema)
18
+ * class CreateUserDto {
19
+ * name: string;
20
+ * email: string;
21
+ * }
22
+ *
23
+ * @Controller('/users')
24
+ * class UserController {
25
+ * @Post()
26
+ * create(@Body() dto: CreateUserDto) {
27
+ * // dto is validated and typed
28
+ * return dto;
29
+ * }
30
+ * }
31
+ * ```
32
+ *
33
+ * @param schema - The Zod schema to use for validation
34
+ * @returns Class decorator
35
+ */
36
+ function ZodSchema(schema) {
37
+ return (target) => {
38
+ Metadata_1.Metadata.set(constants_1.VALIDATION_ZOD_SCHEMA, schema, target);
39
+ };
40
+ }
@@ -5,3 +5,4 @@ export declare const CONTROLLER_EVENTS = "carno:controller:events";
5
5
  export declare const ROUTE_PARAM = "carno:route:param";
6
6
  export declare const ROUTE_MIDDLEWARES = "carno:route:middlewares";
7
7
  export declare const PROVIDER = "carno:provider";
8
+ export declare const VALIDATION_ZOD_SCHEMA = "carno:validation:zod";
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PROVIDER = exports.ROUTE_MIDDLEWARES = exports.ROUTE_PARAM = exports.CONTROLLER_EVENTS = exports.CONTROLLER_MIDDLEWARES = exports.CONTROLLER_ROUTES = exports.CONTROLLER = void 0;
3
+ exports.VALIDATION_ZOD_SCHEMA = exports.PROVIDER = exports.ROUTE_MIDDLEWARES = exports.ROUTE_PARAM = exports.CONTROLLER_EVENTS = exports.CONTROLLER_MIDDLEWARES = exports.CONTROLLER_ROUTES = exports.CONTROLLER = void 0;
4
4
  exports.CONTROLLER = "carno:controller";
5
5
  exports.CONTROLLER_ROUTES = "carno:controller:routes";
6
6
  exports.CONTROLLER_MIDDLEWARES = "carno:controller:middlewares";
@@ -8,3 +8,4 @@ exports.CONTROLLER_EVENTS = "carno:controller:events";
8
8
  exports.ROUTE_PARAM = "carno:route:param";
9
9
  exports.ROUTE_MIDDLEWARES = "carno:route:middlewares";
10
10
  exports.PROVIDER = "carno:provider";
11
+ exports.VALIDATION_ZOD_SCHEMA = "carno:validation:zod";
@@ -1,5 +1,6 @@
1
1
  import type { ApplicationConfig } from "../Carno";
2
2
  import { TokenProvider } from "../commons/registries/ProviderControl";
3
+ import type { ValidatorAdapter } from "../validation/ValidatorAdapter";
3
4
  import { Context } from "../domain/Context";
4
5
  import { LocalsContainer } from "../domain/LocalsContainer";
5
6
  import { Provider } from "../domain/provider";
@@ -20,7 +21,8 @@ export declare class InjectorService {
20
21
  private routeResolver;
21
22
  private dependencyResolver;
22
23
  private methodInvoker;
23
- loadModule(container: Container, applicationConfig: ApplicationConfig, router: Memoirist<any>): Promise<void>;
24
+ private validatorAdapter;
25
+ loadModule(container: Container, applicationConfig: ApplicationConfig, router: Memoirist<any>, validatorAdapter: ValidatorAdapter): Promise<void>;
24
26
  private initializeResolvers;
25
27
  private ensureProvider;
26
28
  get(token: TokenProvider): Provider | undefined;
@@ -40,10 +40,11 @@ let InjectorService = InjectorService_1 = class InjectorService {
40
40
  this._hasOnResponseHook = false;
41
41
  this.controllerScopes = new Map();
42
42
  }
43
- async loadModule(container, applicationConfig, router) {
43
+ async loadModule(container, applicationConfig, router, validatorAdapter) {
44
44
  this.container = container;
45
45
  this.router = router;
46
46
  this.applicationConfig = applicationConfig;
47
+ this.validatorAdapter = validatorAdapter;
47
48
  this.initializeResolvers();
48
49
  this.removeUnknownProviders();
49
50
  this.saveInjector();
@@ -57,7 +58,7 @@ let InjectorService = InjectorService_1 = class InjectorService {
57
58
  initializeResolvers() {
58
59
  this.routeResolver = new RouteResolver_1.RouteResolver(this.router, this.applicationConfig.globalMiddlewares);
59
60
  this.dependencyResolver = new DependencyResolver_1.DependencyResolver(this.container);
60
- this.methodInvoker = new MethodInvoker_1.MethodInvoker(this.applicationConfig);
61
+ this.methodInvoker = new MethodInvoker_1.MethodInvoker(this.applicationConfig, this.validatorAdapter);
61
62
  }
62
63
  ensureProvider(token) {
63
64
  if (!this.container.has(token) && ProviderControl_1.GlobalProvider.has(token)) {
@@ -175,7 +176,7 @@ let InjectorService = InjectorService_1 = class InjectorService {
175
176
  const compiler = new RouteCompiler_1.RouteCompiler({
176
177
  container: this.container,
177
178
  controllerScopes: this.controllerScopes,
178
- validationConfig: this.applicationConfig.validation,
179
+ validatorAdapter: this.validatorAdapter,
179
180
  hasOnRequestHook: this._hasOnRequestHook,
180
181
  hasOnResponseHook: this._hasOnResponseHook,
181
182
  });
@@ -2,10 +2,12 @@ import { ApplicationConfig } from "../Carno";
2
2
  import { TokenProvider } from "../commons/registries/ProviderControl";
3
3
  import { Context } from "../domain/Context";
4
4
  import { LocalsContainer } from "../domain/LocalsContainer";
5
+ import type { ValidatorAdapter } from "../validation/ValidatorAdapter";
5
6
  export declare class MethodInvoker {
6
7
  private applicationConfig;
8
+ private validatorAdapter;
7
9
  private historyMethods;
8
- constructor(applicationConfig: ApplicationConfig);
10
+ constructor(applicationConfig: ApplicationConfig, validatorAdapter: ValidatorAdapter);
9
11
  invoke(instance: any, methodName: string, locals: LocalsContainer, context: Context, invokeCallback: (token: TokenProvider, locals: LocalsContainer) => any): Promise<any>;
10
12
  private getMethodInfo;
11
13
  private getCachedMethod;
@@ -16,5 +18,4 @@ export declare class MethodInvoker {
16
18
  private hasBodyParam;
17
19
  private isBodyParam;
18
20
  private resolveService;
19
- private validateAndTransform;
20
21
  }
@@ -1,16 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MethodInvoker = void 0;
4
- const class_transformer_1 = require("class-transformer");
5
- const class_validator_1 = require("class-validator");
6
4
  const Metadata_1 = require("../domain/Metadata");
7
- const HttpException_1 = require("../exceptions/HttpException");
8
5
  const getClassOrSymbol_1 = require("../utils/getClassOrSymbol");
9
6
  const getMethodArgTypes_1 = require("../utils/getMethodArgTypes");
10
- const isClassValidator_1 = require("../utils/isClassValidator");
11
7
  class MethodInvoker {
12
- constructor(applicationConfig) {
8
+ constructor(applicationConfig, validatorAdapter) {
13
9
  this.applicationConfig = applicationConfig;
10
+ this.validatorAdapter = validatorAdapter;
14
11
  this.historyMethods = new WeakMap();
15
12
  }
16
13
  async invoke(instance, methodName, locals, context, invokeCallback) {
@@ -78,19 +75,9 @@ class MethodInvoker {
78
75
  return invokeCallback((0, getClassOrSymbol_1.getClassOrSymbol)(token), locals);
79
76
  }
80
77
  const value = param.fun(context, param.param);
81
- return (0, isClassValidator_1.isClassValidator)(token)
82
- ? this.validateAndTransform(token, value)
78
+ return this.validatorAdapter.hasValidation(token)
79
+ ? this.validatorAdapter.validateAndTransform(token, value)
83
80
  : value;
84
81
  }
85
- validateAndTransform(token, value) {
86
- const obj = (0, class_transformer_1.plainToInstance)(token, value);
87
- const errors = (0, class_validator_1.validateSync)(obj, this.applicationConfig.validation);
88
- // todo: deve retornar apenas os erros e no o objeto class-validator intei
89
- // ro.
90
- if (errors.length > 0) {
91
- throw new HttpException_1.HttpException(errors, 400);
92
- }
93
- return obj;
94
- }
95
82
  }
96
83
  exports.MethodInvoker = MethodInvoker;
@@ -9,12 +9,12 @@ class HttpException {
9
9
  this.initMessage();
10
10
  }
11
11
  initMessage() {
12
- if ((0, utils_1.isObject)(this.response)) {
13
- this.message = this.response;
14
- }
15
- else {
16
- this.message = this.response;
12
+ const formatted = (0, utils_1.formatValidationErrors)(this.response);
13
+ if ((0, utils_1.isObject)(formatted)) {
14
+ this.message = formatted;
15
+ return;
17
16
  }
17
+ this.message = formatted;
18
18
  }
19
19
  getResponse() {
20
20
  return this.message;
package/dist/index.d.ts CHANGED
@@ -13,3 +13,4 @@ export * from "./services/logger.service";
13
13
  export * from "./cache/cache.service";
14
14
  export * from "./cache/bento-cache.driver";
15
15
  export * from "./testing";
16
+ export * from "./validation";
package/dist/index.js CHANGED
@@ -29,3 +29,4 @@ __exportStar(require("./services/logger.service"), exports);
29
29
  __exportStar(require("./cache/cache.service"), exports);
30
30
  __exportStar(require("./cache/bento-cache.driver"), exports);
31
31
  __exportStar(require("./testing"), exports);
32
+ __exportStar(require("./validation"), exports);
@@ -1,6 +1,4 @@
1
- import { type ValidatorOptions } from 'class-validator';
2
1
  import type { Context } from '../domain/Context';
3
- import type { ParamResolver, AsyncParamResolver } from './CompiledRoute';
4
2
  export type ParamDecoratorType = 'body' | 'query' | 'param' | 'headers' | 'req' | 'locals';
5
3
  export interface ParamDecoratorMeta {
6
4
  fun: (context: Context, data?: any) => any;
@@ -14,6 +12,3 @@ export interface ParamInfo {
14
12
  token?: any;
15
13
  }
16
14
  export declare function analyzeParamDecorator(decoratorMeta: ParamDecoratorMeta | undefined, token: any): ParamInfo;
17
- export declare function createParamResolver(decoratorMeta: ParamDecoratorMeta | undefined, token: any, validationConfig?: ValidatorOptions): ParamResolver | AsyncParamResolver | null;
18
- export declare function createParamResolvers(paramMetas: Record<number, ParamDecoratorMeta> | undefined, argTypes: any[], validationConfig?: ValidatorOptions): (ParamResolver | AsyncParamResolver | null)[];
19
- export declare function hasAnyDIParam(resolvers: (ParamResolver | AsyncParamResolver | null)[]): boolean;
@@ -1,12 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.analyzeParamDecorator = analyzeParamDecorator;
4
- exports.createParamResolver = createParamResolver;
5
- exports.createParamResolvers = createParamResolvers;
6
- exports.hasAnyDIParam = hasAnyDIParam;
7
- const class_transformer_1 = require("class-transformer");
8
- const class_validator_1 = require("class-validator");
9
- const HttpException_1 = require("../exceptions/HttpException");
10
4
  const ValidationCache_1 = require("../utils/ValidationCache");
11
5
  function analyzeParamDecorator(decoratorMeta, token) {
12
6
  if (!decoratorMeta) {
@@ -53,37 +47,3 @@ function inferTypeFromSource(resolver) {
53
47
  }
54
48
  return null;
55
49
  }
56
- function createValidationResolver(extractFn, token, validationConfig) {
57
- return (context) => {
58
- const value = extractFn(context);
59
- const obj = (0, class_transformer_1.plainToInstance)(token, value);
60
- const errors = (0, class_validator_1.validateSync)(obj, validationConfig);
61
- if (errors.length > 0) {
62
- throw new HttpException_1.HttpException(errors, 400);
63
- }
64
- return obj;
65
- };
66
- }
67
- function createParamResolver(decoratorMeta, token, validationConfig) {
68
- if (!decoratorMeta) {
69
- return null;
70
- }
71
- const extractFn = (context) => decoratorMeta.fun(context, decoratorMeta.param);
72
- const needsValidation = typeof token === 'function' && (0, ValidationCache_1.isValidatable)(token);
73
- if (needsValidation) {
74
- return createValidationResolver(extractFn, token, validationConfig);
75
- }
76
- return extractFn;
77
- }
78
- function createParamResolvers(paramMetas, argTypes, validationConfig) {
79
- const resolvers = [];
80
- for (let i = 0; i < argTypes.length; i++) {
81
- const meta = paramMetas?.[i];
82
- const token = argTypes[i];
83
- resolvers.push(createParamResolver(meta, token, validationConfig));
84
- }
85
- return resolvers;
86
- }
87
- function hasAnyDIParam(resolvers) {
88
- return resolvers.some((r) => r === null);
89
- }
@@ -1,19 +1,19 @@
1
- import { type ValidatorOptions } from 'class-validator';
2
1
  import type { TokenRouteWithProvider } from '../container/ContainerConfiguration';
2
+ import type { ValidatorAdapter } from '../validation/ValidatorAdapter';
3
3
  import type { Container } from '../container/container';
4
4
  import { ProviderScope } from '../domain/provider-scope';
5
5
  import { type CompiledRoute } from './CompiledRoute';
6
6
  export interface RouteCompilerOptions {
7
7
  container: Container;
8
8
  controllerScopes: Map<any, ProviderScope>;
9
- validationConfig?: ValidatorOptions;
9
+ validatorAdapter: ValidatorAdapter;
10
10
  hasOnRequestHook: boolean;
11
11
  hasOnResponseHook: boolean;
12
12
  }
13
13
  export declare class RouteCompiler {
14
14
  private container;
15
15
  private controllerScopes;
16
- private validationConfig?;
16
+ private validatorAdapter;
17
17
  private hasOnRequestHook;
18
18
  private hasOnResponseHook;
19
19
  constructor(options: RouteCompilerOptions);
@@ -1,11 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RouteCompiler = void 0;
4
- const class_transformer_1 = require("class-transformer");
5
- const class_validator_1 = require("class-validator");
6
4
  const provider_scope_1 = require("../domain/provider-scope");
7
5
  const Metadata_1 = require("../domain/Metadata");
8
- const HttpException_1 = require("../exceptions/HttpException");
9
6
  const getMethodArgTypes_1 = require("../utils/getMethodArgTypes");
10
7
  const CompiledRoute_1 = require("./CompiledRoute");
11
8
  const ParamResolverFactory_1 = require("./ParamResolverFactory");
@@ -14,7 +11,7 @@ class RouteCompiler {
14
11
  constructor(options) {
15
12
  this.container = options.container;
16
13
  this.controllerScopes = options.controllerScopes;
17
- this.validationConfig = options.validationConfig;
14
+ this.validatorAdapter = options.validatorAdapter;
18
15
  this.hasOnRequestHook = options.hasOnRequestHook;
19
16
  this.hasOnResponseHook = options.hasOnResponseHook;
20
17
  }
@@ -158,7 +155,6 @@ class RouteCompiler {
158
155
  }
159
156
  createValidatedHandler(instance, methodName, paramInfos, hasBodyParam) {
160
157
  const handler = instance[methodName].bind(instance);
161
- const config = this.validationConfig;
162
158
  const resolveArg = (ctx, param) => {
163
159
  let value;
164
160
  switch (param.type) {
@@ -184,12 +180,7 @@ class RouteCompiler {
184
180
  value = undefined;
185
181
  }
186
182
  if (param.needsValidation && param.token) {
187
- const obj = (0, class_transformer_1.plainToInstance)(param.token, value);
188
- const errors = (0, class_validator_1.validateSync)(obj, config);
189
- if (errors.length > 0) {
190
- throw new HttpException_1.HttpException(errors, 400);
191
- }
192
- return obj;
183
+ return this.validatorAdapter.validateAndTransform(param.token, value);
193
184
  }
194
185
  return value;
195
186
  };
@@ -179,6 +179,10 @@ class Memoirist {
179
179
  }
180
180
  if (node.params?.store === oldStore) {
181
181
  node.params.store = newStore;
182
+ const paramName = node.params.names.get(oldStore);
183
+ if (paramName) {
184
+ node.params.names.set(newStore, paramName);
185
+ }
182
186
  this.updateHistoryStore(method, path, newStore);
183
187
  return true;
184
188
  }
@@ -1,3 +1,5 @@
1
+ import type { ValidatorAdapter } from '../validation/ValidatorAdapter';
2
+ export declare function setValidatorAdapter(adapter: ValidatorAdapter): void;
1
3
  export declare function isValidatable(token: Function): boolean;
2
4
  export declare function preloadValidationForParams(args: any[]): number[];
3
5
  export declare function clearValidationCache(): void;
@@ -1,14 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setValidatorAdapter = setValidatorAdapter;
3
4
  exports.isValidatable = isValidatable;
4
5
  exports.preloadValidationForParams = preloadValidationForParams;
5
6
  exports.clearValidationCache = clearValidationCache;
6
- const isClassValidator_1 = require("./isClassValidator");
7
+ let currentAdapter = null;
7
8
  const cache = new Map();
9
+ function setValidatorAdapter(adapter) {
10
+ currentAdapter = adapter;
11
+ cache.clear();
12
+ }
8
13
  function isValidatable(token) {
14
+ if (!currentAdapter) {
15
+ throw new Error('Validator adapter not initialized. Call setValidatorAdapter() first.');
16
+ }
9
17
  let result = cache.get(token);
10
18
  if (result === undefined) {
11
- result = (0, isClassValidator_1.isClassValidator)(token);
19
+ result = currentAdapter.hasValidation(token);
12
20
  cache.set(token, result);
13
21
  }
14
22
  return result;
@@ -0,0 +1,5 @@
1
+ export type ValidationIssue = {
2
+ field: string;
3
+ messages: string[];
4
+ };
5
+ export declare function formatValidationErrors(value: unknown): unknown;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatValidationErrors = formatValidationErrors;
4
+ function formatValidationErrors(value) {
5
+ if (!shouldFormatErrors(value)) {
6
+ return value;
7
+ }
8
+ return collectIssues(value);
9
+ }
10
+ function shouldFormatErrors(value) {
11
+ if (!Array.isArray(value)) {
12
+ return false;
13
+ }
14
+ if (value.length === 0) {
15
+ return false;
16
+ }
17
+ return isValidationError(value[0]);
18
+ }
19
+ function isValidationError(value) {
20
+ if (!value) {
21
+ return false;
22
+ }
23
+ if (typeof value !== "object") {
24
+ return false;
25
+ }
26
+ return hasValidationShape(value);
27
+ }
28
+ function hasValidationShape(value) {
29
+ if ("constraints" in value) {
30
+ return true;
31
+ }
32
+ if ("property" in value) {
33
+ return true;
34
+ }
35
+ if ("children" in value) {
36
+ return true;
37
+ }
38
+ return false;
39
+ }
40
+ function collectIssues(errors) {
41
+ const issues = [];
42
+ for (const error of errors) {
43
+ appendIssues(error, "", issues);
44
+ }
45
+ return issues;
46
+ }
47
+ function appendIssues(error, prefix, issues) {
48
+ const field = buildField(prefix, error.property);
49
+ appendConstraints(error, field, issues);
50
+ appendChildren(error, field, issues);
51
+ }
52
+ function appendConstraints(error, field, issues) {
53
+ const constraints = error.constraints;
54
+ if (!constraints) {
55
+ return;
56
+ }
57
+ const messages = Object.values(constraints);
58
+ if (messages.length === 0) {
59
+ return;
60
+ }
61
+ issues.push({ field, messages });
62
+ }
63
+ function appendChildren(error, prefix, issues) {
64
+ const children = error.children;
65
+ if (!children || children.length === 0) {
66
+ return;
67
+ }
68
+ for (const child of children) {
69
+ appendIssues(child, prefix, issues);
70
+ }
71
+ }
72
+ function buildField(prefix, property) {
73
+ if (!property) {
74
+ return prefix || "body";
75
+ }
76
+ if (!prefix) {
77
+ return property;
78
+ }
79
+ return `${prefix}.${property}`;
80
+ }
@@ -4,7 +4,6 @@ export * from './isString';
4
4
  export * from './isFunction';
5
5
  export * from './getConstructorArgNames';
6
6
  export * from './getValue';
7
- export * from './isClassValidator';
8
7
  export * from './getMethodArgTypes';
9
8
  export * from './getClassOrSymbol';
10
9
  export * from './isRequestScope';
@@ -13,3 +12,4 @@ export * from './isPrimitiveType';
13
12
  export * from './setValue';
14
13
  export * from './isClass';
15
14
  export * from './methodsOf';
15
+ export * from './formatValidationErrors';
@@ -20,7 +20,6 @@ __exportStar(require("./isString"), exports);
20
20
  __exportStar(require("./isFunction"), exports);
21
21
  __exportStar(require("./getConstructorArgNames"), exports);
22
22
  __exportStar(require("./getValue"), exports);
23
- __exportStar(require("./isClassValidator"), exports);
24
23
  __exportStar(require("./getMethodArgTypes"), exports);
25
24
  __exportStar(require("./getClassOrSymbol"), exports);
26
25
  __exportStar(require("./isRequestScope"), exports);
@@ -29,3 +28,4 @@ __exportStar(require("./isPrimitiveType"), exports);
29
28
  __exportStar(require("./setValue"), exports);
30
29
  __exportStar(require("./isClass"), exports);
31
30
  __exportStar(require("./methodsOf"), exports);
31
+ __exportStar(require("./formatValidationErrors"), exports);