npm package: @os-team/graphql-validators
Description: The type-graphql decorator to validate arguments using i18next. Contains the most used validators.
Latest version: 1.2.1

# @os-team/graphql-validators [![NPM version](https://img.shields.io/npm/v/@os-team/graphql-validators)](https://yarnpkg.com/package/@os-team/graphql-validators) [![BundlePhobia](https://img.shields.io/bundlephobia/minzip/@os-team/graphql-validators)](https://bundlephobia.com/result?p=@os-team/graphql-validators)

The type-graphql decorator to validate arguments using i18next. Contains the most used validators.

## Prerequisites

The library uses the `context.req.t` function to get the error message. To populate the `t` function in `req`, you must install the [i18next-http-middleware](https://github.com/i18next/i18next-http-middleware).
Follow the instructions inside this library.

## Installation

Install the package using the following command:

```
yarn add @os-team/graphql-validators
```

It is assumed that the `graphql` and `type-graphql` libraries are already installed.

## Usage

For example, we have the fox entity and 2 files: `CreateFoxInput.ts` and `FoxResolver.ts`.

### Step 1. Create validators

```ts
import { Field, InputType } from 'type-graphql';
import { isNotEmpty, maxLength } from '@os-team/graphql-validators';

@InputType()
class CreateFoxInput {
  @Field()
  name!: string;
}

export const createFoxValidators = {
  name: [isNotEmpty, maxLength(50)],
};

export default CreateFoxInput;
```

### Step 2. Add the `@ValidateArgs` decorator

```ts
import { Arg, Mutation, Resolver } from 'type-graphql';
import { ValidateArgs } from '@os-team/graphql-validators';
import Fox from '../../entities/Fox';
import CreateFoxInput, { createFoxValidators } from './CreateFoxInput';

@Resolver(() => Fox)
class FoxResolver {
  @ValidateArgs(createFoxValidators, { arg: 'input' })
  @Mutation(() => Fox)
  async createFox(@Arg('input') input: CreateFoxInput): Promise<Fox> {
    // The implementation
  }
}

export default FoxResolver;
```

If you did not specify the `arg` parameter, the `@ValidateArgs` decorator will validate all the arguments.
It can be useful, for example, if you want to validate the connection arguments.

```ts
import { Args, Query, Resolver } from 'type-graphql';
import { ValidateArgs } from '@os-team/graphql-validators';
import { ConnectionArgs, createConnectionType } from '@os-team/graphql-utils';
import Fox from '../../entities/Fox';
import FoxConnectionArgs, {
  foxConnectionValidators,
} from './FoxConnectionArgs';

export const FoxConnection = createConnectionType(Fox);

@Resolver(() => Fox)
class FoxResolver {
  @ValidateArgs(foxConnectionValidators)
  @Query(() => FoxConnection)
  async foxes(@Args() args: FoxConnectionArgs): Promise<Connection<Fox>> {
    // The implementation
  }
}

export default FoxResolver;
```

### Step 3. Create the locales

Example of the `locales/en/validation.json` file:

```json
{
  "name": {
    "isEmpty": "Please enter a name",
    "maxLength": "Give a shorter name, up to {{max}} characters"
  }
}
```

By default, it uses the `validation` namespace, but you can specify your own like this:

```ts
@ValidateArgs(createFoxValidators, { arg: 'input', ns: 'custom' })
```

Also, you can add a prefix to the locale key like this:

```ts
@ValidateArgs(createFoxValidators, { arg: 'input', tKey: 'fox' })
```

Now we need to replace the locale file with:

```json
{
  "fox": {
    "name": {
      "isEmpty": "Please enter a fox name",
      "maxLength": "Give a shorter fox name, up to {{max}} characters"
    }
  }
}
```

## Create the custom validator

You can create your own validators like this:

```ts
import { Validator } from '@os-team/graphql-validators';

/**
 * Checks if the trimmed string is not empty.
 */
const isNotEmpty: Validator = {
  name: 'isEmpty',
  validate: (value) => typeof value === 'string' && value.trim().length > 0,
};

export default isNotEmpty;
```

The `validate` function can be either synchronous or asynchronous.

You can also pass validator arguments to the locale like this:

```ts
import { Validator } from '../utils/ValidateArgs';

/**
 * Checks if the string length is not more than given number.
 */
const maxLength = (n: number): Validator => ({
  name: 'maxLength',
  validate: (value) => typeof value === 'string' && value.length <= n,
  tKeys: { max: n },
});

export default maxLength;
```

In the locale, use the arguments as follows:

```json
{
  "name": {
    "maxLength": "Give a shorter name, up to {{max}} characters"
  }
}
```

In rare cases, it is required to pass data from the validate function to the locale. You can do it as follows:

```ts
import { Validator } from '../utils/ValidateArgs';

const hasRequiredFields: Validator = {
  name: 'hasRequiredFields',
  validate: (value) =>
    typeof value === 'object' && value.firstName
      ? true
      : [false, { required: 'firstName' }],
};

export default hasRequiredFields;
```