1.0.5 • Published 2 years ago

class-validator-translator-middleware v1.0.5

Weekly downloads
-
License
GPL-3.0
Repository
github
Last release
2 years ago

class-validator-translator-middleware

How to use this package

  • first install it npm i class-validator-translator-middleware
  • Now create a directory wherever you want and name it what ever you like but I use class-validator-errors: mkdir src/class-validator-errors
  • Then you should create error-codes.json in that directory: touch src/class-validator-errors/error-codes.json
  • Now in it you have to define your error codes like this.
    {
        "title_should_be_sample": "title_should_be_sample"
    }
  • Now you must define your error locale messages in separated files on that directory. E.X. you should touch src/class-validator-errors/en.json and in that file you have:

    {
        "title_should_be_sample": "sample is good"
    }

    And Also touch src/class-validator-errors/fa.json:

    {
        "title_should_be_sample": "تست خوبه"
    }

    Important note: You cannot define an error code in error-codes.json but it had no defined error message in your error locale messages. If you do this intentionally or accidentally you will get an error while creating a new instance of ClassValidatorTranslatorMiddleware, The thrown error is instance of this error custom error class: IncompatibleErrorCodeAndErrorMessage.

    Since I am reading the error messages using require, they will be cached in the memory and this will prevent unnecessary reads from file system. for more info please read ClassValidatorTranslatorMiddleware codes :star_struck:

    Note if you are using tsc: because we will never ever use fa.json and other json files you have to include this unused json files in your tsconfig.json/tsconfig.build.json file like this (If you do not include your fa.json, en.json, ... files will not be in the compiled version. unless you import them implicitly):

    {
        "include": ["src", "src/**/*.json"]
        // ...
    }

    I client side sends an locale that you do not defined its error-message file in the class-validator-errors directory you will get An error in the next error handler middleware. In this case you will get an error that it is instance of SpecifiedErrorMessageFileNotFound.

  • Your frontend have to specify the accept-language header in their requests and it should be within the Locale enum.

  • Final examples:

    • Here is one example in ExpressJS:

      // app.ts
      import { join } from 'path';
      import { Equals, IsOptional } from 'class-validator';
      import {
          ClassValidatorTranslatorMiddleware,
          IncompatibleErrorCodeAndErrorMessage
      } from 'class-validator-translator-middleware';
      
      process.on('uncaughtException', (error) => {
          if (error instanceof IncompatibleErrorCodeAndErrorMessage) {
              // do what ever you like, like sending email/notification to your devops guy
              process.exit(1);
          }
      })
      
      const messagesPath = join(__dirname, 'class-validator-errors');
      const classValidatorTranslatorMiddleware =
          new ClassValidatorTranslatorMiddleware(messagesPath);
        const classValidatorTranslatorMiddleware =
            new ClassValidatorTranslatorMiddleware(messagesPath);

        app.use(classValidatorTranslatorMiddleware.middleware);

        // this can be your class validator
        class TestClassValidator {
            @IsOptional()
            @Equals('sample', { message: 'title_should_be_sample' })
            title: string = 'bad_value';
        }

        app.use((error, req, res, next) => {
            for (const error of errors) {
                console.log(error.constraints); // تست خوبه
            }
        });
        ```

    ````

    ```

    ```

    ```

    ```

-   Here is one example in routing controller

    ```ts
    // messages.ts
    import { ClassValidatorTranslatorMiddleware } from 'class-validator-translator-middleware';

    // city-filter.ts
    import {
        IsBoolean,
        IsAlpha,
        IsOptional,
    } from 'class-validator';

    export class CityFilterQuery {
        @IsOptional()
        @IsAlpha('en', {
            message: 'serviced_should_be_boolean_not_empty',
        })
        @IsBoolean({ message: 'serviced_should_be_boolean' })
        serviced?: boolean;
    }

    // class-validator-error-translator.middleware.ts
    import { join } from 'path';
    import { ValidationError } from 'class-validator';
    import {
        Middleware,
        ExpressErrorMiddlewareInterface,
        HttpError,
    } from 'routing-controllers';
    import { NextFunction, Request, Response } from 'express';
    import { ClassValidatorTranslatorMiddleware } from 'class-validator-translator-middleware';

    const messagesPath = join(
        __dirname,
        'class-validator-errors',
    );
    const classValidatorTranslatorMiddleware =
        new ClassValidatorTranslatorMiddleware(messagesPath);

    class CustomValidationError {
        errors: ValidationError[];
        status?: number;
        statusCode?: number;
    }

    @Middleware({ type: 'after' })
    export class ClassValidatorErrorTranslator
        implements ExpressErrorMiddlewareInterface
    {
        error(
            error: HttpError | CustomValidationError,
            request: Request,
            response: Response,
            next: NextFunction,
        ): void {
            classValidatorTranslatorMiddleware.middleware(
                error,
                request,
                response,
                next,
            );
        }
    }

    // another middleware
    import { ValidationError } from 'class-validator';
    import {
        Middleware,
        ExpressErrorMiddlewareInterface,
        HttpError,
    } from 'routing-controllers';
    import { NextFunction, Request, Response } from 'express';
    import { SpecifiedErrorMessageFileNotFound } from 'class-validator-translator-middleware';

    @Middleware({ type: 'after' })
    export class ClassValidatorErrorTranslator
        implements ExpressErrorMiddlewareInterface
    {
        error(
            error: HttpError | CustomValidationError,
            request: Request,
            response: Response,
            next: NextFunction,
        ): void {
            if (
                error instanceof SpecifiedErrorMessageFileNotFound
            ) {
                // do whatever you want.
                response.status(400).json({
                    message: 'un-supported-language',
                });
            }
            next(error);
        }
    }

    // app.ts
    import { ClassValidatorErrorTranslator } from './middlewares/class-validator-error-translator.middleware';
    import express from 'express';

    const app = express();

    const routingControllersOptions: RoutingControllersOptions = {
        controllers: [
            /* controllers */
        ],
        middlewares: [ClassValidatorErrorTranslator],
        /* other configs */
        validation: {
            whitelist: true,
        },
    };
    useExpressServer(app, routingControllersOptions);
    ```

Supported languages in Locale enum

Notes

  • I had no time to add all the languages in the Locale
  • Please use it with Typescript to prevent any unexpected behaviours
  • Feel free to create issue or pull request

Contribution

  • Clone repository
  • npm i; npm i prepeare
  • Create a new branch from develop branch (git checkout -b develop-your-name)
  • Write you code
  • Write its tests in tests directory
  • run npm test and make sure it works perfectly
1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago

0.0.11

2 years ago

0.0.10

2 years ago

0.0.9

2 years ago

0.0.8

2 years ago

0.0.7

2 years ago

0.0.6

2 years ago

0.0.5

2 years ago

0.0.4

2 years ago

0.0.3

2 years ago

0.0.2

2 years ago

0.0.1

2 years ago