# Validation and Errors Handling

## VGSTextInput Input Validation

VGS Collect SDK provides built-in validation for data intput. Validation is based on defined validation rules set for each specific `VGSTextInput`. These rule sets are defined by default for each VGSTextInput based on it's `type` value, but you still have possibility to customize them.

`VGSTextInput` execute validation after each it's input editing event. You can check validation results through VGSTextInput's state callback: `.onStateChange()`.

### Default Validation

Default validation for specific input `type`:

| **VGSInputType**    | **Validation Details**                                                                                                                                                                                                                                                             |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **.text**           | Any input will be valid if no other validation rules will be applied                                                                                                                                                                                                               |
| **.card**           | Card number validation with checkSum algorithm(Luhn algorithm), available card lengths for defined card types                                                                                                                                                                      |
| **.expDate**        | Any date starting from current month. By default valid expiration date should be in short year format - `mm/yy`                                                                                                                                                                    |
| **.cardHolderName** | Name, should be 2 or more symbols, valid characters shold match pattern: `[a-zA-Z0-9]`                                                                                                                                                                                             |
| **.cvc**            | Card cvc number, should be 3-4 digits. If in same `VGSCollect` instance there is associated `.cardNumer` field, **cvc** validation will be dynamic. It depends on input Card Brand type. For example: for **AMEX** valid cvc only with 4 digits, while for **Visa** 3 digits only. |
| **.ssn**            | US social security number, should be 9 digits, don't start with \[000,666,9] or contain sequences of the same digits. Ignores some SSNs used in advertising                                                                                                                        |

If you didn't find specific `type` for your use case, you can always configure `VGSTextInput` with `text` type. Then assign any specific rule set to the field and use other configuration attributes. Check more on our code examples below.

### Validation Rules

VGS Collect SDK provides pre-build validation rules that you can apply to `VGSTextInput` object through it's `type` configuration.

Here are some examples of the available rules:

| **VGSValidationRule** | **Description**                                                                                                                                                                               |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| PatternRule           | Validates input in scope of matching the regex `pattern`                                                                                                                                      |
| CardExpDateRule       | Validats input in scope of matching card expiration date format and time range. Supports `VGSCardExpDateFormat` date formats validation                                                       |
| PaymentCardRule       | Validates input in scope of matching supported card brands, available lengths and checkSum algorithms. Support optional validation of cards that are not defined in SDK - `CardBrand.unknown` |
| LuhnCheckRule         | Validates input in scope of matching Luhn algorithm                                                                                                                                           |
| LengthRule            | Validates input in scope of `min` & `max` lengths                                                                                                                                             |
| LengthMatchRule       | Validates input in scope of exact length                                                                                                                                                      |
| NotEmptyRule          | Validates input is not empty                                                                                                                                                                  |
| ABARoutingNumberRule  | Validate input against ABA (American Bankers Association) routing number requirements                                                                                                         |

### How to customize VGSTextInput Validation?

Check examples below on how to create your own validation rules or edit exiting rules that will validate input in `VGSTextInput`.

Set custom validation rules:

```javascript
import { NotEmptyRule, LengthRule, PatternRule } from '@vgs/collect-react-native';

<VGSTextInput
  //... other props
  validationRules={[
    new NotEmptyRule('This field is required'),
    new LengthRule(5, 10, 'Length must be between 5 and 10 characters'),
    new PatternRule('/^[a-zA-Z]+$/', 'Only letters are allowed'),
  ]}
/>
```

Use only Luhn validation for card number field:

```javascript
<VGSCardInput
  //... other props
  validationRules={[
    new LuhnCheckRule('Card not valid'),
  ]}
```

Ignore all default validations:

```javascript
<VGSCardInput
  //... other props
  validationRules={[]}
```

## Errors Handling

This guide covers error handling features which will help you to make your App more reliable and recover from errors produced by `VGSCollectSDK`.

### VGSError

An object the SDK uses to produce errors inside the SDK.

#### Declaration

```javascript
class VGSError extends Error
```

Some of `VGSError` provide detailes of error reason in `error.details` prop.

#### Error codes

List of Error codes produced by VGS Collect iOS SDK locally.

| **Code** | **Key**                        | **Description**                                        |
| -------- | ------------------------------ | ------------------------------------------------------ |
| 1001     | `InputDataIsNotValid`          | When input data is not valid, but required to be valid |
| 1101     | `InputFileNotFound`            | When can't find file on device                         |
| 1102     | `InputFileTypeIsNotSupported`  | When selected file type not supported                  |
| 1103     | `InputFileSizeExceedsTheLimit` | When file size is larger then allowed limit            |
| 1150     | `SourceNotAvailable`           | When can't get access to file source                   |
| 1400     | `unexpectedResponseType`       | When response type is not supported                    |
| 1470     | `InvalidVaultConfiguration`    | When VGSCollect init parameters not valid              |
| 1480     | `invalidConfigurationURL`      | When VGS configuration URL is not valid                |
| 1300     | `invalidAccessToken`           | When access token is nil or empty                      |

#### Code example

```javascript
// Add import
import { VGSError, VGSErrorCode } from '@vgs/collect-react-native';
// Other code here...

const handleSubmit = async () => {
    try {
      const { status, response } = await collector.submit('/post', 'POST')
    } catch (error) {
      if (error instanceof VGSError) {
        switch (error.code) {
          case VGSErrorCode.InputDataIsNotValid:
            for (const fieldName in error.details) {
              console.error(
                `Not valid fieldName: ${fieldName}: ${error.details[fieldName].join(', ')}`
              );
            }
            break;
          default:
            console.error('VGSError:', error.code, error.message);
        }
      } else {
        console.error('Network or unexpected error:', error);
      }
    }
```
